19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include "compat.h"
49a747e4fSDavid du Colombier #include "error.h"
59a747e4fSDavid du Colombier
69a747e4fSDavid du Colombier #define Image IMAGE
79a747e4fSDavid du Colombier #include <draw.h>
89a747e4fSDavid du Colombier #include <memdraw.h>
99a747e4fSDavid du Colombier #include <memlayer.h>
109a747e4fSDavid du Colombier #include <cursor.h>
119a747e4fSDavid du Colombier #include "screen.h"
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier enum
149a747e4fSDavid du Colombier {
159a747e4fSDavid du Colombier Qtopdir = 0,
169a747e4fSDavid du Colombier Qnew,
179a747e4fSDavid du Colombier Q3rd,
189a747e4fSDavid du Colombier Q2nd,
199a747e4fSDavid du Colombier Qcolormap,
209a747e4fSDavid du Colombier Qctl,
219a747e4fSDavid du Colombier Qdata,
229a747e4fSDavid du Colombier Qrefresh,
239a747e4fSDavid du Colombier };
249a747e4fSDavid du Colombier
259a747e4fSDavid du Colombier /*
269a747e4fSDavid du Colombier * Qid path is:
279a747e4fSDavid du Colombier * 4 bits of file type (qids above)
289a747e4fSDavid du Colombier * 24 bits of mux slot number +1; 0 means not attached to client
299a747e4fSDavid du Colombier */
309a747e4fSDavid du Colombier #define QSHIFT 4 /* location in qid of client # */
319a747e4fSDavid du Colombier
329a747e4fSDavid du Colombier #define QID(q) ((((ulong)(q).path)&0x0000000F)>>0)
339a747e4fSDavid du Colombier #define CLIENTPATH(q) ((((ulong)q)&0x7FFFFFF0)>>QSHIFT)
349a747e4fSDavid du Colombier #define CLIENT(q) CLIENTPATH((q).path)
359a747e4fSDavid du Colombier
369a747e4fSDavid du Colombier #define NHASH (1<<5)
379a747e4fSDavid du Colombier #define HASHMASK (NHASH-1)
389a747e4fSDavid du Colombier
399a747e4fSDavid du Colombier typedef struct Client Client;
409a747e4fSDavid du Colombier typedef struct Draw Draw;
419a747e4fSDavid du Colombier typedef struct DImage DImage;
429a747e4fSDavid du Colombier typedef struct DScreen DScreen;
439a747e4fSDavid du Colombier typedef struct CScreen CScreen;
449a747e4fSDavid du Colombier typedef struct FChar FChar;
459a747e4fSDavid du Colombier typedef struct Refresh Refresh;
469a747e4fSDavid du Colombier typedef struct Refx Refx;
479a747e4fSDavid du Colombier typedef struct DName DName;
489a747e4fSDavid du Colombier
499a747e4fSDavid du Colombier ulong blanktime = 30; /* in minutes; a half hour */
509a747e4fSDavid du Colombier
519a747e4fSDavid du Colombier struct Draw
529a747e4fSDavid du Colombier {
539a747e4fSDavid du Colombier QLock;
549a747e4fSDavid du Colombier int clientid;
559a747e4fSDavid du Colombier int nclient;
569a747e4fSDavid du Colombier Client** client;
579a747e4fSDavid du Colombier int nname;
589a747e4fSDavid du Colombier DName* name;
599a747e4fSDavid du Colombier int vers;
609a747e4fSDavid du Colombier int softscreen;
619a747e4fSDavid du Colombier int blanked; /* screen turned off */
629a747e4fSDavid du Colombier ulong blanktime; /* time of last operation */
639a747e4fSDavid du Colombier ulong savemap[3*256];
649a747e4fSDavid du Colombier };
659a747e4fSDavid du Colombier
669a747e4fSDavid du Colombier struct Client
679a747e4fSDavid du Colombier {
689a747e4fSDavid du Colombier Ref r;
699a747e4fSDavid du Colombier DImage* dimage[NHASH];
709a747e4fSDavid du Colombier CScreen* cscreen;
719a747e4fSDavid du Colombier Refresh* refresh;
729a747e4fSDavid du Colombier Rendez refrend;
739a747e4fSDavid du Colombier uchar* readdata;
749a747e4fSDavid du Colombier int nreaddata;
759a747e4fSDavid du Colombier int busy;
769a747e4fSDavid du Colombier int clientid;
779a747e4fSDavid du Colombier int slot;
789a747e4fSDavid du Colombier int refreshme;
799a747e4fSDavid du Colombier int infoid;
806a9fc400SDavid du Colombier int op;
819a747e4fSDavid du Colombier };
829a747e4fSDavid du Colombier
839a747e4fSDavid du Colombier struct Refresh
849a747e4fSDavid du Colombier {
859a747e4fSDavid du Colombier DImage* dimage;
869a747e4fSDavid du Colombier Rectangle r;
879a747e4fSDavid du Colombier Refresh* next;
889a747e4fSDavid du Colombier };
899a747e4fSDavid du Colombier
909a747e4fSDavid du Colombier struct Refx
919a747e4fSDavid du Colombier {
929a747e4fSDavid du Colombier Client* client;
939a747e4fSDavid du Colombier DImage* dimage;
949a747e4fSDavid du Colombier };
959a747e4fSDavid du Colombier
969a747e4fSDavid du Colombier struct DName
979a747e4fSDavid du Colombier {
989a747e4fSDavid du Colombier char *name;
999a747e4fSDavid du Colombier Client *client;
1009a747e4fSDavid du Colombier DImage* dimage;
1019a747e4fSDavid du Colombier int vers;
1029a747e4fSDavid du Colombier };
1039a747e4fSDavid du Colombier
1049a747e4fSDavid du Colombier struct FChar
1059a747e4fSDavid du Colombier {
1069a747e4fSDavid du Colombier int minx; /* left edge of bits */
1079a747e4fSDavid du Colombier int maxx; /* right edge of bits */
1089a747e4fSDavid du Colombier uchar miny; /* first non-zero scan-line */
1099a747e4fSDavid du Colombier uchar maxy; /* last non-zero scan-line + 1 */
1109a747e4fSDavid du Colombier schar left; /* offset of baseline */
1119a747e4fSDavid du Colombier uchar width; /* width of baseline */
1129a747e4fSDavid du Colombier };
1139a747e4fSDavid du Colombier
1149a747e4fSDavid du Colombier /*
1159a747e4fSDavid du Colombier * Reference counts in DImages:
1169a747e4fSDavid du Colombier * one per open by original client
1179a747e4fSDavid du Colombier * one per screen image or fill
1189a747e4fSDavid du Colombier * one per image derived from this one by name
1199a747e4fSDavid du Colombier */
1209a747e4fSDavid du Colombier struct DImage
1219a747e4fSDavid du Colombier {
1229a747e4fSDavid du Colombier int id;
1239a747e4fSDavid du Colombier int ref;
1249a747e4fSDavid du Colombier char *name;
1259a747e4fSDavid du Colombier int vers;
1269a747e4fSDavid du Colombier Memimage* image;
1279a747e4fSDavid du Colombier int ascent;
1289a747e4fSDavid du Colombier int nfchar;
1299a747e4fSDavid du Colombier FChar* fchar;
1309a747e4fSDavid du Colombier DScreen* dscreen; /* 0 if not a window */
1319a747e4fSDavid du Colombier DImage* fromname; /* image this one is derived from, by name */
1329a747e4fSDavid du Colombier DImage* next;
1339a747e4fSDavid du Colombier };
1349a747e4fSDavid du Colombier
1359a747e4fSDavid du Colombier struct CScreen
1369a747e4fSDavid du Colombier {
1379a747e4fSDavid du Colombier DScreen* dscreen;
1389a747e4fSDavid du Colombier CScreen* next;
1399a747e4fSDavid du Colombier };
1409a747e4fSDavid du Colombier
1419a747e4fSDavid du Colombier struct DScreen
1429a747e4fSDavid du Colombier {
1439a747e4fSDavid du Colombier int id;
1449a747e4fSDavid du Colombier int public;
1459a747e4fSDavid du Colombier int ref;
1469a747e4fSDavid du Colombier DImage *dimage;
1479a747e4fSDavid du Colombier DImage *dfill;
1489a747e4fSDavid du Colombier Memscreen* screen;
1499a747e4fSDavid du Colombier Client* owner;
1509a747e4fSDavid du Colombier DScreen* next;
1519a747e4fSDavid du Colombier };
1529a747e4fSDavid du Colombier
1539a747e4fSDavid du Colombier static Draw sdraw;
1549a747e4fSDavid du Colombier static Memimage *screenimage;
1559a747e4fSDavid du Colombier static Memdata screendata;
1569a747e4fSDavid du Colombier static Rectangle flushrect;
1579a747e4fSDavid du Colombier static int waste;
1589a747e4fSDavid du Colombier static DScreen* dscreen;
1599a747e4fSDavid du Colombier extern void flushmemscreen(Rectangle);
1609a747e4fSDavid du Colombier void drawmesg(Client*, void*, int);
1619a747e4fSDavid du Colombier void drawuninstall(Client*, int);
1629a747e4fSDavid du Colombier void drawfreedimage(DImage*);
1639a747e4fSDavid du Colombier Client* drawclientofpath(ulong);
1649a747e4fSDavid du Colombier
1659a747e4fSDavid du Colombier static char Enodrawimage[] = "unknown id for draw image";
1669a747e4fSDavid du Colombier static char Enodrawscreen[] = "unknown id for draw screen";
1679a747e4fSDavid du Colombier static char Eshortdraw[] = "short draw message";
1689a747e4fSDavid du Colombier static char Eshortread[] = "draw read too short";
1699a747e4fSDavid du Colombier static char Eimageexists[] = "image id in use";
1709a747e4fSDavid du Colombier static char Escreenexists[] = "screen id in use";
1719a747e4fSDavid du Colombier static char Edrawmem[] = "image memory allocation failed";
1729a747e4fSDavid du Colombier static char Ereadoutside[] = "readimage outside image";
1739a747e4fSDavid du Colombier static char Ewriteoutside[] = "writeimage outside image";
1749a747e4fSDavid du Colombier static char Enotfont[] = "image not a font";
1759a747e4fSDavid du Colombier static char Eindex[] = "character index out of range";
1769a747e4fSDavid du Colombier static char Enoclient[] = "no such draw client";
1779a747e4fSDavid du Colombier static char Edepth[] = "image has bad depth";
1789a747e4fSDavid du Colombier static char Enameused[] = "image name in use";
1799a747e4fSDavid du Colombier static char Enoname[] = "no image with that name";
1809a747e4fSDavid du Colombier static char Eoldname[] = "named image no longer valid";
1819a747e4fSDavid du Colombier static char Enamed[] = "image already has name";
1829a747e4fSDavid du Colombier static char Ewrongname[] = "wrong name for image";
1839a747e4fSDavid du Colombier
1849a747e4fSDavid du Colombier void
drawlock(void)1859a747e4fSDavid du Colombier drawlock(void)
1869a747e4fSDavid du Colombier {
1879a747e4fSDavid du Colombier qlock(&sdraw);
1889a747e4fSDavid du Colombier }
1899a747e4fSDavid du Colombier
1909a747e4fSDavid du Colombier void
drawunlock(void)1919a747e4fSDavid du Colombier drawunlock(void)
1929a747e4fSDavid du Colombier {
1939a747e4fSDavid du Colombier qunlock(&sdraw);
1949a747e4fSDavid du Colombier }
1959a747e4fSDavid du Colombier
1969a747e4fSDavid du Colombier int
candrawlock(void)1979a747e4fSDavid du Colombier candrawlock(void)
1989a747e4fSDavid du Colombier {
1999a747e4fSDavid du Colombier return canqlock(&sdraw);
2009a747e4fSDavid du Colombier }
2019a747e4fSDavid du Colombier
2029a747e4fSDavid du Colombier static int
drawgen(Chan * c,Dirtab *,int,int s,Dir * dp)2039a747e4fSDavid du Colombier drawgen(Chan *c, Dirtab*, int, int s, Dir *dp)
2049a747e4fSDavid du Colombier {
2059a747e4fSDavid du Colombier int t;
2069a747e4fSDavid du Colombier Qid q;
2079a747e4fSDavid du Colombier ulong path;
2089a747e4fSDavid du Colombier Client *cl;
2099a747e4fSDavid du Colombier
2109a747e4fSDavid du Colombier q.vers = 0;
2119a747e4fSDavid du Colombier
2129a747e4fSDavid du Colombier if(s == DEVDOTDOT){
2139a747e4fSDavid du Colombier switch(QID(c->qid)){
2149a747e4fSDavid du Colombier case Qtopdir:
2159a747e4fSDavid du Colombier case Q2nd:
2169a747e4fSDavid du Colombier mkqid(&q, Qtopdir, 0, QTDIR);
2179a747e4fSDavid du Colombier devdir(c, q, "#i", 0, eve, 0500, dp);
2189a747e4fSDavid du Colombier break;
2199a747e4fSDavid du Colombier case Q3rd:
2209a747e4fSDavid du Colombier cl = drawclientofpath(c->qid.path);
2219a747e4fSDavid du Colombier if(cl == nil)
2229a747e4fSDavid du Colombier strcpy(up->genbuf, "??");
2239a747e4fSDavid du Colombier else
2249a747e4fSDavid du Colombier sprint(up->genbuf, "%d", cl->clientid);
2259a747e4fSDavid du Colombier mkqid(&q, Q2nd, 0, QTDIR);
2269a747e4fSDavid du Colombier devdir(c, q, up->genbuf, 0, eve, 0500, dp);
2279a747e4fSDavid du Colombier break;
2289a747e4fSDavid du Colombier default:
229*74f16c81SDavid du Colombier panic("drawwalk %#llux", c->qid.path);
2309a747e4fSDavid du Colombier }
2319a747e4fSDavid du Colombier return 1;
2329a747e4fSDavid du Colombier }
2339a747e4fSDavid du Colombier
2349a747e4fSDavid du Colombier /*
2359a747e4fSDavid du Colombier * Top level directory contains the name of the device.
2369a747e4fSDavid du Colombier */
2379a747e4fSDavid du Colombier t = QID(c->qid);
2389a747e4fSDavid du Colombier if(t == Qtopdir){
2399a747e4fSDavid du Colombier switch(s){
2409a747e4fSDavid du Colombier case 0:
2419a747e4fSDavid du Colombier mkqid(&q, Q2nd, 0, QTDIR);
2429a747e4fSDavid du Colombier devdir(c, q, "draw", 0, eve, 0555, dp);
2439a747e4fSDavid du Colombier break;
2449a747e4fSDavid du Colombier default:
2459a747e4fSDavid du Colombier return -1;
2469a747e4fSDavid du Colombier }
2479a747e4fSDavid du Colombier return 1;
2489a747e4fSDavid du Colombier }
2499a747e4fSDavid du Colombier
2509a747e4fSDavid du Colombier /*
2519a747e4fSDavid du Colombier * Second level contains "new" plus all the clients.
2529a747e4fSDavid du Colombier */
2539a747e4fSDavid du Colombier if(t == Q2nd || t == Qnew){
2549a747e4fSDavid du Colombier if(s == 0){
2559a747e4fSDavid du Colombier mkqid(&q, Qnew, 0, QTFILE);
2569a747e4fSDavid du Colombier devdir(c, q, "new", 0, eve, 0666, dp);
2579a747e4fSDavid du Colombier }
2589a747e4fSDavid du Colombier else if(s <= sdraw.nclient){
2599a747e4fSDavid du Colombier cl = sdraw.client[s-1];
2609a747e4fSDavid du Colombier if(cl == 0)
2619a747e4fSDavid du Colombier return 0;
2629a747e4fSDavid du Colombier sprint(up->genbuf, "%d", cl->clientid);
2639a747e4fSDavid du Colombier mkqid(&q, (s<<QSHIFT)|Q3rd, 0, QTDIR);
2649a747e4fSDavid du Colombier devdir(c, q, up->genbuf, 0, eve, 0555, dp);
2659a747e4fSDavid du Colombier return 1;
2669a747e4fSDavid du Colombier }
2679a747e4fSDavid du Colombier else
2689a747e4fSDavid du Colombier return -1;
2699a747e4fSDavid du Colombier return 1;
2709a747e4fSDavid du Colombier }
2719a747e4fSDavid du Colombier
2729a747e4fSDavid du Colombier /*
2739a747e4fSDavid du Colombier * Third level.
2749a747e4fSDavid du Colombier */
2759a747e4fSDavid du Colombier path = c->qid.path&~(((1<<QSHIFT)-1)); /* slot component */
2769a747e4fSDavid du Colombier q.vers = c->qid.vers;
2779a747e4fSDavid du Colombier q.type = QTFILE;
2789a747e4fSDavid du Colombier switch(s){
2799a747e4fSDavid du Colombier case 0:
2809a747e4fSDavid du Colombier q.path = path|Qcolormap;
2819a747e4fSDavid du Colombier devdir(c, q, "colormap", 0, eve, 0600, dp);
2829a747e4fSDavid du Colombier break;
2839a747e4fSDavid du Colombier case 1:
2849a747e4fSDavid du Colombier q.path = path|Qctl;
2859a747e4fSDavid du Colombier devdir(c, q, "ctl", 0, eve, 0600, dp);
2869a747e4fSDavid du Colombier break;
2879a747e4fSDavid du Colombier case 2:
2889a747e4fSDavid du Colombier q.path = path|Qdata;
2899a747e4fSDavid du Colombier devdir(c, q, "data", 0, eve, 0600, dp);
2909a747e4fSDavid du Colombier break;
2919a747e4fSDavid du Colombier case 3:
2929a747e4fSDavid du Colombier q.path = path|Qrefresh;
2939a747e4fSDavid du Colombier devdir(c, q, "refresh", 0, eve, 0400, dp);
2949a747e4fSDavid du Colombier break;
2959a747e4fSDavid du Colombier default:
2969a747e4fSDavid du Colombier return -1;
2979a747e4fSDavid du Colombier }
2989a747e4fSDavid du Colombier return 1;
2999a747e4fSDavid du Colombier }
3009a747e4fSDavid du Colombier
3019a747e4fSDavid du Colombier static
3029a747e4fSDavid du Colombier int
drawrefactive(void * a)3039a747e4fSDavid du Colombier drawrefactive(void *a)
3049a747e4fSDavid du Colombier {
3059a747e4fSDavid du Colombier Client *c;
3069a747e4fSDavid du Colombier
3079a747e4fSDavid du Colombier c = a;
3089a747e4fSDavid du Colombier return c->refreshme || c->refresh!=0;
3099a747e4fSDavid du Colombier }
3109a747e4fSDavid du Colombier
3119a747e4fSDavid du Colombier static
3129a747e4fSDavid du Colombier void
drawrefreshscreen(DImage * l,Client * client)3139a747e4fSDavid du Colombier drawrefreshscreen(DImage *l, Client *client)
3149a747e4fSDavid du Colombier {
3159a747e4fSDavid du Colombier while(l != nil && l->dscreen == nil)
3169a747e4fSDavid du Colombier l = l->fromname;
3179a747e4fSDavid du Colombier if(l != nil && l->dscreen->owner != client)
3189a747e4fSDavid du Colombier l->dscreen->owner->refreshme = 1;
3199a747e4fSDavid du Colombier }
3209a747e4fSDavid du Colombier
3219a747e4fSDavid du Colombier static
3229a747e4fSDavid du Colombier void
drawrefresh(Memimage * l,Rectangle r,void * v)3239a747e4fSDavid du Colombier drawrefresh(Memimage *l, Rectangle r, void *v)
3249a747e4fSDavid du Colombier {
3259a747e4fSDavid du Colombier Refx *x;
3269a747e4fSDavid du Colombier DImage *d;
3279a747e4fSDavid du Colombier Client *c;
3289a747e4fSDavid du Colombier Refresh *ref;
3299a747e4fSDavid du Colombier
3309a747e4fSDavid du Colombier USED(l);
3319a747e4fSDavid du Colombier if(v == 0)
3329a747e4fSDavid du Colombier return;
3339a747e4fSDavid du Colombier x = v;
3349a747e4fSDavid du Colombier c = x->client;
3359a747e4fSDavid du Colombier d = x->dimage;
3369a747e4fSDavid du Colombier for(ref=c->refresh; ref; ref=ref->next)
3379a747e4fSDavid du Colombier if(ref->dimage == d){
3389a747e4fSDavid du Colombier combinerect(&ref->r, r);
3399a747e4fSDavid du Colombier return;
3409a747e4fSDavid du Colombier }
3419a747e4fSDavid du Colombier ref = malloc(sizeof(Refresh));
3429a747e4fSDavid du Colombier if(ref){
3439a747e4fSDavid du Colombier ref->dimage = d;
3449a747e4fSDavid du Colombier ref->r = r;
3459a747e4fSDavid du Colombier ref->next = c->refresh;
3469a747e4fSDavid du Colombier c->refresh = ref;
3479a747e4fSDavid du Colombier }
3489a747e4fSDavid du Colombier }
3499a747e4fSDavid du Colombier
3509a747e4fSDavid du Colombier static void
addflush(Rectangle r)3519a747e4fSDavid du Colombier addflush(Rectangle r)
3529a747e4fSDavid du Colombier {
3539a747e4fSDavid du Colombier int abb, ar, anbb;
3549a747e4fSDavid du Colombier Rectangle nbb;
3559a747e4fSDavid du Colombier
3569a747e4fSDavid du Colombier if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))
3579a747e4fSDavid du Colombier return;
3589a747e4fSDavid du Colombier
3599a747e4fSDavid du Colombier if(flushrect.min.x >= flushrect.max.x){
3609a747e4fSDavid du Colombier flushrect = r;
3619a747e4fSDavid du Colombier waste = 0;
3629a747e4fSDavid du Colombier return;
3639a747e4fSDavid du Colombier }
3649a747e4fSDavid du Colombier /* VNC uses a region to compute the minimum bounding area.
3659a747e4fSDavid du Colombier * The waste is far less than that of a bounding box. see region.c
3669a747e4fSDavid du Colombier */
3679a747e4fSDavid du Colombier if(1){
3689a747e4fSDavid du Colombier flushmemscreen(flushrect);
3699a747e4fSDavid du Colombier flushrect = r;
3709a747e4fSDavid du Colombier return;
3719a747e4fSDavid du Colombier }
3729a747e4fSDavid du Colombier nbb = flushrect;
3739a747e4fSDavid du Colombier combinerect(&nbb, r);
3749a747e4fSDavid du Colombier ar = Dx(r)*Dy(r);
3759a747e4fSDavid du Colombier abb = Dx(flushrect)*Dy(flushrect);
3769a747e4fSDavid du Colombier anbb = Dx(nbb)*Dy(nbb);
3779a747e4fSDavid du Colombier /*
3789a747e4fSDavid du Colombier * Area of new waste is area of new bb minus area of old bb,
3799a747e4fSDavid du Colombier * less the area of the new segment, which we assume is not waste.
3809a747e4fSDavid du Colombier * This could be negative, but that's OK.
3819a747e4fSDavid du Colombier */
3829a747e4fSDavid du Colombier waste += anbb-abb - ar;
3839a747e4fSDavid du Colombier if(waste < 0)
3849a747e4fSDavid du Colombier waste = 0;
3859a747e4fSDavid du Colombier /*
3869a747e4fSDavid du Colombier * absorb if:
3879a747e4fSDavid du Colombier * total area is small
3889a747e4fSDavid du Colombier * waste is less than half total area
3899a747e4fSDavid du Colombier * rectangles touch
3909a747e4fSDavid du Colombier */
3919a747e4fSDavid du Colombier if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){
3929a747e4fSDavid du Colombier flushrect = nbb;
3939a747e4fSDavid du Colombier return;
3949a747e4fSDavid du Colombier }
3959a747e4fSDavid du Colombier /* emit current state */
3969a747e4fSDavid du Colombier flushmemscreen(flushrect);
3979a747e4fSDavid du Colombier flushrect = r;
3989a747e4fSDavid du Colombier waste = 0;
3999a747e4fSDavid du Colombier }
4009a747e4fSDavid du Colombier
4019a747e4fSDavid du Colombier static
4029a747e4fSDavid du Colombier void
dstflush(int dstid,Memimage * dst,Rectangle r)4039a747e4fSDavid du Colombier dstflush(int dstid, Memimage *dst, Rectangle r)
4049a747e4fSDavid du Colombier {
4059a747e4fSDavid du Colombier Memlayer *l;
4069a747e4fSDavid du Colombier
4079a747e4fSDavid du Colombier if(dstid == 0){
4089a747e4fSDavid du Colombier //combinerect(&flushrect, r);
4099a747e4fSDavid du Colombier addflush(r); // for VNC, see comments in addflush
4109a747e4fSDavid du Colombier return;
4119a747e4fSDavid du Colombier }
4129a747e4fSDavid du Colombier l = dst->layer;
4139a747e4fSDavid du Colombier if(l == nil)
4149a747e4fSDavid du Colombier return;
4159a747e4fSDavid du Colombier do{
4169a747e4fSDavid du Colombier if(l->screen->image->data != screenimage->data)
4179a747e4fSDavid du Colombier return;
4189a747e4fSDavid du Colombier r = rectaddpt(r, l->delta);
4199a747e4fSDavid du Colombier l = l->screen->image->layer;
4209a747e4fSDavid du Colombier }while(l);
4219a747e4fSDavid du Colombier addflush(r);
4229a747e4fSDavid du Colombier }
4239a747e4fSDavid du Colombier
4249a747e4fSDavid du Colombier static
4259a747e4fSDavid du Colombier void
drawflush(void)4269a747e4fSDavid du Colombier drawflush(void)
4279a747e4fSDavid du Colombier {
4289a747e4fSDavid du Colombier flushmemscreen(flushrect);
4299a747e4fSDavid du Colombier flushrect = Rect(10000, 10000, -10000, -10000);
4309a747e4fSDavid du Colombier }
4319a747e4fSDavid du Colombier
4329a747e4fSDavid du Colombier static
4339a747e4fSDavid du Colombier int
drawcmp(char * a,char * b,int n)4349a747e4fSDavid du Colombier drawcmp(char *a, char *b, int n)
4359a747e4fSDavid du Colombier {
4369a747e4fSDavid du Colombier if(strlen(a) != n)
4379a747e4fSDavid du Colombier return 1;
4389a747e4fSDavid du Colombier return memcmp(a, b, n);
4399a747e4fSDavid du Colombier }
4409a747e4fSDavid du Colombier
4419a747e4fSDavid du Colombier DName*
drawlookupname(int n,char * str)4429a747e4fSDavid du Colombier drawlookupname(int n, char *str)
4439a747e4fSDavid du Colombier {
4449a747e4fSDavid du Colombier DName *name, *ename;
4459a747e4fSDavid du Colombier
4469a747e4fSDavid du Colombier name = sdraw.name;
4479a747e4fSDavid du Colombier ename = &name[sdraw.nname];
4489a747e4fSDavid du Colombier for(; name<ename; name++)
4499a747e4fSDavid du Colombier if(drawcmp(name->name, str, n) == 0)
4509a747e4fSDavid du Colombier return name;
4519a747e4fSDavid du Colombier return 0;
4529a747e4fSDavid du Colombier }
4539a747e4fSDavid du Colombier
4549a747e4fSDavid du Colombier int
drawgoodname(DImage * d)4559a747e4fSDavid du Colombier drawgoodname(DImage *d)
4569a747e4fSDavid du Colombier {
4579a747e4fSDavid du Colombier DName *n;
4589a747e4fSDavid du Colombier
4599a747e4fSDavid du Colombier /* if window, validate the screen's own images */
4609a747e4fSDavid du Colombier if(d->dscreen)
4619a747e4fSDavid du Colombier if(drawgoodname(d->dscreen->dimage) == 0
4629a747e4fSDavid du Colombier || drawgoodname(d->dscreen->dfill) == 0)
4639a747e4fSDavid du Colombier return 0;
4649a747e4fSDavid du Colombier if(d->name == nil)
4659a747e4fSDavid du Colombier return 1;
4669a747e4fSDavid du Colombier n = drawlookupname(strlen(d->name), d->name);
4679a747e4fSDavid du Colombier if(n==nil || n->vers!=d->vers)
4689a747e4fSDavid du Colombier return 0;
4699a747e4fSDavid du Colombier return 1;
4709a747e4fSDavid du Colombier }
4719a747e4fSDavid du Colombier
4729a747e4fSDavid du Colombier DImage*
drawlookup(Client * client,int id,int checkname)4739a747e4fSDavid du Colombier drawlookup(Client *client, int id, int checkname)
4749a747e4fSDavid du Colombier {
4759a747e4fSDavid du Colombier DImage *d;
4769a747e4fSDavid du Colombier
4779a747e4fSDavid du Colombier d = client->dimage[id&HASHMASK];
4789a747e4fSDavid du Colombier while(d){
4799a747e4fSDavid du Colombier if(d->id == id){
4809a747e4fSDavid du Colombier if(checkname && !drawgoodname(d))
4819a747e4fSDavid du Colombier error(Eoldname);
4829a747e4fSDavid du Colombier return d;
4839a747e4fSDavid du Colombier }
4849a747e4fSDavid du Colombier d = d->next;
4859a747e4fSDavid du Colombier }
4869a747e4fSDavid du Colombier return 0;
4879a747e4fSDavid du Colombier }
4889a747e4fSDavid du Colombier
4899a747e4fSDavid du Colombier DScreen*
drawlookupdscreen(int id)4909a747e4fSDavid du Colombier drawlookupdscreen(int id)
4919a747e4fSDavid du Colombier {
4929a747e4fSDavid du Colombier DScreen *s;
4939a747e4fSDavid du Colombier
4949a747e4fSDavid du Colombier s = dscreen;
4959a747e4fSDavid du Colombier while(s){
4969a747e4fSDavid du Colombier if(s->id == id)
4979a747e4fSDavid du Colombier return s;
4989a747e4fSDavid du Colombier s = s->next;
4999a747e4fSDavid du Colombier }
5009a747e4fSDavid du Colombier return 0;
5019a747e4fSDavid du Colombier }
5029a747e4fSDavid du Colombier
5039a747e4fSDavid du Colombier DScreen*
drawlookupscreen(Client * client,int id,CScreen ** cs)5049a747e4fSDavid du Colombier drawlookupscreen(Client *client, int id, CScreen **cs)
5059a747e4fSDavid du Colombier {
5069a747e4fSDavid du Colombier CScreen *s;
5079a747e4fSDavid du Colombier
5089a747e4fSDavid du Colombier s = client->cscreen;
5099a747e4fSDavid du Colombier while(s){
5109a747e4fSDavid du Colombier if(s->dscreen->id == id){
5119a747e4fSDavid du Colombier *cs = s;
5129a747e4fSDavid du Colombier return s->dscreen;
5139a747e4fSDavid du Colombier }
5149a747e4fSDavid du Colombier s = s->next;
5159a747e4fSDavid du Colombier }
5169a747e4fSDavid du Colombier error(Enodrawscreen);
5179a747e4fSDavid du Colombier return 0;
5189a747e4fSDavid du Colombier }
5199a747e4fSDavid du Colombier
5209a747e4fSDavid du Colombier Memimage*
drawinstall(Client * client,int id,Memimage * i,DScreen * dscreen)5219a747e4fSDavid du Colombier drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
5229a747e4fSDavid du Colombier {
5239a747e4fSDavid du Colombier DImage *d;
5249a747e4fSDavid du Colombier
5259a747e4fSDavid du Colombier d = malloc(sizeof(DImage));
5269a747e4fSDavid du Colombier if(d == 0)
5279a747e4fSDavid du Colombier return 0;
5289a747e4fSDavid du Colombier d->id = id;
5299a747e4fSDavid du Colombier d->ref = 1;
5309a747e4fSDavid du Colombier d->name = 0;
5319a747e4fSDavid du Colombier d->vers = 0;
5329a747e4fSDavid du Colombier d->image = i;
5339a747e4fSDavid du Colombier d->nfchar = 0;
5349a747e4fSDavid du Colombier d->fchar = 0;
5359a747e4fSDavid du Colombier d->fromname = 0;
5369a747e4fSDavid du Colombier d->dscreen = dscreen;
5379a747e4fSDavid du Colombier d->next = client->dimage[id&HASHMASK];
5389a747e4fSDavid du Colombier client->dimage[id&HASHMASK] = d;
5399a747e4fSDavid du Colombier return i;
5409a747e4fSDavid du Colombier }
5419a747e4fSDavid du Colombier
5429a747e4fSDavid du Colombier Memscreen*
drawinstallscreen(Client * client,DScreen * d,int id,DImage * dimage,DImage * dfill,int public)5439a747e4fSDavid du Colombier drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public)
5449a747e4fSDavid du Colombier {
5459a747e4fSDavid du Colombier Memscreen *s;
5469a747e4fSDavid du Colombier CScreen *c;
5479a747e4fSDavid du Colombier
5489a747e4fSDavid du Colombier c = malloc(sizeof(CScreen));
5499a747e4fSDavid du Colombier if(dimage && dimage->image && dimage->image->chan == 0)
5509a747e4fSDavid du Colombier panic("bad image %p in drawinstallscreen", dimage->image);
5519a747e4fSDavid du Colombier
5529a747e4fSDavid du Colombier if(c == 0)
5539a747e4fSDavid du Colombier return 0;
5549a747e4fSDavid du Colombier if(d == 0){
5559a747e4fSDavid du Colombier d = malloc(sizeof(DScreen));
5569a747e4fSDavid du Colombier if(d == 0){
5579a747e4fSDavid du Colombier free(c);
5589a747e4fSDavid du Colombier return 0;
5599a747e4fSDavid du Colombier }
5609a747e4fSDavid du Colombier s = malloc(sizeof(Memscreen));
5619a747e4fSDavid du Colombier if(s == 0){
5629a747e4fSDavid du Colombier free(c);
5639a747e4fSDavid du Colombier free(d);
5649a747e4fSDavid du Colombier return 0;
5659a747e4fSDavid du Colombier }
5669a747e4fSDavid du Colombier s->frontmost = 0;
5679a747e4fSDavid du Colombier s->rearmost = 0;
5689a747e4fSDavid du Colombier d->dimage = dimage;
5699a747e4fSDavid du Colombier if(dimage){
5709a747e4fSDavid du Colombier s->image = dimage->image;
5719a747e4fSDavid du Colombier dimage->ref++;
5729a747e4fSDavid du Colombier }
5739a747e4fSDavid du Colombier d->dfill = dfill;
5749a747e4fSDavid du Colombier if(dfill){
5759a747e4fSDavid du Colombier s->fill = dfill->image;
5769a747e4fSDavid du Colombier dfill->ref++;
5779a747e4fSDavid du Colombier }
5789a747e4fSDavid du Colombier d->ref = 0;
5799a747e4fSDavid du Colombier d->id = id;
5809a747e4fSDavid du Colombier d->screen = s;
5819a747e4fSDavid du Colombier d->public = public;
5829a747e4fSDavid du Colombier d->next = dscreen;
5839a747e4fSDavid du Colombier d->owner = client;
5849a747e4fSDavid du Colombier dscreen = d;
5859a747e4fSDavid du Colombier }
5869a747e4fSDavid du Colombier c->dscreen = d;
5879a747e4fSDavid du Colombier d->ref++;
5889a747e4fSDavid du Colombier c->next = client->cscreen;
5899a747e4fSDavid du Colombier client->cscreen = c;
5909a747e4fSDavid du Colombier return d->screen;
5919a747e4fSDavid du Colombier }
5929a747e4fSDavid du Colombier
5939a747e4fSDavid du Colombier void
drawdelname(DName * name)5949a747e4fSDavid du Colombier drawdelname(DName *name)
5959a747e4fSDavid du Colombier {
5969a747e4fSDavid du Colombier int i;
5979a747e4fSDavid du Colombier
5989a747e4fSDavid du Colombier i = name-sdraw.name;
5999a747e4fSDavid du Colombier memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
6009a747e4fSDavid du Colombier sdraw.nname--;
6019a747e4fSDavid du Colombier }
6029a747e4fSDavid du Colombier
6039a747e4fSDavid du Colombier void
drawfreedscreen(DScreen * this)6049a747e4fSDavid du Colombier drawfreedscreen(DScreen *this)
6059a747e4fSDavid du Colombier {
6069a747e4fSDavid du Colombier DScreen *ds, *next;
6079a747e4fSDavid du Colombier
6089a747e4fSDavid du Colombier this->ref--;
6099a747e4fSDavid du Colombier if(this->ref < 0)
6109a747e4fSDavid du Colombier print("negative ref in drawfreedscreen\n");
6119a747e4fSDavid du Colombier if(this->ref > 0)
6129a747e4fSDavid du Colombier return;
6139a747e4fSDavid du Colombier ds = dscreen;
6149a747e4fSDavid du Colombier if(ds == this){
6159a747e4fSDavid du Colombier dscreen = this->next;
6169a747e4fSDavid du Colombier goto Found;
6179a747e4fSDavid du Colombier }
6189a747e4fSDavid du Colombier while(next = ds->next){ /* assign = */
6199a747e4fSDavid du Colombier if(next == this){
6209a747e4fSDavid du Colombier ds->next = this->next;
6219a747e4fSDavid du Colombier goto Found;
6229a747e4fSDavid du Colombier }
6239a747e4fSDavid du Colombier ds = next;
6249a747e4fSDavid du Colombier }
6259a747e4fSDavid du Colombier error(Enodrawimage);
6269a747e4fSDavid du Colombier
6279a747e4fSDavid du Colombier Found:
6289a747e4fSDavid du Colombier if(this->dimage)
6299a747e4fSDavid du Colombier drawfreedimage(this->dimage);
6309a747e4fSDavid du Colombier if(this->dfill)
6319a747e4fSDavid du Colombier drawfreedimage(this->dfill);
6329a747e4fSDavid du Colombier free(this->screen);
6339a747e4fSDavid du Colombier free(this);
6349a747e4fSDavid du Colombier }
6359a747e4fSDavid du Colombier
6369a747e4fSDavid du Colombier void
drawfreedimage(DImage * dimage)6379a747e4fSDavid du Colombier drawfreedimage(DImage *dimage)
6389a747e4fSDavid du Colombier {
6399a747e4fSDavid du Colombier int i;
6409a747e4fSDavid du Colombier Memimage *l;
6419a747e4fSDavid du Colombier DScreen *ds;
6429a747e4fSDavid du Colombier
6439a747e4fSDavid du Colombier dimage->ref--;
6449a747e4fSDavid du Colombier if(dimage->ref < 0)
6459a747e4fSDavid du Colombier print("negative ref in drawfreedimage\n");
6469a747e4fSDavid du Colombier if(dimage->ref > 0)
6479a747e4fSDavid du Colombier return;
6489a747e4fSDavid du Colombier
6499a747e4fSDavid du Colombier /* any names? */
6509a747e4fSDavid du Colombier for(i=0; i<sdraw.nname; )
6519a747e4fSDavid du Colombier if(sdraw.name[i].dimage == dimage)
6529a747e4fSDavid du Colombier drawdelname(sdraw.name+i);
6539a747e4fSDavid du Colombier else
6549a747e4fSDavid du Colombier i++;
6559a747e4fSDavid du Colombier if(dimage->fromname){ /* acquired by name; owned by someone else*/
6569a747e4fSDavid du Colombier drawfreedimage(dimage->fromname);
6579a747e4fSDavid du Colombier goto Return;
6589a747e4fSDavid du Colombier }
6599a747e4fSDavid du Colombier if(dimage->image == screenimage) /* don't free the display */
6609a747e4fSDavid du Colombier goto Return;
6619a747e4fSDavid du Colombier ds = dimage->dscreen;
6629a747e4fSDavid du Colombier if(ds){
6639a747e4fSDavid du Colombier l = dimage->image;
6649a747e4fSDavid du Colombier if(l->data == screenimage->data)
6659a747e4fSDavid du Colombier addflush(l->layer->screenr);
6669a747e4fSDavid du Colombier if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
6679a747e4fSDavid du Colombier free(l->layer->refreshptr);
6689a747e4fSDavid du Colombier l->layer->refreshptr = nil;
6699a747e4fSDavid du Colombier if(drawgoodname(dimage))
6709a747e4fSDavid du Colombier memldelete(l);
6719a747e4fSDavid du Colombier else
6729a747e4fSDavid du Colombier memlfree(l);
6739a747e4fSDavid du Colombier drawfreedscreen(ds);
6749a747e4fSDavid du Colombier }else
6759a747e4fSDavid du Colombier freememimage(dimage->image);
6769a747e4fSDavid du Colombier Return:
6779a747e4fSDavid du Colombier free(dimage->fchar);
6789a747e4fSDavid du Colombier free(dimage);
6799a747e4fSDavid du Colombier }
6809a747e4fSDavid du Colombier
6819a747e4fSDavid du Colombier void
drawuninstallscreen(Client * client,CScreen * this)6829a747e4fSDavid du Colombier drawuninstallscreen(Client *client, CScreen *this)
6839a747e4fSDavid du Colombier {
6849a747e4fSDavid du Colombier CScreen *cs, *next;
6859a747e4fSDavid du Colombier
6869a747e4fSDavid du Colombier cs = client->cscreen;
6879a747e4fSDavid du Colombier if(cs == this){
6889a747e4fSDavid du Colombier client->cscreen = this->next;
6899a747e4fSDavid du Colombier drawfreedscreen(this->dscreen);
6909a747e4fSDavid du Colombier free(this);
6919a747e4fSDavid du Colombier return;
6929a747e4fSDavid du Colombier }
6939a747e4fSDavid du Colombier while(next = cs->next){ /* assign = */
6949a747e4fSDavid du Colombier if(next == this){
6959a747e4fSDavid du Colombier cs->next = this->next;
6969a747e4fSDavid du Colombier drawfreedscreen(this->dscreen);
6979a747e4fSDavid du Colombier free(this);
6989a747e4fSDavid du Colombier return;
6999a747e4fSDavid du Colombier }
7009a747e4fSDavid du Colombier cs = next;
7019a747e4fSDavid du Colombier }
7029a747e4fSDavid du Colombier }
7039a747e4fSDavid du Colombier
7049a747e4fSDavid du Colombier void
drawuninstall(Client * client,int id)7059a747e4fSDavid du Colombier drawuninstall(Client *client, int id)
7069a747e4fSDavid du Colombier {
7079a747e4fSDavid du Colombier DImage *d, *next;
7089a747e4fSDavid du Colombier
7099a747e4fSDavid du Colombier d = client->dimage[id&HASHMASK];
7109a747e4fSDavid du Colombier if(d == 0)
7119a747e4fSDavid du Colombier error(Enodrawimage);
7129a747e4fSDavid du Colombier if(d->id == id){
7139a747e4fSDavid du Colombier client->dimage[id&HASHMASK] = d->next;
7149a747e4fSDavid du Colombier drawfreedimage(d);
7159a747e4fSDavid du Colombier return;
7169a747e4fSDavid du Colombier }
7179a747e4fSDavid du Colombier while(next = d->next){ /* assign = */
7189a747e4fSDavid du Colombier if(next->id == id){
7199a747e4fSDavid du Colombier d->next = next->next;
7209a747e4fSDavid du Colombier drawfreedimage(next);
7219a747e4fSDavid du Colombier return;
7229a747e4fSDavid du Colombier }
7239a747e4fSDavid du Colombier d = next;
7249a747e4fSDavid du Colombier }
7259a747e4fSDavid du Colombier error(Enodrawimage);
7269a747e4fSDavid du Colombier }
7279a747e4fSDavid du Colombier
7289a747e4fSDavid du Colombier void
drawaddname(Client * client,DImage * di,int n,char * str)7299a747e4fSDavid du Colombier drawaddname(Client *client, DImage *di, int n, char *str)
7309a747e4fSDavid du Colombier {
7319a747e4fSDavid du Colombier DName *name, *ename, *new, *t;
7329a747e4fSDavid du Colombier
7339a747e4fSDavid du Colombier name = sdraw.name;
7349a747e4fSDavid du Colombier ename = &name[sdraw.nname];
7359a747e4fSDavid du Colombier for(; name<ename; name++)
7369a747e4fSDavid du Colombier if(drawcmp(name->name, str, n) == 0)
7379a747e4fSDavid du Colombier error(Enameused);
7389a747e4fSDavid du Colombier t = smalloc((sdraw.nname+1)*sizeof(DName));
7399a747e4fSDavid du Colombier memmove(t, sdraw.name, sdraw.nname*sizeof(DName));
7409a747e4fSDavid du Colombier free(sdraw.name);
7419a747e4fSDavid du Colombier sdraw.name = t;
7429a747e4fSDavid du Colombier new = &sdraw.name[sdraw.nname++];
7439a747e4fSDavid du Colombier new->name = smalloc(n+1);
7449a747e4fSDavid du Colombier memmove(new->name, str, n);
7459a747e4fSDavid du Colombier new->name[n] = 0;
7469a747e4fSDavid du Colombier new->dimage = di;
7479a747e4fSDavid du Colombier new->client = client;
7489a747e4fSDavid du Colombier new->vers = ++sdraw.vers;
7499a747e4fSDavid du Colombier }
7509a747e4fSDavid du Colombier
7519a747e4fSDavid du Colombier Client*
drawnewclient(void)7529a747e4fSDavid du Colombier drawnewclient(void)
7539a747e4fSDavid du Colombier {
7549a747e4fSDavid du Colombier Client *cl, **cp;
7559a747e4fSDavid du Colombier int i;
7569a747e4fSDavid du Colombier
7579a747e4fSDavid du Colombier for(i=0; i<sdraw.nclient; i++){
7589a747e4fSDavid du Colombier cl = sdraw.client[i];
7599a747e4fSDavid du Colombier if(cl == 0)
7609a747e4fSDavid du Colombier break;
7619a747e4fSDavid du Colombier }
7629a747e4fSDavid du Colombier if(i == sdraw.nclient){
7639a747e4fSDavid du Colombier cp = malloc((sdraw.nclient+1)*sizeof(Client*));
7649a747e4fSDavid du Colombier if(cp == 0)
7659a747e4fSDavid du Colombier return 0;
7669a747e4fSDavid du Colombier memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*));
7679a747e4fSDavid du Colombier free(sdraw.client);
7689a747e4fSDavid du Colombier sdraw.client = cp;
7699a747e4fSDavid du Colombier sdraw.nclient++;
7709a747e4fSDavid du Colombier cp[i] = 0;
7719a747e4fSDavid du Colombier }
7729a747e4fSDavid du Colombier cl = malloc(sizeof(Client));
7739a747e4fSDavid du Colombier if(cl == 0)
7749a747e4fSDavid du Colombier return 0;
7759a747e4fSDavid du Colombier memset(cl, 0, sizeof(Client));
7769a747e4fSDavid du Colombier cl->slot = i;
7779a747e4fSDavid du Colombier cl->clientid = ++sdraw.clientid;
7786a9fc400SDavid du Colombier cl->op = SoverD;
7799a747e4fSDavid du Colombier sdraw.client[i] = cl;
7809a747e4fSDavid du Colombier return cl;
7819a747e4fSDavid du Colombier }
7829a747e4fSDavid du Colombier
7836a9fc400SDavid du Colombier static int
drawclientop(Client * cl)7846a9fc400SDavid du Colombier drawclientop(Client *cl)
7856a9fc400SDavid du Colombier {
7866a9fc400SDavid du Colombier int op;
7876a9fc400SDavid du Colombier
7886a9fc400SDavid du Colombier op = cl->op;
7896a9fc400SDavid du Colombier cl->op = SoverD;
7906a9fc400SDavid du Colombier return op;
7916a9fc400SDavid du Colombier }
7926a9fc400SDavid du Colombier
7939a747e4fSDavid du Colombier int
drawhasclients(void)7949a747e4fSDavid du Colombier drawhasclients(void)
7959a747e4fSDavid du Colombier {
7969a747e4fSDavid du Colombier /*
7979a747e4fSDavid du Colombier * if draw has ever been used, we can't resize the frame buffer,
7989a747e4fSDavid du Colombier * even if all clients have exited (nclients is cumulative); it's too
7999a747e4fSDavid du Colombier * hard to make work.
8009a747e4fSDavid du Colombier */
8019a747e4fSDavid du Colombier return sdraw.nclient != 0;
8029a747e4fSDavid du Colombier }
8039a747e4fSDavid du Colombier
8049a747e4fSDavid du Colombier Client*
drawclientofpath(ulong path)8059a747e4fSDavid du Colombier drawclientofpath(ulong path)
8069a747e4fSDavid du Colombier {
8079a747e4fSDavid du Colombier Client *cl;
8089a747e4fSDavid du Colombier int slot;
8099a747e4fSDavid du Colombier
8109a747e4fSDavid du Colombier slot = CLIENTPATH(path);
8119a747e4fSDavid du Colombier if(slot == 0)
8129a747e4fSDavid du Colombier return nil;
8139a747e4fSDavid du Colombier cl = sdraw.client[slot-1];
8149a747e4fSDavid du Colombier if(cl==0 || cl->clientid==0)
8159a747e4fSDavid du Colombier return nil;
8169a747e4fSDavid du Colombier return cl;
8179a747e4fSDavid du Colombier }
8189a747e4fSDavid du Colombier
8199a747e4fSDavid du Colombier
8209a747e4fSDavid du Colombier Client*
drawclient(Chan * c)8219a747e4fSDavid du Colombier drawclient(Chan *c)
8229a747e4fSDavid du Colombier {
8239a747e4fSDavid du Colombier Client *client;
8249a747e4fSDavid du Colombier
8259a747e4fSDavid du Colombier client = drawclientofpath(c->qid.path);
8269a747e4fSDavid du Colombier if(client == nil)
8279a747e4fSDavid du Colombier error(Enoclient);
8289a747e4fSDavid du Colombier return client;
8299a747e4fSDavid du Colombier }
8309a747e4fSDavid du Colombier
8319a747e4fSDavid du Colombier Memimage*
drawimage(Client * client,uchar * a)8329a747e4fSDavid du Colombier drawimage(Client *client, uchar *a)
8339a747e4fSDavid du Colombier {
8349a747e4fSDavid du Colombier DImage *d;
8359a747e4fSDavid du Colombier
8369a747e4fSDavid du Colombier d = drawlookup(client, BGLONG(a), 1);
8379a747e4fSDavid du Colombier if(d == nil)
8389a747e4fSDavid du Colombier error(Enodrawimage);
8399a747e4fSDavid du Colombier return d->image;
8409a747e4fSDavid du Colombier }
8419a747e4fSDavid du Colombier
8429a747e4fSDavid du Colombier void
drawrectangle(Rectangle * r,uchar * a)8439a747e4fSDavid du Colombier drawrectangle(Rectangle *r, uchar *a)
8449a747e4fSDavid du Colombier {
8459a747e4fSDavid du Colombier r->min.x = BGLONG(a+0*4);
8469a747e4fSDavid du Colombier r->min.y = BGLONG(a+1*4);
8479a747e4fSDavid du Colombier r->max.x = BGLONG(a+2*4);
8489a747e4fSDavid du Colombier r->max.y = BGLONG(a+3*4);
8499a747e4fSDavid du Colombier }
8509a747e4fSDavid du Colombier
8519a747e4fSDavid du Colombier void
drawpoint(Point * p,uchar * a)8529a747e4fSDavid du Colombier drawpoint(Point *p, uchar *a)
8539a747e4fSDavid du Colombier {
8549a747e4fSDavid du Colombier p->x = BGLONG(a+0*4);
8559a747e4fSDavid du Colombier p->y = BGLONG(a+1*4);
8569a747e4fSDavid du Colombier }
8579a747e4fSDavid du Colombier
8589a747e4fSDavid du Colombier Point
drawchar(Memimage * dst,Point p,Memimage * src,Point * sp,DImage * font,int index,int op)8596a9fc400SDavid du Colombier drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
8609a747e4fSDavid du Colombier {
8619a747e4fSDavid du Colombier FChar *fc;
8629a747e4fSDavid du Colombier Rectangle r;
8639a747e4fSDavid du Colombier Point sp1;
8649a747e4fSDavid du Colombier
8659a747e4fSDavid du Colombier fc = &font->fchar[index];
8669a747e4fSDavid du Colombier r.min.x = p.x+fc->left;
8679a747e4fSDavid du Colombier r.min.y = p.y-(font->ascent-fc->miny);
8689a747e4fSDavid du Colombier r.max.x = r.min.x+(fc->maxx-fc->minx);
8699a747e4fSDavid du Colombier r.max.y = r.min.y+(fc->maxy-fc->miny);
8709a747e4fSDavid du Colombier sp1.x = sp->x+fc->left;
8719a747e4fSDavid du Colombier sp1.y = sp->y+fc->miny;
8726a9fc400SDavid du Colombier memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
8739a747e4fSDavid du Colombier p.x += fc->width;
8749a747e4fSDavid du Colombier sp->x += fc->width;
8759a747e4fSDavid du Colombier return p;
8769a747e4fSDavid du Colombier }
8779a747e4fSDavid du Colombier
8789a747e4fSDavid du Colombier static int
initscreenimage(void)8799a747e4fSDavid du Colombier initscreenimage(void)
8809a747e4fSDavid du Colombier {
8819a747e4fSDavid du Colombier int width, depth;
8829a747e4fSDavid du Colombier ulong chan;
8839a747e4fSDavid du Colombier Rectangle r;
8849a747e4fSDavid du Colombier
8859a747e4fSDavid du Colombier if(screenimage != nil)
8869a747e4fSDavid du Colombier return 1;
8879a747e4fSDavid du Colombier
8889a747e4fSDavid du Colombier screendata.base = nil;
8899a747e4fSDavid du Colombier screendata.bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen);
8909a747e4fSDavid du Colombier if(screendata.bdata == nil)
8919a747e4fSDavid du Colombier {fprint(2, "bad bdata\n");
8929a747e4fSDavid du Colombier return 0;
8939a747e4fSDavid du Colombier }
8949a747e4fSDavid du Colombier screendata.ref = 1;
8959a747e4fSDavid du Colombier
8969a747e4fSDavid du Colombier screenimage = allocmemimaged(r, chan, &screendata);
8979a747e4fSDavid du Colombier if(screenimage == nil){
8989a747e4fSDavid du Colombier fprint(2, "bad memimaged: %r\n");
8999a747e4fSDavid du Colombier /* RSC: BUG: detach screen */
9009a747e4fSDavid du Colombier return 0;
9019a747e4fSDavid du Colombier }
9029a747e4fSDavid du Colombier
9039a747e4fSDavid du Colombier screenimage->width = width;
9049a747e4fSDavid du Colombier screenimage->clipr = screenimage->r;
9059a747e4fSDavid du Colombier return 1;
9069a747e4fSDavid du Colombier }
9079a747e4fSDavid du Colombier
9089a747e4fSDavid du Colombier void
deletescreenimage(void)9099a747e4fSDavid du Colombier deletescreenimage(void)
9109a747e4fSDavid du Colombier {
9119a747e4fSDavid du Colombier qlock(&sdraw);
9129a747e4fSDavid du Colombier /* RSC: BUG: detach screen */
9139a747e4fSDavid du Colombier if(screenimage)
9149a747e4fSDavid du Colombier freememimage(screenimage);
9159a747e4fSDavid du Colombier screenimage = nil;
9169a747e4fSDavid du Colombier qunlock(&sdraw);
9179a747e4fSDavid du Colombier }
9189a747e4fSDavid du Colombier
9199a747e4fSDavid du Colombier Chan*
drawattach(char * spec)9209a747e4fSDavid du Colombier drawattach(char *spec)
9219a747e4fSDavid du Colombier {
9229a747e4fSDavid du Colombier qlock(&sdraw);
9239a747e4fSDavid du Colombier if(!initscreenimage()){
9249a747e4fSDavid du Colombier qunlock(&sdraw);
9259a747e4fSDavid du Colombier error("no frame buffer");
9269a747e4fSDavid du Colombier }
9279a747e4fSDavid du Colombier qunlock(&sdraw);
9289a747e4fSDavid du Colombier return devattach('i', spec);
9299a747e4fSDavid du Colombier }
9309a747e4fSDavid du Colombier
9319a747e4fSDavid du Colombier Walkqid*
drawwalk(Chan * c,Chan * nc,char ** name,int nname)9329a747e4fSDavid du Colombier drawwalk(Chan *c, Chan *nc, char **name, int nname)
9339a747e4fSDavid du Colombier {
9349a747e4fSDavid du Colombier if(screendata.bdata == nil)
9359a747e4fSDavid du Colombier error("no frame buffer");
9369a747e4fSDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, drawgen);
9379a747e4fSDavid du Colombier }
9389a747e4fSDavid du Colombier
9399a747e4fSDavid du Colombier static int
drawstat(Chan * c,uchar * db,int n)9409a747e4fSDavid du Colombier drawstat(Chan *c, uchar *db, int n)
9419a747e4fSDavid du Colombier {
9429a747e4fSDavid du Colombier return devstat(c, db, n, 0, 0, drawgen);
9439a747e4fSDavid du Colombier }
9449a747e4fSDavid du Colombier
9459a747e4fSDavid du Colombier static Chan*
drawopen(Chan * c,int omode)9469a747e4fSDavid du Colombier drawopen(Chan *c, int omode)
9479a747e4fSDavid du Colombier {
9489a747e4fSDavid du Colombier Client *cl;
9499a747e4fSDavid du Colombier
9509a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
9519a747e4fSDavid du Colombier return devopen(c, omode, 0, 0, drawgen);
9529a747e4fSDavid du Colombier
9539a747e4fSDavid du Colombier qlock(&sdraw);
9549a747e4fSDavid du Colombier if(waserror()){
9559a747e4fSDavid du Colombier qunlock(&sdraw);
9569a747e4fSDavid du Colombier nexterror();
9579a747e4fSDavid du Colombier }
9589a747e4fSDavid du Colombier
9599a747e4fSDavid du Colombier if(QID(c->qid) == Qnew){
9609a747e4fSDavid du Colombier cl = drawnewclient();
9619a747e4fSDavid du Colombier if(cl == 0)
9629a747e4fSDavid du Colombier error(Enodev);
9639a747e4fSDavid du Colombier c->qid.path = Qctl|((cl->slot+1)<<QSHIFT);
9649a747e4fSDavid du Colombier }
9659a747e4fSDavid du Colombier
9669a747e4fSDavid du Colombier switch(QID(c->qid)){
9679a747e4fSDavid du Colombier case Qnew:
9689a747e4fSDavid du Colombier break;
9699a747e4fSDavid du Colombier
9709a747e4fSDavid du Colombier case Qctl:
9719a747e4fSDavid du Colombier cl = drawclient(c);
9729a747e4fSDavid du Colombier if(cl->busy)
9739a747e4fSDavid du Colombier error(Einuse);
9749a747e4fSDavid du Colombier cl->busy = 1;
9759a747e4fSDavid du Colombier flushrect = Rect(10000, 10000, -10000, -10000);
9769a747e4fSDavid du Colombier drawinstall(cl, 0, screenimage, 0);
9779a747e4fSDavid du Colombier incref(&cl->r);
9789a747e4fSDavid du Colombier break;
9799a747e4fSDavid du Colombier case Qcolormap:
9809a747e4fSDavid du Colombier case Qdata:
9819a747e4fSDavid du Colombier case Qrefresh:
9829a747e4fSDavid du Colombier cl = drawclient(c);
9839a747e4fSDavid du Colombier incref(&cl->r);
9849a747e4fSDavid du Colombier break;
9859a747e4fSDavid du Colombier }
9869a747e4fSDavid du Colombier qunlock(&sdraw);
9879a747e4fSDavid du Colombier poperror();
9889a747e4fSDavid du Colombier c->mode = openmode(omode);
9899a747e4fSDavid du Colombier c->flag |= COPEN;
9909a747e4fSDavid du Colombier c->offset = 0;
9919a747e4fSDavid du Colombier return c;
9929a747e4fSDavid du Colombier }
9939a747e4fSDavid du Colombier
9949a747e4fSDavid du Colombier static void
drawclose(Chan * c)9959a747e4fSDavid du Colombier drawclose(Chan *c)
9969a747e4fSDavid du Colombier {
9979a747e4fSDavid du Colombier int i;
9989a747e4fSDavid du Colombier DImage *d, **dp;
9999a747e4fSDavid du Colombier Client *cl;
10009a747e4fSDavid du Colombier Refresh *r;
10019a747e4fSDavid du Colombier
10029a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
10039a747e4fSDavid du Colombier return;
10049a747e4fSDavid du Colombier qlock(&sdraw);
10059a747e4fSDavid du Colombier if(waserror()){
10069a747e4fSDavid du Colombier qunlock(&sdraw);
10079a747e4fSDavid du Colombier nexterror();
10089a747e4fSDavid du Colombier }
10099a747e4fSDavid du Colombier
10109a747e4fSDavid du Colombier cl = drawclient(c);
10119a747e4fSDavid du Colombier if(QID(c->qid) == Qctl)
10129a747e4fSDavid du Colombier cl->busy = 0;
10139a747e4fSDavid du Colombier if((c->flag&COPEN) && (decref(&cl->r)==0)){
10149a747e4fSDavid du Colombier while(r = cl->refresh){ /* assign = */
10159a747e4fSDavid du Colombier cl->refresh = r->next;
10169a747e4fSDavid du Colombier free(r);
10179a747e4fSDavid du Colombier }
10189a747e4fSDavid du Colombier /* free names */
10199a747e4fSDavid du Colombier for(i=0; i<sdraw.nname; )
10209a747e4fSDavid du Colombier if(sdraw.name[i].client == cl)
10219a747e4fSDavid du Colombier drawdelname(sdraw.name+i);
10229a747e4fSDavid du Colombier else
10239a747e4fSDavid du Colombier i++;
10249a747e4fSDavid du Colombier while(cl->cscreen)
10259a747e4fSDavid du Colombier drawuninstallscreen(cl, cl->cscreen);
10269a747e4fSDavid du Colombier /* all screens are freed, so now we can free images */
10279a747e4fSDavid du Colombier dp = cl->dimage;
10289a747e4fSDavid du Colombier for(i=0; i<NHASH; i++){
10299a747e4fSDavid du Colombier while((d = *dp) != nil){
10309a747e4fSDavid du Colombier *dp = d->next;
10319a747e4fSDavid du Colombier drawfreedimage(d);
10329a747e4fSDavid du Colombier }
10339a747e4fSDavid du Colombier dp++;
10349a747e4fSDavid du Colombier }
10359a747e4fSDavid du Colombier sdraw.client[cl->slot] = 0;
10369a747e4fSDavid du Colombier drawflush(); /* to erase visible, now dead windows */
10379a747e4fSDavid du Colombier free(cl);
10389a747e4fSDavid du Colombier }
10399a747e4fSDavid du Colombier qunlock(&sdraw);
10409a747e4fSDavid du Colombier poperror();
10419a747e4fSDavid du Colombier }
10429a747e4fSDavid du Colombier
10439a747e4fSDavid du Colombier long
drawread(Chan * c,void * a,long n,vlong off)10449a747e4fSDavid du Colombier drawread(Chan *c, void *a, long n, vlong off)
10459a747e4fSDavid du Colombier {
10469a747e4fSDavid du Colombier int index, m;
10479a747e4fSDavid du Colombier ulong red, green, blue;
10489a747e4fSDavid du Colombier Client *cl;
10499a747e4fSDavid du Colombier uchar *p;
10509a747e4fSDavid du Colombier Refresh *r;
10519a747e4fSDavid du Colombier DImage *di;
10529a747e4fSDavid du Colombier Memimage *i;
10539a747e4fSDavid du Colombier ulong offset = off;
10549a747e4fSDavid du Colombier char buf[16];
10559a747e4fSDavid du Colombier
10569a747e4fSDavid du Colombier USED(offset);
10579a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
10589a747e4fSDavid du Colombier return devdirread(c, a, n, 0, 0, drawgen);
10599a747e4fSDavid du Colombier cl = drawclient(c);
10609a747e4fSDavid du Colombier qlock(&sdraw);
10619a747e4fSDavid du Colombier if(waserror()){
10629a747e4fSDavid du Colombier qunlock(&sdraw);
10639a747e4fSDavid du Colombier nexterror();
10649a747e4fSDavid du Colombier }
10659a747e4fSDavid du Colombier switch(QID(c->qid)){
10669a747e4fSDavid du Colombier case Qctl:
10679a747e4fSDavid du Colombier if(n < 12*12)
10689a747e4fSDavid du Colombier error(Eshortread);
10699a747e4fSDavid du Colombier if(cl->infoid < 0)
10709a747e4fSDavid du Colombier error(Enodrawimage);
10719a747e4fSDavid du Colombier if(cl->infoid == 0){
10729a747e4fSDavid du Colombier i = screenimage;
10739a747e4fSDavid du Colombier if(i == nil)
10749a747e4fSDavid du Colombier error(Enodrawimage);
10759a747e4fSDavid du Colombier }else{
10769a747e4fSDavid du Colombier di = drawlookup(cl, cl->infoid, 1);
10779a747e4fSDavid du Colombier if(di == nil)
10789a747e4fSDavid du Colombier error(Enodrawimage);
10799a747e4fSDavid du Colombier i = di->image;
10809a747e4fSDavid du Colombier }
10819a747e4fSDavid du Colombier n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ",
10829a747e4fSDavid du Colombier cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl,
10839a747e4fSDavid du Colombier i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
10849a747e4fSDavid du Colombier i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
10859a747e4fSDavid du Colombier cl->infoid = -1;
10869a747e4fSDavid du Colombier break;
10879a747e4fSDavid du Colombier
10889a747e4fSDavid du Colombier case Qcolormap:
10899a747e4fSDavid du Colombier drawactive(1); /* to restore map from backup */
10909a747e4fSDavid du Colombier p = malloc(4*12*256+1);
10919a747e4fSDavid du Colombier if(p == 0)
10929a747e4fSDavid du Colombier error(Enomem);
10939a747e4fSDavid du Colombier m = 0;
10949a747e4fSDavid du Colombier for(index = 0; index < 256; index++){
10959a747e4fSDavid du Colombier getcolor(index, &red, &green, &blue);
10969a747e4fSDavid du Colombier m += sprint((char*)p+m, "%11d %11lud %11lud %11lud\n", index, red>>24, green>>24, blue>>24);
10979a747e4fSDavid du Colombier }
10989a747e4fSDavid du Colombier n = readstr(offset, a, n, (char*)p);
10999a747e4fSDavid du Colombier free(p);
11009a747e4fSDavid du Colombier break;
11019a747e4fSDavid du Colombier
11029a747e4fSDavid du Colombier case Qdata:
11039a747e4fSDavid du Colombier if(cl->readdata == nil)
11049a747e4fSDavid du Colombier error("no draw data");
11059a747e4fSDavid du Colombier if(n < cl->nreaddata)
11069a747e4fSDavid du Colombier error(Eshortread);
11079a747e4fSDavid du Colombier n = cl->nreaddata;
11089a747e4fSDavid du Colombier memmove(a, cl->readdata, cl->nreaddata);
11099a747e4fSDavid du Colombier free(cl->readdata);
11109a747e4fSDavid du Colombier cl->readdata = nil;
11119a747e4fSDavid du Colombier break;
11129a747e4fSDavid du Colombier
11139a747e4fSDavid du Colombier case Qrefresh:
11149a747e4fSDavid du Colombier if(n < 5*4)
11159a747e4fSDavid du Colombier error(Ebadarg);
11169a747e4fSDavid du Colombier for(;;){
11179a747e4fSDavid du Colombier if(cl->refreshme || cl->refresh)
11189a747e4fSDavid du Colombier break;
11199a747e4fSDavid du Colombier qunlock(&sdraw);
11209a747e4fSDavid du Colombier if(waserror()){
11219a747e4fSDavid du Colombier qlock(&sdraw); /* restore lock for waserror() above */
11229a747e4fSDavid du Colombier nexterror();
11239a747e4fSDavid du Colombier }
11249a747e4fSDavid du Colombier rendsleep(&cl->refrend, drawrefactive, cl);
11259a747e4fSDavid du Colombier poperror();
11269a747e4fSDavid du Colombier qlock(&sdraw);
11279a747e4fSDavid du Colombier }
11289a747e4fSDavid du Colombier p = a;
11299a747e4fSDavid du Colombier while(cl->refresh && n>=5*4){
11309a747e4fSDavid du Colombier r = cl->refresh;
11319a747e4fSDavid du Colombier BPLONG(p+0*4, r->dimage->id);
11329a747e4fSDavid du Colombier BPLONG(p+1*4, r->r.min.x);
11339a747e4fSDavid du Colombier BPLONG(p+2*4, r->r.min.y);
11349a747e4fSDavid du Colombier BPLONG(p+3*4, r->r.max.x);
11359a747e4fSDavid du Colombier BPLONG(p+4*4, r->r.max.y);
11369a747e4fSDavid du Colombier cl->refresh = r->next;
11379a747e4fSDavid du Colombier free(r);
11389a747e4fSDavid du Colombier p += 5*4;
11399a747e4fSDavid du Colombier n -= 5*4;
11409a747e4fSDavid du Colombier }
11419a747e4fSDavid du Colombier cl->refreshme = 0;
11429a747e4fSDavid du Colombier n = p-(uchar*)a;
11439a747e4fSDavid du Colombier }
11449a747e4fSDavid du Colombier qunlock(&sdraw);
11459a747e4fSDavid du Colombier poperror();
11469a747e4fSDavid du Colombier return n;
11479a747e4fSDavid du Colombier }
11489a747e4fSDavid du Colombier
11499a747e4fSDavid du Colombier void
drawwakeall(void)11509a747e4fSDavid du Colombier drawwakeall(void)
11519a747e4fSDavid du Colombier {
11529a747e4fSDavid du Colombier Client *cl;
11539a747e4fSDavid du Colombier int i;
11549a747e4fSDavid du Colombier
11559a747e4fSDavid du Colombier for(i=0; i<sdraw.nclient; i++){
11569a747e4fSDavid du Colombier cl = sdraw.client[i];
11579a747e4fSDavid du Colombier if(cl && (cl->refreshme || cl->refresh))
11589a747e4fSDavid du Colombier rendwakeup(&cl->refrend);
11599a747e4fSDavid du Colombier }
11609a747e4fSDavid du Colombier }
11619a747e4fSDavid du Colombier
11629a747e4fSDavid du Colombier static long
drawwrite(Chan * c,void * a,long n,vlong off)11639a747e4fSDavid du Colombier drawwrite(Chan *c, void *a, long n, vlong off)
11649a747e4fSDavid du Colombier {
11659a747e4fSDavid du Colombier char buf[128], *fields[4], *q;
11669a747e4fSDavid du Colombier Client *cl;
11679a747e4fSDavid du Colombier int i, m, red, green, blue, x;
11689a747e4fSDavid du Colombier ulong offset = off;
11699a747e4fSDavid du Colombier
11709a747e4fSDavid du Colombier USED(offset);
11719a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
11729a747e4fSDavid du Colombier error(Eisdir);
11739a747e4fSDavid du Colombier cl = drawclient(c);
11749a747e4fSDavid du Colombier qlock(&sdraw);
11759a747e4fSDavid du Colombier if(waserror()){
11769a747e4fSDavid du Colombier drawwakeall();
11779a747e4fSDavid du Colombier qunlock(&sdraw);
11789a747e4fSDavid du Colombier nexterror();
11799a747e4fSDavid du Colombier }
11809a747e4fSDavid du Colombier switch(QID(c->qid)){
11819a747e4fSDavid du Colombier case Qctl:
11829a747e4fSDavid du Colombier if(n != 4)
11839a747e4fSDavid du Colombier error("unknown draw control request");
11849a747e4fSDavid du Colombier cl->infoid = BGLONG((uchar*)a);
11859a747e4fSDavid du Colombier break;
11869a747e4fSDavid du Colombier
11879a747e4fSDavid du Colombier case Qcolormap:
11889a747e4fSDavid du Colombier drawactive(1); /* to restore map from backup */
11899a747e4fSDavid du Colombier m = n;
11909a747e4fSDavid du Colombier n = 0;
11919a747e4fSDavid du Colombier while(m > 0){
11929a747e4fSDavid du Colombier x = m;
11939a747e4fSDavid du Colombier if(x > sizeof(buf)-1)
11949a747e4fSDavid du Colombier x = sizeof(buf)-1;
11959a747e4fSDavid du Colombier q = memccpy(buf, a, '\n', x);
11969a747e4fSDavid du Colombier if(q == 0)
11979a747e4fSDavid du Colombier break;
11989a747e4fSDavid du Colombier i = q-buf;
11999a747e4fSDavid du Colombier n += i;
12009a747e4fSDavid du Colombier a = (char*)a + i;
12019a747e4fSDavid du Colombier m -= i;
12029a747e4fSDavid du Colombier *q = 0;
12039a747e4fSDavid du Colombier if(getfields(buf, fields, nelem(fields), 1, " ") != 4)
12049a747e4fSDavid du Colombier error(Ebadarg);
12059a747e4fSDavid du Colombier i = strtoul(fields[0], 0, 0);
12069a747e4fSDavid du Colombier red = strtoul(fields[1], 0, 0);
12079a747e4fSDavid du Colombier green = strtoul(fields[2], 0, 0);
12089a747e4fSDavid du Colombier blue = strtoul(fields[3], &q, 0);
12099a747e4fSDavid du Colombier if(fields[3] == q)
12109a747e4fSDavid du Colombier error(Ebadarg);
12119a747e4fSDavid du Colombier if(red>255 || green>255 || blue>255 || i<0 || i>255)
12129a747e4fSDavid du Colombier error(Ebadarg);
12139a747e4fSDavid du Colombier red |= red<<8;
12149a747e4fSDavid du Colombier red |= red<<16;
12159a747e4fSDavid du Colombier green |= green<<8;
12169a747e4fSDavid du Colombier green |= green<<16;
12179a747e4fSDavid du Colombier blue |= blue<<8;
12189a747e4fSDavid du Colombier blue |= blue<<16;
12199a747e4fSDavid du Colombier setcolor(i, red, green, blue);
12209a747e4fSDavid du Colombier }
12219a747e4fSDavid du Colombier break;
12229a747e4fSDavid du Colombier
12239a747e4fSDavid du Colombier case Qdata:
12249a747e4fSDavid du Colombier drawmesg(cl, a, n);
12259a747e4fSDavid du Colombier drawwakeall();
12269a747e4fSDavid du Colombier break;
12279a747e4fSDavid du Colombier
12289a747e4fSDavid du Colombier default:
12299a747e4fSDavid du Colombier error(Ebadusefd);
12309a747e4fSDavid du Colombier }
12319a747e4fSDavid du Colombier qunlock(&sdraw);
12329a747e4fSDavid du Colombier poperror();
12339a747e4fSDavid du Colombier return n;
12349a747e4fSDavid du Colombier }
12359a747e4fSDavid du Colombier
12369a747e4fSDavid du Colombier uchar*
drawcoord(uchar * p,uchar * maxp,int oldx,int * newx)12379a747e4fSDavid du Colombier drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
12389a747e4fSDavid du Colombier {
12399a747e4fSDavid du Colombier int b, x;
12409a747e4fSDavid du Colombier
12419a747e4fSDavid du Colombier if(p >= maxp)
12429a747e4fSDavid du Colombier error(Eshortdraw);
12439a747e4fSDavid du Colombier b = *p++;
12449a747e4fSDavid du Colombier x = b & 0x7F;
12459a747e4fSDavid du Colombier if(b & 0x80){
12469a747e4fSDavid du Colombier if(p+1 >= maxp)
12479a747e4fSDavid du Colombier error(Eshortdraw);
12489a747e4fSDavid du Colombier x |= *p++ << 7;
12499a747e4fSDavid du Colombier x |= *p++ << 15;
12509a747e4fSDavid du Colombier if(x & (1<<22))
12519a747e4fSDavid du Colombier x |= ~0<<23;
12529a747e4fSDavid du Colombier }else{
12539a747e4fSDavid du Colombier if(b & 0x40)
12549a747e4fSDavid du Colombier x |= ~0<<7;
12559a747e4fSDavid du Colombier x += oldx;
12569a747e4fSDavid du Colombier }
12579a747e4fSDavid du Colombier *newx = x;
12589a747e4fSDavid du Colombier return p;
12599a747e4fSDavid du Colombier }
12609a747e4fSDavid du Colombier
12619a747e4fSDavid du Colombier static void
printmesg(char * fmt,uchar * a,int plsprnt)12629a747e4fSDavid du Colombier printmesg(char *fmt, uchar *a, int plsprnt)
12639a747e4fSDavid du Colombier {
12649a747e4fSDavid du Colombier char buf[256];
12659a747e4fSDavid du Colombier char *p, *q;
12669a747e4fSDavid du Colombier int s;
12679a747e4fSDavid du Colombier
12689a747e4fSDavid du Colombier if(1|| plsprnt==0){
12699a747e4fSDavid du Colombier SET(s,q,p);
12709a747e4fSDavid du Colombier USED(fmt, a, buf, p, q, s);
12719a747e4fSDavid du Colombier return;
12729a747e4fSDavid du Colombier }
12739a747e4fSDavid du Colombier q = buf;
12749a747e4fSDavid du Colombier *q++ = *a++;
12759a747e4fSDavid du Colombier for(p=fmt; *p; p++){
12769a747e4fSDavid du Colombier switch(*p){
12779a747e4fSDavid du Colombier case 'l':
12789a747e4fSDavid du Colombier q += sprint(q, " %ld", (long)BGLONG(a));
12799a747e4fSDavid du Colombier a += 4;
12809a747e4fSDavid du Colombier break;
12819a747e4fSDavid du Colombier case 'L':
12829a747e4fSDavid du Colombier q += sprint(q, " %.8lux", (ulong)BGLONG(a));
12839a747e4fSDavid du Colombier a += 4;
12849a747e4fSDavid du Colombier break;
12859a747e4fSDavid du Colombier case 'R':
12869a747e4fSDavid du Colombier q += sprint(q, " [%d %d %d %d]", BGLONG(a), BGLONG(a+4), BGLONG(a+8), BGLONG(a+12));
12879a747e4fSDavid du Colombier a += 16;
12889a747e4fSDavid du Colombier break;
12899a747e4fSDavid du Colombier case 'P':
12909a747e4fSDavid du Colombier q += sprint(q, " [%d %d]", BGLONG(a), BGLONG(a+4));
12919a747e4fSDavid du Colombier a += 8;
12929a747e4fSDavid du Colombier break;
12939a747e4fSDavid du Colombier case 'b':
12949a747e4fSDavid du Colombier q += sprint(q, " %d", *a++);
12959a747e4fSDavid du Colombier break;
12969a747e4fSDavid du Colombier case 's':
12979a747e4fSDavid du Colombier q += sprint(q, " %d", BGSHORT(a));
12989a747e4fSDavid du Colombier a += 2;
12999a747e4fSDavid du Colombier break;
13009a747e4fSDavid du Colombier case 'S':
13019a747e4fSDavid du Colombier q += sprint(q, " %.4ux", BGSHORT(a));
13029a747e4fSDavid du Colombier a += 2;
13039a747e4fSDavid du Colombier break;
13049a747e4fSDavid du Colombier }
13059a747e4fSDavid du Colombier }
13069a747e4fSDavid du Colombier *q++ = '\n';
13079a747e4fSDavid du Colombier *q = 0;
13089a747e4fSDavid du Colombier iprint("%.*s", (int)(q-buf), buf);
13099a747e4fSDavid du Colombier }
13109a747e4fSDavid du Colombier
13119a747e4fSDavid du Colombier void
drawmesg(Client * client,void * av,int n)13129a747e4fSDavid du Colombier drawmesg(Client *client, void *av, int n)
13139a747e4fSDavid du Colombier {
13146a9fc400SDavid du Colombier int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
13159a747e4fSDavid du Colombier uchar *u, *a, refresh;
13169a747e4fSDavid du Colombier char *fmt;
13179a747e4fSDavid du Colombier ulong value, chan;
13189a747e4fSDavid du Colombier Rectangle r, clipr;
13199a747e4fSDavid du Colombier Point p, q, *pp, sp;
13209a747e4fSDavid du Colombier Memimage *i, *dst, *src, *mask;
13219a747e4fSDavid du Colombier Memimage *l, **lp;
13229a747e4fSDavid du Colombier Memscreen *scrn;
13239a747e4fSDavid du Colombier DImage *font, *ll, *di, *ddst, *dsrc;
13249a747e4fSDavid du Colombier DName *dn;
13259a747e4fSDavid du Colombier DScreen *dscrn;
13269a747e4fSDavid du Colombier FChar *fc;
13279a747e4fSDavid du Colombier Refx *refx;
13289a747e4fSDavid du Colombier CScreen *cs;
13299a747e4fSDavid du Colombier Refreshfn reffn;
13309a747e4fSDavid du Colombier
13319a747e4fSDavid du Colombier a = av;
13329a747e4fSDavid du Colombier m = 0;
13339a747e4fSDavid du Colombier fmt = nil;
13349a747e4fSDavid du Colombier if(waserror()){
13359a747e4fSDavid du Colombier if(fmt) printmesg(fmt, a, 1);
13369a747e4fSDavid du Colombier /* iprint("error: %s\n", up->error); */
13379a747e4fSDavid du Colombier nexterror();
13389a747e4fSDavid du Colombier }
13399a747e4fSDavid du Colombier while((n-=m) > 0){
13409a747e4fSDavid du Colombier USED(fmt);
13419a747e4fSDavid du Colombier a += m;
13429a747e4fSDavid du Colombier switch(*a){
13439a747e4fSDavid du Colombier default:
13449a747e4fSDavid du Colombier error("bad draw command");
13459a747e4fSDavid du Colombier /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */
13469a747e4fSDavid du Colombier case 'b':
13479a747e4fSDavid du Colombier printmesg(fmt="LLbLbRRL", a, 0);
13489a747e4fSDavid du Colombier m = 1+4+4+1+4+1+4*4+4*4+4;
13499a747e4fSDavid du Colombier if(n < m)
13509a747e4fSDavid du Colombier error(Eshortdraw);
13519a747e4fSDavid du Colombier dstid = BGLONG(a+1);
13529a747e4fSDavid du Colombier scrnid = BGSHORT(a+5);
13539a747e4fSDavid du Colombier refresh = a[9];
13549a747e4fSDavid du Colombier chan = BGLONG(a+10);
13559a747e4fSDavid du Colombier repl = a[14];
13569a747e4fSDavid du Colombier drawrectangle(&r, a+15);
13579a747e4fSDavid du Colombier drawrectangle(&clipr, a+31);
13589a747e4fSDavid du Colombier value = BGLONG(a+47);
13599a747e4fSDavid du Colombier if(drawlookup(client, dstid, 0))
13609a747e4fSDavid du Colombier error(Eimageexists);
13619a747e4fSDavid du Colombier if(scrnid){
13629a747e4fSDavid du Colombier dscrn = drawlookupscreen(client, scrnid, &cs);
13639a747e4fSDavid du Colombier scrn = dscrn->screen;
13649a747e4fSDavid du Colombier if(repl || chan!=scrn->image->chan)
13659a747e4fSDavid du Colombier error("image parameters incompatible with screen");
13669a747e4fSDavid du Colombier reffn = nil;
13679a747e4fSDavid du Colombier switch(refresh){
13689a747e4fSDavid du Colombier case Refbackup:
13699a747e4fSDavid du Colombier break;
13709a747e4fSDavid du Colombier case Refnone:
13719a747e4fSDavid du Colombier reffn = memlnorefresh;
13729a747e4fSDavid du Colombier break;
13739a747e4fSDavid du Colombier case Refmesg:
13749a747e4fSDavid du Colombier reffn = drawrefresh;
13759a747e4fSDavid du Colombier break;
13769a747e4fSDavid du Colombier default:
13779a747e4fSDavid du Colombier error("unknown refresh method");
13789a747e4fSDavid du Colombier }
13799a747e4fSDavid du Colombier l = memlalloc(scrn, r, reffn, 0, value);
13809a747e4fSDavid du Colombier if(l == 0)
13819a747e4fSDavid du Colombier error(Edrawmem);
13829a747e4fSDavid du Colombier addflush(l->layer->screenr);
13839a747e4fSDavid du Colombier l->clipr = clipr;
13849a747e4fSDavid du Colombier rectclip(&l->clipr, r);
13859a747e4fSDavid du Colombier if(drawinstall(client, dstid, l, dscrn) == 0){
13869a747e4fSDavid du Colombier memldelete(l);
13879a747e4fSDavid du Colombier error(Edrawmem);
13889a747e4fSDavid du Colombier }
13899a747e4fSDavid du Colombier dscrn->ref++;
13909a747e4fSDavid du Colombier if(reffn){
13919a747e4fSDavid du Colombier refx = nil;
13929a747e4fSDavid du Colombier if(reffn == drawrefresh){
13939a747e4fSDavid du Colombier refx = malloc(sizeof(Refx));
13949a747e4fSDavid du Colombier if(refx == 0){
13959a747e4fSDavid du Colombier drawuninstall(client, dstid);
13969a747e4fSDavid du Colombier error(Edrawmem);
13979a747e4fSDavid du Colombier }
13989a747e4fSDavid du Colombier refx->client = client;
13999a747e4fSDavid du Colombier refx->dimage = drawlookup(client, dstid, 1);
14009a747e4fSDavid du Colombier }
14019a747e4fSDavid du Colombier memlsetrefresh(l, reffn, refx);
14029a747e4fSDavid du Colombier }
14039a747e4fSDavid du Colombier continue;
14049a747e4fSDavid du Colombier }
14059a747e4fSDavid du Colombier i = allocmemimage(r, chan);
14069a747e4fSDavid du Colombier if(i == 0)
14079a747e4fSDavid du Colombier error(Edrawmem);
14089a747e4fSDavid du Colombier if(repl)
14099a747e4fSDavid du Colombier i->flags |= Frepl;
14109a747e4fSDavid du Colombier i->clipr = clipr;
14119a747e4fSDavid du Colombier if(!repl)
14129a747e4fSDavid du Colombier rectclip(&i->clipr, r);
14139a747e4fSDavid du Colombier if(drawinstall(client, dstid, i, 0) == 0){
14149a747e4fSDavid du Colombier freememimage(i);
14159a747e4fSDavid du Colombier error(Edrawmem);
14169a747e4fSDavid du Colombier }
14179a747e4fSDavid du Colombier memfillcolor(i, value);
14189a747e4fSDavid du Colombier continue;
14199a747e4fSDavid du Colombier
14209a747e4fSDavid du Colombier /* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */
14219a747e4fSDavid du Colombier case 'A':
14229a747e4fSDavid du Colombier printmesg(fmt="LLLb", a, 1);
14239a747e4fSDavid du Colombier m = 1+4+4+4+1;
14249a747e4fSDavid du Colombier if(n < m)
14259a747e4fSDavid du Colombier error(Eshortdraw);
14269a747e4fSDavid du Colombier dstid = BGLONG(a+1);
14279a747e4fSDavid du Colombier if(dstid == 0)
14289a747e4fSDavid du Colombier error(Ebadarg);
14299a747e4fSDavid du Colombier if(drawlookupdscreen(dstid))
14309a747e4fSDavid du Colombier error(Escreenexists);
14319a747e4fSDavid du Colombier ddst = drawlookup(client, BGLONG(a+5), 1);
14329a747e4fSDavid du Colombier dsrc = drawlookup(client, BGLONG(a+9), 1);
14339a747e4fSDavid du Colombier if(ddst==0 || dsrc==0)
14349a747e4fSDavid du Colombier error(Enodrawimage);
14359a747e4fSDavid du Colombier if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0)
14369a747e4fSDavid du Colombier error(Edrawmem);
14379a747e4fSDavid du Colombier continue;
14389a747e4fSDavid du Colombier
14399a747e4fSDavid du Colombier /* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */
14409a747e4fSDavid du Colombier case 'c':
14419a747e4fSDavid du Colombier printmesg(fmt="LbR", a, 0);
14429a747e4fSDavid du Colombier m = 1+4+1+4*4;
14439a747e4fSDavid du Colombier if(n < m)
14449a747e4fSDavid du Colombier error(Eshortdraw);
14459a747e4fSDavid du Colombier ddst = drawlookup(client, BGLONG(a+1), 1);
14469a747e4fSDavid du Colombier if(ddst == nil)
14479a747e4fSDavid du Colombier error(Enodrawimage);
14489a747e4fSDavid du Colombier if(ddst->name)
14499a747e4fSDavid du Colombier error("can't change repl/clipr of shared image");
14509a747e4fSDavid du Colombier dst = ddst->image;
14519a747e4fSDavid du Colombier if(a[5])
14529a747e4fSDavid du Colombier dst->flags |= Frepl;
14539a747e4fSDavid du Colombier drawrectangle(&dst->clipr, a+6);
14549a747e4fSDavid du Colombier continue;
14559a747e4fSDavid du Colombier
14569a747e4fSDavid du Colombier /* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */
14579a747e4fSDavid du Colombier case 'd':
14589a747e4fSDavid du Colombier printmesg(fmt="LLLRPP", a, 0);
14599a747e4fSDavid du Colombier m = 1+4+4+4+4*4+2*4+2*4;
14609a747e4fSDavid du Colombier if(n < m)
14619a747e4fSDavid du Colombier error(Eshortdraw);
14629a747e4fSDavid du Colombier dst = drawimage(client, a+1);
14639a747e4fSDavid du Colombier dstid = BGLONG(a+1);
14649a747e4fSDavid du Colombier src = drawimage(client, a+5);
14659a747e4fSDavid du Colombier mask = drawimage(client, a+9);
14669a747e4fSDavid du Colombier drawrectangle(&r, a+13);
14679a747e4fSDavid du Colombier drawpoint(&p, a+29);
14689a747e4fSDavid du Colombier drawpoint(&q, a+37);
14696a9fc400SDavid du Colombier op = drawclientop(client);
14706a9fc400SDavid du Colombier memdraw(dst, r, src, p, mask, q, op);
14719a747e4fSDavid du Colombier dstflush(dstid, dst, r);
14729a747e4fSDavid du Colombier continue;
14739a747e4fSDavid du Colombier
14749a747e4fSDavid du Colombier /* toggle debugging: 'D' val[1] */
14759a747e4fSDavid du Colombier case 'D':
14769a747e4fSDavid du Colombier printmesg(fmt="b", a, 0);
14779a747e4fSDavid du Colombier m = 1+1;
14789a747e4fSDavid du Colombier if(n < m)
14799a747e4fSDavid du Colombier error(Eshortdraw);
14809a747e4fSDavid du Colombier drawdebug = a[1];
14819a747e4fSDavid du Colombier continue;
14829a747e4fSDavid du Colombier
14839a747e4fSDavid du Colombier /* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/
14849a747e4fSDavid du Colombier case 'e':
14859a747e4fSDavid du Colombier case 'E':
14869a747e4fSDavid du Colombier printmesg(fmt="LLPlllPll", a, 0);
14879a747e4fSDavid du Colombier m = 1+4+4+2*4+4+4+4+2*4+2*4;
14889a747e4fSDavid du Colombier if(n < m)
14899a747e4fSDavid du Colombier error(Eshortdraw);
14909a747e4fSDavid du Colombier dst = drawimage(client, a+1);
14919a747e4fSDavid du Colombier dstid = BGLONG(a+1);
14929a747e4fSDavid du Colombier src = drawimage(client, a+5);
14939a747e4fSDavid du Colombier drawpoint(&p, a+9);
14949a747e4fSDavid du Colombier e0 = BGLONG(a+17);
14959a747e4fSDavid du Colombier e1 = BGLONG(a+21);
14969a747e4fSDavid du Colombier if(e0<0 || e1<0)
14979a747e4fSDavid du Colombier error("invalid ellipse semidiameter");
14989a747e4fSDavid du Colombier j = BGLONG(a+25);
14999a747e4fSDavid du Colombier if(j < 0)
15009a747e4fSDavid du Colombier error("negative ellipse thickness");
15019a747e4fSDavid du Colombier drawpoint(&sp, a+29);
15029a747e4fSDavid du Colombier c = j;
15039a747e4fSDavid du Colombier if(*a == 'E')
15049a747e4fSDavid du Colombier c = -1;
15059a747e4fSDavid du Colombier ox = BGLONG(a+37);
15069a747e4fSDavid du Colombier oy = BGLONG(a+41);
15076a9fc400SDavid du Colombier op = drawclientop(client);
15089a747e4fSDavid du Colombier /* high bit indicates arc angles are present */
15099a747e4fSDavid du Colombier if(ox & (1<<31)){
15109a747e4fSDavid du Colombier if((ox & (1<<30)) == 0)
15119a747e4fSDavid du Colombier ox &= ~(1<<31);
15126a9fc400SDavid du Colombier memarc(dst, p, e0, e1, c, src, sp, ox, oy, op);
15139a747e4fSDavid du Colombier }else
15146a9fc400SDavid du Colombier memellipse(dst, p, e0, e1, c, src, sp, op);
15159a747e4fSDavid du Colombier dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
15169a747e4fSDavid du Colombier continue;
15179a747e4fSDavid du Colombier
15189a747e4fSDavid du Colombier /* free: 'f' id[4] */
15199a747e4fSDavid du Colombier case 'f':
15209a747e4fSDavid du Colombier printmesg(fmt="L", a, 1);
15219a747e4fSDavid du Colombier m = 1+4;
15229a747e4fSDavid du Colombier if(n < m)
15239a747e4fSDavid du Colombier error(Eshortdraw);
15249a747e4fSDavid du Colombier ll = drawlookup(client, BGLONG(a+1), 0);
15259a747e4fSDavid du Colombier if(ll && ll->dscreen && ll->dscreen->owner != client)
15269a747e4fSDavid du Colombier ll->dscreen->owner->refreshme = 1;
15279a747e4fSDavid du Colombier drawuninstall(client, BGLONG(a+1));
15289a747e4fSDavid du Colombier continue;
15299a747e4fSDavid du Colombier
15309a747e4fSDavid du Colombier /* free screen: 'F' id[4] */
15319a747e4fSDavid du Colombier case 'F':
15329a747e4fSDavid du Colombier printmesg(fmt="L", a, 1);
15339a747e4fSDavid du Colombier m = 1+4;
15349a747e4fSDavid du Colombier if(n < m)
15359a747e4fSDavid du Colombier error(Eshortdraw);
15369a747e4fSDavid du Colombier drawlookupscreen(client, BGLONG(a+1), &cs);
15379a747e4fSDavid du Colombier drawuninstallscreen(client, cs);
15389a747e4fSDavid du Colombier continue;
15399a747e4fSDavid du Colombier
15409a747e4fSDavid du Colombier /* initialize font: 'i' fontid[4] nchars[4] ascent[1] */
15419a747e4fSDavid du Colombier case 'i':
15429a747e4fSDavid du Colombier printmesg(fmt="Llb", a, 1);
15439a747e4fSDavid du Colombier m = 1+4+4+1;
15449a747e4fSDavid du Colombier if(n < m)
15459a747e4fSDavid du Colombier error(Eshortdraw);
15469a747e4fSDavid du Colombier dstid = BGLONG(a+1);
15479a747e4fSDavid du Colombier if(dstid == 0)
15489a747e4fSDavid du Colombier error("can't use display as font");
15499a747e4fSDavid du Colombier font = drawlookup(client, dstid, 1);
15509a747e4fSDavid du Colombier if(font == 0)
15519a747e4fSDavid du Colombier error(Enodrawimage);
15529a747e4fSDavid du Colombier if(font->image->layer)
15539a747e4fSDavid du Colombier error("can't use window as font");
15549a747e4fSDavid du Colombier free(font->fchar); /* should we complain if non-zero? */
15559a747e4fSDavid du Colombier ni = BGLONG(a+5);
15569a747e4fSDavid du Colombier font->fchar = malloc(ni*sizeof(FChar));
15579a747e4fSDavid du Colombier if(font->fchar == 0)
15589a747e4fSDavid du Colombier error("no memory for font");
15599a747e4fSDavid du Colombier memset(font->fchar, 0, ni*sizeof(FChar));
15609a747e4fSDavid du Colombier font->nfchar = ni;
15619a747e4fSDavid du Colombier font->ascent = a[9];
15629a747e4fSDavid du Colombier continue;
15639a747e4fSDavid du Colombier
15649a747e4fSDavid du Colombier /* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
15659a747e4fSDavid du Colombier case 'l':
15669a747e4fSDavid du Colombier printmesg(fmt="LLSRPbb", a, 0);
15679a747e4fSDavid du Colombier m = 1+4+4+2+4*4+2*4+1+1;
15689a747e4fSDavid du Colombier if(n < m)
15699a747e4fSDavid du Colombier error(Eshortdraw);
15709a747e4fSDavid du Colombier font = drawlookup(client, BGLONG(a+1), 1);
15719a747e4fSDavid du Colombier if(font == 0)
15729a747e4fSDavid du Colombier error(Enodrawimage);
15739a747e4fSDavid du Colombier if(font->nfchar == 0)
15749a747e4fSDavid du Colombier error(Enotfont);
15759a747e4fSDavid du Colombier src = drawimage(client, a+5);
15769a747e4fSDavid du Colombier ci = BGSHORT(a+9);
15779a747e4fSDavid du Colombier if(ci >= font->nfchar)
15789a747e4fSDavid du Colombier error(Eindex);
15799a747e4fSDavid du Colombier drawrectangle(&r, a+11);
15809a747e4fSDavid du Colombier drawpoint(&p, a+27);
15816a9fc400SDavid du Colombier memdraw(font->image, r, src, p, memopaque, p, S);
15829a747e4fSDavid du Colombier fc = &font->fchar[ci];
15839a747e4fSDavid du Colombier fc->minx = r.min.x;
15849a747e4fSDavid du Colombier fc->maxx = r.max.x;
15859a747e4fSDavid du Colombier fc->miny = r.min.y;
15869a747e4fSDavid du Colombier fc->maxy = r.max.y;
15879a747e4fSDavid du Colombier fc->left = a[35];
15889a747e4fSDavid du Colombier fc->width = a[36];
15899a747e4fSDavid du Colombier continue;
15909a747e4fSDavid du Colombier
15919a747e4fSDavid du Colombier /* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */
15929a747e4fSDavid du Colombier case 'L':
15939a747e4fSDavid du Colombier printmesg(fmt="LPPlllLP", a, 0);
15949a747e4fSDavid du Colombier m = 1+4+2*4+2*4+4+4+4+4+2*4;
15959a747e4fSDavid du Colombier if(n < m)
15969a747e4fSDavid du Colombier error(Eshortdraw);
15979a747e4fSDavid du Colombier dst = drawimage(client, a+1);
15989a747e4fSDavid du Colombier dstid = BGLONG(a+1);
15999a747e4fSDavid du Colombier drawpoint(&p, a+5);
16009a747e4fSDavid du Colombier drawpoint(&q, a+13);
16019a747e4fSDavid du Colombier e0 = BGLONG(a+21);
16029a747e4fSDavid du Colombier e1 = BGLONG(a+25);
16039a747e4fSDavid du Colombier j = BGLONG(a+29);
16049a747e4fSDavid du Colombier if(j < 0)
16059a747e4fSDavid du Colombier error("negative line width");
16069a747e4fSDavid du Colombier src = drawimage(client, a+33);
16079a747e4fSDavid du Colombier drawpoint(&sp, a+37);
16086a9fc400SDavid du Colombier op = drawclientop(client);
16096a9fc400SDavid du Colombier memline(dst, p, q, e0, e1, j, src, sp, op);
16109a747e4fSDavid du Colombier /* avoid memlinebbox if possible */
16119a747e4fSDavid du Colombier if(dstid==0 || dst->layer!=nil){
16129a747e4fSDavid du Colombier /* BUG: this is terribly inefficient: update maximal containing rect*/
16139a747e4fSDavid du Colombier r = memlinebbox(p, q, e0, e1, j);
16149a747e4fSDavid du Colombier dstflush(dstid, dst, insetrect(r, -(1+1+j)));
16159a747e4fSDavid du Colombier }
16169a747e4fSDavid du Colombier continue;
16179a747e4fSDavid du Colombier
16189a747e4fSDavid du Colombier /* create image mask: 'm' newid[4] id[4] */
16199a747e4fSDavid du Colombier /*
16209a747e4fSDavid du Colombier *
16219a747e4fSDavid du Colombier case 'm':
16229a747e4fSDavid du Colombier printmesg("LL", a, 0);
16239a747e4fSDavid du Colombier m = 4+4;
16249a747e4fSDavid du Colombier if(n < m)
16259a747e4fSDavid du Colombier error(Eshortdraw);
16269a747e4fSDavid du Colombier break;
16279a747e4fSDavid du Colombier *
16289a747e4fSDavid du Colombier */
16299a747e4fSDavid du Colombier
16309a747e4fSDavid du Colombier /* attach to a named image: 'n' dstid[4] j[1] name[j] */
16319a747e4fSDavid du Colombier case 'n':
16329a747e4fSDavid du Colombier printmesg(fmt="Lz", a, 0);
16339a747e4fSDavid du Colombier m = 1+4+1;
16349a747e4fSDavid du Colombier if(n < m)
16359a747e4fSDavid du Colombier error(Eshortdraw);
16369a747e4fSDavid du Colombier j = a[5];
16379a747e4fSDavid du Colombier if(j == 0) /* give me a non-empty name please */
16389a747e4fSDavid du Colombier error(Eshortdraw);
16399a747e4fSDavid du Colombier m += j;
16409a747e4fSDavid du Colombier if(n < m)
16419a747e4fSDavid du Colombier error(Eshortdraw);
16429a747e4fSDavid du Colombier dstid = BGLONG(a+1);
16439a747e4fSDavid du Colombier if(drawlookup(client, dstid, 0))
16449a747e4fSDavid du Colombier error(Eimageexists);
16459a747e4fSDavid du Colombier dn = drawlookupname(j, (char*)a+6);
16469a747e4fSDavid du Colombier if(dn == nil)
16479a747e4fSDavid du Colombier error(Enoname);
16489a747e4fSDavid du Colombier if(drawinstall(client, dstid, dn->dimage->image, 0) == 0)
16499a747e4fSDavid du Colombier error(Edrawmem);
16509a747e4fSDavid du Colombier di = drawlookup(client, dstid, 0);
16519a747e4fSDavid du Colombier if(di == 0)
16529a747e4fSDavid du Colombier error("draw: can't happen");
16539a747e4fSDavid du Colombier di->vers = dn->vers;
16549a747e4fSDavid du Colombier di->name = smalloc(j+1);
16559a747e4fSDavid du Colombier di->fromname = dn->dimage;
16569a747e4fSDavid du Colombier di->fromname->ref++;
16579a747e4fSDavid du Colombier memmove(di->name, a+6, j);
16589a747e4fSDavid du Colombier di->name[j] = 0;
16599a747e4fSDavid du Colombier client->infoid = dstid;
16609a747e4fSDavid du Colombier continue;
16619a747e4fSDavid du Colombier
16629a747e4fSDavid du Colombier /* name an image: 'N' dstid[4] in[1] j[1] name[j] */
16639a747e4fSDavid du Colombier case 'N':
16649a747e4fSDavid du Colombier printmesg(fmt="Lbz", a, 0);
16659a747e4fSDavid du Colombier m = 1+4+1+1;
16669a747e4fSDavid du Colombier if(n < m)
16679a747e4fSDavid du Colombier error(Eshortdraw);
16689a747e4fSDavid du Colombier c = a[5];
16699a747e4fSDavid du Colombier j = a[6];
16709a747e4fSDavid du Colombier if(j == 0) /* give me a non-empty name please */
16719a747e4fSDavid du Colombier error(Eshortdraw);
16729a747e4fSDavid du Colombier m += j;
16739a747e4fSDavid du Colombier if(n < m)
16749a747e4fSDavid du Colombier error(Eshortdraw);
16759a747e4fSDavid du Colombier di = drawlookup(client, BGLONG(a+1), 0);
16769a747e4fSDavid du Colombier if(di == 0)
16779a747e4fSDavid du Colombier error(Enodrawimage);
16789a747e4fSDavid du Colombier if(di->name)
16799a747e4fSDavid du Colombier error(Enamed);
16809a747e4fSDavid du Colombier if(c)
16819a747e4fSDavid du Colombier drawaddname(client, di, j, (char*)a+7);
16829a747e4fSDavid du Colombier else{
16839a747e4fSDavid du Colombier dn = drawlookupname(j, (char*)a+7);
16849a747e4fSDavid du Colombier if(dn == nil)
16859a747e4fSDavid du Colombier error(Enoname);
16869a747e4fSDavid du Colombier if(dn->dimage != di)
16879a747e4fSDavid du Colombier error(Ewrongname);
16889a747e4fSDavid du Colombier drawdelname(dn);
16899a747e4fSDavid du Colombier }
16909a747e4fSDavid du Colombier continue;
16919a747e4fSDavid du Colombier
16929a747e4fSDavid du Colombier /* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */
16939a747e4fSDavid du Colombier case 'o':
16949a747e4fSDavid du Colombier printmesg(fmt="LPP", a, 0);
16959a747e4fSDavid du Colombier m = 1+4+2*4+2*4;
16969a747e4fSDavid du Colombier if(n < m)
16979a747e4fSDavid du Colombier error(Eshortdraw);
16989a747e4fSDavid du Colombier dst = drawimage(client, a+1);
16999a747e4fSDavid du Colombier if(dst->layer){
17009a747e4fSDavid du Colombier drawpoint(&p, a+5);
17019a747e4fSDavid du Colombier drawpoint(&q, a+13);
17029a747e4fSDavid du Colombier r = dst->layer->screenr;
17039a747e4fSDavid du Colombier ni = memlorigin(dst, p, q);
17049a747e4fSDavid du Colombier if(ni < 0)
17059a747e4fSDavid du Colombier error("image origin failed");
17069a747e4fSDavid du Colombier if(ni > 0){
17079a747e4fSDavid du Colombier addflush(r);
17089a747e4fSDavid du Colombier addflush(dst->layer->screenr);
17099a747e4fSDavid du Colombier ll = drawlookup(client, BGLONG(a+1), 1);
17109a747e4fSDavid du Colombier drawrefreshscreen(ll, client);
17119a747e4fSDavid du Colombier }
17129a747e4fSDavid du Colombier }
17139a747e4fSDavid du Colombier continue;
17149a747e4fSDavid du Colombier
17156a9fc400SDavid du Colombier /* set compositing operator for next draw operation: 'O' op */
17166a9fc400SDavid du Colombier case 'O':
17176a9fc400SDavid du Colombier printmesg(fmt="b", a, 0);
17186a9fc400SDavid du Colombier m = 1+1;
17196a9fc400SDavid du Colombier if(n < m)
17206a9fc400SDavid du Colombier error(Eshortdraw);
17216a9fc400SDavid du Colombier client->op = a[1];
17226a9fc400SDavid du Colombier continue;
17236a9fc400SDavid du Colombier
17249a747e4fSDavid 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] */
17259a747e4fSDavid 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] */
17269a747e4fSDavid du Colombier case 'p':
17279a747e4fSDavid du Colombier case 'P':
17289a747e4fSDavid du Colombier printmesg(fmt="LslllLPP", a, 0);
17299a747e4fSDavid du Colombier m = 1+4+2+4+4+4+4+2*4;
17309a747e4fSDavid du Colombier if(n < m)
17319a747e4fSDavid du Colombier error(Eshortdraw);
17329a747e4fSDavid du Colombier dstid = BGLONG(a+1);
17339a747e4fSDavid du Colombier dst = drawimage(client, a+1);
17349a747e4fSDavid du Colombier ni = BGSHORT(a+5);
17359a747e4fSDavid du Colombier if(ni < 0)
17369a747e4fSDavid du Colombier error("negative count in polygon");
17379a747e4fSDavid du Colombier e0 = BGLONG(a+7);
17389a747e4fSDavid du Colombier e1 = BGLONG(a+11);
17399a747e4fSDavid du Colombier j = 0;
17409a747e4fSDavid du Colombier if(*a == 'p'){
17419a747e4fSDavid du Colombier j = BGLONG(a+15);
17429a747e4fSDavid du Colombier if(j < 0)
17439a747e4fSDavid du Colombier error("negative polygon line width");
17449a747e4fSDavid du Colombier }
17459a747e4fSDavid du Colombier src = drawimage(client, a+19);
17469a747e4fSDavid du Colombier drawpoint(&sp, a+23);
17479a747e4fSDavid du Colombier drawpoint(&p, a+31);
17489a747e4fSDavid du Colombier ni++;
17499a747e4fSDavid du Colombier pp = malloc(ni*sizeof(Point));
17509a747e4fSDavid du Colombier if(pp == nil)
17519a747e4fSDavid du Colombier error(Enomem);
17529a747e4fSDavid du Colombier doflush = 0;
17539a747e4fSDavid du Colombier if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data))
17549a747e4fSDavid du Colombier doflush = 1; /* simplify test in loop */
17559a747e4fSDavid du Colombier ox = oy = 0;
17566a9fc400SDavid du Colombier esize = 0;
17579a747e4fSDavid du Colombier u = a+m;
17589a747e4fSDavid du Colombier for(y=0; y<ni; y++){
17596a9fc400SDavid du Colombier q = p;
17606a9fc400SDavid du Colombier oesize = esize;
17619a747e4fSDavid du Colombier u = drawcoord(u, a+n, ox, &p.x);
17629a747e4fSDavid du Colombier u = drawcoord(u, a+n, oy, &p.y);
17639a747e4fSDavid du Colombier ox = p.x;
17649a747e4fSDavid du Colombier oy = p.y;
17659a747e4fSDavid du Colombier if(doflush){
17669a747e4fSDavid du Colombier esize = j;
17679a747e4fSDavid du Colombier if(*a == 'p'){
17689a747e4fSDavid du Colombier if(y == 0){
17699a747e4fSDavid du Colombier c = memlineendsize(e0);
17709a747e4fSDavid du Colombier if(c > esize)
17719a747e4fSDavid du Colombier esize = c;
17729a747e4fSDavid du Colombier }
17739a747e4fSDavid du Colombier if(y == ni-1){
17749a747e4fSDavid du Colombier c = memlineendsize(e1);
17759a747e4fSDavid du Colombier if(c > esize)
17769a747e4fSDavid du Colombier esize = c;
17779a747e4fSDavid du Colombier }
17789a747e4fSDavid du Colombier }
17799a747e4fSDavid du Colombier if(*a=='P' && e0!=1 && e0 !=~0)
17809a747e4fSDavid du Colombier r = dst->clipr;
17816a9fc400SDavid du Colombier else if(y > 0){
17826a9fc400SDavid du Colombier r = Rect(q.x-oesize, q.y-oesize, q.x+oesize+1, q.y+oesize+1);
17836a9fc400SDavid du Colombier combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
17846a9fc400SDavid du Colombier }
17856a9fc400SDavid du Colombier if(rectclip(&r, dst->clipr)) /* should perhaps be an arg to dstflush */
17869a747e4fSDavid du Colombier dstflush(dstid, dst, r);
17879a747e4fSDavid du Colombier }
17889a747e4fSDavid du Colombier pp[y] = p;
17899a747e4fSDavid du Colombier }
17906a9fc400SDavid du Colombier if(y == 1)
17916a9fc400SDavid du Colombier dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
17926a9fc400SDavid du Colombier op = drawclientop(client);
17939a747e4fSDavid du Colombier if(*a == 'p')
17946a9fc400SDavid du Colombier mempoly(dst, pp, ni, e0, e1, j, src, sp, op);
17959a747e4fSDavid du Colombier else
17966a9fc400SDavid du Colombier memfillpoly(dst, pp, ni, e0, src, sp, op);
17979a747e4fSDavid du Colombier free(pp);
17989a747e4fSDavid du Colombier m = u-a;
17999a747e4fSDavid du Colombier continue;
18009a747e4fSDavid du Colombier
18019a747e4fSDavid du Colombier /* read: 'r' id[4] R[4*4] */
18029a747e4fSDavid du Colombier case 'r':
18039a747e4fSDavid du Colombier printmesg(fmt="LR", a, 0);
18049a747e4fSDavid du Colombier m = 1+4+4*4;
18059a747e4fSDavid du Colombier if(n < m)
18069a747e4fSDavid du Colombier error(Eshortdraw);
18079a747e4fSDavid du Colombier i = drawimage(client, a+1);
18089a747e4fSDavid du Colombier if(0 && i->layer)
18099a747e4fSDavid du Colombier error("readimage from window unimplemented");
18109a747e4fSDavid du Colombier drawrectangle(&r, a+5);
18119a747e4fSDavid du Colombier if(!rectinrect(r, i->r))
18129a747e4fSDavid du Colombier error(Ereadoutside);
18139a747e4fSDavid du Colombier c = bytesperline(r, i->depth);
18149a747e4fSDavid du Colombier c *= Dy(r);
18159a747e4fSDavid du Colombier free(client->readdata);
18169a747e4fSDavid du Colombier client->readdata = mallocz(c, 0);
18179a747e4fSDavid du Colombier if(client->readdata == nil)
18189a747e4fSDavid du Colombier error("readimage malloc failed");
18199a747e4fSDavid du Colombier client->nreaddata = unloadmemimage(i, r, client->readdata, c);
18209a747e4fSDavid du Colombier if(client->nreaddata < 0){
18219a747e4fSDavid du Colombier free(client->readdata);
18229a747e4fSDavid du Colombier client->readdata = nil;
18239a747e4fSDavid du Colombier error("bad readimage call");
18249a747e4fSDavid du Colombier }
18259a747e4fSDavid du Colombier continue;
18269a747e4fSDavid du Colombier
18279a747e4fSDavid du Colombier /* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */
18289a747e4fSDavid 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]) */
18299a747e4fSDavid du Colombier case 's':
18309a747e4fSDavid du Colombier case 'x':
18319a747e4fSDavid du Colombier printmesg(fmt="LLLPRPs", a, 0);
18329a747e4fSDavid du Colombier m = 1+4+4+4+2*4+4*4+2*4+2;
18339a747e4fSDavid du Colombier if(*a == 'x')
18349a747e4fSDavid du Colombier m += 4+2*4;
18359a747e4fSDavid du Colombier if(n < m)
18369a747e4fSDavid du Colombier error(Eshortdraw);
18379a747e4fSDavid du Colombier
18389a747e4fSDavid du Colombier dst = drawimage(client, a+1);
18399a747e4fSDavid du Colombier dstid = BGLONG(a+1);
18409a747e4fSDavid du Colombier src = drawimage(client, a+5);
18419a747e4fSDavid du Colombier font = drawlookup(client, BGLONG(a+9), 1);
18429a747e4fSDavid du Colombier if(font == 0)
18439a747e4fSDavid du Colombier error(Enodrawimage);
18449a747e4fSDavid du Colombier if(font->nfchar == 0)
18459a747e4fSDavid du Colombier error(Enotfont);
18469a747e4fSDavid du Colombier drawpoint(&p, a+13);
18479a747e4fSDavid du Colombier drawrectangle(&r, a+21);
18489a747e4fSDavid du Colombier drawpoint(&sp, a+37);
18499a747e4fSDavid du Colombier ni = BGSHORT(a+45);
18509a747e4fSDavid du Colombier u = a+m;
18519a747e4fSDavid du Colombier m += ni*2;
18529a747e4fSDavid du Colombier if(n < m)
18539a747e4fSDavid du Colombier error(Eshortdraw);
18549a747e4fSDavid du Colombier clipr = dst->clipr;
18559a747e4fSDavid du Colombier dst->clipr = r;
18566a9fc400SDavid du Colombier op = drawclientop(client);
18579a747e4fSDavid du Colombier if(*a == 'x'){
18589a747e4fSDavid du Colombier /* paint background */
18599a747e4fSDavid du Colombier l = drawimage(client, a+47);
18609a747e4fSDavid du Colombier drawpoint(&q, a+51);
18619a747e4fSDavid du Colombier r.min.x = p.x;
18629a747e4fSDavid du Colombier r.min.y = p.y-font->ascent;
18639a747e4fSDavid du Colombier r.max.x = p.x;
18649a747e4fSDavid du Colombier r.max.y = r.min.y+Dy(font->image->r);
18659a747e4fSDavid du Colombier j = ni;
18669a747e4fSDavid du Colombier while(--j >= 0){
18679a747e4fSDavid du Colombier ci = BGSHORT(u);
18689a747e4fSDavid du Colombier if(ci<0 || ci>=font->nfchar){
18699a747e4fSDavid du Colombier dst->clipr = clipr;
18709a747e4fSDavid du Colombier error(Eindex);
18719a747e4fSDavid du Colombier }
18729a747e4fSDavid du Colombier r.max.x += font->fchar[ci].width;
18739a747e4fSDavid du Colombier u += 2;
18749a747e4fSDavid du Colombier }
18756a9fc400SDavid du Colombier memdraw(dst, r, l, q, memopaque, ZP, op);
18769a747e4fSDavid du Colombier u -= 2*ni;
18779a747e4fSDavid du Colombier }
18789a747e4fSDavid du Colombier q = p;
18799a747e4fSDavid du Colombier while(--ni >= 0){
18809a747e4fSDavid du Colombier ci = BGSHORT(u);
18819a747e4fSDavid du Colombier if(ci<0 || ci>=font->nfchar){
18829a747e4fSDavid du Colombier dst->clipr = clipr;
18839a747e4fSDavid du Colombier error(Eindex);
18849a747e4fSDavid du Colombier }
18856a9fc400SDavid du Colombier q = drawchar(dst, q, src, &sp, font, ci, op);
18869a747e4fSDavid du Colombier u += 2;
18879a747e4fSDavid du Colombier }
18889a747e4fSDavid du Colombier dst->clipr = clipr;
18899a747e4fSDavid du Colombier p.y -= font->ascent;
18909a747e4fSDavid du Colombier dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
18919a747e4fSDavid du Colombier continue;
18929a747e4fSDavid du Colombier
18939a747e4fSDavid du Colombier /* use public screen: 'S' id[4] chan[4] */
18949a747e4fSDavid du Colombier case 'S':
18959a747e4fSDavid du Colombier printmesg(fmt="Ll", a, 0);
18969a747e4fSDavid du Colombier m = 1+4+4;
18979a747e4fSDavid du Colombier if(n < m)
18989a747e4fSDavid du Colombier error(Eshortdraw);
18999a747e4fSDavid du Colombier dstid = BGLONG(a+1);
19009a747e4fSDavid du Colombier if(dstid == 0)
19019a747e4fSDavid du Colombier error(Ebadarg);
19029a747e4fSDavid du Colombier dscrn = drawlookupdscreen(dstid);
19039a747e4fSDavid du Colombier if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client))
19049a747e4fSDavid du Colombier error(Enodrawscreen);
19059a747e4fSDavid du Colombier if(dscrn->screen->image->chan != BGLONG(a+5))
19069a747e4fSDavid du Colombier error("inconsistent chan");
19079a747e4fSDavid du Colombier if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0)
19089a747e4fSDavid du Colombier error(Edrawmem);
19099a747e4fSDavid du Colombier continue;
19109a747e4fSDavid du Colombier
19119a747e4fSDavid du Colombier /* top or bottom windows: 't' top[1] nw[2] n*id[4] */
19129a747e4fSDavid du Colombier case 't':
19139a747e4fSDavid du Colombier printmesg(fmt="bsL", a, 0);
19149a747e4fSDavid du Colombier m = 1+1+2;
19159a747e4fSDavid du Colombier if(n < m)
19169a747e4fSDavid du Colombier error(Eshortdraw);
19179a747e4fSDavid du Colombier nw = BGSHORT(a+2);
19189a747e4fSDavid du Colombier if(nw < 0)
19199a747e4fSDavid du Colombier error(Ebadarg);
19209a747e4fSDavid du Colombier if(nw == 0)
19219a747e4fSDavid du Colombier continue;
19229a747e4fSDavid du Colombier m += nw*4;
19239a747e4fSDavid du Colombier if(n < m)
19249a747e4fSDavid du Colombier error(Eshortdraw);
19259a747e4fSDavid du Colombier lp = malloc(nw*sizeof(Memimage*));
19269a747e4fSDavid du Colombier if(lp == 0)
19279a747e4fSDavid du Colombier error(Enomem);
19289a747e4fSDavid du Colombier if(waserror()){
19299a747e4fSDavid du Colombier free(lp);
19309a747e4fSDavid du Colombier nexterror();
19319a747e4fSDavid du Colombier }
19329a747e4fSDavid du Colombier for(j=0; j<nw; j++)
19339a747e4fSDavid du Colombier lp[j] = drawimage(client, a+1+1+2+j*4);
19349a747e4fSDavid du Colombier if(lp[0]->layer == 0)
19359a747e4fSDavid du Colombier error("images are not windows");
19369a747e4fSDavid du Colombier for(j=1; j<nw; j++)
19379a747e4fSDavid du Colombier if(lp[j]->layer->screen != lp[0]->layer->screen)
19389a747e4fSDavid du Colombier error("images not on same screen");
19399a747e4fSDavid du Colombier if(a[1])
19409a747e4fSDavid du Colombier memltofrontn(lp, nw);
19419a747e4fSDavid du Colombier else
19429a747e4fSDavid du Colombier memltorearn(lp, nw);
19439a747e4fSDavid du Colombier if(lp[0]->layer->screen->image->data == screenimage->data)
19449a747e4fSDavid du Colombier for(j=0; j<nw; j++)
19459a747e4fSDavid du Colombier addflush(lp[j]->layer->screenr);
19469a747e4fSDavid du Colombier ll = drawlookup(client, BGLONG(a+1+1+2), 1);
19479a747e4fSDavid du Colombier drawrefreshscreen(ll, client);
19489a747e4fSDavid du Colombier poperror();
19499a747e4fSDavid du Colombier free(lp);
19509a747e4fSDavid du Colombier continue;
19519a747e4fSDavid du Colombier
19529a747e4fSDavid du Colombier /* visible: 'v' */
19539a747e4fSDavid du Colombier case 'v':
19549a747e4fSDavid du Colombier printmesg(fmt="", a, 0);
19559a747e4fSDavid du Colombier m = 1;
19569a747e4fSDavid du Colombier drawflush();
19579a747e4fSDavid du Colombier continue;
19589a747e4fSDavid du Colombier
19599a747e4fSDavid du Colombier /* write: 'y' id[4] R[4*4] data[x*1] */
19609a747e4fSDavid du Colombier /* write from compressed data: 'Y' id[4] R[4*4] data[x*1] */
19619a747e4fSDavid du Colombier case 'y':
19629a747e4fSDavid du Colombier case 'Y':
19639a747e4fSDavid du Colombier printmesg(fmt="LR", a, 0);
19649a747e4fSDavid du Colombier // iprint("load %c\n", *a);
19659a747e4fSDavid du Colombier m = 1+4+4*4;
19669a747e4fSDavid du Colombier if(n < m)
19679a747e4fSDavid du Colombier error(Eshortdraw);
19689a747e4fSDavid du Colombier dstid = BGLONG(a+1);
19699a747e4fSDavid du Colombier dst = drawimage(client, a+1);
19709a747e4fSDavid du Colombier drawrectangle(&r, a+5);
19719a747e4fSDavid du Colombier if(!rectinrect(r, dst->r))
19729a747e4fSDavid du Colombier error(Ewriteoutside);
19739a747e4fSDavid du Colombier y = memload(dst, r, a+m, n-m, *a=='Y');
19749a747e4fSDavid du Colombier if(y < 0)
19759a747e4fSDavid du Colombier error("bad writeimage call");
19769a747e4fSDavid du Colombier dstflush(dstid, dst, r);
19779a747e4fSDavid du Colombier m += y;
19789a747e4fSDavid du Colombier continue;
19799a747e4fSDavid du Colombier }
19809a747e4fSDavid du Colombier }
19819a747e4fSDavid du Colombier poperror();
19829a747e4fSDavid du Colombier }
19839a747e4fSDavid du Colombier
19849a747e4fSDavid du Colombier Dev drawdevtab = {
19859a747e4fSDavid du Colombier 'i',
19869a747e4fSDavid du Colombier "draw",
19879a747e4fSDavid du Colombier
19889a747e4fSDavid du Colombier devreset,
19899a747e4fSDavid du Colombier devinit,
19909a747e4fSDavid du Colombier drawattach,
19919a747e4fSDavid du Colombier drawwalk,
19929a747e4fSDavid du Colombier drawstat,
19939a747e4fSDavid du Colombier drawopen,
19949a747e4fSDavid du Colombier devcreate,
19959a747e4fSDavid du Colombier drawclose,
19969a747e4fSDavid du Colombier drawread,
19979a747e4fSDavid du Colombier devbread,
19989a747e4fSDavid du Colombier drawwrite,
19999a747e4fSDavid du Colombier devbwrite,
20009a747e4fSDavid du Colombier devremove,
20019a747e4fSDavid du Colombier devwstat,
20029a747e4fSDavid du Colombier };
20039a747e4fSDavid du Colombier
20049a747e4fSDavid du Colombier /*
20059a747e4fSDavid du Colombier * On 8 bit displays, load the default color map
20069a747e4fSDavid du Colombier */
20079a747e4fSDavid du Colombier void
drawcmap(void)20089a747e4fSDavid du Colombier drawcmap(void)
20099a747e4fSDavid du Colombier {
20109a747e4fSDavid du Colombier int r, g, b, cr, cg, cb, v;
20119a747e4fSDavid du Colombier int num, den;
20129a747e4fSDavid du Colombier int i, j;
20139a747e4fSDavid du Colombier
20149a747e4fSDavid du Colombier drawactive(1); /* to restore map from backup */
20159a747e4fSDavid du Colombier for(r=0,i=0; r!=4; r++)
20169a747e4fSDavid du Colombier for(v=0; v!=4; v++,i+=16){
20179a747e4fSDavid du Colombier for(g=0,j=v-r; g!=4; g++)
20189a747e4fSDavid du Colombier for(b=0;b!=4;b++,j++){
20199a747e4fSDavid du Colombier den = r;
20209a747e4fSDavid du Colombier if(g > den)
20219a747e4fSDavid du Colombier den = g;
20229a747e4fSDavid du Colombier if(b > den)
20239a747e4fSDavid du Colombier den = b;
20249a747e4fSDavid du Colombier if(den == 0) /* divide check -- pick grey shades */
20259a747e4fSDavid du Colombier cr = cg = cb = v*17;
20269a747e4fSDavid du Colombier else{
20279a747e4fSDavid du Colombier num = 17*(4*den+v);
20289a747e4fSDavid du Colombier cr = r*num/den;
20299a747e4fSDavid du Colombier cg = g*num/den;
20309a747e4fSDavid du Colombier cb = b*num/den;
20319a747e4fSDavid du Colombier }
20329a747e4fSDavid du Colombier setcolor(i+(j&15),
20339a747e4fSDavid du Colombier cr*0x01010101, cg*0x01010101, cb*0x01010101);
20349a747e4fSDavid du Colombier }
20359a747e4fSDavid du Colombier }
20369a747e4fSDavid du Colombier }
20379a747e4fSDavid du Colombier
20389a747e4fSDavid du Colombier void
drawblankscreen(int blank)20399a747e4fSDavid du Colombier drawblankscreen(int blank)
20409a747e4fSDavid du Colombier {
20419a747e4fSDavid du Colombier int i, nc;
20429a747e4fSDavid du Colombier ulong *p;
20439a747e4fSDavid du Colombier
20449a747e4fSDavid du Colombier if(blank == sdraw.blanked)
20459a747e4fSDavid du Colombier return;
20469a747e4fSDavid du Colombier if(!canqlock(&sdraw))
20479a747e4fSDavid du Colombier return;
20489a747e4fSDavid du Colombier if(!initscreenimage()){
20499a747e4fSDavid du Colombier qunlock(&sdraw);
20509a747e4fSDavid du Colombier return;
20519a747e4fSDavid du Colombier }
20529a747e4fSDavid du Colombier p = sdraw.savemap;
20539a747e4fSDavid du Colombier nc = screenimage->depth > 8 ? 256 : 1<<screenimage->depth;
20549a747e4fSDavid du Colombier
20559a747e4fSDavid du Colombier /*
20569a747e4fSDavid du Colombier * blankscreen uses the hardware to blank the screen
20579a747e4fSDavid du Colombier * when possible. to help in cases when it is not possible,
20589a747e4fSDavid du Colombier * we set the color map to be all black.
20599a747e4fSDavid du Colombier */
20609a747e4fSDavid du Colombier if(blank == 0){ /* turn screen on */
20619a747e4fSDavid du Colombier for(i=0; i<nc; i++, p+=3)
20629a747e4fSDavid du Colombier setcolor(i, p[0], p[1], p[2]);
20639a747e4fSDavid du Colombier blankscreen(0);
20649a747e4fSDavid du Colombier }else{ /* turn screen off */
20659a747e4fSDavid du Colombier blankscreen(1);
20669a747e4fSDavid du Colombier for(i=0; i<nc; i++, p+=3){
20679a747e4fSDavid du Colombier getcolor(i, &p[0], &p[1], &p[2]);
20689a747e4fSDavid du Colombier setcolor(i, 0, 0, 0);
20699a747e4fSDavid du Colombier }
20709a747e4fSDavid du Colombier }
20719a747e4fSDavid du Colombier sdraw.blanked = blank;
20729a747e4fSDavid du Colombier qunlock(&sdraw);
20739a747e4fSDavid du Colombier }
20749a747e4fSDavid du Colombier
20759a747e4fSDavid du Colombier /*
20769a747e4fSDavid du Colombier * record activity on screen, changing blanking as appropriate
20779a747e4fSDavid du Colombier */
20789a747e4fSDavid du Colombier void
drawactive(int active)20799a747e4fSDavid du Colombier drawactive(int active)
20809a747e4fSDavid du Colombier {
20819a747e4fSDavid du Colombier if(active){
20829a747e4fSDavid du Colombier drawblankscreen(0);
20839a747e4fSDavid du Colombier sdraw.blanktime = 0;
208422a127bbSDavid du Colombier }else
20859a747e4fSDavid du Colombier sdraw.blanktime++;
20869a747e4fSDavid du Colombier }
2087