1*45e6af3bSDavid du Colombier #include "u.h"
2*45e6af3bSDavid du Colombier #include "../port/lib.h"
3*45e6af3bSDavid du Colombier #include "mem.h"
4*45e6af3bSDavid du Colombier #include "dat.h"
5*45e6af3bSDavid du Colombier #include "fns.h"
6*45e6af3bSDavid du Colombier #include "../port/error.h"
7*45e6af3bSDavid du Colombier
8*45e6af3bSDavid du Colombier #define Image IMAGE
9*45e6af3bSDavid du Colombier #include <draw.h>
10*45e6af3bSDavid du Colombier #include <memdraw.h>
11*45e6af3bSDavid du Colombier #include <memlayer.h>
12*45e6af3bSDavid du Colombier #include <cursor.h>
13*45e6af3bSDavid du Colombier #include "screen.h"
14*45e6af3bSDavid du Colombier
15*45e6af3bSDavid du Colombier enum
16*45e6af3bSDavid du Colombier {
17*45e6af3bSDavid du Colombier Qtopdir = 0,
18*45e6af3bSDavid du Colombier Qnew,
19*45e6af3bSDavid du Colombier Qwinname,
20*45e6af3bSDavid du Colombier Q3rd,
21*45e6af3bSDavid du Colombier Q2nd,
22*45e6af3bSDavid du Colombier Qcolormap,
23*45e6af3bSDavid du Colombier Qctl,
24*45e6af3bSDavid du Colombier Qdata,
25*45e6af3bSDavid du Colombier Qrefresh,
26*45e6af3bSDavid du Colombier };
27*45e6af3bSDavid du Colombier
28*45e6af3bSDavid du Colombier /*
29*45e6af3bSDavid du Colombier * Qid path is:
30*45e6af3bSDavid du Colombier * 4 bits of file type (qids above)
31*45e6af3bSDavid du Colombier * 24 bits of mux slot number +1; 0 means not attached to client
32*45e6af3bSDavid du Colombier */
33*45e6af3bSDavid du Colombier #define QSHIFT 4 /* location in qid of client # */
34*45e6af3bSDavid du Colombier
35*45e6af3bSDavid du Colombier #define QID(q) ((((ulong)(q).path)&0x0000000F)>>0)
36*45e6af3bSDavid du Colombier #define CLIENTPATH(q) ((((ulong)q)&0x7FFFFFF0)>>QSHIFT)
37*45e6af3bSDavid du Colombier #define CLIENT(q) CLIENTPATH((q).path)
38*45e6af3bSDavid du Colombier
39*45e6af3bSDavid du Colombier #define NHASH (1<<5)
40*45e6af3bSDavid du Colombier #define HASHMASK (NHASH-1)
41*45e6af3bSDavid du Colombier #define IOUNIT (64*1024)
42*45e6af3bSDavid du Colombier
43*45e6af3bSDavid du Colombier typedef struct Client Client;
44*45e6af3bSDavid du Colombier typedef struct Draw Draw;
45*45e6af3bSDavid du Colombier typedef struct DImage DImage;
46*45e6af3bSDavid du Colombier typedef struct DScreen DScreen;
47*45e6af3bSDavid du Colombier typedef struct CScreen CScreen;
48*45e6af3bSDavid du Colombier typedef struct FChar FChar;
49*45e6af3bSDavid du Colombier typedef struct Refresh Refresh;
50*45e6af3bSDavid du Colombier typedef struct Refx Refx;
51*45e6af3bSDavid du Colombier typedef struct DName DName;
52*45e6af3bSDavid du Colombier
53*45e6af3bSDavid du Colombier ulong blanktime = 30; /* in minutes; a half hour */
54*45e6af3bSDavid du Colombier
55*45e6af3bSDavid du Colombier struct Draw
56*45e6af3bSDavid du Colombier {
57*45e6af3bSDavid du Colombier int clientid;
58*45e6af3bSDavid du Colombier int nclient;
59*45e6af3bSDavid du Colombier Client** client;
60*45e6af3bSDavid du Colombier int nname;
61*45e6af3bSDavid du Colombier DName* name;
62*45e6af3bSDavid du Colombier int vers;
63*45e6af3bSDavid du Colombier int softscreen;
64*45e6af3bSDavid du Colombier int blanked; /* screen turned off */
65*45e6af3bSDavid du Colombier ulong blanktime; /* time of last operation */
66*45e6af3bSDavid du Colombier ulong savemap[3*256];
67*45e6af3bSDavid du Colombier };
68*45e6af3bSDavid du Colombier
69*45e6af3bSDavid du Colombier struct Client
70*45e6af3bSDavid du Colombier {
71*45e6af3bSDavid du Colombier Ref r;
72*45e6af3bSDavid du Colombier DImage* dimage[NHASH];
73*45e6af3bSDavid du Colombier CScreen* cscreen;
74*45e6af3bSDavid du Colombier Refresh* refresh;
75*45e6af3bSDavid du Colombier Rendez refrend;
76*45e6af3bSDavid du Colombier uchar* readdata;
77*45e6af3bSDavid du Colombier int nreaddata;
78*45e6af3bSDavid du Colombier int busy;
79*45e6af3bSDavid du Colombier int clientid;
80*45e6af3bSDavid du Colombier int slot;
81*45e6af3bSDavid du Colombier int refreshme;
82*45e6af3bSDavid du Colombier int infoid;
83*45e6af3bSDavid du Colombier int op;
84*45e6af3bSDavid du Colombier };
85*45e6af3bSDavid du Colombier
86*45e6af3bSDavid du Colombier struct Refresh
87*45e6af3bSDavid du Colombier {
88*45e6af3bSDavid du Colombier DImage* dimage;
89*45e6af3bSDavid du Colombier Rectangle r;
90*45e6af3bSDavid du Colombier Refresh* next;
91*45e6af3bSDavid du Colombier };
92*45e6af3bSDavid du Colombier
93*45e6af3bSDavid du Colombier struct Refx
94*45e6af3bSDavid du Colombier {
95*45e6af3bSDavid du Colombier Client* client;
96*45e6af3bSDavid du Colombier DImage* dimage;
97*45e6af3bSDavid du Colombier };
98*45e6af3bSDavid du Colombier
99*45e6af3bSDavid du Colombier struct DName
100*45e6af3bSDavid du Colombier {
101*45e6af3bSDavid du Colombier char *name;
102*45e6af3bSDavid du Colombier Client *client;
103*45e6af3bSDavid du Colombier DImage* dimage;
104*45e6af3bSDavid du Colombier int vers;
105*45e6af3bSDavid du Colombier };
106*45e6af3bSDavid du Colombier
107*45e6af3bSDavid du Colombier struct FChar
108*45e6af3bSDavid du Colombier {
109*45e6af3bSDavid du Colombier int minx; /* left edge of bits */
110*45e6af3bSDavid du Colombier int maxx; /* right edge of bits */
111*45e6af3bSDavid du Colombier uchar miny; /* first non-zero scan-line */
112*45e6af3bSDavid du Colombier uchar maxy; /* last non-zero scan-line + 1 */
113*45e6af3bSDavid du Colombier schar left; /* offset of baseline */
114*45e6af3bSDavid du Colombier uchar width; /* width of baseline */
115*45e6af3bSDavid du Colombier };
116*45e6af3bSDavid du Colombier
117*45e6af3bSDavid du Colombier /*
118*45e6af3bSDavid du Colombier * Reference counts in DImages:
119*45e6af3bSDavid du Colombier * one per open by original client
120*45e6af3bSDavid du Colombier * one per screen image or fill
121*45e6af3bSDavid du Colombier * one per image derived from this one by name
122*45e6af3bSDavid du Colombier */
123*45e6af3bSDavid du Colombier struct DImage
124*45e6af3bSDavid du Colombier {
125*45e6af3bSDavid du Colombier int id;
126*45e6af3bSDavid du Colombier int ref;
127*45e6af3bSDavid du Colombier char *name;
128*45e6af3bSDavid du Colombier int vers;
129*45e6af3bSDavid du Colombier Memimage* image;
130*45e6af3bSDavid du Colombier int ascent;
131*45e6af3bSDavid du Colombier int nfchar;
132*45e6af3bSDavid du Colombier FChar* fchar;
133*45e6af3bSDavid du Colombier DScreen* dscreen; /* 0 if not a window */
134*45e6af3bSDavid du Colombier DImage* fromname; /* image this one is derived from, by name */
135*45e6af3bSDavid du Colombier DImage* next;
136*45e6af3bSDavid du Colombier };
137*45e6af3bSDavid du Colombier
138*45e6af3bSDavid du Colombier struct CScreen
139*45e6af3bSDavid du Colombier {
140*45e6af3bSDavid du Colombier DScreen* dscreen;
141*45e6af3bSDavid du Colombier CScreen* next;
142*45e6af3bSDavid du Colombier };
143*45e6af3bSDavid du Colombier
144*45e6af3bSDavid du Colombier struct DScreen
145*45e6af3bSDavid du Colombier {
146*45e6af3bSDavid du Colombier int id;
147*45e6af3bSDavid du Colombier int public;
148*45e6af3bSDavid du Colombier int ref;
149*45e6af3bSDavid du Colombier DImage *dimage;
150*45e6af3bSDavid du Colombier DImage *dfill;
151*45e6af3bSDavid du Colombier Memscreen* screen;
152*45e6af3bSDavid du Colombier Client* owner;
153*45e6af3bSDavid du Colombier DScreen* next;
154*45e6af3bSDavid du Colombier };
155*45e6af3bSDavid du Colombier
156*45e6af3bSDavid du Colombier static Draw sdraw;
157*45e6af3bSDavid du Colombier QLock drawlock;
158*45e6af3bSDavid du Colombier
159*45e6af3bSDavid du Colombier static Memimage *screenimage;
160*45e6af3bSDavid du Colombier static DImage* screendimage;
161*45e6af3bSDavid du Colombier static char screenname[40];
162*45e6af3bSDavid du Colombier static int screennameid;
163*45e6af3bSDavid du Colombier
164*45e6af3bSDavid du Colombier static Rectangle flushrect;
165*45e6af3bSDavid du Colombier static int waste;
166*45e6af3bSDavid du Colombier static DScreen* dscreen;
167*45e6af3bSDavid du Colombier extern void flushmemscreen(Rectangle);
168*45e6af3bSDavid du Colombier void drawmesg(Client*, void*, int);
169*45e6af3bSDavid du Colombier void drawuninstall(Client*, int);
170*45e6af3bSDavid du Colombier void drawfreedimage(DImage*);
171*45e6af3bSDavid du Colombier Client* drawclientofpath(ulong);
172*45e6af3bSDavid du Colombier DImage* allocdimage(Memimage*);
173*45e6af3bSDavid du Colombier
174*45e6af3bSDavid du Colombier static char Enodrawimage[] = "unknown id for draw image";
175*45e6af3bSDavid du Colombier static char Enodrawscreen[] = "unknown id for draw screen";
176*45e6af3bSDavid du Colombier static char Eshortdraw[] = "short draw message";
177*45e6af3bSDavid du Colombier static char Eshortread[] = "draw read too short";
178*45e6af3bSDavid du Colombier static char Eimageexists[] = "image id in use";
179*45e6af3bSDavid du Colombier static char Escreenexists[] = "screen id in use";
180*45e6af3bSDavid du Colombier static char Edrawmem[] = "image memory allocation failed";
181*45e6af3bSDavid du Colombier static char Ereadoutside[] = "readimage outside image";
182*45e6af3bSDavid du Colombier static char Ewriteoutside[] = "writeimage outside image";
183*45e6af3bSDavid du Colombier static char Enotfont[] = "image not a font";
184*45e6af3bSDavid du Colombier static char Eindex[] = "character index out of range";
185*45e6af3bSDavid du Colombier static char Enoclient[] = "no such draw client";
186*45e6af3bSDavid du Colombier static char Edepth[] = "image has bad depth";
187*45e6af3bSDavid du Colombier static char Enameused[] = "image name in use";
188*45e6af3bSDavid du Colombier static char Enoname[] = "no image with that name";
189*45e6af3bSDavid du Colombier static char Eoldname[] = "named image no longer valid";
190*45e6af3bSDavid du Colombier static char Enamed[] = "image already has name";
191*45e6af3bSDavid du Colombier static char Ewrongname[] = "wrong name for image";
192*45e6af3bSDavid du Colombier
193*45e6af3bSDavid du Colombier static void
dlock(void)194*45e6af3bSDavid du Colombier dlock(void)
195*45e6af3bSDavid du Colombier {
196*45e6af3bSDavid du Colombier qlock(&drawlock);
197*45e6af3bSDavid du Colombier }
198*45e6af3bSDavid du Colombier
199*45e6af3bSDavid du Colombier static int
candlock(void)200*45e6af3bSDavid du Colombier candlock(void)
201*45e6af3bSDavid du Colombier {
202*45e6af3bSDavid du Colombier return canqlock(&drawlock);
203*45e6af3bSDavid du Colombier }
204*45e6af3bSDavid du Colombier
205*45e6af3bSDavid du Colombier static void
dunlock(void)206*45e6af3bSDavid du Colombier dunlock(void)
207*45e6af3bSDavid du Colombier {
208*45e6af3bSDavid du Colombier qunlock(&drawlock);
209*45e6af3bSDavid du Colombier }
210*45e6af3bSDavid du Colombier
211*45e6af3bSDavid du Colombier static int
drawgen(Chan * c,char *,Dirtab *,int,int s,Dir * dp)212*45e6af3bSDavid du Colombier drawgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
213*45e6af3bSDavid du Colombier {
214*45e6af3bSDavid du Colombier int t;
215*45e6af3bSDavid du Colombier Qid q;
216*45e6af3bSDavid du Colombier ulong path;
217*45e6af3bSDavid du Colombier Client *cl;
218*45e6af3bSDavid du Colombier
219*45e6af3bSDavid du Colombier q.vers = 0;
220*45e6af3bSDavid du Colombier
221*45e6af3bSDavid du Colombier if(s == DEVDOTDOT){
222*45e6af3bSDavid du Colombier switch(QID(c->qid)){
223*45e6af3bSDavid du Colombier case Qtopdir:
224*45e6af3bSDavid du Colombier case Q2nd:
225*45e6af3bSDavid du Colombier mkqid(&q, Qtopdir, 0, QTDIR);
226*45e6af3bSDavid du Colombier devdir(c, q, "#i", 0, eve, 0500, dp);
227*45e6af3bSDavid du Colombier break;
228*45e6af3bSDavid du Colombier case Q3rd:
229*45e6af3bSDavid du Colombier cl = drawclientofpath(c->qid.path);
230*45e6af3bSDavid du Colombier if(cl == nil)
231*45e6af3bSDavid du Colombier strncpy(up->genbuf, "??", sizeof up->genbuf);
232*45e6af3bSDavid du Colombier else
233*45e6af3bSDavid du Colombier snprint(up->genbuf, sizeof up->genbuf,
234*45e6af3bSDavid du Colombier "%d", cl->clientid);
235*45e6af3bSDavid du Colombier mkqid(&q, Q2nd, 0, QTDIR);
236*45e6af3bSDavid du Colombier devdir(c, q, up->genbuf, 0, eve, 0500, dp);
237*45e6af3bSDavid du Colombier break;
238*45e6af3bSDavid du Colombier default:
239*45e6af3bSDavid du Colombier panic("drawwalk %llux", c->qid.path);
240*45e6af3bSDavid du Colombier }
241*45e6af3bSDavid du Colombier return 1;
242*45e6af3bSDavid du Colombier }
243*45e6af3bSDavid du Colombier
244*45e6af3bSDavid du Colombier /*
245*45e6af3bSDavid du Colombier * Top level directory contains the name of the device.
246*45e6af3bSDavid du Colombier */
247*45e6af3bSDavid du Colombier t = QID(c->qid);
248*45e6af3bSDavid du Colombier if(t == Qtopdir){
249*45e6af3bSDavid du Colombier switch(s){
250*45e6af3bSDavid du Colombier case 0:
251*45e6af3bSDavid du Colombier mkqid(&q, Q2nd, 0, QTDIR);
252*45e6af3bSDavid du Colombier devdir(c, q, "draw", 0, eve, 0555, dp);
253*45e6af3bSDavid du Colombier break;
254*45e6af3bSDavid du Colombier case 1:
255*45e6af3bSDavid du Colombier mkqid(&q, Qwinname, 0, QTFILE);
256*45e6af3bSDavid du Colombier devdir(c, q, "winname", 0, eve, 0444, dp);
257*45e6af3bSDavid du Colombier break;
258*45e6af3bSDavid du Colombier default:
259*45e6af3bSDavid du Colombier return -1;
260*45e6af3bSDavid du Colombier }
261*45e6af3bSDavid du Colombier return 1;
262*45e6af3bSDavid du Colombier }
263*45e6af3bSDavid du Colombier
264*45e6af3bSDavid du Colombier if(t == Qwinname){
265*45e6af3bSDavid du Colombier mkqid(&q, Qwinname, 0, QTFILE);
266*45e6af3bSDavid du Colombier devdir(c, q, "winname", 0, eve, 0444, dp);
267*45e6af3bSDavid du Colombier return 1;
268*45e6af3bSDavid du Colombier }
269*45e6af3bSDavid du Colombier
270*45e6af3bSDavid du Colombier /*
271*45e6af3bSDavid du Colombier * Second level contains "new" plus all the clients.
272*45e6af3bSDavid du Colombier */
273*45e6af3bSDavid du Colombier if(t == Q2nd || t == Qnew){
274*45e6af3bSDavid du Colombier if(s == 0){
275*45e6af3bSDavid du Colombier mkqid(&q, Qnew, 0, QTFILE);
276*45e6af3bSDavid du Colombier devdir(c, q, "new", 0, eve, 0666, dp);
277*45e6af3bSDavid du Colombier }
278*45e6af3bSDavid du Colombier else if(s <= sdraw.nclient){
279*45e6af3bSDavid du Colombier cl = sdraw.client[s-1];
280*45e6af3bSDavid du Colombier if(cl == 0)
281*45e6af3bSDavid du Colombier return 0;
282*45e6af3bSDavid du Colombier snprint(up->genbuf, sizeof up->genbuf, "%d",
283*45e6af3bSDavid du Colombier cl->clientid);
284*45e6af3bSDavid du Colombier mkqid(&q, (s<<QSHIFT)|Q3rd, 0, QTDIR);
285*45e6af3bSDavid du Colombier devdir(c, q, up->genbuf, 0, eve, 0555, dp);
286*45e6af3bSDavid du Colombier return 1;
287*45e6af3bSDavid du Colombier }
288*45e6af3bSDavid du Colombier else
289*45e6af3bSDavid du Colombier return -1;
290*45e6af3bSDavid du Colombier return 1;
291*45e6af3bSDavid du Colombier }
292*45e6af3bSDavid du Colombier
293*45e6af3bSDavid du Colombier /*
294*45e6af3bSDavid du Colombier * Third level.
295*45e6af3bSDavid du Colombier */
296*45e6af3bSDavid du Colombier path = c->qid.path&~((1<<QSHIFT)-1); /* slot component */
297*45e6af3bSDavid du Colombier q.vers = c->qid.vers;
298*45e6af3bSDavid du Colombier q.type = QTFILE;
299*45e6af3bSDavid du Colombier switch(s){
300*45e6af3bSDavid du Colombier case 0:
301*45e6af3bSDavid du Colombier q.path = path|Qcolormap;
302*45e6af3bSDavid du Colombier devdir(c, q, "colormap", 0, eve, 0600, dp);
303*45e6af3bSDavid du Colombier break;
304*45e6af3bSDavid du Colombier case 1:
305*45e6af3bSDavid du Colombier q.path = path|Qctl;
306*45e6af3bSDavid du Colombier devdir(c, q, "ctl", 0, eve, 0600, dp);
307*45e6af3bSDavid du Colombier break;
308*45e6af3bSDavid du Colombier case 2:
309*45e6af3bSDavid du Colombier q.path = path|Qdata;
310*45e6af3bSDavid du Colombier devdir(c, q, "data", 0, eve, 0600, dp);
311*45e6af3bSDavid du Colombier break;
312*45e6af3bSDavid du Colombier case 3:
313*45e6af3bSDavid du Colombier q.path = path|Qrefresh;
314*45e6af3bSDavid du Colombier devdir(c, q, "refresh", 0, eve, 0400, dp);
315*45e6af3bSDavid du Colombier break;
316*45e6af3bSDavid du Colombier default:
317*45e6af3bSDavid du Colombier return -1;
318*45e6af3bSDavid du Colombier }
319*45e6af3bSDavid du Colombier return 1;
320*45e6af3bSDavid du Colombier }
321*45e6af3bSDavid du Colombier
322*45e6af3bSDavid du Colombier static
323*45e6af3bSDavid du Colombier int
drawrefactive(void * a)324*45e6af3bSDavid du Colombier drawrefactive(void *a)
325*45e6af3bSDavid du Colombier {
326*45e6af3bSDavid du Colombier Client *c;
327*45e6af3bSDavid du Colombier
328*45e6af3bSDavid du Colombier c = a;
329*45e6af3bSDavid du Colombier return c->refreshme || c->refresh!=0;
330*45e6af3bSDavid du Colombier }
331*45e6af3bSDavid du Colombier
332*45e6af3bSDavid du Colombier static
333*45e6af3bSDavid du Colombier void
drawrefreshscreen(DImage * l,Client * client)334*45e6af3bSDavid du Colombier drawrefreshscreen(DImage *l, Client *client)
335*45e6af3bSDavid du Colombier {
336*45e6af3bSDavid du Colombier while(l != nil && l->dscreen == nil)
337*45e6af3bSDavid du Colombier l = l->fromname;
338*45e6af3bSDavid du Colombier if(l != nil && l->dscreen->owner != client)
339*45e6af3bSDavid du Colombier l->dscreen->owner->refreshme = 1;
340*45e6af3bSDavid du Colombier }
341*45e6af3bSDavid du Colombier
342*45e6af3bSDavid du Colombier static
343*45e6af3bSDavid du Colombier void
drawrefresh(Memimage *,Rectangle r,void * v)344*45e6af3bSDavid du Colombier drawrefresh(Memimage*, Rectangle r, void *v)
345*45e6af3bSDavid du Colombier {
346*45e6af3bSDavid du Colombier Refx *x;
347*45e6af3bSDavid du Colombier DImage *d;
348*45e6af3bSDavid du Colombier Client *c;
349*45e6af3bSDavid du Colombier Refresh *ref;
350*45e6af3bSDavid du Colombier
351*45e6af3bSDavid du Colombier if(v == 0)
352*45e6af3bSDavid du Colombier return;
353*45e6af3bSDavid du Colombier x = v;
354*45e6af3bSDavid du Colombier c = x->client;
355*45e6af3bSDavid du Colombier d = x->dimage;
356*45e6af3bSDavid du Colombier for(ref=c->refresh; ref; ref=ref->next)
357*45e6af3bSDavid du Colombier if(ref->dimage == d){
358*45e6af3bSDavid du Colombier combinerect(&ref->r, r);
359*45e6af3bSDavid du Colombier return;
360*45e6af3bSDavid du Colombier }
361*45e6af3bSDavid du Colombier ref = malloc(sizeof(Refresh));
362*45e6af3bSDavid du Colombier if(ref){
363*45e6af3bSDavid du Colombier ref->dimage = d;
364*45e6af3bSDavid du Colombier ref->r = r;
365*45e6af3bSDavid du Colombier ref->next = c->refresh;
366*45e6af3bSDavid du Colombier c->refresh = ref;
367*45e6af3bSDavid du Colombier }
368*45e6af3bSDavid du Colombier }
369*45e6af3bSDavid du Colombier
370*45e6af3bSDavid du Colombier static void
addflush(Rectangle r)371*45e6af3bSDavid du Colombier addflush(Rectangle r)
372*45e6af3bSDavid du Colombier {
373*45e6af3bSDavid du Colombier int abb, ar, anbb;
374*45e6af3bSDavid du Colombier Rectangle nbb;
375*45e6af3bSDavid du Colombier
376*45e6af3bSDavid du Colombier if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))
377*45e6af3bSDavid du Colombier return;
378*45e6af3bSDavid du Colombier
379*45e6af3bSDavid du Colombier if(flushrect.min.x >= flushrect.max.x){
380*45e6af3bSDavid du Colombier flushrect = r;
381*45e6af3bSDavid du Colombier waste = 0;
382*45e6af3bSDavid du Colombier return;
383*45e6af3bSDavid du Colombier }
384*45e6af3bSDavid du Colombier nbb = flushrect;
385*45e6af3bSDavid du Colombier combinerect(&nbb, r);
386*45e6af3bSDavid du Colombier ar = Dx(r)*Dy(r);
387*45e6af3bSDavid du Colombier abb = Dx(flushrect)*Dy(flushrect);
388*45e6af3bSDavid du Colombier anbb = Dx(nbb)*Dy(nbb);
389*45e6af3bSDavid du Colombier /*
390*45e6af3bSDavid du Colombier * Area of new waste is area of new bb minus area of old bb,
391*45e6af3bSDavid du Colombier * less the area of the new segment, which we assume is not waste.
392*45e6af3bSDavid du Colombier * This could be negative, but that's OK.
393*45e6af3bSDavid du Colombier */
394*45e6af3bSDavid du Colombier waste += anbb-abb - ar;
395*45e6af3bSDavid du Colombier if(waste < 0)
396*45e6af3bSDavid du Colombier waste = 0;
397*45e6af3bSDavid du Colombier /*
398*45e6af3bSDavid du Colombier * absorb if:
399*45e6af3bSDavid du Colombier * total area is small
400*45e6af3bSDavid du Colombier * waste is less than half total area
401*45e6af3bSDavid du Colombier * rectangles touch
402*45e6af3bSDavid du Colombier */
403*45e6af3bSDavid du Colombier if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){
404*45e6af3bSDavid du Colombier flushrect = nbb;
405*45e6af3bSDavid du Colombier return;
406*45e6af3bSDavid du Colombier }
407*45e6af3bSDavid du Colombier /* emit current state */
408*45e6af3bSDavid du Colombier if(flushrect.min.x < flushrect.max.x)
409*45e6af3bSDavid du Colombier flushmemscreen(flushrect);
410*45e6af3bSDavid du Colombier flushrect = r;
411*45e6af3bSDavid du Colombier waste = 0;
412*45e6af3bSDavid du Colombier }
413*45e6af3bSDavid du Colombier
414*45e6af3bSDavid du Colombier static
415*45e6af3bSDavid du Colombier void
dstflush(int dstid,Memimage * dst,Rectangle r)416*45e6af3bSDavid du Colombier dstflush(int dstid, Memimage *dst, Rectangle r)
417*45e6af3bSDavid du Colombier {
418*45e6af3bSDavid du Colombier Memlayer *l;
419*45e6af3bSDavid du Colombier
420*45e6af3bSDavid du Colombier if(dstid == 0){
421*45e6af3bSDavid du Colombier combinerect(&flushrect, r);
422*45e6af3bSDavid du Colombier return;
423*45e6af3bSDavid du Colombier }
424*45e6af3bSDavid du Colombier /* how can this happen? -rsc, dec 12 2002 */
425*45e6af3bSDavid du Colombier if(dst == 0){
426*45e6af3bSDavid du Colombier print("nil dstflush\n");
427*45e6af3bSDavid du Colombier return;
428*45e6af3bSDavid du Colombier }
429*45e6af3bSDavid du Colombier l = dst->layer;
430*45e6af3bSDavid du Colombier if(l == nil)
431*45e6af3bSDavid du Colombier return;
432*45e6af3bSDavid du Colombier do{
433*45e6af3bSDavid du Colombier if(l->screen->image->data != screenimage->data)
434*45e6af3bSDavid du Colombier return;
435*45e6af3bSDavid du Colombier r = rectaddpt(r, l->delta);
436*45e6af3bSDavid du Colombier l = l->screen->image->layer;
437*45e6af3bSDavid du Colombier }while(l);
438*45e6af3bSDavid du Colombier addflush(r);
439*45e6af3bSDavid du Colombier }
440*45e6af3bSDavid du Colombier
441*45e6af3bSDavid du Colombier void
drawflush(void)442*45e6af3bSDavid du Colombier drawflush(void)
443*45e6af3bSDavid du Colombier {
444*45e6af3bSDavid du Colombier if(flushrect.min.x < flushrect.max.x)
445*45e6af3bSDavid du Colombier flushmemscreen(flushrect);
446*45e6af3bSDavid du Colombier flushrect = Rect(10000, 10000, -10000, -10000);
447*45e6af3bSDavid du Colombier }
448*45e6af3bSDavid du Colombier
449*45e6af3bSDavid du Colombier static
450*45e6af3bSDavid du Colombier int
drawcmp(char * a,char * b,int n)451*45e6af3bSDavid du Colombier drawcmp(char *a, char *b, int n)
452*45e6af3bSDavid du Colombier {
453*45e6af3bSDavid du Colombier if(strlen(a) != n)
454*45e6af3bSDavid du Colombier return 1;
455*45e6af3bSDavid du Colombier return memcmp(a, b, n);
456*45e6af3bSDavid du Colombier }
457*45e6af3bSDavid du Colombier
458*45e6af3bSDavid du Colombier DName*
drawlookupname(int n,char * str)459*45e6af3bSDavid du Colombier drawlookupname(int n, char *str)
460*45e6af3bSDavid du Colombier {
461*45e6af3bSDavid du Colombier DName *name, *ename;
462*45e6af3bSDavid du Colombier
463*45e6af3bSDavid du Colombier name = sdraw.name;
464*45e6af3bSDavid du Colombier ename = &name[sdraw.nname];
465*45e6af3bSDavid du Colombier for(; name<ename; name++)
466*45e6af3bSDavid du Colombier if(drawcmp(name->name, str, n) == 0)
467*45e6af3bSDavid du Colombier return name;
468*45e6af3bSDavid du Colombier return 0;
469*45e6af3bSDavid du Colombier }
470*45e6af3bSDavid du Colombier
471*45e6af3bSDavid du Colombier int
drawgoodname(DImage * d)472*45e6af3bSDavid du Colombier drawgoodname(DImage *d)
473*45e6af3bSDavid du Colombier {
474*45e6af3bSDavid du Colombier DName *n;
475*45e6af3bSDavid du Colombier
476*45e6af3bSDavid du Colombier /* if window, validate the screen's own images */
477*45e6af3bSDavid du Colombier if(d->dscreen)
478*45e6af3bSDavid du Colombier if(drawgoodname(d->dscreen->dimage) == 0
479*45e6af3bSDavid du Colombier || drawgoodname(d->dscreen->dfill) == 0)
480*45e6af3bSDavid du Colombier return 0;
481*45e6af3bSDavid du Colombier if(d->name == nil)
482*45e6af3bSDavid du Colombier return 1;
483*45e6af3bSDavid du Colombier n = drawlookupname(strlen(d->name), d->name);
484*45e6af3bSDavid du Colombier if(n==nil || n->vers!=d->vers)
485*45e6af3bSDavid du Colombier return 0;
486*45e6af3bSDavid du Colombier return 1;
487*45e6af3bSDavid du Colombier }
488*45e6af3bSDavid du Colombier
489*45e6af3bSDavid du Colombier DImage*
drawlookup(Client * client,int id,int checkname)490*45e6af3bSDavid du Colombier drawlookup(Client *client, int id, int checkname)
491*45e6af3bSDavid du Colombier {
492*45e6af3bSDavid du Colombier DImage *d;
493*45e6af3bSDavid du Colombier
494*45e6af3bSDavid du Colombier d = client->dimage[id&HASHMASK];
495*45e6af3bSDavid du Colombier while(d){
496*45e6af3bSDavid du Colombier if(d->id == id){
497*45e6af3bSDavid du Colombier if(checkname && !drawgoodname(d))
498*45e6af3bSDavid du Colombier error(Eoldname);
499*45e6af3bSDavid du Colombier return d;
500*45e6af3bSDavid du Colombier }
501*45e6af3bSDavid du Colombier d = d->next;
502*45e6af3bSDavid du Colombier }
503*45e6af3bSDavid du Colombier return 0;
504*45e6af3bSDavid du Colombier }
505*45e6af3bSDavid du Colombier
506*45e6af3bSDavid du Colombier DScreen*
drawlookupdscreen(int id)507*45e6af3bSDavid du Colombier drawlookupdscreen(int id)
508*45e6af3bSDavid du Colombier {
509*45e6af3bSDavid du Colombier DScreen *s;
510*45e6af3bSDavid du Colombier
511*45e6af3bSDavid du Colombier s = dscreen;
512*45e6af3bSDavid du Colombier while(s){
513*45e6af3bSDavid du Colombier if(s->id == id)
514*45e6af3bSDavid du Colombier return s;
515*45e6af3bSDavid du Colombier s = s->next;
516*45e6af3bSDavid du Colombier }
517*45e6af3bSDavid du Colombier return 0;
518*45e6af3bSDavid du Colombier }
519*45e6af3bSDavid du Colombier
520*45e6af3bSDavid du Colombier DScreen*
drawlookupscreen(Client * client,int id,CScreen ** cs)521*45e6af3bSDavid du Colombier drawlookupscreen(Client *client, int id, CScreen **cs)
522*45e6af3bSDavid du Colombier {
523*45e6af3bSDavid du Colombier CScreen *s;
524*45e6af3bSDavid du Colombier
525*45e6af3bSDavid du Colombier s = client->cscreen;
526*45e6af3bSDavid du Colombier while(s){
527*45e6af3bSDavid du Colombier if(s->dscreen->id == id){
528*45e6af3bSDavid du Colombier *cs = s;
529*45e6af3bSDavid du Colombier return s->dscreen;
530*45e6af3bSDavid du Colombier }
531*45e6af3bSDavid du Colombier s = s->next;
532*45e6af3bSDavid du Colombier }
533*45e6af3bSDavid du Colombier error(Enodrawscreen);
534*45e6af3bSDavid du Colombier return 0;
535*45e6af3bSDavid du Colombier }
536*45e6af3bSDavid du Colombier
537*45e6af3bSDavid du Colombier DImage*
allocdimage(Memimage * i)538*45e6af3bSDavid du Colombier allocdimage(Memimage *i)
539*45e6af3bSDavid du Colombier {
540*45e6af3bSDavid du Colombier DImage *d;
541*45e6af3bSDavid du Colombier
542*45e6af3bSDavid du Colombier d = malloc(sizeof(DImage));
543*45e6af3bSDavid du Colombier if(d == 0)
544*45e6af3bSDavid du Colombier return 0;
545*45e6af3bSDavid du Colombier d->ref = 1;
546*45e6af3bSDavid du Colombier d->name = 0;
547*45e6af3bSDavid du Colombier d->vers = 0;
548*45e6af3bSDavid du Colombier d->image = i;
549*45e6af3bSDavid du Colombier d->nfchar = 0;
550*45e6af3bSDavid du Colombier d->fchar = 0;
551*45e6af3bSDavid du Colombier d->fromname = 0;
552*45e6af3bSDavid du Colombier return d;
553*45e6af3bSDavid du Colombier }
554*45e6af3bSDavid du Colombier
555*45e6af3bSDavid du Colombier Memimage*
drawinstall(Client * client,int id,Memimage * i,DScreen * dscreen)556*45e6af3bSDavid du Colombier drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
557*45e6af3bSDavid du Colombier {
558*45e6af3bSDavid du Colombier DImage *d;
559*45e6af3bSDavid du Colombier
560*45e6af3bSDavid du Colombier d = allocdimage(i);
561*45e6af3bSDavid du Colombier if(d == 0)
562*45e6af3bSDavid du Colombier return 0;
563*45e6af3bSDavid du Colombier d->id = id;
564*45e6af3bSDavid du Colombier d->dscreen = dscreen;
565*45e6af3bSDavid du Colombier d->next = client->dimage[id&HASHMASK];
566*45e6af3bSDavid du Colombier client->dimage[id&HASHMASK] = d;
567*45e6af3bSDavid du Colombier return i;
568*45e6af3bSDavid du Colombier }
569*45e6af3bSDavid du Colombier
570*45e6af3bSDavid du Colombier Memscreen*
drawinstallscreen(Client * client,DScreen * d,int id,DImage * dimage,DImage * dfill,int public)571*45e6af3bSDavid du Colombier drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public)
572*45e6af3bSDavid du Colombier {
573*45e6af3bSDavid du Colombier Memscreen *s;
574*45e6af3bSDavid du Colombier CScreen *c;
575*45e6af3bSDavid du Colombier
576*45e6af3bSDavid du Colombier c = malloc(sizeof(CScreen));
577*45e6af3bSDavid du Colombier if(dimage && dimage->image && dimage->image->chan == 0)
578*45e6af3bSDavid du Colombier panic("bad image %p in drawinstallscreen", dimage->image);
579*45e6af3bSDavid du Colombier
580*45e6af3bSDavid du Colombier if(c == 0)
581*45e6af3bSDavid du Colombier return 0;
582*45e6af3bSDavid du Colombier if(d == 0){
583*45e6af3bSDavid du Colombier d = malloc(sizeof(DScreen));
584*45e6af3bSDavid du Colombier if(d == 0){
585*45e6af3bSDavid du Colombier free(c);
586*45e6af3bSDavid du Colombier return 0;
587*45e6af3bSDavid du Colombier }
588*45e6af3bSDavid du Colombier s = malloc(sizeof(Memscreen));
589*45e6af3bSDavid du Colombier if(s == 0){
590*45e6af3bSDavid du Colombier free(c);
591*45e6af3bSDavid du Colombier free(d);
592*45e6af3bSDavid du Colombier return 0;
593*45e6af3bSDavid du Colombier }
594*45e6af3bSDavid du Colombier s->frontmost = 0;
595*45e6af3bSDavid du Colombier s->rearmost = 0;
596*45e6af3bSDavid du Colombier d->dimage = dimage;
597*45e6af3bSDavid du Colombier if(dimage){
598*45e6af3bSDavid du Colombier s->image = dimage->image;
599*45e6af3bSDavid du Colombier dimage->ref++;
600*45e6af3bSDavid du Colombier }
601*45e6af3bSDavid du Colombier d->dfill = dfill;
602*45e6af3bSDavid du Colombier if(dfill){
603*45e6af3bSDavid du Colombier s->fill = dfill->image;
604*45e6af3bSDavid du Colombier dfill->ref++;
605*45e6af3bSDavid du Colombier }
606*45e6af3bSDavid du Colombier d->ref = 0;
607*45e6af3bSDavid du Colombier d->id = id;
608*45e6af3bSDavid du Colombier d->screen = s;
609*45e6af3bSDavid du Colombier d->public = public;
610*45e6af3bSDavid du Colombier d->next = dscreen;
611*45e6af3bSDavid du Colombier d->owner = client;
612*45e6af3bSDavid du Colombier dscreen = d;
613*45e6af3bSDavid du Colombier }
614*45e6af3bSDavid du Colombier c->dscreen = d;
615*45e6af3bSDavid du Colombier d->ref++;
616*45e6af3bSDavid du Colombier c->next = client->cscreen;
617*45e6af3bSDavid du Colombier client->cscreen = c;
618*45e6af3bSDavid du Colombier return d->screen;
619*45e6af3bSDavid du Colombier }
620*45e6af3bSDavid du Colombier
621*45e6af3bSDavid du Colombier void
drawdelname(DName * name)622*45e6af3bSDavid du Colombier drawdelname(DName *name)
623*45e6af3bSDavid du Colombier {
624*45e6af3bSDavid du Colombier int i;
625*45e6af3bSDavid du Colombier
626*45e6af3bSDavid du Colombier i = name-sdraw.name;
627*45e6af3bSDavid du Colombier memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
628*45e6af3bSDavid du Colombier sdraw.nname--;
629*45e6af3bSDavid du Colombier }
630*45e6af3bSDavid du Colombier
631*45e6af3bSDavid du Colombier void
drawfreedscreen(DScreen * this)632*45e6af3bSDavid du Colombier drawfreedscreen(DScreen *this)
633*45e6af3bSDavid du Colombier {
634*45e6af3bSDavid du Colombier DScreen *ds, *next;
635*45e6af3bSDavid du Colombier
636*45e6af3bSDavid du Colombier this->ref--;
637*45e6af3bSDavid du Colombier if(this->ref < 0)
638*45e6af3bSDavid du Colombier print("negative ref in drawfreedscreen\n");
639*45e6af3bSDavid du Colombier if(this->ref > 0)
640*45e6af3bSDavid du Colombier return;
641*45e6af3bSDavid du Colombier ds = dscreen;
642*45e6af3bSDavid du Colombier if(ds == this){
643*45e6af3bSDavid du Colombier dscreen = this->next;
644*45e6af3bSDavid du Colombier goto Found;
645*45e6af3bSDavid du Colombier }
646*45e6af3bSDavid du Colombier while(next = ds->next){ /* assign = */
647*45e6af3bSDavid du Colombier if(next == this){
648*45e6af3bSDavid du Colombier ds->next = this->next;
649*45e6af3bSDavid du Colombier goto Found;
650*45e6af3bSDavid du Colombier }
651*45e6af3bSDavid du Colombier ds = next;
652*45e6af3bSDavid du Colombier }
653*45e6af3bSDavid du Colombier error(Enodrawimage);
654*45e6af3bSDavid du Colombier
655*45e6af3bSDavid du Colombier Found:
656*45e6af3bSDavid du Colombier if(this->dimage)
657*45e6af3bSDavid du Colombier drawfreedimage(this->dimage);
658*45e6af3bSDavid du Colombier if(this->dfill)
659*45e6af3bSDavid du Colombier drawfreedimage(this->dfill);
660*45e6af3bSDavid du Colombier free(this->screen);
661*45e6af3bSDavid du Colombier free(this);
662*45e6af3bSDavid du Colombier }
663*45e6af3bSDavid du Colombier
664*45e6af3bSDavid du Colombier void
drawfreedimage(DImage * dimage)665*45e6af3bSDavid du Colombier drawfreedimage(DImage *dimage)
666*45e6af3bSDavid du Colombier {
667*45e6af3bSDavid du Colombier int i;
668*45e6af3bSDavid du Colombier Memimage *l;
669*45e6af3bSDavid du Colombier DScreen *ds;
670*45e6af3bSDavid du Colombier
671*45e6af3bSDavid du Colombier dimage->ref--;
672*45e6af3bSDavid du Colombier if(dimage->ref < 0)
673*45e6af3bSDavid du Colombier print("negative ref in drawfreedimage\n");
674*45e6af3bSDavid du Colombier if(dimage->ref > 0)
675*45e6af3bSDavid du Colombier return;
676*45e6af3bSDavid du Colombier
677*45e6af3bSDavid du Colombier /* any names? */
678*45e6af3bSDavid du Colombier for(i=0; i<sdraw.nname; )
679*45e6af3bSDavid du Colombier if(sdraw.name[i].dimage == dimage)
680*45e6af3bSDavid du Colombier drawdelname(sdraw.name+i);
681*45e6af3bSDavid du Colombier else
682*45e6af3bSDavid du Colombier i++;
683*45e6af3bSDavid du Colombier if(dimage->fromname){ /* acquired by name; owned by someone else*/
684*45e6af3bSDavid du Colombier drawfreedimage(dimage->fromname);
685*45e6af3bSDavid du Colombier goto Return;
686*45e6af3bSDavid du Colombier }
687*45e6af3bSDavid du Colombier // if(dimage->image == screenimage) /* don't free the display */
688*45e6af3bSDavid du Colombier // goto Return;
689*45e6af3bSDavid du Colombier ds = dimage->dscreen;
690*45e6af3bSDavid du Colombier if(ds){
691*45e6af3bSDavid du Colombier l = dimage->image;
692*45e6af3bSDavid du Colombier if(l->data == screenimage->data)
693*45e6af3bSDavid du Colombier addflush(l->layer->screenr);
694*45e6af3bSDavid du Colombier if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
695*45e6af3bSDavid du Colombier free(l->layer->refreshptr);
696*45e6af3bSDavid du Colombier l->layer->refreshptr = nil;
697*45e6af3bSDavid du Colombier if(drawgoodname(dimage))
698*45e6af3bSDavid du Colombier memldelete(l);
699*45e6af3bSDavid du Colombier else
700*45e6af3bSDavid du Colombier memlfree(l);
701*45e6af3bSDavid du Colombier drawfreedscreen(ds);
702*45e6af3bSDavid du Colombier }else
703*45e6af3bSDavid du Colombier freememimage(dimage->image);
704*45e6af3bSDavid du Colombier Return:
705*45e6af3bSDavid du Colombier free(dimage->fchar);
706*45e6af3bSDavid du Colombier free(dimage);
707*45e6af3bSDavid du Colombier }
708*45e6af3bSDavid du Colombier
709*45e6af3bSDavid du Colombier void
drawuninstallscreen(Client * client,CScreen * this)710*45e6af3bSDavid du Colombier drawuninstallscreen(Client *client, CScreen *this)
711*45e6af3bSDavid du Colombier {
712*45e6af3bSDavid du Colombier CScreen *cs, *next;
713*45e6af3bSDavid du Colombier
714*45e6af3bSDavid du Colombier cs = client->cscreen;
715*45e6af3bSDavid du Colombier if(cs == this){
716*45e6af3bSDavid du Colombier client->cscreen = this->next;
717*45e6af3bSDavid du Colombier drawfreedscreen(this->dscreen);
718*45e6af3bSDavid du Colombier free(this);
719*45e6af3bSDavid du Colombier return;
720*45e6af3bSDavid du Colombier }
721*45e6af3bSDavid du Colombier while(next = cs->next){ /* assign = */
722*45e6af3bSDavid du Colombier if(next == this){
723*45e6af3bSDavid du Colombier cs->next = this->next;
724*45e6af3bSDavid du Colombier drawfreedscreen(this->dscreen);
725*45e6af3bSDavid du Colombier free(this);
726*45e6af3bSDavid du Colombier return;
727*45e6af3bSDavid du Colombier }
728*45e6af3bSDavid du Colombier cs = next;
729*45e6af3bSDavid du Colombier }
730*45e6af3bSDavid du Colombier }
731*45e6af3bSDavid du Colombier
732*45e6af3bSDavid du Colombier void
drawuninstall(Client * client,int id)733*45e6af3bSDavid du Colombier drawuninstall(Client *client, int id)
734*45e6af3bSDavid du Colombier {
735*45e6af3bSDavid du Colombier DImage *d, *next;
736*45e6af3bSDavid du Colombier
737*45e6af3bSDavid du Colombier d = client->dimage[id&HASHMASK];
738*45e6af3bSDavid du Colombier if(d == 0)
739*45e6af3bSDavid du Colombier error(Enodrawimage);
740*45e6af3bSDavid du Colombier if(d->id == id){
741*45e6af3bSDavid du Colombier client->dimage[id&HASHMASK] = d->next;
742*45e6af3bSDavid du Colombier drawfreedimage(d);
743*45e6af3bSDavid du Colombier return;
744*45e6af3bSDavid du Colombier }
745*45e6af3bSDavid du Colombier while(next = d->next){ /* assign = */
746*45e6af3bSDavid du Colombier if(next->id == id){
747*45e6af3bSDavid du Colombier d->next = next->next;
748*45e6af3bSDavid du Colombier drawfreedimage(next);
749*45e6af3bSDavid du Colombier return;
750*45e6af3bSDavid du Colombier }
751*45e6af3bSDavid du Colombier d = next;
752*45e6af3bSDavid du Colombier }
753*45e6af3bSDavid du Colombier error(Enodrawimage);
754*45e6af3bSDavid du Colombier }
755*45e6af3bSDavid du Colombier
756*45e6af3bSDavid du Colombier void
drawaddname(Client * client,DImage * di,int n,char * str)757*45e6af3bSDavid du Colombier drawaddname(Client *client, DImage *di, int n, char *str)
758*45e6af3bSDavid du Colombier {
759*45e6af3bSDavid du Colombier DName *name, *ename, *new, *t;
760*45e6af3bSDavid du Colombier
761*45e6af3bSDavid du Colombier name = sdraw.name;
762*45e6af3bSDavid du Colombier ename = &name[sdraw.nname];
763*45e6af3bSDavid du Colombier for(; name<ename; name++)
764*45e6af3bSDavid du Colombier if(drawcmp(name->name, str, n) == 0)
765*45e6af3bSDavid du Colombier error(Enameused);
766*45e6af3bSDavid du Colombier t = smalloc((sdraw.nname+1)*sizeof(DName));
767*45e6af3bSDavid du Colombier memmove(t, sdraw.name, sdraw.nname*sizeof(DName));
768*45e6af3bSDavid du Colombier free(sdraw.name);
769*45e6af3bSDavid du Colombier sdraw.name = t;
770*45e6af3bSDavid du Colombier new = &sdraw.name[sdraw.nname++];
771*45e6af3bSDavid du Colombier new->name = smalloc(n+1);
772*45e6af3bSDavid du Colombier memmove(new->name, str, n);
773*45e6af3bSDavid du Colombier new->name[n] = 0;
774*45e6af3bSDavid du Colombier new->dimage = di;
775*45e6af3bSDavid du Colombier new->client = client;
776*45e6af3bSDavid du Colombier new->vers = ++sdraw.vers;
777*45e6af3bSDavid du Colombier }
778*45e6af3bSDavid du Colombier
779*45e6af3bSDavid du Colombier Client*
drawnewclient(void)780*45e6af3bSDavid du Colombier drawnewclient(void)
781*45e6af3bSDavid du Colombier {
782*45e6af3bSDavid du Colombier Client *cl, **cp;
783*45e6af3bSDavid du Colombier int i;
784*45e6af3bSDavid du Colombier
785*45e6af3bSDavid du Colombier for(i=0; i<sdraw.nclient; i++){
786*45e6af3bSDavid du Colombier cl = sdraw.client[i];
787*45e6af3bSDavid du Colombier if(cl == 0)
788*45e6af3bSDavid du Colombier break;
789*45e6af3bSDavid du Colombier }
790*45e6af3bSDavid du Colombier if(i == sdraw.nclient){
791*45e6af3bSDavid du Colombier cp = malloc((sdraw.nclient+1)*sizeof(Client*));
792*45e6af3bSDavid du Colombier if(cp == 0)
793*45e6af3bSDavid du Colombier return 0;
794*45e6af3bSDavid du Colombier memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*));
795*45e6af3bSDavid du Colombier free(sdraw.client);
796*45e6af3bSDavid du Colombier sdraw.client = cp;
797*45e6af3bSDavid du Colombier sdraw.nclient++;
798*45e6af3bSDavid du Colombier cp[i] = 0;
799*45e6af3bSDavid du Colombier }
800*45e6af3bSDavid du Colombier cl = malloc(sizeof(Client));
801*45e6af3bSDavid du Colombier if(cl == 0)
802*45e6af3bSDavid du Colombier return 0;
803*45e6af3bSDavid du Colombier memset(cl, 0, sizeof(Client));
804*45e6af3bSDavid du Colombier cl->slot = i;
805*45e6af3bSDavid du Colombier cl->clientid = ++sdraw.clientid;
806*45e6af3bSDavid du Colombier cl->op = SoverD;
807*45e6af3bSDavid du Colombier sdraw.client[i] = cl;
808*45e6af3bSDavid du Colombier return cl;
809*45e6af3bSDavid du Colombier }
810*45e6af3bSDavid du Colombier
811*45e6af3bSDavid du Colombier static int
drawclientop(Client * cl)812*45e6af3bSDavid du Colombier drawclientop(Client *cl)
813*45e6af3bSDavid du Colombier {
814*45e6af3bSDavid du Colombier int op;
815*45e6af3bSDavid du Colombier
816*45e6af3bSDavid du Colombier op = cl->op;
817*45e6af3bSDavid du Colombier cl->op = SoverD;
818*45e6af3bSDavid du Colombier return op;
819*45e6af3bSDavid du Colombier }
820*45e6af3bSDavid du Colombier
821*45e6af3bSDavid du Colombier int
drawhasclients(void)822*45e6af3bSDavid du Colombier drawhasclients(void)
823*45e6af3bSDavid du Colombier {
824*45e6af3bSDavid du Colombier /*
825*45e6af3bSDavid du Colombier * if draw has ever been used, we can't resize the frame buffer,
826*45e6af3bSDavid du Colombier * even if all clients have exited (nclients is cumulative); it's too
827*45e6af3bSDavid du Colombier * hard to make work.
828*45e6af3bSDavid du Colombier */
829*45e6af3bSDavid du Colombier return sdraw.nclient != 0;
830*45e6af3bSDavid du Colombier }
831*45e6af3bSDavid du Colombier
832*45e6af3bSDavid du Colombier Client*
drawclientofpath(ulong path)833*45e6af3bSDavid du Colombier drawclientofpath(ulong path)
834*45e6af3bSDavid du Colombier {
835*45e6af3bSDavid du Colombier Client *cl;
836*45e6af3bSDavid du Colombier int slot;
837*45e6af3bSDavid du Colombier
838*45e6af3bSDavid du Colombier slot = CLIENTPATH(path);
839*45e6af3bSDavid du Colombier if(slot == 0)
840*45e6af3bSDavid du Colombier return nil;
841*45e6af3bSDavid du Colombier cl = sdraw.client[slot-1];
842*45e6af3bSDavid du Colombier if(cl==0 || cl->clientid==0)
843*45e6af3bSDavid du Colombier return nil;
844*45e6af3bSDavid du Colombier return cl;
845*45e6af3bSDavid du Colombier }
846*45e6af3bSDavid du Colombier
847*45e6af3bSDavid du Colombier
848*45e6af3bSDavid du Colombier Client*
drawclient(Chan * c)849*45e6af3bSDavid du Colombier drawclient(Chan *c)
850*45e6af3bSDavid du Colombier {
851*45e6af3bSDavid du Colombier Client *client;
852*45e6af3bSDavid du Colombier
853*45e6af3bSDavid du Colombier client = drawclientofpath(c->qid.path);
854*45e6af3bSDavid du Colombier if(client == nil)
855*45e6af3bSDavid du Colombier error(Enoclient);
856*45e6af3bSDavid du Colombier return client;
857*45e6af3bSDavid du Colombier }
858*45e6af3bSDavid du Colombier
859*45e6af3bSDavid du Colombier Memimage*
drawimage(Client * client,uchar * a)860*45e6af3bSDavid du Colombier drawimage(Client *client, uchar *a)
861*45e6af3bSDavid du Colombier {
862*45e6af3bSDavid du Colombier DImage *d;
863*45e6af3bSDavid du Colombier
864*45e6af3bSDavid du Colombier d = drawlookup(client, BGLONG(a), 1);
865*45e6af3bSDavid du Colombier if(d == nil)
866*45e6af3bSDavid du Colombier error(Enodrawimage);
867*45e6af3bSDavid du Colombier return d->image;
868*45e6af3bSDavid du Colombier }
869*45e6af3bSDavid du Colombier
870*45e6af3bSDavid du Colombier void
drawrectangle(Rectangle * r,uchar * a)871*45e6af3bSDavid du Colombier drawrectangle(Rectangle *r, uchar *a)
872*45e6af3bSDavid du Colombier {
873*45e6af3bSDavid du Colombier r->min.x = BGLONG(a+0*4);
874*45e6af3bSDavid du Colombier r->min.y = BGLONG(a+1*4);
875*45e6af3bSDavid du Colombier r->max.x = BGLONG(a+2*4);
876*45e6af3bSDavid du Colombier r->max.y = BGLONG(a+3*4);
877*45e6af3bSDavid du Colombier }
878*45e6af3bSDavid du Colombier
879*45e6af3bSDavid du Colombier void
drawpoint(Point * p,uchar * a)880*45e6af3bSDavid du Colombier drawpoint(Point *p, uchar *a)
881*45e6af3bSDavid du Colombier {
882*45e6af3bSDavid du Colombier p->x = BGLONG(a+0*4);
883*45e6af3bSDavid du Colombier p->y = BGLONG(a+1*4);
884*45e6af3bSDavid du Colombier }
885*45e6af3bSDavid du Colombier
886*45e6af3bSDavid du Colombier Point
drawchar(Memimage * dst,Memimage * rdst,Point p,Memimage * src,Point * sp,DImage * font,int index,int op)887*45e6af3bSDavid du Colombier drawchar(Memimage *dst, Memimage *rdst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
888*45e6af3bSDavid du Colombier {
889*45e6af3bSDavid du Colombier FChar *fc;
890*45e6af3bSDavid du Colombier Rectangle r;
891*45e6af3bSDavid du Colombier Point sp1;
892*45e6af3bSDavid du Colombier static Memimage *tmp;
893*45e6af3bSDavid du Colombier
894*45e6af3bSDavid du Colombier fc = &font->fchar[index];
895*45e6af3bSDavid du Colombier r.min.x = p.x+fc->left;
896*45e6af3bSDavid du Colombier r.min.y = p.y-(font->ascent-fc->miny);
897*45e6af3bSDavid du Colombier r.max.x = r.min.x+(fc->maxx-fc->minx);
898*45e6af3bSDavid du Colombier r.max.y = r.min.y+(fc->maxy-fc->miny);
899*45e6af3bSDavid du Colombier sp1.x = sp->x+fc->left;
900*45e6af3bSDavid du Colombier sp1.y = sp->y+fc->miny;
901*45e6af3bSDavid du Colombier
902*45e6af3bSDavid du Colombier /*
903*45e6af3bSDavid du Colombier * If we're drawing greyscale fonts onto a VGA screen,
904*45e6af3bSDavid du Colombier * it's very costly to read the screen memory to do the
905*45e6af3bSDavid du Colombier * alpha blending inside memdraw. If this is really a stringbg,
906*45e6af3bSDavid du Colombier * then rdst is the bg image (in main memory) which we can
907*45e6af3bSDavid du Colombier * refer to for the underlying dst pixels instead of reading dst
908*45e6af3bSDavid du Colombier * directly.
909*45e6af3bSDavid du Colombier */
910*45e6af3bSDavid du Colombier if(ishwimage(dst) && !ishwimage(rdst) && font->image->depth > 1){
911*45e6af3bSDavid du Colombier if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){
912*45e6af3bSDavid du Colombier if(tmp)
913*45e6af3bSDavid du Colombier freememimage(tmp);
914*45e6af3bSDavid du Colombier tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan);
915*45e6af3bSDavid du Colombier if(tmp == nil)
916*45e6af3bSDavid du Colombier goto fallback;
917*45e6af3bSDavid du Colombier }
918*45e6af3bSDavid du Colombier memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S);
919*45e6af3bSDavid du Colombier memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op);
920*45e6af3bSDavid du Colombier memdraw(dst, r, tmp, ZP, memopaque, ZP, S);
921*45e6af3bSDavid du Colombier }else{
922*45e6af3bSDavid du Colombier fallback:
923*45e6af3bSDavid du Colombier memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
924*45e6af3bSDavid du Colombier }
925*45e6af3bSDavid du Colombier
926*45e6af3bSDavid du Colombier p.x += fc->width;
927*45e6af3bSDavid du Colombier sp->x += fc->width;
928*45e6af3bSDavid du Colombier return p;
929*45e6af3bSDavid du Colombier }
930*45e6af3bSDavid du Colombier
931*45e6af3bSDavid du Colombier static DImage*
makescreenimage(void)932*45e6af3bSDavid du Colombier makescreenimage(void)
933*45e6af3bSDavid du Colombier {
934*45e6af3bSDavid du Colombier int width, depth;
935*45e6af3bSDavid du Colombier ulong chan;
936*45e6af3bSDavid du Colombier DImage *di;
937*45e6af3bSDavid du Colombier Memdata *md;
938*45e6af3bSDavid du Colombier Memimage *i;
939*45e6af3bSDavid du Colombier Rectangle r;
940*45e6af3bSDavid du Colombier
941*45e6af3bSDavid du Colombier md = malloc(sizeof *md);
942*45e6af3bSDavid du Colombier if(md == nil)
943*45e6af3bSDavid du Colombier return nil;
944*45e6af3bSDavid du Colombier md->allocd = 1;
945*45e6af3bSDavid du Colombier md->base = nil;
946*45e6af3bSDavid du Colombier md->bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen);
947*45e6af3bSDavid du Colombier if(md->bdata == nil){
948*45e6af3bSDavid du Colombier free(md);
949*45e6af3bSDavid du Colombier return nil;
950*45e6af3bSDavid du Colombier }
951*45e6af3bSDavid du Colombier md->ref = 1;
952*45e6af3bSDavid du Colombier i = allocmemimaged(r, chan, md);
953*45e6af3bSDavid du Colombier if(i == nil){
954*45e6af3bSDavid du Colombier free(md);
955*45e6af3bSDavid du Colombier return nil;
956*45e6af3bSDavid du Colombier }
957*45e6af3bSDavid du Colombier i->width = width;
958*45e6af3bSDavid du Colombier i->clipr = r;
959*45e6af3bSDavid du Colombier
960*45e6af3bSDavid du Colombier di = allocdimage(i);
961*45e6af3bSDavid du Colombier if(di == nil){
962*45e6af3bSDavid du Colombier freememimage(i); /* frees md */
963*45e6af3bSDavid du Colombier return nil;
964*45e6af3bSDavid du Colombier }
965*45e6af3bSDavid du Colombier if(!waserror()){
966*45e6af3bSDavid du Colombier snprint(screenname, sizeof screenname, "noborder.screen.%d", ++screennameid);
967*45e6af3bSDavid du Colombier drawaddname(nil, di, strlen(screenname), screenname);
968*45e6af3bSDavid du Colombier poperror();
969*45e6af3bSDavid du Colombier }
970*45e6af3bSDavid du Colombier return di;
971*45e6af3bSDavid du Colombier }
972*45e6af3bSDavid du Colombier
973*45e6af3bSDavid du Colombier static int
initscreenimage(void)974*45e6af3bSDavid du Colombier initscreenimage(void)
975*45e6af3bSDavid du Colombier {
976*45e6af3bSDavid du Colombier if(screenimage != nil)
977*45e6af3bSDavid du Colombier return 1;
978*45e6af3bSDavid du Colombier
979*45e6af3bSDavid du Colombier screendimage = makescreenimage();
980*45e6af3bSDavid du Colombier if(screendimage == nil)
981*45e6af3bSDavid du Colombier return 0;
982*45e6af3bSDavid du Colombier screenimage = screendimage->image;
983*45e6af3bSDavid du Colombier // iprint("initscreenimage %p %p\n", screendimage, screenimage);
984*45e6af3bSDavid du Colombier mouseresize();
985*45e6af3bSDavid du Colombier return 1;
986*45e6af3bSDavid du Colombier }
987*45e6af3bSDavid du Colombier
988*45e6af3bSDavid du Colombier void
deletescreenimage(void)989*45e6af3bSDavid du Colombier deletescreenimage(void)
990*45e6af3bSDavid du Colombier {
991*45e6af3bSDavid du Colombier dlock();
992*45e6af3bSDavid du Colombier if(screenimage){
993*45e6af3bSDavid du Colombier /* will be freed via screendimage; disable */
994*45e6af3bSDavid du Colombier screenimage->clipr = ZR;
995*45e6af3bSDavid du Colombier screenimage = nil;
996*45e6af3bSDavid du Colombier }
997*45e6af3bSDavid du Colombier if(screendimage){
998*45e6af3bSDavid du Colombier drawfreedimage(screendimage);
999*45e6af3bSDavid du Colombier screendimage = nil;
1000*45e6af3bSDavid du Colombier }
1001*45e6af3bSDavid du Colombier dunlock();
1002*45e6af3bSDavid du Colombier }
1003*45e6af3bSDavid du Colombier
1004*45e6af3bSDavid du Colombier void
resetscreenimage(void)1005*45e6af3bSDavid du Colombier resetscreenimage(void)
1006*45e6af3bSDavid du Colombier {
1007*45e6af3bSDavid du Colombier dlock();
1008*45e6af3bSDavid du Colombier initscreenimage();
1009*45e6af3bSDavid du Colombier dunlock();
1010*45e6af3bSDavid du Colombier }
1011*45e6af3bSDavid du Colombier
1012*45e6af3bSDavid du Colombier static Chan*
drawattach(char * spec)1013*45e6af3bSDavid du Colombier drawattach(char *spec)
1014*45e6af3bSDavid du Colombier {
1015*45e6af3bSDavid du Colombier dlock();
1016*45e6af3bSDavid du Colombier if(!initscreenimage()){
1017*45e6af3bSDavid du Colombier dunlock();
1018*45e6af3bSDavid du Colombier error("no frame buffer");
1019*45e6af3bSDavid du Colombier }
1020*45e6af3bSDavid du Colombier dunlock();
1021*45e6af3bSDavid du Colombier return devattach('i', spec);
1022*45e6af3bSDavid du Colombier }
1023*45e6af3bSDavid du Colombier
1024*45e6af3bSDavid du Colombier static Walkqid*
drawwalk(Chan * c,Chan * nc,char ** name,int nname)1025*45e6af3bSDavid du Colombier drawwalk(Chan *c, Chan *nc, char **name, int nname)
1026*45e6af3bSDavid du Colombier {
1027*45e6af3bSDavid du Colombier if(screenimage == nil)
1028*45e6af3bSDavid du Colombier error("no frame buffer");
1029*45e6af3bSDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, drawgen);
1030*45e6af3bSDavid du Colombier }
1031*45e6af3bSDavid du Colombier
1032*45e6af3bSDavid du Colombier static long
drawstat(Chan * c,uchar * db,long n)1033*45e6af3bSDavid du Colombier drawstat(Chan *c, uchar *db, long n)
1034*45e6af3bSDavid du Colombier {
1035*45e6af3bSDavid du Colombier return devstat(c, db, n, 0, 0, drawgen);
1036*45e6af3bSDavid du Colombier }
1037*45e6af3bSDavid du Colombier
1038*45e6af3bSDavid du Colombier static Chan*
drawopen(Chan * c,int omode)1039*45e6af3bSDavid du Colombier drawopen(Chan *c, int omode)
1040*45e6af3bSDavid du Colombier {
1041*45e6af3bSDavid du Colombier Client *cl;
1042*45e6af3bSDavid du Colombier DName *dn;
1043*45e6af3bSDavid du Colombier DImage *di;
1044*45e6af3bSDavid du Colombier
1045*45e6af3bSDavid du Colombier if(c->qid.type & QTDIR){
1046*45e6af3bSDavid du Colombier c = devopen(c, omode, 0, 0, drawgen);
1047*45e6af3bSDavid du Colombier c->iounit = IOUNIT;
1048*45e6af3bSDavid du Colombier }
1049*45e6af3bSDavid du Colombier
1050*45e6af3bSDavid du Colombier dlock();
1051*45e6af3bSDavid du Colombier if(waserror()){
1052*45e6af3bSDavid du Colombier dunlock();
1053*45e6af3bSDavid du Colombier nexterror();
1054*45e6af3bSDavid du Colombier }
1055*45e6af3bSDavid du Colombier
1056*45e6af3bSDavid du Colombier if(QID(c->qid) == Qnew){
1057*45e6af3bSDavid du Colombier cl = drawnewclient();
1058*45e6af3bSDavid du Colombier if(cl == 0)
1059*45e6af3bSDavid du Colombier error(Enodev);
1060*45e6af3bSDavid du Colombier c->qid.path = Qctl|((cl->slot+1)<<QSHIFT);
1061*45e6af3bSDavid du Colombier }
1062*45e6af3bSDavid du Colombier
1063*45e6af3bSDavid du Colombier switch(QID(c->qid)){
1064*45e6af3bSDavid du Colombier case Qwinname:
1065*45e6af3bSDavid du Colombier break;
1066*45e6af3bSDavid du Colombier
1067*45e6af3bSDavid du Colombier case Qnew:
1068*45e6af3bSDavid du Colombier break;
1069*45e6af3bSDavid du Colombier
1070*45e6af3bSDavid du Colombier case Qctl:
1071*45e6af3bSDavid du Colombier cl = drawclient(c);
1072*45e6af3bSDavid du Colombier if(cl->busy)
1073*45e6af3bSDavid du Colombier error(Einuse);
1074*45e6af3bSDavid du Colombier cl->busy = 1;
1075*45e6af3bSDavid du Colombier flushrect = Rect(10000, 10000, -10000, -10000);
1076*45e6af3bSDavid du Colombier dn = drawlookupname(strlen(screenname), screenname);
1077*45e6af3bSDavid du Colombier if(dn == 0)
1078*45e6af3bSDavid du Colombier error("draw: cannot happen 2");
1079*45e6af3bSDavid du Colombier if(drawinstall(cl, 0, dn->dimage->image, 0) == 0)
1080*45e6af3bSDavid du Colombier error(Edrawmem);
1081*45e6af3bSDavid du Colombier di = drawlookup(cl, 0, 0);
1082*45e6af3bSDavid du Colombier if(di == 0)
1083*45e6af3bSDavid du Colombier error("draw: cannot happen 1");
1084*45e6af3bSDavid du Colombier di->vers = dn->vers;
1085*45e6af3bSDavid du Colombier di->name = smalloc(strlen(screenname)+1);
1086*45e6af3bSDavid du Colombier strcpy(di->name, screenname);
1087*45e6af3bSDavid du Colombier di->fromname = dn->dimage;
1088*45e6af3bSDavid du Colombier di->fromname->ref++;
1089*45e6af3bSDavid du Colombier incref(&cl->r);
1090*45e6af3bSDavid du Colombier break;
1091*45e6af3bSDavid du Colombier
1092*45e6af3bSDavid du Colombier case Qcolormap:
1093*45e6af3bSDavid du Colombier case Qdata:
1094*45e6af3bSDavid du Colombier case Qrefresh:
1095*45e6af3bSDavid du Colombier cl = drawclient(c);
1096*45e6af3bSDavid du Colombier incref(&cl->r);
1097*45e6af3bSDavid du Colombier break;
1098*45e6af3bSDavid du Colombier }
1099*45e6af3bSDavid du Colombier dunlock();
1100*45e6af3bSDavid du Colombier poperror();
1101*45e6af3bSDavid du Colombier c->mode = openmode(omode);
1102*45e6af3bSDavid du Colombier c->flag |= COPEN;
1103*45e6af3bSDavid du Colombier c->offset = 0;
1104*45e6af3bSDavid du Colombier c->iounit = IOUNIT;
1105*45e6af3bSDavid du Colombier return c;
1106*45e6af3bSDavid du Colombier }
1107*45e6af3bSDavid du Colombier
1108*45e6af3bSDavid du Colombier static void
drawclose(Chan * c)1109*45e6af3bSDavid du Colombier drawclose(Chan *c)
1110*45e6af3bSDavid du Colombier {
1111*45e6af3bSDavid du Colombier int i;
1112*45e6af3bSDavid du Colombier DImage *d, **dp;
1113*45e6af3bSDavid du Colombier Client *cl;
1114*45e6af3bSDavid du Colombier Refresh *r;
1115*45e6af3bSDavid du Colombier
1116*45e6af3bSDavid du Colombier if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */
1117*45e6af3bSDavid du Colombier return;
1118*45e6af3bSDavid du Colombier dlock();
1119*45e6af3bSDavid du Colombier if(waserror()){
1120*45e6af3bSDavid du Colombier dunlock();
1121*45e6af3bSDavid du Colombier nexterror();
1122*45e6af3bSDavid du Colombier }
1123*45e6af3bSDavid du Colombier
1124*45e6af3bSDavid du Colombier cl = drawclient(c);
1125*45e6af3bSDavid du Colombier if(QID(c->qid) == Qctl)
1126*45e6af3bSDavid du Colombier cl->busy = 0;
1127*45e6af3bSDavid du Colombier if((c->flag&COPEN) && (decref(&cl->r)==0)){
1128*45e6af3bSDavid du Colombier while(r = cl->refresh){ /* assign = */
1129*45e6af3bSDavid du Colombier cl->refresh = r->next;
1130*45e6af3bSDavid du Colombier free(r);
1131*45e6af3bSDavid du Colombier }
1132*45e6af3bSDavid du Colombier /* free names */
1133*45e6af3bSDavid du Colombier for(i=0; i<sdraw.nname; )
1134*45e6af3bSDavid du Colombier if(sdraw.name[i].client == cl)
1135*45e6af3bSDavid du Colombier drawdelname(sdraw.name+i);
1136*45e6af3bSDavid du Colombier else
1137*45e6af3bSDavid du Colombier i++;
1138*45e6af3bSDavid du Colombier while(cl->cscreen)
1139*45e6af3bSDavid du Colombier drawuninstallscreen(cl, cl->cscreen);
1140*45e6af3bSDavid du Colombier /* all screens are freed, so now we can free images */
1141*45e6af3bSDavid du Colombier dp = cl->dimage;
1142*45e6af3bSDavid du Colombier for(i=0; i<NHASH; i++){
1143*45e6af3bSDavid du Colombier while((d = *dp) != nil){
1144*45e6af3bSDavid du Colombier *dp = d->next;
1145*45e6af3bSDavid du Colombier drawfreedimage(d);
1146*45e6af3bSDavid du Colombier }
1147*45e6af3bSDavid du Colombier dp++;
1148*45e6af3bSDavid du Colombier }
1149*45e6af3bSDavid du Colombier sdraw.client[cl->slot] = 0;
1150*45e6af3bSDavid du Colombier drawflush(); /* to erase visible, now dead windows */
1151*45e6af3bSDavid du Colombier free(cl);
1152*45e6af3bSDavid du Colombier }
1153*45e6af3bSDavid du Colombier dunlock();
1154*45e6af3bSDavid du Colombier poperror();
1155*45e6af3bSDavid du Colombier }
1156*45e6af3bSDavid du Colombier
1157*45e6af3bSDavid du Colombier long
drawread(Chan * c,void * a,long n,vlong off)1158*45e6af3bSDavid du Colombier drawread(Chan *c, void *a, long n, vlong off)
1159*45e6af3bSDavid du Colombier {
1160*45e6af3bSDavid du Colombier int index, m;
1161*45e6af3bSDavid du Colombier ulong red, green, blue;
1162*45e6af3bSDavid du Colombier Client *cl;
1163*45e6af3bSDavid du Colombier uchar *p;
1164*45e6af3bSDavid du Colombier Refresh *r;
1165*45e6af3bSDavid du Colombier DImage *di;
1166*45e6af3bSDavid du Colombier Memimage *i;
1167*45e6af3bSDavid du Colombier ulong offset = off;
1168*45e6af3bSDavid du Colombier char buf[16];
1169*45e6af3bSDavid du Colombier
1170*45e6af3bSDavid du Colombier if(c->qid.type & QTDIR)
1171*45e6af3bSDavid du Colombier return devdirread(c, a, n, 0, 0, drawgen);
1172*45e6af3bSDavid du Colombier if(QID(c->qid) == Qwinname)
1173*45e6af3bSDavid du Colombier return readstr(off, a, n, screenname);
1174*45e6af3bSDavid du Colombier
1175*45e6af3bSDavid du Colombier cl = drawclient(c);
1176*45e6af3bSDavid du Colombier dlock();
1177*45e6af3bSDavid du Colombier if(waserror()){
1178*45e6af3bSDavid du Colombier dunlock();
1179*45e6af3bSDavid du Colombier nexterror();
1180*45e6af3bSDavid du Colombier }
1181*45e6af3bSDavid du Colombier switch(QID(c->qid)){
1182*45e6af3bSDavid du Colombier case Qctl:
1183*45e6af3bSDavid du Colombier if(n < 12*12)
1184*45e6af3bSDavid du Colombier error(Eshortread);
1185*45e6af3bSDavid du Colombier if(cl->infoid < 0)
1186*45e6af3bSDavid du Colombier error(Enodrawimage);
1187*45e6af3bSDavid du Colombier if(cl->infoid == 0){
1188*45e6af3bSDavid du Colombier i = screenimage;
1189*45e6af3bSDavid du Colombier if(i == nil)
1190*45e6af3bSDavid du Colombier error(Enodrawimage);
1191*45e6af3bSDavid du Colombier }else{
1192*45e6af3bSDavid du Colombier di = drawlookup(cl, cl->infoid, 1);
1193*45e6af3bSDavid du Colombier if(di == nil)
1194*45e6af3bSDavid du Colombier error(Enodrawimage);
1195*45e6af3bSDavid du Colombier i = di->image;
1196*45e6af3bSDavid du Colombier }
1197*45e6af3bSDavid du Colombier n = snprint(a, n,
1198*45e6af3bSDavid du Colombier "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ",
1199*45e6af3bSDavid du Colombier cl->clientid, cl->infoid, chantostr(buf, i->chan),
1200*45e6af3bSDavid du Colombier (i->flags&Frepl)==Frepl,
1201*45e6af3bSDavid du Colombier i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
1202*45e6af3bSDavid du Colombier i->clipr.min.x, i->clipr.min.y, i->clipr.max.x,
1203*45e6af3bSDavid du Colombier i->clipr.max.y);
1204*45e6af3bSDavid du Colombier cl->infoid = -1;
1205*45e6af3bSDavid du Colombier break;
1206*45e6af3bSDavid du Colombier
1207*45e6af3bSDavid du Colombier case Qcolormap:
1208*45e6af3bSDavid du Colombier drawactive(1); /* to restore map from backup */
1209*45e6af3bSDavid du Colombier p = malloc(4*12*256+1);
1210*45e6af3bSDavid du Colombier if(p == 0)
1211*45e6af3bSDavid du Colombier error(Enomem);
1212*45e6af3bSDavid du Colombier m = 0;
1213*45e6af3bSDavid du Colombier for(index = 0; index < 256; index++){
1214*45e6af3bSDavid du Colombier getcolor(index, &red, &green, &blue);
1215*45e6af3bSDavid du Colombier m += snprint((char*)p+m, 4*12*256+1 - m,
1216*45e6af3bSDavid du Colombier "%11d %11lud %11lud %11lud\n", index,
1217*45e6af3bSDavid du Colombier red>>24, green>>24, blue>>24);
1218*45e6af3bSDavid du Colombier }
1219*45e6af3bSDavid du Colombier n = readstr(offset, a, n, (char*)p);
1220*45e6af3bSDavid du Colombier free(p);
1221*45e6af3bSDavid du Colombier break;
1222*45e6af3bSDavid du Colombier
1223*45e6af3bSDavid du Colombier case Qdata:
1224*45e6af3bSDavid du Colombier if(cl->readdata == nil)
1225*45e6af3bSDavid du Colombier error("no draw data");
1226*45e6af3bSDavid du Colombier if(n < cl->nreaddata)
1227*45e6af3bSDavid du Colombier error(Eshortread);
1228*45e6af3bSDavid du Colombier n = cl->nreaddata;
1229*45e6af3bSDavid du Colombier memmove(a, cl->readdata, cl->nreaddata);
1230*45e6af3bSDavid du Colombier free(cl->readdata);
1231*45e6af3bSDavid du Colombier cl->readdata = nil;
1232*45e6af3bSDavid du Colombier break;
1233*45e6af3bSDavid du Colombier
1234*45e6af3bSDavid du Colombier case Qrefresh:
1235*45e6af3bSDavid du Colombier if(n < 5*4)
1236*45e6af3bSDavid du Colombier error(Ebadarg);
1237*45e6af3bSDavid du Colombier for(;;){
1238*45e6af3bSDavid du Colombier if(cl->refreshme || cl->refresh)
1239*45e6af3bSDavid du Colombier break;
1240*45e6af3bSDavid du Colombier dunlock();
1241*45e6af3bSDavid du Colombier if(waserror()){
1242*45e6af3bSDavid du Colombier dlock(); /* restore lock for waserror() above */
1243*45e6af3bSDavid du Colombier nexterror();
1244*45e6af3bSDavid du Colombier }
1245*45e6af3bSDavid du Colombier sleep(&cl->refrend, drawrefactive, cl);
1246*45e6af3bSDavid du Colombier poperror();
1247*45e6af3bSDavid du Colombier dlock();
1248*45e6af3bSDavid du Colombier }
1249*45e6af3bSDavid du Colombier p = a;
1250*45e6af3bSDavid du Colombier while(cl->refresh && n>=5*4){
1251*45e6af3bSDavid du Colombier r = cl->refresh;
1252*45e6af3bSDavid du Colombier BPLONG(p+0*4, r->dimage->id);
1253*45e6af3bSDavid du Colombier BPLONG(p+1*4, r->r.min.x);
1254*45e6af3bSDavid du Colombier BPLONG(p+2*4, r->r.min.y);
1255*45e6af3bSDavid du Colombier BPLONG(p+3*4, r->r.max.x);
1256*45e6af3bSDavid du Colombier BPLONG(p+4*4, r->r.max.y);
1257*45e6af3bSDavid du Colombier cl->refresh = r->next;
1258*45e6af3bSDavid du Colombier free(r);
1259*45e6af3bSDavid du Colombier p += 5*4;
1260*45e6af3bSDavid du Colombier n -= 5*4;
1261*45e6af3bSDavid du Colombier }
1262*45e6af3bSDavid du Colombier cl->refreshme = 0;
1263*45e6af3bSDavid du Colombier n = p-(uchar*)a;
1264*45e6af3bSDavid du Colombier break;
1265*45e6af3bSDavid du Colombier }
1266*45e6af3bSDavid du Colombier dunlock();
1267*45e6af3bSDavid du Colombier poperror();
1268*45e6af3bSDavid du Colombier return n;
1269*45e6af3bSDavid du Colombier }
1270*45e6af3bSDavid du Colombier
1271*45e6af3bSDavid du Colombier void
drawwakeall(void)1272*45e6af3bSDavid du Colombier drawwakeall(void)
1273*45e6af3bSDavid du Colombier {
1274*45e6af3bSDavid du Colombier Client *cl;
1275*45e6af3bSDavid du Colombier int i;
1276*45e6af3bSDavid du Colombier
1277*45e6af3bSDavid du Colombier for(i=0; i<sdraw.nclient; i++){
1278*45e6af3bSDavid du Colombier cl = sdraw.client[i];
1279*45e6af3bSDavid du Colombier if(cl && (cl->refreshme || cl->refresh))
1280*45e6af3bSDavid du Colombier wakeup(&cl->refrend);
1281*45e6af3bSDavid du Colombier }
1282*45e6af3bSDavid du Colombier }
1283*45e6af3bSDavid du Colombier
1284*45e6af3bSDavid du Colombier static long
drawwrite(Chan * c,void * a,long n,vlong)1285*45e6af3bSDavid du Colombier drawwrite(Chan *c, void *a, long n, vlong)
1286*45e6af3bSDavid du Colombier {
1287*45e6af3bSDavid du Colombier char buf[128], *fields[4], *q;
1288*45e6af3bSDavid du Colombier Client *cl;
1289*45e6af3bSDavid du Colombier int i, m, red, green, blue, x;
1290*45e6af3bSDavid du Colombier
1291*45e6af3bSDavid du Colombier if(c->qid.type & QTDIR)
1292*45e6af3bSDavid du Colombier error(Eisdir);
1293*45e6af3bSDavid du Colombier cl = drawclient(c);
1294*45e6af3bSDavid du Colombier dlock();
1295*45e6af3bSDavid du Colombier if(waserror()){
1296*45e6af3bSDavid du Colombier drawwakeall();
1297*45e6af3bSDavid du Colombier dunlock();
1298*45e6af3bSDavid du Colombier nexterror();
1299*45e6af3bSDavid du Colombier }
1300*45e6af3bSDavid du Colombier switch(QID(c->qid)){
1301*45e6af3bSDavid du Colombier case Qctl:
1302*45e6af3bSDavid du Colombier if(n != 4)
1303*45e6af3bSDavid du Colombier error("unknown draw control request");
1304*45e6af3bSDavid du Colombier cl->infoid = BGLONG((uchar*)a);
1305*45e6af3bSDavid du Colombier break;
1306*45e6af3bSDavid du Colombier
1307*45e6af3bSDavid du Colombier case Qcolormap:
1308*45e6af3bSDavid du Colombier drawactive(1); /* to restore map from backup */
1309*45e6af3bSDavid du Colombier m = n;
1310*45e6af3bSDavid du Colombier n = 0;
1311*45e6af3bSDavid du Colombier while(m > 0){
1312*45e6af3bSDavid du Colombier x = m;
1313*45e6af3bSDavid du Colombier if(x > sizeof(buf)-1)
1314*45e6af3bSDavid du Colombier x = sizeof(buf)-1;
1315*45e6af3bSDavid du Colombier q = memccpy(buf, a, '\n', x);
1316*45e6af3bSDavid du Colombier if(q == 0)
1317*45e6af3bSDavid du Colombier break;
1318*45e6af3bSDavid du Colombier i = q-buf;
1319*45e6af3bSDavid du Colombier n += i;
1320*45e6af3bSDavid du Colombier a = (char*)a + i;
1321*45e6af3bSDavid du Colombier m -= i;
1322*45e6af3bSDavid du Colombier *q = 0;
1323*45e6af3bSDavid du Colombier if(tokenize(buf, fields, nelem(fields)) != 4)
1324*45e6af3bSDavid du Colombier error(Ebadarg);
1325*45e6af3bSDavid du Colombier i = strtoul(fields[0], 0, 0);
1326*45e6af3bSDavid du Colombier red = strtoul(fields[1], 0, 0);
1327*45e6af3bSDavid du Colombier green = strtoul(fields[2], 0, 0);
1328*45e6af3bSDavid du Colombier blue = strtoul(fields[3], &q, 0);
1329*45e6af3bSDavid du Colombier if(fields[3] == q)
1330*45e6af3bSDavid du Colombier error(Ebadarg);
1331*45e6af3bSDavid du Colombier if(red>255 || green>255 || blue>255 || i<0 || i>255)
1332*45e6af3bSDavid du Colombier error(Ebadarg);
1333*45e6af3bSDavid du Colombier red |= red<<8;
1334*45e6af3bSDavid du Colombier red |= red<<16;
1335*45e6af3bSDavid du Colombier green |= green<<8;
1336*45e6af3bSDavid du Colombier green |= green<<16;
1337*45e6af3bSDavid du Colombier blue |= blue<<8;
1338*45e6af3bSDavid du Colombier blue |= blue<<16;
1339*45e6af3bSDavid du Colombier setcolor(i, red, green, blue);
1340*45e6af3bSDavid du Colombier }
1341*45e6af3bSDavid du Colombier break;
1342*45e6af3bSDavid du Colombier
1343*45e6af3bSDavid du Colombier case Qdata:
1344*45e6af3bSDavid du Colombier drawmesg(cl, a, n);
1345*45e6af3bSDavid du Colombier drawwakeall();
1346*45e6af3bSDavid du Colombier break;
1347*45e6af3bSDavid du Colombier
1348*45e6af3bSDavid du Colombier default:
1349*45e6af3bSDavid du Colombier error(Ebadusefd);
1350*45e6af3bSDavid du Colombier }
1351*45e6af3bSDavid du Colombier dunlock();
1352*45e6af3bSDavid du Colombier poperror();
1353*45e6af3bSDavid du Colombier return n;
1354*45e6af3bSDavid du Colombier }
1355*45e6af3bSDavid du Colombier
1356*45e6af3bSDavid du Colombier uchar*
drawcoord(uchar * p,uchar * maxp,int oldx,int * newx)1357*45e6af3bSDavid du Colombier drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
1358*45e6af3bSDavid du Colombier {
1359*45e6af3bSDavid du Colombier int b, x;
1360*45e6af3bSDavid du Colombier
1361*45e6af3bSDavid du Colombier if(p >= maxp)
1362*45e6af3bSDavid du Colombier error(Eshortdraw);
1363*45e6af3bSDavid du Colombier b = *p++;
1364*45e6af3bSDavid du Colombier x = b & 0x7F;
1365*45e6af3bSDavid du Colombier if(b & 0x80){
1366*45e6af3bSDavid du Colombier if(p+1 >= maxp)
1367*45e6af3bSDavid du Colombier error(Eshortdraw);
1368*45e6af3bSDavid du Colombier x |= *p++ << 7;
1369*45e6af3bSDavid du Colombier x |= *p++ << 15;
1370*45e6af3bSDavid du Colombier if(x & (1<<22))
1371*45e6af3bSDavid du Colombier x |= ~0<<23;
1372*45e6af3bSDavid du Colombier }else{
1373*45e6af3bSDavid du Colombier if(b & 0x40)
1374*45e6af3bSDavid du Colombier x |= ~0<<7;
1375*45e6af3bSDavid du Colombier x += oldx;
1376*45e6af3bSDavid du Colombier }
1377*45e6af3bSDavid du Colombier *newx = x;
1378*45e6af3bSDavid du Colombier return p;
1379*45e6af3bSDavid du Colombier }
1380*45e6af3bSDavid du Colombier
1381*45e6af3bSDavid du Colombier static void
printmesg(char * fmt,uchar * a,int plsprnt)1382*45e6af3bSDavid du Colombier printmesg(char *fmt, uchar *a, int plsprnt)
1383*45e6af3bSDavid du Colombier {
1384*45e6af3bSDavid du Colombier char buf[256];
1385*45e6af3bSDavid du Colombier char *p, *q;
1386*45e6af3bSDavid du Colombier int s, left;
1387*45e6af3bSDavid du Colombier
1388*45e6af3bSDavid du Colombier if(1|| plsprnt==0){
1389*45e6af3bSDavid du Colombier SET(s,q,p);
1390*45e6af3bSDavid du Colombier USED(fmt, a, buf, p, q, s);
1391*45e6af3bSDavid du Colombier return;
1392*45e6af3bSDavid du Colombier }
1393*45e6af3bSDavid du Colombier q = buf;
1394*45e6af3bSDavid du Colombier *q++ = *a++;
1395*45e6af3bSDavid du Colombier for(p=fmt; *p; p++){
1396*45e6af3bSDavid du Colombier left = sizeof buf - 2 - (q - buf); /* 2 for \n\0 */
1397*45e6af3bSDavid du Colombier switch(*p){
1398*45e6af3bSDavid du Colombier case 'l':
1399*45e6af3bSDavid du Colombier q += snprint(q, left, " %ld", (long)BGLONG(a));
1400*45e6af3bSDavid du Colombier a += 4;
1401*45e6af3bSDavid du Colombier break;
1402*45e6af3bSDavid du Colombier case 'L':
1403*45e6af3bSDavid du Colombier q += snprint(q, left, " %.8lux", (ulong)BGLONG(a));
1404*45e6af3bSDavid du Colombier a += 4;
1405*45e6af3bSDavid du Colombier break;
1406*45e6af3bSDavid du Colombier case 'R':
1407*45e6af3bSDavid du Colombier q += snprint(q, left, " [%d %d %d %d]", BGLONG(a),
1408*45e6af3bSDavid du Colombier BGLONG(a+4), BGLONG(a+8), BGLONG(a+12));
1409*45e6af3bSDavid du Colombier a += 16;
1410*45e6af3bSDavid du Colombier break;
1411*45e6af3bSDavid du Colombier case 'P':
1412*45e6af3bSDavid du Colombier q += snprint(q, left, " [%d %d]", BGLONG(a), BGLONG(a+4));
1413*45e6af3bSDavid du Colombier a += 8;
1414*45e6af3bSDavid du Colombier break;
1415*45e6af3bSDavid du Colombier case 'b':
1416*45e6af3bSDavid du Colombier q += snprint(q, left, " %d", *a++);
1417*45e6af3bSDavid du Colombier break;
1418*45e6af3bSDavid du Colombier case 's':
1419*45e6af3bSDavid du Colombier q += snprint(q, left, " %d", BGSHORT(a));
1420*45e6af3bSDavid du Colombier a += 2;
1421*45e6af3bSDavid du Colombier break;
1422*45e6af3bSDavid du Colombier case 'S':
1423*45e6af3bSDavid du Colombier q += snprint(q, left, " %.4ux", BGSHORT(a));
1424*45e6af3bSDavid du Colombier a += 2;
1425*45e6af3bSDavid du Colombier break;
1426*45e6af3bSDavid du Colombier }
1427*45e6af3bSDavid du Colombier }
1428*45e6af3bSDavid du Colombier *q++ = '\n';
1429*45e6af3bSDavid du Colombier *q = 0;
1430*45e6af3bSDavid du Colombier iprint("%.*s", (int)(q-buf), buf);
1431*45e6af3bSDavid du Colombier }
1432*45e6af3bSDavid du Colombier
1433*45e6af3bSDavid du Colombier void
drawmesg(Client * client,void * av,int n)1434*45e6af3bSDavid du Colombier drawmesg(Client *client, void *av, int n)
1435*45e6af3bSDavid du Colombier {
1436*45e6af3bSDavid du Colombier int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
1437*45e6af3bSDavid du Colombier uchar *u, *a, refresh;
1438*45e6af3bSDavid du Colombier char *fmt;
1439*45e6af3bSDavid du Colombier ulong value, chan;
1440*45e6af3bSDavid du Colombier Rectangle r, clipr;
1441*45e6af3bSDavid du Colombier Point p, q, *pp, sp;
1442*45e6af3bSDavid du Colombier Memimage *i, *bg, *dst, *src, *mask;
1443*45e6af3bSDavid du Colombier Memimage *l, **lp;
1444*45e6af3bSDavid du Colombier Memscreen *scrn;
1445*45e6af3bSDavid du Colombier DImage *font, *ll, *di, *ddst, *dsrc;
1446*45e6af3bSDavid du Colombier DName *dn;
1447*45e6af3bSDavid du Colombier DScreen *dscrn;
1448*45e6af3bSDavid du Colombier FChar *fc;
1449*45e6af3bSDavid du Colombier Refx *refx;
1450*45e6af3bSDavid du Colombier CScreen *cs;
1451*45e6af3bSDavid du Colombier Refreshfn reffn;
1452*45e6af3bSDavid du Colombier
1453*45e6af3bSDavid du Colombier a = av;
1454*45e6af3bSDavid du Colombier m = 0;
1455*45e6af3bSDavid du Colombier fmt = nil;
1456*45e6af3bSDavid du Colombier if(waserror()){
1457*45e6af3bSDavid du Colombier if(fmt) printmesg(fmt, a, 1);
1458*45e6af3bSDavid du Colombier /* iprint("error: %s\n", up->errstr); */
1459*45e6af3bSDavid du Colombier nexterror();
1460*45e6af3bSDavid du Colombier }
1461*45e6af3bSDavid du Colombier while((n-=m) > 0){
1462*45e6af3bSDavid du Colombier USED(fmt);
1463*45e6af3bSDavid du Colombier a += m;
1464*45e6af3bSDavid du Colombier switch(*a){
1465*45e6af3bSDavid du Colombier default:
1466*45e6af3bSDavid du Colombier error("bad draw command");
1467*45e6af3bSDavid du Colombier /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */
1468*45e6af3bSDavid du Colombier case 'b':
1469*45e6af3bSDavid du Colombier printmesg(fmt="LLbLbRRL", a, 0);
1470*45e6af3bSDavid du Colombier m = 1+4+4+1+4+1+4*4+4*4+4;
1471*45e6af3bSDavid du Colombier if(n < m)
1472*45e6af3bSDavid du Colombier error(Eshortdraw);
1473*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1474*45e6af3bSDavid du Colombier scrnid = BGSHORT(a+5);
1475*45e6af3bSDavid du Colombier refresh = a[9];
1476*45e6af3bSDavid du Colombier chan = BGLONG(a+10);
1477*45e6af3bSDavid du Colombier repl = a[14];
1478*45e6af3bSDavid du Colombier drawrectangle(&r, a+15);
1479*45e6af3bSDavid du Colombier drawrectangle(&clipr, a+31);
1480*45e6af3bSDavid du Colombier value = BGLONG(a+47);
1481*45e6af3bSDavid du Colombier if(drawlookup(client, dstid, 0))
1482*45e6af3bSDavid du Colombier error(Eimageexists);
1483*45e6af3bSDavid du Colombier if(scrnid){
1484*45e6af3bSDavid du Colombier dscrn = drawlookupscreen(client, scrnid, &cs);
1485*45e6af3bSDavid du Colombier scrn = dscrn->screen;
1486*45e6af3bSDavid du Colombier if(repl || chan!=scrn->image->chan)
1487*45e6af3bSDavid du Colombier error("image parameters incompatible with screen");
1488*45e6af3bSDavid du Colombier reffn = nil;
1489*45e6af3bSDavid du Colombier switch(refresh){
1490*45e6af3bSDavid du Colombier case Refbackup:
1491*45e6af3bSDavid du Colombier break;
1492*45e6af3bSDavid du Colombier case Refnone:
1493*45e6af3bSDavid du Colombier reffn = memlnorefresh;
1494*45e6af3bSDavid du Colombier break;
1495*45e6af3bSDavid du Colombier case Refmesg:
1496*45e6af3bSDavid du Colombier reffn = drawrefresh;
1497*45e6af3bSDavid du Colombier break;
1498*45e6af3bSDavid du Colombier default:
1499*45e6af3bSDavid du Colombier error("unknown refresh method");
1500*45e6af3bSDavid du Colombier }
1501*45e6af3bSDavid du Colombier l = memlalloc(scrn, r, reffn, 0, value);
1502*45e6af3bSDavid du Colombier if(l == 0)
1503*45e6af3bSDavid du Colombier error(Edrawmem);
1504*45e6af3bSDavid du Colombier addflush(l->layer->screenr);
1505*45e6af3bSDavid du Colombier l->clipr = clipr;
1506*45e6af3bSDavid du Colombier rectclip(&l->clipr, r);
1507*45e6af3bSDavid du Colombier if(drawinstall(client, dstid, l, dscrn) == 0){
1508*45e6af3bSDavid du Colombier memldelete(l);
1509*45e6af3bSDavid du Colombier error(Edrawmem);
1510*45e6af3bSDavid du Colombier }
1511*45e6af3bSDavid du Colombier dscrn->ref++;
1512*45e6af3bSDavid du Colombier if(reffn){
1513*45e6af3bSDavid du Colombier refx = nil;
1514*45e6af3bSDavid du Colombier if(reffn == drawrefresh){
1515*45e6af3bSDavid du Colombier refx = malloc(sizeof(Refx));
1516*45e6af3bSDavid du Colombier if(refx == 0){
1517*45e6af3bSDavid du Colombier drawuninstall(client, dstid);
1518*45e6af3bSDavid du Colombier error(Edrawmem);
1519*45e6af3bSDavid du Colombier }
1520*45e6af3bSDavid du Colombier refx->client = client;
1521*45e6af3bSDavid du Colombier refx->dimage = drawlookup(client, dstid, 1);
1522*45e6af3bSDavid du Colombier }
1523*45e6af3bSDavid du Colombier memlsetrefresh(l, reffn, refx);
1524*45e6af3bSDavid du Colombier }
1525*45e6af3bSDavid du Colombier continue;
1526*45e6af3bSDavid du Colombier }
1527*45e6af3bSDavid du Colombier i = allocmemimage(r, chan);
1528*45e6af3bSDavid du Colombier if(i == 0)
1529*45e6af3bSDavid du Colombier error(Edrawmem);
1530*45e6af3bSDavid du Colombier if(repl)
1531*45e6af3bSDavid du Colombier i->flags |= Frepl;
1532*45e6af3bSDavid du Colombier i->clipr = clipr;
1533*45e6af3bSDavid du Colombier if(!repl)
1534*45e6af3bSDavid du Colombier rectclip(&i->clipr, r);
1535*45e6af3bSDavid du Colombier if(drawinstall(client, dstid, i, 0) == 0){
1536*45e6af3bSDavid du Colombier freememimage(i);
1537*45e6af3bSDavid du Colombier error(Edrawmem);
1538*45e6af3bSDavid du Colombier }
1539*45e6af3bSDavid du Colombier memfillcolor(i, value);
1540*45e6af3bSDavid du Colombier continue;
1541*45e6af3bSDavid du Colombier
1542*45e6af3bSDavid du Colombier /* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */
1543*45e6af3bSDavid du Colombier case 'A':
1544*45e6af3bSDavid du Colombier printmesg(fmt="LLLb", a, 1);
1545*45e6af3bSDavid du Colombier m = 1+4+4+4+1;
1546*45e6af3bSDavid du Colombier if(n < m)
1547*45e6af3bSDavid du Colombier error(Eshortdraw);
1548*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1549*45e6af3bSDavid du Colombier if(dstid == 0)
1550*45e6af3bSDavid du Colombier error(Ebadarg);
1551*45e6af3bSDavid du Colombier if(drawlookupdscreen(dstid))
1552*45e6af3bSDavid du Colombier error(Escreenexists);
1553*45e6af3bSDavid du Colombier ddst = drawlookup(client, BGLONG(a+5), 1);
1554*45e6af3bSDavid du Colombier dsrc = drawlookup(client, BGLONG(a+9), 1);
1555*45e6af3bSDavid du Colombier if(ddst==0 || dsrc==0)
1556*45e6af3bSDavid du Colombier error(Enodrawimage);
1557*45e6af3bSDavid du Colombier if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0)
1558*45e6af3bSDavid du Colombier error(Edrawmem);
1559*45e6af3bSDavid du Colombier continue;
1560*45e6af3bSDavid du Colombier
1561*45e6af3bSDavid du Colombier /* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */
1562*45e6af3bSDavid du Colombier case 'c':
1563*45e6af3bSDavid du Colombier printmesg(fmt="LbR", a, 0);
1564*45e6af3bSDavid du Colombier m = 1+4+1+4*4;
1565*45e6af3bSDavid du Colombier if(n < m)
1566*45e6af3bSDavid du Colombier error(Eshortdraw);
1567*45e6af3bSDavid du Colombier ddst = drawlookup(client, BGLONG(a+1), 1);
1568*45e6af3bSDavid du Colombier if(ddst == nil)
1569*45e6af3bSDavid du Colombier error(Enodrawimage);
1570*45e6af3bSDavid du Colombier if(ddst->name)
1571*45e6af3bSDavid du Colombier error("cannot change repl/clipr of shared image");
1572*45e6af3bSDavid du Colombier dst = ddst->image;
1573*45e6af3bSDavid du Colombier if(a[5])
1574*45e6af3bSDavid du Colombier dst->flags |= Frepl;
1575*45e6af3bSDavid du Colombier drawrectangle(&dst->clipr, a+6);
1576*45e6af3bSDavid du Colombier continue;
1577*45e6af3bSDavid du Colombier
1578*45e6af3bSDavid du Colombier /* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */
1579*45e6af3bSDavid du Colombier case 'd':
1580*45e6af3bSDavid du Colombier printmesg(fmt="LLLRPP", a, 0);
1581*45e6af3bSDavid du Colombier m = 1+4+4+4+4*4+2*4+2*4;
1582*45e6af3bSDavid du Colombier if(n < m)
1583*45e6af3bSDavid du Colombier error(Eshortdraw);
1584*45e6af3bSDavid du Colombier dst = drawimage(client, a+1);
1585*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1586*45e6af3bSDavid du Colombier src = drawimage(client, a+5);
1587*45e6af3bSDavid du Colombier mask = drawimage(client, a+9);
1588*45e6af3bSDavid du Colombier drawrectangle(&r, a+13);
1589*45e6af3bSDavid du Colombier drawpoint(&p, a+29);
1590*45e6af3bSDavid du Colombier drawpoint(&q, a+37);
1591*45e6af3bSDavid du Colombier op = drawclientop(client);
1592*45e6af3bSDavid du Colombier memdraw(dst, r, src, p, mask, q, op);
1593*45e6af3bSDavid du Colombier dstflush(dstid, dst, r);
1594*45e6af3bSDavid du Colombier continue;
1595*45e6af3bSDavid du Colombier
1596*45e6af3bSDavid du Colombier /* toggle debugging: 'D' val[1] */
1597*45e6af3bSDavid du Colombier case 'D':
1598*45e6af3bSDavid du Colombier printmesg(fmt="b", a, 0);
1599*45e6af3bSDavid du Colombier m = 1+1;
1600*45e6af3bSDavid du Colombier if(n < m)
1601*45e6af3bSDavid du Colombier error(Eshortdraw);
1602*45e6af3bSDavid du Colombier drawdebug = a[1];
1603*45e6af3bSDavid du Colombier continue;
1604*45e6af3bSDavid du Colombier
1605*45e6af3bSDavid du Colombier /* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/
1606*45e6af3bSDavid du Colombier case 'e':
1607*45e6af3bSDavid du Colombier case 'E':
1608*45e6af3bSDavid du Colombier printmesg(fmt="LLPlllPll", a, 0);
1609*45e6af3bSDavid du Colombier m = 1+4+4+2*4+4+4+4+2*4+2*4;
1610*45e6af3bSDavid du Colombier if(n < m)
1611*45e6af3bSDavid du Colombier error(Eshortdraw);
1612*45e6af3bSDavid du Colombier dst = drawimage(client, a+1);
1613*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1614*45e6af3bSDavid du Colombier src = drawimage(client, a+5);
1615*45e6af3bSDavid du Colombier drawpoint(&p, a+9);
1616*45e6af3bSDavid du Colombier e0 = BGLONG(a+17);
1617*45e6af3bSDavid du Colombier e1 = BGLONG(a+21);
1618*45e6af3bSDavid du Colombier if(e0<0 || e1<0)
1619*45e6af3bSDavid du Colombier error("invalid ellipse semidiameter");
1620*45e6af3bSDavid du Colombier j = BGLONG(a+25);
1621*45e6af3bSDavid du Colombier if(j < 0)
1622*45e6af3bSDavid du Colombier error("negative ellipse thickness");
1623*45e6af3bSDavid du Colombier drawpoint(&sp, a+29);
1624*45e6af3bSDavid du Colombier c = j;
1625*45e6af3bSDavid du Colombier if(*a == 'E')
1626*45e6af3bSDavid du Colombier c = -1;
1627*45e6af3bSDavid du Colombier ox = BGLONG(a+37);
1628*45e6af3bSDavid du Colombier oy = BGLONG(a+41);
1629*45e6af3bSDavid du Colombier op = drawclientop(client);
1630*45e6af3bSDavid du Colombier /* high bit indicates arc angles are present */
1631*45e6af3bSDavid du Colombier if(ox & (1<<31)){
1632*45e6af3bSDavid du Colombier if((ox & (1<<30)) == 0)
1633*45e6af3bSDavid du Colombier ox &= ~(1<<31);
1634*45e6af3bSDavid du Colombier memarc(dst, p, e0, e1, c, src, sp, ox, oy, op);
1635*45e6af3bSDavid du Colombier }else
1636*45e6af3bSDavid du Colombier memellipse(dst, p, e0, e1, c, src, sp, op);
1637*45e6af3bSDavid du Colombier dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
1638*45e6af3bSDavid du Colombier continue;
1639*45e6af3bSDavid du Colombier
1640*45e6af3bSDavid du Colombier /* free: 'f' id[4] */
1641*45e6af3bSDavid du Colombier case 'f':
1642*45e6af3bSDavid du Colombier printmesg(fmt="L", a, 1);
1643*45e6af3bSDavid du Colombier m = 1+4;
1644*45e6af3bSDavid du Colombier if(n < m)
1645*45e6af3bSDavid du Colombier error(Eshortdraw);
1646*45e6af3bSDavid du Colombier ll = drawlookup(client, BGLONG(a+1), 0);
1647*45e6af3bSDavid du Colombier if(ll && ll->dscreen && ll->dscreen->owner != client)
1648*45e6af3bSDavid du Colombier ll->dscreen->owner->refreshme = 1;
1649*45e6af3bSDavid du Colombier drawuninstall(client, BGLONG(a+1));
1650*45e6af3bSDavid du Colombier continue;
1651*45e6af3bSDavid du Colombier
1652*45e6af3bSDavid du Colombier /* free screen: 'F' id[4] */
1653*45e6af3bSDavid du Colombier case 'F':
1654*45e6af3bSDavid du Colombier printmesg(fmt="L", a, 1);
1655*45e6af3bSDavid du Colombier m = 1+4;
1656*45e6af3bSDavid du Colombier if(n < m)
1657*45e6af3bSDavid du Colombier error(Eshortdraw);
1658*45e6af3bSDavid du Colombier drawlookupscreen(client, BGLONG(a+1), &cs);
1659*45e6af3bSDavid du Colombier drawuninstallscreen(client, cs);
1660*45e6af3bSDavid du Colombier continue;
1661*45e6af3bSDavid du Colombier
1662*45e6af3bSDavid du Colombier /* initialize font: 'i' fontid[4] nchars[4] ascent[1] */
1663*45e6af3bSDavid du Colombier case 'i':
1664*45e6af3bSDavid du Colombier printmesg(fmt="Llb", a, 1);
1665*45e6af3bSDavid du Colombier m = 1+4+4+1;
1666*45e6af3bSDavid du Colombier if(n < m)
1667*45e6af3bSDavid du Colombier error(Eshortdraw);
1668*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1669*45e6af3bSDavid du Colombier if(dstid == 0)
1670*45e6af3bSDavid du Colombier error("cannot use display as font");
1671*45e6af3bSDavid du Colombier font = drawlookup(client, dstid, 1);
1672*45e6af3bSDavid du Colombier if(font == 0)
1673*45e6af3bSDavid du Colombier error(Enodrawimage);
1674*45e6af3bSDavid du Colombier if(font->image->layer)
1675*45e6af3bSDavid du Colombier error("cannot use window as font");
1676*45e6af3bSDavid du Colombier ni = BGLONG(a+5);
1677*45e6af3bSDavid du Colombier if(ni<=0 || ni>4096)
1678*45e6af3bSDavid du Colombier error("bad font size (4096 chars max)");
1679*45e6af3bSDavid du Colombier free(font->fchar); /* should we complain if non-zero? */
1680*45e6af3bSDavid du Colombier font->fchar = malloc(ni*sizeof(FChar));
1681*45e6af3bSDavid du Colombier if(font->fchar == 0)
1682*45e6af3bSDavid du Colombier error("no memory for font");
1683*45e6af3bSDavid du Colombier memset(font->fchar, 0, ni*sizeof(FChar));
1684*45e6af3bSDavid du Colombier font->nfchar = ni;
1685*45e6af3bSDavid du Colombier font->ascent = a[9];
1686*45e6af3bSDavid du Colombier continue;
1687*45e6af3bSDavid du Colombier
1688*45e6af3bSDavid du Colombier /* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
1689*45e6af3bSDavid du Colombier case 'l':
1690*45e6af3bSDavid du Colombier printmesg(fmt="LLSRPbb", a, 0);
1691*45e6af3bSDavid du Colombier m = 1+4+4+2+4*4+2*4+1+1;
1692*45e6af3bSDavid du Colombier if(n < m)
1693*45e6af3bSDavid du Colombier error(Eshortdraw);
1694*45e6af3bSDavid du Colombier font = drawlookup(client, BGLONG(a+1), 1);
1695*45e6af3bSDavid du Colombier if(font == 0)
1696*45e6af3bSDavid du Colombier error(Enodrawimage);
1697*45e6af3bSDavid du Colombier if(font->nfchar == 0)
1698*45e6af3bSDavid du Colombier error(Enotfont);
1699*45e6af3bSDavid du Colombier src = drawimage(client, a+5);
1700*45e6af3bSDavid du Colombier ci = BGSHORT(a+9);
1701*45e6af3bSDavid du Colombier if(ci >= font->nfchar)
1702*45e6af3bSDavid du Colombier error(Eindex);
1703*45e6af3bSDavid du Colombier drawrectangle(&r, a+11);
1704*45e6af3bSDavid du Colombier drawpoint(&p, a+27);
1705*45e6af3bSDavid du Colombier memdraw(font->image, r, src, p, memopaque, p, S);
1706*45e6af3bSDavid du Colombier fc = &font->fchar[ci];
1707*45e6af3bSDavid du Colombier fc->minx = r.min.x;
1708*45e6af3bSDavid du Colombier fc->maxx = r.max.x;
1709*45e6af3bSDavid du Colombier fc->miny = r.min.y;
1710*45e6af3bSDavid du Colombier fc->maxy = r.max.y;
1711*45e6af3bSDavid du Colombier fc->left = a[35];
1712*45e6af3bSDavid du Colombier fc->width = a[36];
1713*45e6af3bSDavid du Colombier continue;
1714*45e6af3bSDavid du Colombier
1715*45e6af3bSDavid du Colombier /* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */
1716*45e6af3bSDavid du Colombier case 'L':
1717*45e6af3bSDavid du Colombier printmesg(fmt="LPPlllLP", a, 0);
1718*45e6af3bSDavid du Colombier m = 1+4+2*4+2*4+4+4+4+4+2*4;
1719*45e6af3bSDavid du Colombier if(n < m)
1720*45e6af3bSDavid du Colombier error(Eshortdraw);
1721*45e6af3bSDavid du Colombier dst = drawimage(client, a+1);
1722*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1723*45e6af3bSDavid du Colombier drawpoint(&p, a+5);
1724*45e6af3bSDavid du Colombier drawpoint(&q, a+13);
1725*45e6af3bSDavid du Colombier e0 = BGLONG(a+21);
1726*45e6af3bSDavid du Colombier e1 = BGLONG(a+25);
1727*45e6af3bSDavid du Colombier j = BGLONG(a+29);
1728*45e6af3bSDavid du Colombier if(j < 0)
1729*45e6af3bSDavid du Colombier error("negative line width");
1730*45e6af3bSDavid du Colombier src = drawimage(client, a+33);
1731*45e6af3bSDavid du Colombier drawpoint(&sp, a+37);
1732*45e6af3bSDavid du Colombier op = drawclientop(client);
1733*45e6af3bSDavid du Colombier memline(dst, p, q, e0, e1, j, src, sp, op);
1734*45e6af3bSDavid du Colombier /* avoid memlinebbox if possible */
1735*45e6af3bSDavid du Colombier if(dstid==0 || dst->layer!=nil){
1736*45e6af3bSDavid du Colombier /* BUG: this is terribly inefficient: update maximal containing rect*/
1737*45e6af3bSDavid du Colombier r = memlinebbox(p, q, e0, e1, j);
1738*45e6af3bSDavid du Colombier dstflush(dstid, dst, insetrect(r, -(1+1+j)));
1739*45e6af3bSDavid du Colombier }
1740*45e6af3bSDavid du Colombier continue;
1741*45e6af3bSDavid du Colombier
1742*45e6af3bSDavid du Colombier /* create image mask: 'm' newid[4] id[4] */
1743*45e6af3bSDavid du Colombier /*
1744*45e6af3bSDavid du Colombier *
1745*45e6af3bSDavid du Colombier case 'm':
1746*45e6af3bSDavid du Colombier printmesg("LL", a, 0);
1747*45e6af3bSDavid du Colombier m = 4+4;
1748*45e6af3bSDavid du Colombier if(n < m)
1749*45e6af3bSDavid du Colombier error(Eshortdraw);
1750*45e6af3bSDavid du Colombier break;
1751*45e6af3bSDavid du Colombier *
1752*45e6af3bSDavid du Colombier */
1753*45e6af3bSDavid du Colombier
1754*45e6af3bSDavid du Colombier /* attach to a named image: 'n' dstid[4] j[1] name[j] */
1755*45e6af3bSDavid du Colombier case 'n':
1756*45e6af3bSDavid du Colombier printmesg(fmt="Lz", a, 0);
1757*45e6af3bSDavid du Colombier m = 1+4+1;
1758*45e6af3bSDavid du Colombier if(n < m)
1759*45e6af3bSDavid du Colombier error(Eshortdraw);
1760*45e6af3bSDavid du Colombier j = a[5];
1761*45e6af3bSDavid du Colombier if(j == 0) /* give me a non-empty name please */
1762*45e6af3bSDavid du Colombier error(Eshortdraw);
1763*45e6af3bSDavid du Colombier m += j;
1764*45e6af3bSDavid du Colombier if(n < m)
1765*45e6af3bSDavid du Colombier error(Eshortdraw);
1766*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1767*45e6af3bSDavid du Colombier if(drawlookup(client, dstid, 0))
1768*45e6af3bSDavid du Colombier error(Eimageexists);
1769*45e6af3bSDavid du Colombier dn = drawlookupname(j, (char*)a+6);
1770*45e6af3bSDavid du Colombier if(dn == nil)
1771*45e6af3bSDavid du Colombier error(Enoname);
1772*45e6af3bSDavid du Colombier if(drawinstall(client, dstid, dn->dimage->image, 0) == 0)
1773*45e6af3bSDavid du Colombier error(Edrawmem);
1774*45e6af3bSDavid du Colombier di = drawlookup(client, dstid, 0);
1775*45e6af3bSDavid du Colombier if(di == 0)
1776*45e6af3bSDavid du Colombier error("draw: cannot happen");
1777*45e6af3bSDavid du Colombier di->vers = dn->vers;
1778*45e6af3bSDavid du Colombier di->name = smalloc(j+1);
1779*45e6af3bSDavid du Colombier di->fromname = dn->dimage;
1780*45e6af3bSDavid du Colombier di->fromname->ref++;
1781*45e6af3bSDavid du Colombier memmove(di->name, a+6, j);
1782*45e6af3bSDavid du Colombier di->name[j] = 0;
1783*45e6af3bSDavid du Colombier client->infoid = dstid;
1784*45e6af3bSDavid du Colombier continue;
1785*45e6af3bSDavid du Colombier
1786*45e6af3bSDavid du Colombier /* name an image: 'N' dstid[4] in[1] j[1] name[j] */
1787*45e6af3bSDavid du Colombier case 'N':
1788*45e6af3bSDavid du Colombier printmesg(fmt="Lbz", a, 0);
1789*45e6af3bSDavid du Colombier m = 1+4+1+1;
1790*45e6af3bSDavid du Colombier if(n < m)
1791*45e6af3bSDavid du Colombier error(Eshortdraw);
1792*45e6af3bSDavid du Colombier c = a[5];
1793*45e6af3bSDavid du Colombier j = a[6];
1794*45e6af3bSDavid du Colombier if(j == 0) /* give me a non-empty name please */
1795*45e6af3bSDavid du Colombier error(Eshortdraw);
1796*45e6af3bSDavid du Colombier m += j;
1797*45e6af3bSDavid du Colombier if(n < m)
1798*45e6af3bSDavid du Colombier error(Eshortdraw);
1799*45e6af3bSDavid du Colombier di = drawlookup(client, BGLONG(a+1), 0);
1800*45e6af3bSDavid du Colombier if(di == 0)
1801*45e6af3bSDavid du Colombier error(Enodrawimage);
1802*45e6af3bSDavid du Colombier if(di->name)
1803*45e6af3bSDavid du Colombier error(Enamed);
1804*45e6af3bSDavid du Colombier if(c)
1805*45e6af3bSDavid du Colombier drawaddname(client, di, j, (char*)a+7);
1806*45e6af3bSDavid du Colombier else{
1807*45e6af3bSDavid du Colombier dn = drawlookupname(j, (char*)a+7);
1808*45e6af3bSDavid du Colombier if(dn == nil)
1809*45e6af3bSDavid du Colombier error(Enoname);
1810*45e6af3bSDavid du Colombier if(dn->dimage != di)
1811*45e6af3bSDavid du Colombier error(Ewrongname);
1812*45e6af3bSDavid du Colombier drawdelname(dn);
1813*45e6af3bSDavid du Colombier }
1814*45e6af3bSDavid du Colombier continue;
1815*45e6af3bSDavid du Colombier
1816*45e6af3bSDavid du Colombier /* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */
1817*45e6af3bSDavid du Colombier case 'o':
1818*45e6af3bSDavid du Colombier printmesg(fmt="LPP", a, 0);
1819*45e6af3bSDavid du Colombier m = 1+4+2*4+2*4;
1820*45e6af3bSDavid du Colombier if(n < m)
1821*45e6af3bSDavid du Colombier error(Eshortdraw);
1822*45e6af3bSDavid du Colombier dst = drawimage(client, a+1);
1823*45e6af3bSDavid du Colombier if(dst->layer){
1824*45e6af3bSDavid du Colombier drawpoint(&p, a+5);
1825*45e6af3bSDavid du Colombier drawpoint(&q, a+13);
1826*45e6af3bSDavid du Colombier r = dst->layer->screenr;
1827*45e6af3bSDavid du Colombier ni = memlorigin(dst, p, q);
1828*45e6af3bSDavid du Colombier if(ni < 0)
1829*45e6af3bSDavid du Colombier error("image origin failed");
1830*45e6af3bSDavid du Colombier if(ni > 0){
1831*45e6af3bSDavid du Colombier addflush(r);
1832*45e6af3bSDavid du Colombier addflush(dst->layer->screenr);
1833*45e6af3bSDavid du Colombier ll = drawlookup(client, BGLONG(a+1), 1);
1834*45e6af3bSDavid du Colombier drawrefreshscreen(ll, client);
1835*45e6af3bSDavid du Colombier }
1836*45e6af3bSDavid du Colombier }
1837*45e6af3bSDavid du Colombier continue;
1838*45e6af3bSDavid du Colombier
1839*45e6af3bSDavid du Colombier /* set compositing operator for next draw operation: 'O' op */
1840*45e6af3bSDavid du Colombier case 'O':
1841*45e6af3bSDavid du Colombier printmesg(fmt="b", a, 0);
1842*45e6af3bSDavid du Colombier m = 1+1;
1843*45e6af3bSDavid du Colombier if(n < m)
1844*45e6af3bSDavid du Colombier error(Eshortdraw);
1845*45e6af3bSDavid du Colombier client->op = a[1];
1846*45e6af3bSDavid du Colombier continue;
1847*45e6af3bSDavid du Colombier
1848*45e6af3bSDavid du Colombier /* filled polygon: 'P' dstid[4] n[2] wind[4] ignore[2*4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */
1849*45e6af3bSDavid du Colombier /* polygon: 'p' dstid[4] n[2] end0[4] end1[4] radius[4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */
1850*45e6af3bSDavid du Colombier case 'p':
1851*45e6af3bSDavid du Colombier case 'P':
1852*45e6af3bSDavid du Colombier printmesg(fmt="LslllLPP", a, 0);
1853*45e6af3bSDavid du Colombier m = 1+4+2+4+4+4+4+2*4;
1854*45e6af3bSDavid du Colombier if(n < m)
1855*45e6af3bSDavid du Colombier error(Eshortdraw);
1856*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1857*45e6af3bSDavid du Colombier dst = drawimage(client, a+1);
1858*45e6af3bSDavid du Colombier ni = BGSHORT(a+5);
1859*45e6af3bSDavid du Colombier if(ni < 0)
1860*45e6af3bSDavid du Colombier error("negative count in polygon");
1861*45e6af3bSDavid du Colombier e0 = BGLONG(a+7);
1862*45e6af3bSDavid du Colombier e1 = BGLONG(a+11);
1863*45e6af3bSDavid du Colombier j = 0;
1864*45e6af3bSDavid du Colombier if(*a == 'p'){
1865*45e6af3bSDavid du Colombier j = BGLONG(a+15);
1866*45e6af3bSDavid du Colombier if(j < 0)
1867*45e6af3bSDavid du Colombier error("negative polygon line width");
1868*45e6af3bSDavid du Colombier }
1869*45e6af3bSDavid du Colombier src = drawimage(client, a+19);
1870*45e6af3bSDavid du Colombier drawpoint(&sp, a+23);
1871*45e6af3bSDavid du Colombier drawpoint(&p, a+31);
1872*45e6af3bSDavid du Colombier ni++;
1873*45e6af3bSDavid du Colombier pp = malloc(ni*sizeof(Point));
1874*45e6af3bSDavid du Colombier if(pp == nil)
1875*45e6af3bSDavid du Colombier error(Enomem);
1876*45e6af3bSDavid du Colombier doflush = 0;
1877*45e6af3bSDavid du Colombier if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data))
1878*45e6af3bSDavid du Colombier doflush = 1; /* simplify test in loop */
1879*45e6af3bSDavid du Colombier ox = oy = 0;
1880*45e6af3bSDavid du Colombier esize = 0;
1881*45e6af3bSDavid du Colombier u = a+m;
1882*45e6af3bSDavid du Colombier for(y=0; y<ni; y++){
1883*45e6af3bSDavid du Colombier q = p;
1884*45e6af3bSDavid du Colombier oesize = esize;
1885*45e6af3bSDavid du Colombier u = drawcoord(u, a+n, ox, &p.x);
1886*45e6af3bSDavid du Colombier u = drawcoord(u, a+n, oy, &p.y);
1887*45e6af3bSDavid du Colombier ox = p.x;
1888*45e6af3bSDavid du Colombier oy = p.y;
1889*45e6af3bSDavid du Colombier if(doflush){
1890*45e6af3bSDavid du Colombier esize = j;
1891*45e6af3bSDavid du Colombier if(*a == 'p'){
1892*45e6af3bSDavid du Colombier if(y == 0){
1893*45e6af3bSDavid du Colombier c = memlineendsize(e0);
1894*45e6af3bSDavid du Colombier if(c > esize)
1895*45e6af3bSDavid du Colombier esize = c;
1896*45e6af3bSDavid du Colombier }
1897*45e6af3bSDavid du Colombier if(y == ni-1){
1898*45e6af3bSDavid du Colombier c = memlineendsize(e1);
1899*45e6af3bSDavid du Colombier if(c > esize)
1900*45e6af3bSDavid du Colombier esize = c;
1901*45e6af3bSDavid du Colombier }
1902*45e6af3bSDavid du Colombier }
1903*45e6af3bSDavid du Colombier if(*a=='P' && e0!=1 && e0 !=~0)
1904*45e6af3bSDavid du Colombier r = dst->clipr;
1905*45e6af3bSDavid du Colombier else if(y > 0){
1906*45e6af3bSDavid du Colombier r = Rect(q.x-oesize, q.y-oesize, q.x+oesize+1, q.y+oesize+1);
1907*45e6af3bSDavid du Colombier combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
1908*45e6af3bSDavid du Colombier }
1909*45e6af3bSDavid du Colombier if(rectclip(&r, dst->clipr)) /* should perhaps be an arg to dstflush */
1910*45e6af3bSDavid du Colombier dstflush(dstid, dst, r);
1911*45e6af3bSDavid du Colombier }
1912*45e6af3bSDavid du Colombier pp[y] = p;
1913*45e6af3bSDavid du Colombier }
1914*45e6af3bSDavid du Colombier if(y == 1)
1915*45e6af3bSDavid du Colombier dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
1916*45e6af3bSDavid du Colombier op = drawclientop(client);
1917*45e6af3bSDavid du Colombier if(*a == 'p')
1918*45e6af3bSDavid du Colombier mempoly(dst, pp, ni, e0, e1, j, src, sp, op);
1919*45e6af3bSDavid du Colombier else
1920*45e6af3bSDavid du Colombier memfillpoly(dst, pp, ni, e0, src, sp, op);
1921*45e6af3bSDavid du Colombier free(pp);
1922*45e6af3bSDavid du Colombier m = u-a;
1923*45e6af3bSDavid du Colombier continue;
1924*45e6af3bSDavid du Colombier
1925*45e6af3bSDavid du Colombier /* read: 'r' id[4] R[4*4] */
1926*45e6af3bSDavid du Colombier case 'r':
1927*45e6af3bSDavid du Colombier printmesg(fmt="LR", a, 0);
1928*45e6af3bSDavid du Colombier m = 1+4+4*4;
1929*45e6af3bSDavid du Colombier if(n < m)
1930*45e6af3bSDavid du Colombier error(Eshortdraw);
1931*45e6af3bSDavid du Colombier i = drawimage(client, a+1);
1932*45e6af3bSDavid du Colombier drawrectangle(&r, a+5);
1933*45e6af3bSDavid du Colombier if(!rectinrect(r, i->r))
1934*45e6af3bSDavid du Colombier error(Ereadoutside);
1935*45e6af3bSDavid du Colombier c = bytesperline(r, i->depth);
1936*45e6af3bSDavid du Colombier c *= Dy(r);
1937*45e6af3bSDavid du Colombier free(client->readdata);
1938*45e6af3bSDavid du Colombier client->readdata = mallocz(c, 0);
1939*45e6af3bSDavid du Colombier if(client->readdata == nil)
1940*45e6af3bSDavid du Colombier error("readimage malloc failed");
1941*45e6af3bSDavid du Colombier client->nreaddata = memunload(i, r, client->readdata, c);
1942*45e6af3bSDavid du Colombier if(client->nreaddata < 0){
1943*45e6af3bSDavid du Colombier free(client->readdata);
1944*45e6af3bSDavid du Colombier client->readdata = nil;
1945*45e6af3bSDavid du Colombier error("bad readimage call");
1946*45e6af3bSDavid du Colombier }
1947*45e6af3bSDavid du Colombier continue;
1948*45e6af3bSDavid du Colombier
1949*45e6af3bSDavid du Colombier /* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */
1950*45e6af3bSDavid du Colombier /* stringbg: 'x' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] bgid[4] bgpt[2*4] ni*(index[2]) */
1951*45e6af3bSDavid du Colombier case 's':
1952*45e6af3bSDavid du Colombier case 'x':
1953*45e6af3bSDavid du Colombier printmesg(fmt="LLLPRPs", a, 0);
1954*45e6af3bSDavid du Colombier m = 1+4+4+4+2*4+4*4+2*4+2;
1955*45e6af3bSDavid du Colombier if(*a == 'x')
1956*45e6af3bSDavid du Colombier m += 4+2*4;
1957*45e6af3bSDavid du Colombier if(n < m)
1958*45e6af3bSDavid du Colombier error(Eshortdraw);
1959*45e6af3bSDavid du Colombier
1960*45e6af3bSDavid du Colombier dst = drawimage(client, a+1);
1961*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
1962*45e6af3bSDavid du Colombier src = drawimage(client, a+5);
1963*45e6af3bSDavid du Colombier font = drawlookup(client, BGLONG(a+9), 1);
1964*45e6af3bSDavid du Colombier if(font == 0)
1965*45e6af3bSDavid du Colombier error(Enodrawimage);
1966*45e6af3bSDavid du Colombier if(font->nfchar == 0)
1967*45e6af3bSDavid du Colombier error(Enotfont);
1968*45e6af3bSDavid du Colombier drawpoint(&p, a+13);
1969*45e6af3bSDavid du Colombier drawrectangle(&r, a+21);
1970*45e6af3bSDavid du Colombier drawpoint(&sp, a+37);
1971*45e6af3bSDavid du Colombier ni = BGSHORT(a+45);
1972*45e6af3bSDavid du Colombier u = a+m;
1973*45e6af3bSDavid du Colombier m += ni*2;
1974*45e6af3bSDavid du Colombier if(n < m)
1975*45e6af3bSDavid du Colombier error(Eshortdraw);
1976*45e6af3bSDavid du Colombier clipr = dst->clipr;
1977*45e6af3bSDavid du Colombier dst->clipr = r;
1978*45e6af3bSDavid du Colombier op = drawclientop(client);
1979*45e6af3bSDavid du Colombier bg = dst;
1980*45e6af3bSDavid du Colombier if(*a == 'x'){
1981*45e6af3bSDavid du Colombier /* paint background */
1982*45e6af3bSDavid du Colombier bg = drawimage(client, a+47);
1983*45e6af3bSDavid du Colombier drawpoint(&q, a+51);
1984*45e6af3bSDavid du Colombier r.min.x = p.x;
1985*45e6af3bSDavid du Colombier r.min.y = p.y-font->ascent;
1986*45e6af3bSDavid du Colombier r.max.x = p.x;
1987*45e6af3bSDavid du Colombier r.max.y = r.min.y+Dy(font->image->r);
1988*45e6af3bSDavid du Colombier j = ni;
1989*45e6af3bSDavid du Colombier while(--j >= 0){
1990*45e6af3bSDavid du Colombier ci = BGSHORT(u);
1991*45e6af3bSDavid du Colombier if(ci<0 || ci>=font->nfchar){
1992*45e6af3bSDavid du Colombier dst->clipr = clipr;
1993*45e6af3bSDavid du Colombier error(Eindex);
1994*45e6af3bSDavid du Colombier }
1995*45e6af3bSDavid du Colombier r.max.x += font->fchar[ci].width;
1996*45e6af3bSDavid du Colombier u += 2;
1997*45e6af3bSDavid du Colombier }
1998*45e6af3bSDavid du Colombier memdraw(dst, r, bg, q, memopaque, ZP, op);
1999*45e6af3bSDavid du Colombier u -= 2*ni;
2000*45e6af3bSDavid du Colombier }
2001*45e6af3bSDavid du Colombier q = p;
2002*45e6af3bSDavid du Colombier while(--ni >= 0){
2003*45e6af3bSDavid du Colombier ci = BGSHORT(u);
2004*45e6af3bSDavid du Colombier if(ci<0 || ci>=font->nfchar){
2005*45e6af3bSDavid du Colombier dst->clipr = clipr;
2006*45e6af3bSDavid du Colombier error(Eindex);
2007*45e6af3bSDavid du Colombier }
2008*45e6af3bSDavid du Colombier q = drawchar(dst, bg, q, src, &sp, font, ci, op);
2009*45e6af3bSDavid du Colombier u += 2;
2010*45e6af3bSDavid du Colombier }
2011*45e6af3bSDavid du Colombier dst->clipr = clipr;
2012*45e6af3bSDavid du Colombier p.y -= font->ascent;
2013*45e6af3bSDavid du Colombier dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
2014*45e6af3bSDavid du Colombier continue;
2015*45e6af3bSDavid du Colombier
2016*45e6af3bSDavid du Colombier /* use public screen: 'S' id[4] chan[4] */
2017*45e6af3bSDavid du Colombier case 'S':
2018*45e6af3bSDavid du Colombier printmesg(fmt="Ll", a, 0);
2019*45e6af3bSDavid du Colombier m = 1+4+4;
2020*45e6af3bSDavid du Colombier if(n < m)
2021*45e6af3bSDavid du Colombier error(Eshortdraw);
2022*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
2023*45e6af3bSDavid du Colombier if(dstid == 0)
2024*45e6af3bSDavid du Colombier error(Ebadarg);
2025*45e6af3bSDavid du Colombier dscrn = drawlookupdscreen(dstid);
2026*45e6af3bSDavid du Colombier if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client))
2027*45e6af3bSDavid du Colombier error(Enodrawscreen);
2028*45e6af3bSDavid du Colombier if(dscrn->screen->image->chan != BGLONG(a+5))
2029*45e6af3bSDavid du Colombier error("inconsistent chan");
2030*45e6af3bSDavid du Colombier if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0)
2031*45e6af3bSDavid du Colombier error(Edrawmem);
2032*45e6af3bSDavid du Colombier continue;
2033*45e6af3bSDavid du Colombier
2034*45e6af3bSDavid du Colombier /* top or bottom windows: 't' top[1] nw[2] n*id[4] */
2035*45e6af3bSDavid du Colombier case 't':
2036*45e6af3bSDavid du Colombier printmesg(fmt="bsL", a, 0);
2037*45e6af3bSDavid du Colombier m = 1+1+2;
2038*45e6af3bSDavid du Colombier if(n < m)
2039*45e6af3bSDavid du Colombier error(Eshortdraw);
2040*45e6af3bSDavid du Colombier nw = BGSHORT(a+2);
2041*45e6af3bSDavid du Colombier if(nw < 0)
2042*45e6af3bSDavid du Colombier error(Ebadarg);
2043*45e6af3bSDavid du Colombier if(nw == 0)
2044*45e6af3bSDavid du Colombier continue;
2045*45e6af3bSDavid du Colombier m += nw*4;
2046*45e6af3bSDavid du Colombier if(n < m)
2047*45e6af3bSDavid du Colombier error(Eshortdraw);
2048*45e6af3bSDavid du Colombier lp = malloc(nw*sizeof(Memimage*));
2049*45e6af3bSDavid du Colombier if(lp == 0)
2050*45e6af3bSDavid du Colombier error(Enomem);
2051*45e6af3bSDavid du Colombier if(waserror()){
2052*45e6af3bSDavid du Colombier free(lp);
2053*45e6af3bSDavid du Colombier nexterror();
2054*45e6af3bSDavid du Colombier }
2055*45e6af3bSDavid du Colombier for(j=0; j<nw; j++)
2056*45e6af3bSDavid du Colombier lp[j] = drawimage(client, a+1+1+2+j*4);
2057*45e6af3bSDavid du Colombier if(lp[0]->layer == 0)
2058*45e6af3bSDavid du Colombier error("images are not windows");
2059*45e6af3bSDavid du Colombier for(j=1; j<nw; j++)
2060*45e6af3bSDavid du Colombier if(lp[j]->layer->screen != lp[0]->layer->screen)
2061*45e6af3bSDavid du Colombier error("images not on same screen");
2062*45e6af3bSDavid du Colombier if(a[1])
2063*45e6af3bSDavid du Colombier memltofrontn(lp, nw);
2064*45e6af3bSDavid du Colombier else
2065*45e6af3bSDavid du Colombier memltorearn(lp, nw);
2066*45e6af3bSDavid du Colombier if(lp[0]->layer->screen->image->data == screenimage->data)
2067*45e6af3bSDavid du Colombier for(j=0; j<nw; j++)
2068*45e6af3bSDavid du Colombier addflush(lp[j]->layer->screenr);
2069*45e6af3bSDavid du Colombier ll = drawlookup(client, BGLONG(a+1+1+2), 1);
2070*45e6af3bSDavid du Colombier drawrefreshscreen(ll, client);
2071*45e6af3bSDavid du Colombier poperror();
2072*45e6af3bSDavid du Colombier free(lp);
2073*45e6af3bSDavid du Colombier continue;
2074*45e6af3bSDavid du Colombier
2075*45e6af3bSDavid du Colombier /* visible: 'v' */
2076*45e6af3bSDavid du Colombier case 'v':
2077*45e6af3bSDavid du Colombier printmesg(fmt="", a, 0);
2078*45e6af3bSDavid du Colombier m = 1;
2079*45e6af3bSDavid du Colombier drawflush();
2080*45e6af3bSDavid du Colombier continue;
2081*45e6af3bSDavid du Colombier
2082*45e6af3bSDavid du Colombier /* write: 'y' id[4] R[4*4] data[x*1] */
2083*45e6af3bSDavid du Colombier /* write from compressed data: 'Y' id[4] R[4*4] data[x*1] */
2084*45e6af3bSDavid du Colombier case 'y':
2085*45e6af3bSDavid du Colombier case 'Y':
2086*45e6af3bSDavid du Colombier printmesg(fmt="LR", a, 0);
2087*45e6af3bSDavid du Colombier // iprint("load %c\n", *a);
2088*45e6af3bSDavid du Colombier m = 1+4+4*4;
2089*45e6af3bSDavid du Colombier if(n < m)
2090*45e6af3bSDavid du Colombier error(Eshortdraw);
2091*45e6af3bSDavid du Colombier dstid = BGLONG(a+1);
2092*45e6af3bSDavid du Colombier dst = drawimage(client, a+1);
2093*45e6af3bSDavid du Colombier drawrectangle(&r, a+5);
2094*45e6af3bSDavid du Colombier if(!rectinrect(r, dst->r))
2095*45e6af3bSDavid du Colombier error(Ewriteoutside);
2096*45e6af3bSDavid du Colombier y = memload(dst, r, a+m, n-m, *a=='Y');
2097*45e6af3bSDavid du Colombier if(y < 0)
2098*45e6af3bSDavid du Colombier error("bad writeimage call");
2099*45e6af3bSDavid du Colombier dstflush(dstid, dst, r);
2100*45e6af3bSDavid du Colombier m += y;
2101*45e6af3bSDavid du Colombier continue;
2102*45e6af3bSDavid du Colombier }
2103*45e6af3bSDavid du Colombier }
2104*45e6af3bSDavid du Colombier poperror();
2105*45e6af3bSDavid du Colombier }
2106*45e6af3bSDavid du Colombier
2107*45e6af3bSDavid du Colombier Dev drawdevtab = {
2108*45e6af3bSDavid du Colombier 'i',
2109*45e6af3bSDavid du Colombier "draw",
2110*45e6af3bSDavid du Colombier
2111*45e6af3bSDavid du Colombier devreset,
2112*45e6af3bSDavid du Colombier devinit,
2113*45e6af3bSDavid du Colombier devshutdown,
2114*45e6af3bSDavid du Colombier drawattach,
2115*45e6af3bSDavid du Colombier drawwalk,
2116*45e6af3bSDavid du Colombier drawstat,
2117*45e6af3bSDavid du Colombier drawopen,
2118*45e6af3bSDavid du Colombier devcreate,
2119*45e6af3bSDavid du Colombier drawclose,
2120*45e6af3bSDavid du Colombier drawread,
2121*45e6af3bSDavid du Colombier devbread,
2122*45e6af3bSDavid du Colombier drawwrite,
2123*45e6af3bSDavid du Colombier devbwrite,
2124*45e6af3bSDavid du Colombier devremove,
2125*45e6af3bSDavid du Colombier devwstat,
2126*45e6af3bSDavid du Colombier };
2127*45e6af3bSDavid du Colombier
2128*45e6af3bSDavid du Colombier /*
2129*45e6af3bSDavid du Colombier * On 8 bit displays, load the default color map
2130*45e6af3bSDavid du Colombier */
2131*45e6af3bSDavid du Colombier void
drawcmap(void)2132*45e6af3bSDavid du Colombier drawcmap(void)
2133*45e6af3bSDavid du Colombier {
2134*45e6af3bSDavid du Colombier int r, g, b, cr, cg, cb, v;
2135*45e6af3bSDavid du Colombier int num, den;
2136*45e6af3bSDavid du Colombier int i, j;
2137*45e6af3bSDavid du Colombier
2138*45e6af3bSDavid du Colombier drawactive(1); /* to restore map from backup */
2139*45e6af3bSDavid du Colombier for(r=0,i=0; r!=4; r++)
2140*45e6af3bSDavid du Colombier for(v=0; v!=4; v++,i+=16){
2141*45e6af3bSDavid du Colombier for(g=0,j=v-r; g!=4; g++)
2142*45e6af3bSDavid du Colombier for(b=0;b!=4;b++,j++){
2143*45e6af3bSDavid du Colombier den = r;
2144*45e6af3bSDavid du Colombier if(g > den)
2145*45e6af3bSDavid du Colombier den = g;
2146*45e6af3bSDavid du Colombier if(b > den)
2147*45e6af3bSDavid du Colombier den = b;
2148*45e6af3bSDavid du Colombier if(den == 0) /* divide check -- pick grey shades */
2149*45e6af3bSDavid du Colombier cr = cg = cb = v*17;
2150*45e6af3bSDavid du Colombier else{
2151*45e6af3bSDavid du Colombier num = 17*(4*den+v);
2152*45e6af3bSDavid du Colombier cr = r*num/den;
2153*45e6af3bSDavid du Colombier cg = g*num/den;
2154*45e6af3bSDavid du Colombier cb = b*num/den;
2155*45e6af3bSDavid du Colombier }
2156*45e6af3bSDavid du Colombier setcolor(i+(j&15),
2157*45e6af3bSDavid du Colombier cr*0x01010101, cg*0x01010101, cb*0x01010101);
2158*45e6af3bSDavid du Colombier }
2159*45e6af3bSDavid du Colombier }
2160*45e6af3bSDavid du Colombier }
2161*45e6af3bSDavid du Colombier
2162*45e6af3bSDavid du Colombier void
drawblankscreen(int blank)2163*45e6af3bSDavid du Colombier drawblankscreen(int blank)
2164*45e6af3bSDavid du Colombier {
2165*45e6af3bSDavid du Colombier int i, nc;
2166*45e6af3bSDavid du Colombier ulong *p;
2167*45e6af3bSDavid du Colombier
2168*45e6af3bSDavid du Colombier if(blank == sdraw.blanked)
2169*45e6af3bSDavid du Colombier return;
2170*45e6af3bSDavid du Colombier if(!candlock())
2171*45e6af3bSDavid du Colombier return;
2172*45e6af3bSDavid du Colombier if(screenimage == nil){
2173*45e6af3bSDavid du Colombier dunlock();
2174*45e6af3bSDavid du Colombier return;
2175*45e6af3bSDavid du Colombier }
2176*45e6af3bSDavid du Colombier p = sdraw.savemap;
2177*45e6af3bSDavid du Colombier nc = screenimage->depth > 8 ? 256 : 1<<screenimage->depth;
2178*45e6af3bSDavid du Colombier
2179*45e6af3bSDavid du Colombier /*
2180*45e6af3bSDavid du Colombier * blankscreen uses the hardware to blank the screen
2181*45e6af3bSDavid du Colombier * when possible. to help in cases when it is not possible,
2182*45e6af3bSDavid du Colombier * we set the color map to be all black.
2183*45e6af3bSDavid du Colombier */
2184*45e6af3bSDavid du Colombier if(blank == 0){ /* turn screen on */
2185*45e6af3bSDavid du Colombier for(i=0; i<nc; i++, p+=3)
2186*45e6af3bSDavid du Colombier setcolor(i, p[0], p[1], p[2]);
2187*45e6af3bSDavid du Colombier blankscreen(0);
2188*45e6af3bSDavid du Colombier }else{ /* turn screen off */
2189*45e6af3bSDavid du Colombier blankscreen(1);
2190*45e6af3bSDavid du Colombier for(i=0; i<nc; i++, p+=3){
2191*45e6af3bSDavid du Colombier getcolor(i, &p[0], &p[1], &p[2]);
2192*45e6af3bSDavid du Colombier setcolor(i, 0, 0, 0);
2193*45e6af3bSDavid du Colombier }
2194*45e6af3bSDavid du Colombier }
2195*45e6af3bSDavid du Colombier sdraw.blanked = blank;
2196*45e6af3bSDavid du Colombier dunlock();
2197*45e6af3bSDavid du Colombier }
2198*45e6af3bSDavid du Colombier
2199*45e6af3bSDavid du Colombier /*
2200*45e6af3bSDavid du Colombier * record activity on screen, changing blanking as appropriate
2201*45e6af3bSDavid du Colombier */
2202*45e6af3bSDavid du Colombier void
drawactive(int active)2203*45e6af3bSDavid du Colombier drawactive(int active)
2204*45e6af3bSDavid du Colombier {
2205*45e6af3bSDavid du Colombier if(active){
2206*45e6af3bSDavid du Colombier drawblankscreen(0);
2207*45e6af3bSDavid du Colombier sdraw.blanktime = sys->ticks;
2208*45e6af3bSDavid du Colombier }else{
2209*45e6af3bSDavid du Colombier if(blanktime && sdraw.blanktime && TK2SEC(sys->ticks - sdraw.blanktime)/60 >= blanktime)
2210*45e6af3bSDavid du Colombier drawblankscreen(1);
2211*45e6af3bSDavid du Colombier }
2212*45e6af3bSDavid du Colombier }
2213*45e6af3bSDavid du Colombier
2214*45e6af3bSDavid du Colombier int
drawidletime(void)2215*45e6af3bSDavid du Colombier drawidletime(void)
2216*45e6af3bSDavid du Colombier {
2217*45e6af3bSDavid du Colombier return TK2SEC(sys->ticks - sdraw.blanktime)/60;
2218*45e6af3bSDavid du Colombier }
2219