18ccd4a63SDavid du Colombier #include "u.h"
28ccd4a63SDavid du Colombier #include "lib.h"
38ccd4a63SDavid du Colombier #include "dat.h"
48ccd4a63SDavid du Colombier #include "fns.h"
58ccd4a63SDavid du Colombier #include "error.h"
68ccd4a63SDavid du Colombier
78ccd4a63SDavid du Colombier #define Image IMAGE
88ccd4a63SDavid du Colombier #include <draw.h>
98ccd4a63SDavid du Colombier #include <memdraw.h>
108ccd4a63SDavid du Colombier #include <memlayer.h>
118ccd4a63SDavid du Colombier #include <cursor.h>
128ccd4a63SDavid du Colombier #include "screen.h"
138ccd4a63SDavid du Colombier
148ccd4a63SDavid du Colombier enum
158ccd4a63SDavid du Colombier {
168ccd4a63SDavid du Colombier Qtopdir = 0,
178ccd4a63SDavid du Colombier Qnew,
188ccd4a63SDavid du Colombier Q3rd,
198ccd4a63SDavid du Colombier Q2nd,
208ccd4a63SDavid du Colombier Qcolormap,
218ccd4a63SDavid du Colombier Qctl,
228ccd4a63SDavid du Colombier Qdata,
238ccd4a63SDavid du Colombier Qrefresh,
248ccd4a63SDavid du Colombier };
258ccd4a63SDavid du Colombier
268ccd4a63SDavid du Colombier /*
278ccd4a63SDavid du Colombier * Qid path is:
288ccd4a63SDavid du Colombier * 4 bits of file type (qids above)
298ccd4a63SDavid du Colombier * 24 bits of mux slot number +1; 0 means not attached to client
308ccd4a63SDavid du Colombier */
318ccd4a63SDavid du Colombier #define QSHIFT 4 /* location in qid of client # */
328ccd4a63SDavid du Colombier
338ccd4a63SDavid du Colombier #define QID(q) ((((ulong)(q).path)&0x0000000F)>>0)
348ccd4a63SDavid du Colombier #define CLIENTPATH(q) ((((ulong)q)&0x7FFFFFF0)>>QSHIFT)
358ccd4a63SDavid du Colombier #define CLIENT(q) CLIENTPATH((q).path)
368ccd4a63SDavid du Colombier
378ccd4a63SDavid du Colombier #define NHASH (1<<5)
388ccd4a63SDavid du Colombier #define HASHMASK (NHASH-1)
398ccd4a63SDavid du Colombier #define IOUNIT (64*1024)
408ccd4a63SDavid du Colombier
418ccd4a63SDavid du Colombier typedef struct Client Client;
428ccd4a63SDavid du Colombier typedef struct Draw Draw;
438ccd4a63SDavid du Colombier typedef struct DImage DImage;
448ccd4a63SDavid du Colombier typedef struct DScreen DScreen;
458ccd4a63SDavid du Colombier typedef struct CScreen CScreen;
468ccd4a63SDavid du Colombier typedef struct FChar FChar;
478ccd4a63SDavid du Colombier typedef struct Refresh Refresh;
488ccd4a63SDavid du Colombier typedef struct Refx Refx;
498ccd4a63SDavid du Colombier typedef struct DName DName;
508ccd4a63SDavid du Colombier
518ccd4a63SDavid du Colombier ulong blanktime = 30; /* in minutes; a half hour */
528ccd4a63SDavid du Colombier
538ccd4a63SDavid du Colombier struct Draw
548ccd4a63SDavid du Colombier {
558ccd4a63SDavid du Colombier QLock lk;
568ccd4a63SDavid du Colombier int clientid;
578ccd4a63SDavid du Colombier int nclient;
588ccd4a63SDavid du Colombier Client** client;
598ccd4a63SDavid du Colombier int nname;
608ccd4a63SDavid du Colombier DName* name;
618ccd4a63SDavid du Colombier int vers;
628ccd4a63SDavid du Colombier int softscreen;
638ccd4a63SDavid du Colombier int blanked; /* screen turned off */
648ccd4a63SDavid du Colombier ulong blanktime; /* time of last operation */
658ccd4a63SDavid du Colombier ulong savemap[3*256];
668ccd4a63SDavid du Colombier };
678ccd4a63SDavid du Colombier
688ccd4a63SDavid du Colombier struct Client
698ccd4a63SDavid du Colombier {
708ccd4a63SDavid du Colombier Ref r;
718ccd4a63SDavid du Colombier DImage* dimage[NHASH];
728ccd4a63SDavid du Colombier CScreen* cscreen;
738ccd4a63SDavid du Colombier Refresh* refresh;
748ccd4a63SDavid du Colombier Rendez refrend;
758ccd4a63SDavid du Colombier uchar* readdata;
768ccd4a63SDavid du Colombier int nreaddata;
778ccd4a63SDavid du Colombier int busy;
788ccd4a63SDavid du Colombier int clientid;
798ccd4a63SDavid du Colombier int slot;
808ccd4a63SDavid du Colombier int refreshme;
818ccd4a63SDavid du Colombier int infoid;
828ccd4a63SDavid du Colombier int op;
838ccd4a63SDavid du Colombier };
848ccd4a63SDavid du Colombier
858ccd4a63SDavid du Colombier struct Refresh
868ccd4a63SDavid du Colombier {
878ccd4a63SDavid du Colombier DImage* dimage;
888ccd4a63SDavid du Colombier Rectangle r;
898ccd4a63SDavid du Colombier Refresh* next;
908ccd4a63SDavid du Colombier };
918ccd4a63SDavid du Colombier
928ccd4a63SDavid du Colombier struct Refx
938ccd4a63SDavid du Colombier {
948ccd4a63SDavid du Colombier Client* client;
958ccd4a63SDavid du Colombier DImage* dimage;
968ccd4a63SDavid du Colombier };
978ccd4a63SDavid du Colombier
988ccd4a63SDavid du Colombier struct DName
998ccd4a63SDavid du Colombier {
1008ccd4a63SDavid du Colombier char *name;
1018ccd4a63SDavid du Colombier Client *client;
1028ccd4a63SDavid du Colombier DImage* dimage;
1038ccd4a63SDavid du Colombier int vers;
1048ccd4a63SDavid du Colombier };
1058ccd4a63SDavid du Colombier
1068ccd4a63SDavid du Colombier struct FChar
1078ccd4a63SDavid du Colombier {
1088ccd4a63SDavid du Colombier int minx; /* left edge of bits */
1098ccd4a63SDavid du Colombier int maxx; /* right edge of bits */
1108ccd4a63SDavid du Colombier uchar miny; /* first non-zero scan-line */
1118ccd4a63SDavid du Colombier uchar maxy; /* last non-zero scan-line + 1 */
1128ccd4a63SDavid du Colombier schar left; /* offset of baseline */
1138ccd4a63SDavid du Colombier uchar width; /* width of baseline */
1148ccd4a63SDavid du Colombier };
1158ccd4a63SDavid du Colombier
1168ccd4a63SDavid du Colombier /*
1178ccd4a63SDavid du Colombier * Reference counts in DImages:
1188ccd4a63SDavid du Colombier * one per open by original client
1198ccd4a63SDavid du Colombier * one per screen image or fill
1208ccd4a63SDavid du Colombier * one per image derived from this one by name
1218ccd4a63SDavid du Colombier */
1228ccd4a63SDavid du Colombier struct DImage
1238ccd4a63SDavid du Colombier {
1248ccd4a63SDavid du Colombier int id;
1258ccd4a63SDavid du Colombier int ref;
1268ccd4a63SDavid du Colombier char *name;
1278ccd4a63SDavid du Colombier int vers;
1288ccd4a63SDavid du Colombier Memimage* image;
1298ccd4a63SDavid du Colombier int ascent;
1308ccd4a63SDavid du Colombier int nfchar;
1318ccd4a63SDavid du Colombier FChar* fchar;
1328ccd4a63SDavid du Colombier DScreen* dscreen; /* 0 if not a window */
1338ccd4a63SDavid du Colombier DImage* fromname; /* image this one is derived from, by name */
1348ccd4a63SDavid du Colombier DImage* next;
1358ccd4a63SDavid du Colombier };
1368ccd4a63SDavid du Colombier
1378ccd4a63SDavid du Colombier struct CScreen
1388ccd4a63SDavid du Colombier {
1398ccd4a63SDavid du Colombier DScreen* dscreen;
1408ccd4a63SDavid du Colombier CScreen* next;
1418ccd4a63SDavid du Colombier };
1428ccd4a63SDavid du Colombier
1438ccd4a63SDavid du Colombier struct DScreen
1448ccd4a63SDavid du Colombier {
1458ccd4a63SDavid du Colombier int id;
1468ccd4a63SDavid du Colombier int public;
1478ccd4a63SDavid du Colombier int ref;
1488ccd4a63SDavid du Colombier DImage *dimage;
1498ccd4a63SDavid du Colombier DImage *dfill;
1508ccd4a63SDavid du Colombier Memscreen* screen;
1518ccd4a63SDavid du Colombier Client* owner;
1528ccd4a63SDavid du Colombier DScreen* next;
1538ccd4a63SDavid du Colombier };
1548ccd4a63SDavid du Colombier
1558ccd4a63SDavid du Colombier static Draw sdraw;
1568ccd4a63SDavid du Colombier static Memimage *screenimage;
1578ccd4a63SDavid du Colombier static Memdata screendata;
1588ccd4a63SDavid du Colombier static Rectangle flushrect;
1598ccd4a63SDavid du Colombier static int waste;
1608ccd4a63SDavid du Colombier static DScreen* dscreen;
1618ccd4a63SDavid du Colombier extern void flushmemscreen(Rectangle);
1628ccd4a63SDavid du Colombier void drawmesg(Client*, void*, int);
1638ccd4a63SDavid du Colombier void drawuninstall(Client*, int);
1648ccd4a63SDavid du Colombier void drawfreedimage(DImage*);
1658ccd4a63SDavid du Colombier Client* drawclientofpath(ulong);
1668ccd4a63SDavid du Colombier
1678ccd4a63SDavid du Colombier static char Enodrawimage[] = "unknown id for draw image";
1688ccd4a63SDavid du Colombier static char Enodrawscreen[] = "unknown id for draw screen";
1698ccd4a63SDavid du Colombier static char Eshortdraw[] = "short draw message";
1708ccd4a63SDavid du Colombier static char Eshortread[] = "draw read too short";
1718ccd4a63SDavid du Colombier static char Eimageexists[] = "image id in use";
1728ccd4a63SDavid du Colombier static char Escreenexists[] = "screen id in use";
1738ccd4a63SDavid du Colombier static char Edrawmem[] = "image memory allocation failed";
1748ccd4a63SDavid du Colombier static char Ereadoutside[] = "readimage outside image";
1758ccd4a63SDavid du Colombier static char Ewriteoutside[] = "writeimage outside image";
1768ccd4a63SDavid du Colombier static char Enotfont[] = "image not a font";
1778ccd4a63SDavid du Colombier static char Eindex[] = "character index out of range";
1788ccd4a63SDavid du Colombier static char Enoclient[] = "no such draw client";
1798ccd4a63SDavid du Colombier /* static char Edepth[] = "image has bad depth"; */
1808ccd4a63SDavid du Colombier static char Enameused[] = "image name in use";
1818ccd4a63SDavid du Colombier static char Enoname[] = "no image with that name";
1828ccd4a63SDavid du Colombier static char Eoldname[] = "named image no longer valid";
1838ccd4a63SDavid du Colombier static char Enamed[] = "image already has name";
1848ccd4a63SDavid du Colombier static char Ewrongname[] = "wrong name for image";
1858ccd4a63SDavid du Colombier
1868ccd4a63SDavid du Colombier int
drawcanqlock(void)1878ccd4a63SDavid du Colombier drawcanqlock(void)
1888ccd4a63SDavid du Colombier {
1898ccd4a63SDavid du Colombier return canqlock(&sdraw.lk);
1908ccd4a63SDavid du Colombier }
1918ccd4a63SDavid du Colombier
1928ccd4a63SDavid du Colombier void
drawqlock(void)1938ccd4a63SDavid du Colombier drawqlock(void)
1948ccd4a63SDavid du Colombier {
1958ccd4a63SDavid du Colombier qlock(&sdraw.lk);
1968ccd4a63SDavid du Colombier }
1978ccd4a63SDavid du Colombier
1988ccd4a63SDavid du Colombier void
drawqunlock(void)1998ccd4a63SDavid du Colombier drawqunlock(void)
2008ccd4a63SDavid du Colombier {
2018ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
2028ccd4a63SDavid du Colombier }
2038ccd4a63SDavid du Colombier
2048ccd4a63SDavid du Colombier static int
drawgen(Chan * c,char * name,Dirtab * dt,int ndt,int s,Dir * dp)2058ccd4a63SDavid du Colombier drawgen(Chan *c, char *name, Dirtab *dt, int ndt, int s, Dir *dp)
2068ccd4a63SDavid du Colombier {
2078ccd4a63SDavid du Colombier int t;
2088ccd4a63SDavid du Colombier Qid q;
2098ccd4a63SDavid du Colombier ulong path;
2108ccd4a63SDavid du Colombier Client *cl;
2118ccd4a63SDavid du Colombier
2128ccd4a63SDavid du Colombier USED(name);
2138ccd4a63SDavid du Colombier USED(dt);
2148ccd4a63SDavid du Colombier USED(ndt);
2158ccd4a63SDavid du Colombier
2168ccd4a63SDavid du Colombier q.vers = 0;
2178ccd4a63SDavid du Colombier
2188ccd4a63SDavid du Colombier if(s == DEVDOTDOT){
2198ccd4a63SDavid du Colombier switch(QID(c->qid)){
2208ccd4a63SDavid du Colombier case Qtopdir:
2218ccd4a63SDavid du Colombier case Q2nd:
2228ccd4a63SDavid du Colombier mkqid(&q, Qtopdir, 0, QTDIR);
2238ccd4a63SDavid du Colombier devdir(c, q, "#i", 0, eve, 0500, dp);
2248ccd4a63SDavid du Colombier break;
2258ccd4a63SDavid du Colombier case Q3rd:
2268ccd4a63SDavid du Colombier cl = drawclientofpath(c->qid.path);
2278ccd4a63SDavid du Colombier if(cl == nil)
2288ccd4a63SDavid du Colombier strcpy(up->genbuf, "??");
2298ccd4a63SDavid du Colombier else
2308ccd4a63SDavid du Colombier sprint(up->genbuf, "%d", cl->clientid);
2318ccd4a63SDavid du Colombier mkqid(&q, Q2nd, 0, QTDIR);
2328ccd4a63SDavid du Colombier devdir(c, q, up->genbuf, 0, eve, 0500, dp);
2338ccd4a63SDavid du Colombier break;
2348ccd4a63SDavid du Colombier default:
2358ccd4a63SDavid du Colombier panic("drawwalk %llux", c->qid.path);
2368ccd4a63SDavid du Colombier }
2378ccd4a63SDavid du Colombier return 1;
2388ccd4a63SDavid du Colombier }
2398ccd4a63SDavid du Colombier
2408ccd4a63SDavid du Colombier /*
2418ccd4a63SDavid du Colombier * Top level directory contains the name of the device.
2428ccd4a63SDavid du Colombier */
2438ccd4a63SDavid du Colombier t = QID(c->qid);
2448ccd4a63SDavid du Colombier if(t == Qtopdir){
2458ccd4a63SDavid du Colombier switch(s){
2468ccd4a63SDavid du Colombier case 0:
2478ccd4a63SDavid du Colombier mkqid(&q, Q2nd, 0, QTDIR);
2488ccd4a63SDavid du Colombier devdir(c, q, "draw", 0, eve, 0555, dp);
2498ccd4a63SDavid du Colombier break;
2508ccd4a63SDavid du Colombier default:
2518ccd4a63SDavid du Colombier return -1;
2528ccd4a63SDavid du Colombier }
2538ccd4a63SDavid du Colombier return 1;
2548ccd4a63SDavid du Colombier }
2558ccd4a63SDavid du Colombier
2568ccd4a63SDavid du Colombier /*
2578ccd4a63SDavid du Colombier * Second level contains "new" plus all the clients.
2588ccd4a63SDavid du Colombier */
2598ccd4a63SDavid du Colombier if(t == Q2nd || t == Qnew){
2608ccd4a63SDavid du Colombier if(s == 0){
2618ccd4a63SDavid du Colombier mkqid(&q, Qnew, 0, QTFILE);
2628ccd4a63SDavid du Colombier devdir(c, q, "new", 0, eve, 0666, dp);
2638ccd4a63SDavid du Colombier }
2648ccd4a63SDavid du Colombier else if(s <= sdraw.nclient){
2658ccd4a63SDavid du Colombier cl = sdraw.client[s-1];
2668ccd4a63SDavid du Colombier if(cl == 0)
2678ccd4a63SDavid du Colombier return 0;
2688ccd4a63SDavid du Colombier sprint(up->genbuf, "%d", cl->clientid);
2698ccd4a63SDavid du Colombier mkqid(&q, (s<<QSHIFT)|Q3rd, 0, QTDIR);
2708ccd4a63SDavid du Colombier devdir(c, q, up->genbuf, 0, eve, 0555, dp);
2718ccd4a63SDavid du Colombier return 1;
2728ccd4a63SDavid du Colombier }
2738ccd4a63SDavid du Colombier else
2748ccd4a63SDavid du Colombier return -1;
2758ccd4a63SDavid du Colombier return 1;
2768ccd4a63SDavid du Colombier }
2778ccd4a63SDavid du Colombier
2788ccd4a63SDavid du Colombier /*
2798ccd4a63SDavid du Colombier * Third level.
2808ccd4a63SDavid du Colombier */
2818ccd4a63SDavid du Colombier path = c->qid.path&~((1<<QSHIFT)-1); /* slot component */
2828ccd4a63SDavid du Colombier q.vers = c->qid.vers;
2838ccd4a63SDavid du Colombier q.type = QTFILE;
2848ccd4a63SDavid du Colombier switch(s){
2858ccd4a63SDavid du Colombier case 0:
2868ccd4a63SDavid du Colombier q.path = path|Qcolormap;
2878ccd4a63SDavid du Colombier devdir(c, q, "colormap", 0, eve, 0600, dp);
2888ccd4a63SDavid du Colombier break;
2898ccd4a63SDavid du Colombier case 1:
2908ccd4a63SDavid du Colombier q.path = path|Qctl;
2918ccd4a63SDavid du Colombier devdir(c, q, "ctl", 0, eve, 0600, dp);
2928ccd4a63SDavid du Colombier break;
2938ccd4a63SDavid du Colombier case 2:
2948ccd4a63SDavid du Colombier q.path = path|Qdata;
2958ccd4a63SDavid du Colombier devdir(c, q, "data", 0, eve, 0600, dp);
2968ccd4a63SDavid du Colombier break;
2978ccd4a63SDavid du Colombier case 3:
2988ccd4a63SDavid du Colombier q.path = path|Qrefresh;
2998ccd4a63SDavid du Colombier devdir(c, q, "refresh", 0, eve, 0400, dp);
3008ccd4a63SDavid du Colombier break;
3018ccd4a63SDavid du Colombier default:
3028ccd4a63SDavid du Colombier return -1;
3038ccd4a63SDavid du Colombier }
3048ccd4a63SDavid du Colombier return 1;
3058ccd4a63SDavid du Colombier }
3068ccd4a63SDavid du Colombier
3078ccd4a63SDavid du Colombier static
3088ccd4a63SDavid du Colombier int
drawrefactive(void * a)3098ccd4a63SDavid du Colombier drawrefactive(void *a)
3108ccd4a63SDavid du Colombier {
3118ccd4a63SDavid du Colombier Client *c;
3128ccd4a63SDavid du Colombier
3138ccd4a63SDavid du Colombier c = a;
3148ccd4a63SDavid du Colombier return c->refreshme || c->refresh!=0;
3158ccd4a63SDavid du Colombier }
3168ccd4a63SDavid du Colombier
3178ccd4a63SDavid du Colombier static
3188ccd4a63SDavid du Colombier void
drawrefreshscreen(DImage * l,Client * client)3198ccd4a63SDavid du Colombier drawrefreshscreen(DImage *l, Client *client)
3208ccd4a63SDavid du Colombier {
3218ccd4a63SDavid du Colombier while(l != nil && l->dscreen == nil)
3228ccd4a63SDavid du Colombier l = l->fromname;
3238ccd4a63SDavid du Colombier if(l != nil && l->dscreen->owner != client)
3248ccd4a63SDavid du Colombier l->dscreen->owner->refreshme = 1;
3258ccd4a63SDavid du Colombier }
3268ccd4a63SDavid du Colombier
3278ccd4a63SDavid du Colombier static
3288ccd4a63SDavid du Colombier void
drawrefresh(Memimage * m,Rectangle r,void * v)3298ccd4a63SDavid du Colombier drawrefresh(Memimage *m, Rectangle r, void *v)
3308ccd4a63SDavid du Colombier {
3318ccd4a63SDavid du Colombier Refx *x;
3328ccd4a63SDavid du Colombier DImage *d;
3338ccd4a63SDavid du Colombier Client *c;
3348ccd4a63SDavid du Colombier Refresh *ref;
3358ccd4a63SDavid du Colombier
3368ccd4a63SDavid du Colombier USED(m);
3378ccd4a63SDavid du Colombier
3388ccd4a63SDavid du Colombier if(v == 0)
3398ccd4a63SDavid du Colombier return;
3408ccd4a63SDavid du Colombier x = v;
3418ccd4a63SDavid du Colombier c = x->client;
3428ccd4a63SDavid du Colombier d = x->dimage;
3438ccd4a63SDavid du Colombier for(ref=c->refresh; ref; ref=ref->next)
3448ccd4a63SDavid du Colombier if(ref->dimage == d){
3458ccd4a63SDavid du Colombier combinerect(&ref->r, r);
3468ccd4a63SDavid du Colombier return;
3478ccd4a63SDavid du Colombier }
3488ccd4a63SDavid du Colombier ref = malloc(sizeof(Refresh));
3498ccd4a63SDavid du Colombier if(ref){
3508ccd4a63SDavid du Colombier ref->dimage = d;
3518ccd4a63SDavid du Colombier ref->r = r;
3528ccd4a63SDavid du Colombier ref->next = c->refresh;
3538ccd4a63SDavid du Colombier c->refresh = ref;
3548ccd4a63SDavid du Colombier }
3558ccd4a63SDavid du Colombier }
3568ccd4a63SDavid du Colombier
3578ccd4a63SDavid du Colombier static void
addflush(Rectangle r)3588ccd4a63SDavid du Colombier addflush(Rectangle r)
3598ccd4a63SDavid du Colombier {
3608ccd4a63SDavid du Colombier int abb, ar, anbb;
3618ccd4a63SDavid du Colombier Rectangle nbb;
3628ccd4a63SDavid du Colombier
3638ccd4a63SDavid du Colombier if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))
3648ccd4a63SDavid du Colombier return;
3658ccd4a63SDavid du Colombier
3668ccd4a63SDavid du Colombier if(flushrect.min.x >= flushrect.max.x){
3678ccd4a63SDavid du Colombier flushrect = r;
3688ccd4a63SDavid du Colombier waste = 0;
3698ccd4a63SDavid du Colombier return;
3708ccd4a63SDavid du Colombier }
3718ccd4a63SDavid du Colombier nbb = flushrect;
3728ccd4a63SDavid du Colombier combinerect(&nbb, r);
3738ccd4a63SDavid du Colombier ar = Dx(r)*Dy(r);
3748ccd4a63SDavid du Colombier abb = Dx(flushrect)*Dy(flushrect);
3758ccd4a63SDavid du Colombier anbb = Dx(nbb)*Dy(nbb);
3768ccd4a63SDavid du Colombier /*
3778ccd4a63SDavid du Colombier * Area of new waste is area of new bb minus area of old bb,
3788ccd4a63SDavid du Colombier * less the area of the new segment, which we assume is not waste.
3798ccd4a63SDavid du Colombier * This could be negative, but that's OK.
3808ccd4a63SDavid du Colombier */
3818ccd4a63SDavid du Colombier waste += anbb-abb - ar;
3828ccd4a63SDavid du Colombier if(waste < 0)
3838ccd4a63SDavid du Colombier waste = 0;
3848ccd4a63SDavid du Colombier /*
3858ccd4a63SDavid du Colombier * absorb if:
3868ccd4a63SDavid du Colombier * total area is small
3878ccd4a63SDavid du Colombier * waste is less than half total area
3888ccd4a63SDavid du Colombier * rectangles touch
3898ccd4a63SDavid du Colombier */
3908ccd4a63SDavid du Colombier if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){
3918ccd4a63SDavid du Colombier flushrect = nbb;
3928ccd4a63SDavid du Colombier return;
3938ccd4a63SDavid du Colombier }
3948ccd4a63SDavid du Colombier /* emit current state */
3958ccd4a63SDavid du Colombier if(flushrect.min.x < flushrect.max.x)
3968ccd4a63SDavid du Colombier flushmemscreen(flushrect);
3978ccd4a63SDavid du Colombier flushrect = r;
3988ccd4a63SDavid du Colombier waste = 0;
3998ccd4a63SDavid du Colombier }
4008ccd4a63SDavid du Colombier
4018ccd4a63SDavid du Colombier static
4028ccd4a63SDavid du Colombier void
dstflush(int dstid,Memimage * dst,Rectangle r)4038ccd4a63SDavid du Colombier dstflush(int dstid, Memimage *dst, Rectangle r)
4048ccd4a63SDavid du Colombier {
4058ccd4a63SDavid du Colombier Memlayer *l;
4068ccd4a63SDavid du Colombier
4078ccd4a63SDavid du Colombier if(dstid == 0){
4088ccd4a63SDavid du Colombier combinerect(&flushrect, r);
4098ccd4a63SDavid du Colombier return;
4108ccd4a63SDavid du Colombier }
4118ccd4a63SDavid du Colombier /* how can this happen? -rsc, dec 12 2002 */
4128ccd4a63SDavid du Colombier if(dst == 0){
4138ccd4a63SDavid du Colombier print("nil dstflush\n");
4148ccd4a63SDavid du Colombier return;
4158ccd4a63SDavid du Colombier }
4168ccd4a63SDavid du Colombier l = dst->layer;
4178ccd4a63SDavid du Colombier if(l == nil)
4188ccd4a63SDavid du Colombier return;
4198ccd4a63SDavid du Colombier do{
4208ccd4a63SDavid du Colombier if(l->screen->image->data != screenimage->data)
4218ccd4a63SDavid du Colombier return;
4228ccd4a63SDavid du Colombier r = rectaddpt(r, l->delta);
4238ccd4a63SDavid du Colombier l = l->screen->image->layer;
4248ccd4a63SDavid du Colombier }while(l);
4258ccd4a63SDavid du Colombier addflush(r);
4268ccd4a63SDavid du Colombier }
4278ccd4a63SDavid du Colombier
4288ccd4a63SDavid du Colombier void
drawflush(void)4298ccd4a63SDavid du Colombier drawflush(void)
4308ccd4a63SDavid du Colombier {
4318ccd4a63SDavid du Colombier if(flushrect.min.x < flushrect.max.x)
4328ccd4a63SDavid du Colombier flushmemscreen(flushrect);
4338ccd4a63SDavid du Colombier flushrect = Rect(10000, 10000, -10000, -10000);
4348ccd4a63SDavid du Colombier }
4358ccd4a63SDavid du Colombier
4368ccd4a63SDavid du Colombier void
drawflushr(Rectangle r)4378ccd4a63SDavid du Colombier drawflushr(Rectangle r)
4388ccd4a63SDavid du Colombier {
4398ccd4a63SDavid du Colombier qlock(&sdraw.lk);
4408ccd4a63SDavid du Colombier flushmemscreen(r);
4418ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
4428ccd4a63SDavid du Colombier }
4438ccd4a63SDavid du Colombier
4448ccd4a63SDavid du Colombier static
4458ccd4a63SDavid du Colombier int
drawcmp(char * a,char * b,int n)4468ccd4a63SDavid du Colombier drawcmp(char *a, char *b, int n)
4478ccd4a63SDavid du Colombier {
4488ccd4a63SDavid du Colombier if(strlen(a) != n)
4498ccd4a63SDavid du Colombier return 1;
4508ccd4a63SDavid du Colombier return memcmp(a, b, n);
4518ccd4a63SDavid du Colombier }
4528ccd4a63SDavid du Colombier
4538ccd4a63SDavid du Colombier DName*
drawlookupname(int n,char * str)4548ccd4a63SDavid du Colombier drawlookupname(int n, char *str)
4558ccd4a63SDavid du Colombier {
4568ccd4a63SDavid du Colombier DName *name, *ename;
4578ccd4a63SDavid du Colombier
4588ccd4a63SDavid du Colombier name = sdraw.name;
4598ccd4a63SDavid du Colombier ename = &name[sdraw.nname];
4608ccd4a63SDavid du Colombier for(; name<ename; name++)
4618ccd4a63SDavid du Colombier if(drawcmp(name->name, str, n) == 0)
4628ccd4a63SDavid du Colombier return name;
4638ccd4a63SDavid du Colombier return 0;
4648ccd4a63SDavid du Colombier }
4658ccd4a63SDavid du Colombier
4668ccd4a63SDavid du Colombier int
drawgoodname(DImage * d)4678ccd4a63SDavid du Colombier drawgoodname(DImage *d)
4688ccd4a63SDavid du Colombier {
4698ccd4a63SDavid du Colombier DName *n;
4708ccd4a63SDavid du Colombier
4718ccd4a63SDavid du Colombier /* if window, validate the screen's own images */
4728ccd4a63SDavid du Colombier if(d->dscreen)
4738ccd4a63SDavid du Colombier if(drawgoodname(d->dscreen->dimage) == 0
4748ccd4a63SDavid du Colombier || drawgoodname(d->dscreen->dfill) == 0)
4758ccd4a63SDavid du Colombier return 0;
4768ccd4a63SDavid du Colombier if(d->name == nil)
4778ccd4a63SDavid du Colombier return 1;
4788ccd4a63SDavid du Colombier n = drawlookupname(strlen(d->name), d->name);
4798ccd4a63SDavid du Colombier if(n==nil || n->vers!=d->vers)
4808ccd4a63SDavid du Colombier return 0;
4818ccd4a63SDavid du Colombier return 1;
4828ccd4a63SDavid du Colombier }
4838ccd4a63SDavid du Colombier
4848ccd4a63SDavid du Colombier DImage*
drawlookup(Client * client,int id,int checkname)4858ccd4a63SDavid du Colombier drawlookup(Client *client, int id, int checkname)
4868ccd4a63SDavid du Colombier {
4878ccd4a63SDavid du Colombier DImage *d;
4888ccd4a63SDavid du Colombier
4898ccd4a63SDavid du Colombier d = client->dimage[id&HASHMASK];
4908ccd4a63SDavid du Colombier while(d){
4918ccd4a63SDavid du Colombier if(d->id == id){
4928ccd4a63SDavid du Colombier if(checkname && !drawgoodname(d))
4938ccd4a63SDavid du Colombier error(Eoldname);
4948ccd4a63SDavid du Colombier return d;
4958ccd4a63SDavid du Colombier }
4968ccd4a63SDavid du Colombier d = d->next;
4978ccd4a63SDavid du Colombier }
4988ccd4a63SDavid du Colombier return 0;
4998ccd4a63SDavid du Colombier }
5008ccd4a63SDavid du Colombier
5018ccd4a63SDavid du Colombier DScreen*
drawlookupdscreen(int id)5028ccd4a63SDavid du Colombier drawlookupdscreen(int id)
5038ccd4a63SDavid du Colombier {
5048ccd4a63SDavid du Colombier DScreen *s;
5058ccd4a63SDavid du Colombier
5068ccd4a63SDavid du Colombier s = dscreen;
5078ccd4a63SDavid du Colombier while(s){
5088ccd4a63SDavid du Colombier if(s->id == id)
5098ccd4a63SDavid du Colombier return s;
5108ccd4a63SDavid du Colombier s = s->next;
5118ccd4a63SDavid du Colombier }
5128ccd4a63SDavid du Colombier return 0;
5138ccd4a63SDavid du Colombier }
5148ccd4a63SDavid du Colombier
5158ccd4a63SDavid du Colombier DScreen*
drawlookupscreen(Client * client,int id,CScreen ** cs)5168ccd4a63SDavid du Colombier drawlookupscreen(Client *client, int id, CScreen **cs)
5178ccd4a63SDavid du Colombier {
5188ccd4a63SDavid du Colombier CScreen *s;
5198ccd4a63SDavid du Colombier
5208ccd4a63SDavid du Colombier s = client->cscreen;
5218ccd4a63SDavid du Colombier while(s){
5228ccd4a63SDavid du Colombier if(s->dscreen->id == id){
5238ccd4a63SDavid du Colombier *cs = s;
5248ccd4a63SDavid du Colombier return s->dscreen;
5258ccd4a63SDavid du Colombier }
5268ccd4a63SDavid du Colombier s = s->next;
5278ccd4a63SDavid du Colombier }
5288ccd4a63SDavid du Colombier error(Enodrawscreen);
5298ccd4a63SDavid du Colombier return 0;
5308ccd4a63SDavid du Colombier }
5318ccd4a63SDavid du Colombier
5328ccd4a63SDavid du Colombier Memimage*
drawinstall(Client * client,int id,Memimage * i,DScreen * dscreen)5338ccd4a63SDavid du Colombier drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
5348ccd4a63SDavid du Colombier {
5358ccd4a63SDavid du Colombier DImage *d;
5368ccd4a63SDavid du Colombier
5378ccd4a63SDavid du Colombier d = malloc(sizeof(DImage));
5388ccd4a63SDavid du Colombier if(d == 0)
5398ccd4a63SDavid du Colombier return 0;
5408ccd4a63SDavid du Colombier d->id = id;
5418ccd4a63SDavid du Colombier d->ref = 1;
5428ccd4a63SDavid du Colombier d->name = 0;
5438ccd4a63SDavid du Colombier d->vers = 0;
5448ccd4a63SDavid du Colombier d->image = i;
5458ccd4a63SDavid du Colombier d->nfchar = 0;
5468ccd4a63SDavid du Colombier d->fchar = 0;
5478ccd4a63SDavid du Colombier d->fromname = 0;
5488ccd4a63SDavid du Colombier d->dscreen = dscreen;
5498ccd4a63SDavid du Colombier d->next = client->dimage[id&HASHMASK];
5508ccd4a63SDavid du Colombier client->dimage[id&HASHMASK] = d;
5518ccd4a63SDavid du Colombier return i;
5528ccd4a63SDavid du Colombier }
5538ccd4a63SDavid du Colombier
5548ccd4a63SDavid du Colombier Memscreen*
drawinstallscreen(Client * client,DScreen * d,int id,DImage * dimage,DImage * dfill,int public)5558ccd4a63SDavid du Colombier drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public)
5568ccd4a63SDavid du Colombier {
5578ccd4a63SDavid du Colombier Memscreen *s;
5588ccd4a63SDavid du Colombier CScreen *c;
5598ccd4a63SDavid du Colombier
5608ccd4a63SDavid du Colombier c = malloc(sizeof(CScreen));
5618ccd4a63SDavid du Colombier if(dimage && dimage->image && dimage->image->chan == 0)
5628ccd4a63SDavid du Colombier panic("bad image %p in drawinstallscreen", dimage->image);
5638ccd4a63SDavid du Colombier
5648ccd4a63SDavid du Colombier if(c == 0)
5658ccd4a63SDavid du Colombier return 0;
5668ccd4a63SDavid du Colombier if(d == 0){
5678ccd4a63SDavid du Colombier d = malloc(sizeof(DScreen));
5688ccd4a63SDavid du Colombier if(d == 0){
5698ccd4a63SDavid du Colombier free(c);
5708ccd4a63SDavid du Colombier return 0;
5718ccd4a63SDavid du Colombier }
5728ccd4a63SDavid du Colombier s = malloc(sizeof(Memscreen));
5738ccd4a63SDavid du Colombier if(s == 0){
5748ccd4a63SDavid du Colombier free(c);
5758ccd4a63SDavid du Colombier free(d);
5768ccd4a63SDavid du Colombier return 0;
5778ccd4a63SDavid du Colombier }
5788ccd4a63SDavid du Colombier s->frontmost = 0;
5798ccd4a63SDavid du Colombier s->rearmost = 0;
5808ccd4a63SDavid du Colombier d->dimage = dimage;
5818ccd4a63SDavid du Colombier if(dimage){
5828ccd4a63SDavid du Colombier s->image = dimage->image;
5838ccd4a63SDavid du Colombier dimage->ref++;
5848ccd4a63SDavid du Colombier }
5858ccd4a63SDavid du Colombier d->dfill = dfill;
5868ccd4a63SDavid du Colombier if(dfill){
5878ccd4a63SDavid du Colombier s->fill = dfill->image;
5888ccd4a63SDavid du Colombier dfill->ref++;
5898ccd4a63SDavid du Colombier }
5908ccd4a63SDavid du Colombier d->ref = 0;
5918ccd4a63SDavid du Colombier d->id = id;
5928ccd4a63SDavid du Colombier d->screen = s;
5938ccd4a63SDavid du Colombier d->public = public;
5948ccd4a63SDavid du Colombier d->next = dscreen;
5958ccd4a63SDavid du Colombier d->owner = client;
5968ccd4a63SDavid du Colombier dscreen = d;
5978ccd4a63SDavid du Colombier }
5988ccd4a63SDavid du Colombier c->dscreen = d;
5998ccd4a63SDavid du Colombier d->ref++;
6008ccd4a63SDavid du Colombier c->next = client->cscreen;
6018ccd4a63SDavid du Colombier client->cscreen = c;
6028ccd4a63SDavid du Colombier return d->screen;
6038ccd4a63SDavid du Colombier }
6048ccd4a63SDavid du Colombier
6058ccd4a63SDavid du Colombier void
drawdelname(DName * name)6068ccd4a63SDavid du Colombier drawdelname(DName *name)
6078ccd4a63SDavid du Colombier {
6088ccd4a63SDavid du Colombier int i;
6098ccd4a63SDavid du Colombier
6108ccd4a63SDavid du Colombier i = name-sdraw.name;
6118ccd4a63SDavid du Colombier memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
6128ccd4a63SDavid du Colombier sdraw.nname--;
6138ccd4a63SDavid du Colombier }
6148ccd4a63SDavid du Colombier
6158ccd4a63SDavid du Colombier void
drawfreedscreen(DScreen * this)6168ccd4a63SDavid du Colombier drawfreedscreen(DScreen *this)
6178ccd4a63SDavid du Colombier {
6188ccd4a63SDavid du Colombier DScreen *ds, *next;
6198ccd4a63SDavid du Colombier
6208ccd4a63SDavid du Colombier this->ref--;
6218ccd4a63SDavid du Colombier if(this->ref < 0)
6228ccd4a63SDavid du Colombier print("negative ref in drawfreedscreen\n");
6238ccd4a63SDavid du Colombier if(this->ref > 0)
6248ccd4a63SDavid du Colombier return;
6258ccd4a63SDavid du Colombier ds = dscreen;
6268ccd4a63SDavid du Colombier if(ds == this){
6278ccd4a63SDavid du Colombier dscreen = this->next;
6288ccd4a63SDavid du Colombier goto Found;
6298ccd4a63SDavid du Colombier }
6308ccd4a63SDavid du Colombier while((next = ds->next)){ /* assign = */
6318ccd4a63SDavid du Colombier if(next == this){
6328ccd4a63SDavid du Colombier ds->next = this->next;
6338ccd4a63SDavid du Colombier goto Found;
6348ccd4a63SDavid du Colombier }
6358ccd4a63SDavid du Colombier ds = next;
6368ccd4a63SDavid du Colombier }
6378ccd4a63SDavid du Colombier error(Enodrawimage);
6388ccd4a63SDavid du Colombier
6398ccd4a63SDavid du Colombier Found:
6408ccd4a63SDavid du Colombier if(this->dimage)
6418ccd4a63SDavid du Colombier drawfreedimage(this->dimage);
6428ccd4a63SDavid du Colombier if(this->dfill)
6438ccd4a63SDavid du Colombier drawfreedimage(this->dfill);
6448ccd4a63SDavid du Colombier free(this->screen);
6458ccd4a63SDavid du Colombier free(this);
6468ccd4a63SDavid du Colombier }
6478ccd4a63SDavid du Colombier
6488ccd4a63SDavid du Colombier void
drawfreedimage(DImage * dimage)6498ccd4a63SDavid du Colombier drawfreedimage(DImage *dimage)
6508ccd4a63SDavid du Colombier {
6518ccd4a63SDavid du Colombier int i;
6528ccd4a63SDavid du Colombier Memimage *l;
6538ccd4a63SDavid du Colombier DScreen *ds;
6548ccd4a63SDavid du Colombier
6558ccd4a63SDavid du Colombier dimage->ref--;
6568ccd4a63SDavid du Colombier if(dimage->ref < 0)
6578ccd4a63SDavid du Colombier print("negative ref in drawfreedimage\n");
6588ccd4a63SDavid du Colombier if(dimage->ref > 0)
6598ccd4a63SDavid du Colombier return;
6608ccd4a63SDavid du Colombier
6618ccd4a63SDavid du Colombier /* any names? */
6628ccd4a63SDavid du Colombier for(i=0; i<sdraw.nname; )
6638ccd4a63SDavid du Colombier if(sdraw.name[i].dimage == dimage)
6648ccd4a63SDavid du Colombier drawdelname(sdraw.name+i);
6658ccd4a63SDavid du Colombier else
6668ccd4a63SDavid du Colombier i++;
6678ccd4a63SDavid du Colombier if(dimage->fromname){ /* acquired by name; owned by someone else*/
6688ccd4a63SDavid du Colombier drawfreedimage(dimage->fromname);
6698ccd4a63SDavid du Colombier goto Return;
6708ccd4a63SDavid du Colombier }
6718ccd4a63SDavid du Colombier if(dimage->image == screenimage) /* don't free the display */
6728ccd4a63SDavid du Colombier goto Return;
6738ccd4a63SDavid du Colombier ds = dimage->dscreen;
6748ccd4a63SDavid du Colombier if(ds){
6758ccd4a63SDavid du Colombier l = dimage->image;
6768ccd4a63SDavid du Colombier if(l->data == screenimage->data)
6778ccd4a63SDavid du Colombier addflush(l->layer->screenr);
6788ccd4a63SDavid du Colombier if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
6798ccd4a63SDavid du Colombier free(l->layer->refreshptr);
6808ccd4a63SDavid du Colombier l->layer->refreshptr = nil;
6818ccd4a63SDavid du Colombier if(drawgoodname(dimage))
6828ccd4a63SDavid du Colombier memldelete(l);
6838ccd4a63SDavid du Colombier else
6848ccd4a63SDavid du Colombier memlfree(l);
6858ccd4a63SDavid du Colombier drawfreedscreen(ds);
6868ccd4a63SDavid du Colombier }else
6878ccd4a63SDavid du Colombier freememimage(dimage->image);
6888ccd4a63SDavid du Colombier Return:
6898ccd4a63SDavid du Colombier free(dimage->fchar);
6908ccd4a63SDavid du Colombier free(dimage);
6918ccd4a63SDavid du Colombier }
6928ccd4a63SDavid du Colombier
6938ccd4a63SDavid du Colombier void
drawuninstallscreen(Client * client,CScreen * this)6948ccd4a63SDavid du Colombier drawuninstallscreen(Client *client, CScreen *this)
6958ccd4a63SDavid du Colombier {
6968ccd4a63SDavid du Colombier CScreen *cs, *next;
6978ccd4a63SDavid du Colombier
6988ccd4a63SDavid du Colombier cs = client->cscreen;
6998ccd4a63SDavid du Colombier if(cs == this){
7008ccd4a63SDavid du Colombier client->cscreen = this->next;
7018ccd4a63SDavid du Colombier drawfreedscreen(this->dscreen);
7028ccd4a63SDavid du Colombier free(this);
7038ccd4a63SDavid du Colombier return;
7048ccd4a63SDavid du Colombier }
7058ccd4a63SDavid du Colombier while((next = cs->next)){ /* assign = */
7068ccd4a63SDavid du Colombier if(next == this){
7078ccd4a63SDavid du Colombier cs->next = this->next;
7088ccd4a63SDavid du Colombier drawfreedscreen(this->dscreen);
7098ccd4a63SDavid du Colombier free(this);
7108ccd4a63SDavid du Colombier return;
7118ccd4a63SDavid du Colombier }
7128ccd4a63SDavid du Colombier cs = next;
7138ccd4a63SDavid du Colombier }
7148ccd4a63SDavid du Colombier }
7158ccd4a63SDavid du Colombier
7168ccd4a63SDavid du Colombier void
drawuninstall(Client * client,int id)7178ccd4a63SDavid du Colombier drawuninstall(Client *client, int id)
7188ccd4a63SDavid du Colombier {
7198ccd4a63SDavid du Colombier DImage *d, *next;
7208ccd4a63SDavid du Colombier
7218ccd4a63SDavid du Colombier d = client->dimage[id&HASHMASK];
7228ccd4a63SDavid du Colombier if(d == 0)
7238ccd4a63SDavid du Colombier error(Enodrawimage);
7248ccd4a63SDavid du Colombier if(d->id == id){
7258ccd4a63SDavid du Colombier client->dimage[id&HASHMASK] = d->next;
7268ccd4a63SDavid du Colombier drawfreedimage(d);
7278ccd4a63SDavid du Colombier return;
7288ccd4a63SDavid du Colombier }
7298ccd4a63SDavid du Colombier while((next = d->next)){ /* assign = */
7308ccd4a63SDavid du Colombier if(next->id == id){
7318ccd4a63SDavid du Colombier d->next = next->next;
7328ccd4a63SDavid du Colombier drawfreedimage(next);
7338ccd4a63SDavid du Colombier return;
7348ccd4a63SDavid du Colombier }
7358ccd4a63SDavid du Colombier d = next;
7368ccd4a63SDavid du Colombier }
7378ccd4a63SDavid du Colombier error(Enodrawimage);
7388ccd4a63SDavid du Colombier }
7398ccd4a63SDavid du Colombier
7408ccd4a63SDavid du Colombier void
drawaddname(Client * client,DImage * di,int n,char * str)7418ccd4a63SDavid du Colombier drawaddname(Client *client, DImage *di, int n, char *str)
7428ccd4a63SDavid du Colombier {
7438ccd4a63SDavid du Colombier DName *name, *ename, *new, *t;
7448ccd4a63SDavid du Colombier
7458ccd4a63SDavid du Colombier name = sdraw.name;
7468ccd4a63SDavid du Colombier ename = &name[sdraw.nname];
7478ccd4a63SDavid du Colombier for(; name<ename; name++)
7488ccd4a63SDavid du Colombier if(drawcmp(name->name, str, n) == 0)
7498ccd4a63SDavid du Colombier error(Enameused);
7508ccd4a63SDavid du Colombier t = smalloc((sdraw.nname+1)*sizeof(DName));
7518ccd4a63SDavid du Colombier memmove(t, sdraw.name, sdraw.nname*sizeof(DName));
7528ccd4a63SDavid du Colombier free(sdraw.name);
7538ccd4a63SDavid du Colombier sdraw.name = t;
7548ccd4a63SDavid du Colombier new = &sdraw.name[sdraw.nname++];
7558ccd4a63SDavid du Colombier new->name = smalloc(n+1);
7568ccd4a63SDavid du Colombier memmove(new->name, str, n);
7578ccd4a63SDavid du Colombier new->name[n] = 0;
7588ccd4a63SDavid du Colombier new->dimage = di;
7598ccd4a63SDavid du Colombier new->client = client;
7608ccd4a63SDavid du Colombier new->vers = ++sdraw.vers;
7618ccd4a63SDavid du Colombier }
7628ccd4a63SDavid du Colombier
7638ccd4a63SDavid du Colombier Client*
drawnewclient(void)7648ccd4a63SDavid du Colombier drawnewclient(void)
7658ccd4a63SDavid du Colombier {
7668ccd4a63SDavid du Colombier Client *cl, **cp;
7678ccd4a63SDavid du Colombier int i;
7688ccd4a63SDavid du Colombier
7698ccd4a63SDavid du Colombier for(i=0; i<sdraw.nclient; i++){
7708ccd4a63SDavid du Colombier cl = sdraw.client[i];
7718ccd4a63SDavid du Colombier if(cl == 0)
7728ccd4a63SDavid du Colombier break;
7738ccd4a63SDavid du Colombier }
7748ccd4a63SDavid du Colombier if(i == sdraw.nclient){
7758ccd4a63SDavid du Colombier cp = malloc((sdraw.nclient+1)*sizeof(Client*));
7768ccd4a63SDavid du Colombier if(cp == 0)
7778ccd4a63SDavid du Colombier return 0;
7788ccd4a63SDavid du Colombier memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*));
7798ccd4a63SDavid du Colombier free(sdraw.client);
7808ccd4a63SDavid du Colombier sdraw.client = cp;
7818ccd4a63SDavid du Colombier sdraw.nclient++;
7828ccd4a63SDavid du Colombier cp[i] = 0;
7838ccd4a63SDavid du Colombier }
7848ccd4a63SDavid du Colombier cl = malloc(sizeof(Client));
7858ccd4a63SDavid du Colombier if(cl == 0)
7868ccd4a63SDavid du Colombier return 0;
7878ccd4a63SDavid du Colombier memset(cl, 0, sizeof(Client));
7888ccd4a63SDavid du Colombier cl->slot = i;
7898ccd4a63SDavid du Colombier cl->clientid = ++sdraw.clientid;
7908ccd4a63SDavid du Colombier cl->op = SoverD;
7918ccd4a63SDavid du Colombier sdraw.client[i] = cl;
7928ccd4a63SDavid du Colombier return cl;
7938ccd4a63SDavid du Colombier }
7948ccd4a63SDavid du Colombier
7958ccd4a63SDavid du Colombier static int
drawclientop(Client * cl)7968ccd4a63SDavid du Colombier drawclientop(Client *cl)
7978ccd4a63SDavid du Colombier {
7988ccd4a63SDavid du Colombier int op;
7998ccd4a63SDavid du Colombier
8008ccd4a63SDavid du Colombier op = cl->op;
8018ccd4a63SDavid du Colombier cl->op = SoverD;
8028ccd4a63SDavid du Colombier return op;
8038ccd4a63SDavid du Colombier }
8048ccd4a63SDavid du Colombier
8058ccd4a63SDavid du Colombier int
drawhasclients(void)8068ccd4a63SDavid du Colombier drawhasclients(void)
8078ccd4a63SDavid du Colombier {
8088ccd4a63SDavid du Colombier /*
8098ccd4a63SDavid du Colombier * if draw has ever been used, we can't resize the frame buffer,
8108ccd4a63SDavid du Colombier * even if all clients have exited (nclients is cumulative); it's too
8118ccd4a63SDavid du Colombier * hard to make work.
8128ccd4a63SDavid du Colombier */
8138ccd4a63SDavid du Colombier return sdraw.nclient != 0;
8148ccd4a63SDavid du Colombier }
8158ccd4a63SDavid du Colombier
8168ccd4a63SDavid du Colombier Client*
drawclientofpath(ulong path)8178ccd4a63SDavid du Colombier drawclientofpath(ulong path)
8188ccd4a63SDavid du Colombier {
8198ccd4a63SDavid du Colombier Client *cl;
8208ccd4a63SDavid du Colombier int slot;
8218ccd4a63SDavid du Colombier
8228ccd4a63SDavid du Colombier slot = CLIENTPATH(path);
8238ccd4a63SDavid du Colombier if(slot == 0)
8248ccd4a63SDavid du Colombier return nil;
8258ccd4a63SDavid du Colombier cl = sdraw.client[slot-1];
8268ccd4a63SDavid du Colombier if(cl==0 || cl->clientid==0)
8278ccd4a63SDavid du Colombier return nil;
8288ccd4a63SDavid du Colombier return cl;
8298ccd4a63SDavid du Colombier }
8308ccd4a63SDavid du Colombier
8318ccd4a63SDavid du Colombier
8328ccd4a63SDavid du Colombier Client*
drawclient(Chan * c)8338ccd4a63SDavid du Colombier drawclient(Chan *c)
8348ccd4a63SDavid du Colombier {
8358ccd4a63SDavid du Colombier Client *client;
8368ccd4a63SDavid du Colombier
8378ccd4a63SDavid du Colombier client = drawclientofpath(c->qid.path);
8388ccd4a63SDavid du Colombier if(client == nil)
8398ccd4a63SDavid du Colombier error(Enoclient);
8408ccd4a63SDavid du Colombier return client;
8418ccd4a63SDavid du Colombier }
8428ccd4a63SDavid du Colombier
8438ccd4a63SDavid du Colombier Memimage*
drawimage(Client * client,uchar * a)8448ccd4a63SDavid du Colombier drawimage(Client *client, uchar *a)
8458ccd4a63SDavid du Colombier {
8468ccd4a63SDavid du Colombier DImage *d;
8478ccd4a63SDavid du Colombier
8488ccd4a63SDavid du Colombier d = drawlookup(client, BGLONG(a), 1);
8498ccd4a63SDavid du Colombier if(d == nil)
8508ccd4a63SDavid du Colombier error(Enodrawimage);
8518ccd4a63SDavid du Colombier return d->image;
8528ccd4a63SDavid du Colombier }
8538ccd4a63SDavid du Colombier
8548ccd4a63SDavid du Colombier void
drawrectangle(Rectangle * r,uchar * a)8558ccd4a63SDavid du Colombier drawrectangle(Rectangle *r, uchar *a)
8568ccd4a63SDavid du Colombier {
8578ccd4a63SDavid du Colombier r->min.x = BGLONG(a+0*4);
8588ccd4a63SDavid du Colombier r->min.y = BGLONG(a+1*4);
8598ccd4a63SDavid du Colombier r->max.x = BGLONG(a+2*4);
8608ccd4a63SDavid du Colombier r->max.y = BGLONG(a+3*4);
8618ccd4a63SDavid du Colombier }
8628ccd4a63SDavid du Colombier
8638ccd4a63SDavid du Colombier void
drawpoint(Point * p,uchar * a)8648ccd4a63SDavid du Colombier drawpoint(Point *p, uchar *a)
8658ccd4a63SDavid du Colombier {
8668ccd4a63SDavid du Colombier p->x = BGLONG(a+0*4);
8678ccd4a63SDavid du Colombier p->y = BGLONG(a+1*4);
8688ccd4a63SDavid du Colombier }
8698ccd4a63SDavid du Colombier
870ec59a3ddSDavid du Colombier #define isvgascreen(dst) 1
871ec59a3ddSDavid du Colombier
872ec59a3ddSDavid du Colombier
8738ccd4a63SDavid du Colombier Point
drawchar(Memimage * dst,Memimage * rdst,Point p,Memimage * src,Point * sp,DImage * font,int index,int op)874ec59a3ddSDavid du Colombier drawchar(Memimage *dst, Memimage *rdst, Point p,
875ec59a3ddSDavid du Colombier Memimage *src, Point *sp, DImage *font, int index, int op)
8768ccd4a63SDavid du Colombier {
8778ccd4a63SDavid du Colombier FChar *fc;
8788ccd4a63SDavid du Colombier Rectangle r;
8798ccd4a63SDavid du Colombier Point sp1;
880ec59a3ddSDavid du Colombier static Memimage *tmp;
8818ccd4a63SDavid du Colombier
8828ccd4a63SDavid du Colombier fc = &font->fchar[index];
8838ccd4a63SDavid du Colombier r.min.x = p.x+fc->left;
8848ccd4a63SDavid du Colombier r.min.y = p.y-(font->ascent-fc->miny);
8858ccd4a63SDavid du Colombier r.max.x = r.min.x+(fc->maxx-fc->minx);
8868ccd4a63SDavid du Colombier r.max.y = r.min.y+(fc->maxy-fc->miny);
8878ccd4a63SDavid du Colombier sp1.x = sp->x+fc->left;
8888ccd4a63SDavid du Colombier sp1.y = sp->y+fc->miny;
889ec59a3ddSDavid du Colombier
890ec59a3ddSDavid du Colombier /*
891ec59a3ddSDavid du Colombier * If we're drawing greyscale fonts onto a VGA screen,
892ec59a3ddSDavid du Colombier * it's very costly to read the screen memory to do the
893ec59a3ddSDavid du Colombier * alpha blending inside memdraw. If this is really a stringbg,
894ec59a3ddSDavid du Colombier * then rdst is the bg image (in main memory) which we can
895ec59a3ddSDavid du Colombier * refer to for the underlying dst pixels instead of reading dst
896ec59a3ddSDavid du Colombier * directly.
897ec59a3ddSDavid du Colombier */
898ec59a3ddSDavid du Colombier if(1 || (isvgascreen(dst) && !isvgascreen(rdst) /*&& font->image->depth > 1*/)){
899ec59a3ddSDavid du Colombier if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){
900ec59a3ddSDavid du Colombier if(tmp)
901ec59a3ddSDavid du Colombier freememimage(tmp);
902ec59a3ddSDavid du Colombier tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan);
903ec59a3ddSDavid du Colombier if(tmp == nil)
904ec59a3ddSDavid du Colombier goto fallback;
905ec59a3ddSDavid du Colombier }
906ec59a3ddSDavid du Colombier memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S);
907ec59a3ddSDavid du Colombier memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op);
908ec59a3ddSDavid du Colombier memdraw(dst, r, tmp, ZP, memopaque, ZP, S);
909ec59a3ddSDavid du Colombier }else{
910ec59a3ddSDavid du Colombier fallback:
9118ccd4a63SDavid du Colombier memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
912ec59a3ddSDavid du Colombier }
913ec59a3ddSDavid du Colombier
9148ccd4a63SDavid du Colombier p.x += fc->width;
9158ccd4a63SDavid du Colombier sp->x += fc->width;
9168ccd4a63SDavid du Colombier return p;
9178ccd4a63SDavid du Colombier }
9188ccd4a63SDavid du Colombier
9198ccd4a63SDavid du Colombier static int
initscreenimage(void)9208ccd4a63SDavid du Colombier initscreenimage(void)
9218ccd4a63SDavid du Colombier {
9228ccd4a63SDavid du Colombier int width, depth;
9238ccd4a63SDavid du Colombier ulong chan;
9248ccd4a63SDavid du Colombier void *X;
9258ccd4a63SDavid du Colombier Rectangle r;
9268ccd4a63SDavid du Colombier
9278ccd4a63SDavid du Colombier if(screenimage != nil)
9288ccd4a63SDavid du Colombier return 1;
9298ccd4a63SDavid du Colombier
9308ccd4a63SDavid du Colombier screendata.base = nil;
9318ccd4a63SDavid du Colombier screendata.bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen, &X);
9328ccd4a63SDavid du Colombier if(screendata.bdata == nil && X == nil)
9338ccd4a63SDavid du Colombier return 0;
9348ccd4a63SDavid du Colombier screendata.ref = 1;
9358ccd4a63SDavid du Colombier
9368ccd4a63SDavid du Colombier screenimage = allocmemimaged(r, chan, &screendata, X);
9378ccd4a63SDavid du Colombier if(screenimage == nil){
9388ccd4a63SDavid du Colombier /* RSC: BUG: detach screen */
9398ccd4a63SDavid du Colombier return 0;
9408ccd4a63SDavid du Colombier }
9418ccd4a63SDavid du Colombier
9428ccd4a63SDavid du Colombier screenimage->width = width;
9438ccd4a63SDavid du Colombier screenimage->clipr = r;
9448ccd4a63SDavid du Colombier return 1;
9458ccd4a63SDavid du Colombier }
9468ccd4a63SDavid du Colombier
9478ccd4a63SDavid du Colombier void
deletescreenimage(void)9488ccd4a63SDavid du Colombier deletescreenimage(void)
9498ccd4a63SDavid du Colombier {
9508ccd4a63SDavid du Colombier qlock(&sdraw.lk);
9518ccd4a63SDavid du Colombier /* RSC: BUG: detach screen */
9528ccd4a63SDavid du Colombier if(screenimage)
9538ccd4a63SDavid du Colombier freememimage(screenimage);
9548ccd4a63SDavid du Colombier screenimage = nil;
9558ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
9568ccd4a63SDavid du Colombier }
9578ccd4a63SDavid du Colombier
9588ccd4a63SDavid du Colombier static Chan*
drawattach(char * spec)9598ccd4a63SDavid du Colombier drawattach(char *spec)
9608ccd4a63SDavid du Colombier {
9618ccd4a63SDavid du Colombier qlock(&sdraw.lk);
9628ccd4a63SDavid du Colombier if(!initscreenimage()){
9638ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
9648ccd4a63SDavid du Colombier error("no frame buffer");
9658ccd4a63SDavid du Colombier }
9668ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
9678ccd4a63SDavid du Colombier return devattach('i', spec);
9688ccd4a63SDavid du Colombier }
9698ccd4a63SDavid du Colombier
9708ccd4a63SDavid du Colombier static Walkqid*
drawwalk(Chan * c,Chan * nc,char ** name,int nname)9718ccd4a63SDavid du Colombier drawwalk(Chan *c, Chan *nc, char **name, int nname)
9728ccd4a63SDavid du Colombier {
9738ccd4a63SDavid du Colombier if(screendata.bdata == nil)
9748ccd4a63SDavid du Colombier error("no frame buffer");
9758ccd4a63SDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, drawgen);
9768ccd4a63SDavid du Colombier }
9778ccd4a63SDavid du Colombier
9788ccd4a63SDavid du Colombier static int
drawstat(Chan * c,uchar * db,int n)9798ccd4a63SDavid du Colombier drawstat(Chan *c, uchar *db, int n)
9808ccd4a63SDavid du Colombier {
9818ccd4a63SDavid du Colombier return devstat(c, db, n, 0, 0, drawgen);
9828ccd4a63SDavid du Colombier }
9838ccd4a63SDavid du Colombier
9848ccd4a63SDavid du Colombier static Chan*
drawopen(Chan * c,int omode)9858ccd4a63SDavid du Colombier drawopen(Chan *c, int omode)
9868ccd4a63SDavid du Colombier {
9878ccd4a63SDavid du Colombier Client *cl;
9888ccd4a63SDavid du Colombier
9898ccd4a63SDavid du Colombier if(c->qid.type & QTDIR){
9908ccd4a63SDavid du Colombier c = devopen(c, omode, 0, 0, drawgen);
9918ccd4a63SDavid du Colombier c->iounit = IOUNIT;
9928ccd4a63SDavid du Colombier }
9938ccd4a63SDavid du Colombier
9948ccd4a63SDavid du Colombier qlock(&sdraw.lk);
9958ccd4a63SDavid du Colombier if(waserror()){
9968ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
9978ccd4a63SDavid du Colombier nexterror();
9988ccd4a63SDavid du Colombier }
9998ccd4a63SDavid du Colombier
10008ccd4a63SDavid du Colombier if(QID(c->qid) == Qnew){
10018ccd4a63SDavid du Colombier cl = drawnewclient();
10028ccd4a63SDavid du Colombier if(cl == 0)
10038ccd4a63SDavid du Colombier error(Enodev);
10048ccd4a63SDavid du Colombier c->qid.path = Qctl|((cl->slot+1)<<QSHIFT);
10058ccd4a63SDavid du Colombier }
10068ccd4a63SDavid du Colombier
10078ccd4a63SDavid du Colombier switch(QID(c->qid)){
10088ccd4a63SDavid du Colombier case Qnew:
10098ccd4a63SDavid du Colombier break;
10108ccd4a63SDavid du Colombier
10118ccd4a63SDavid du Colombier case Qctl:
10128ccd4a63SDavid du Colombier cl = drawclient(c);
10138ccd4a63SDavid du Colombier if(cl->busy)
10148ccd4a63SDavid du Colombier error(Einuse);
10158ccd4a63SDavid du Colombier cl->busy = 1;
10168ccd4a63SDavid du Colombier flushrect = Rect(10000, 10000, -10000, -10000);
10178ccd4a63SDavid du Colombier drawinstall(cl, 0, screenimage, 0);
10188ccd4a63SDavid du Colombier incref(&cl->r);
10198ccd4a63SDavid du Colombier break;
10208ccd4a63SDavid du Colombier case Qcolormap:
10218ccd4a63SDavid du Colombier case Qdata:
10228ccd4a63SDavid du Colombier case Qrefresh:
10238ccd4a63SDavid du Colombier cl = drawclient(c);
10248ccd4a63SDavid du Colombier incref(&cl->r);
10258ccd4a63SDavid du Colombier break;
10268ccd4a63SDavid du Colombier }
10278ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
10288ccd4a63SDavid du Colombier poperror();
10298ccd4a63SDavid du Colombier c->mode = openmode(omode);
10308ccd4a63SDavid du Colombier c->flag |= COPEN;
10318ccd4a63SDavid du Colombier c->offset = 0;
10328ccd4a63SDavid du Colombier c->iounit = IOUNIT;
10338ccd4a63SDavid du Colombier return c;
10348ccd4a63SDavid du Colombier }
10358ccd4a63SDavid du Colombier
10368ccd4a63SDavid du Colombier static void
drawclose(Chan * c)10378ccd4a63SDavid du Colombier drawclose(Chan *c)
10388ccd4a63SDavid du Colombier {
10398ccd4a63SDavid du Colombier int i;
10408ccd4a63SDavid du Colombier DImage *d, **dp;
10418ccd4a63SDavid du Colombier Client *cl;
10428ccd4a63SDavid du Colombier Refresh *r;
10438ccd4a63SDavid du Colombier
10448ccd4a63SDavid du Colombier if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */
10458ccd4a63SDavid du Colombier return;
10468ccd4a63SDavid du Colombier qlock(&sdraw.lk);
10478ccd4a63SDavid du Colombier if(waserror()){
10488ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
10498ccd4a63SDavid du Colombier nexterror();
10508ccd4a63SDavid du Colombier }
10518ccd4a63SDavid du Colombier
10528ccd4a63SDavid du Colombier cl = drawclient(c);
10538ccd4a63SDavid du Colombier if(QID(c->qid) == Qctl)
10548ccd4a63SDavid du Colombier cl->busy = 0;
10558ccd4a63SDavid du Colombier if((c->flag&COPEN) && (decref(&cl->r)==0)){
10568ccd4a63SDavid du Colombier while((r = cl->refresh)){ /* assign = */
10578ccd4a63SDavid du Colombier cl->refresh = r->next;
10588ccd4a63SDavid du Colombier free(r);
10598ccd4a63SDavid du Colombier }
10608ccd4a63SDavid du Colombier /* free names */
10618ccd4a63SDavid du Colombier for(i=0; i<sdraw.nname; )
10628ccd4a63SDavid du Colombier if(sdraw.name[i].client == cl)
10638ccd4a63SDavid du Colombier drawdelname(sdraw.name+i);
10648ccd4a63SDavid du Colombier else
10658ccd4a63SDavid du Colombier i++;
10668ccd4a63SDavid du Colombier while(cl->cscreen)
10678ccd4a63SDavid du Colombier drawuninstallscreen(cl, cl->cscreen);
10688ccd4a63SDavid du Colombier /* all screens are freed, so now we can free images */
10698ccd4a63SDavid du Colombier dp = cl->dimage;
10708ccd4a63SDavid du Colombier for(i=0; i<NHASH; i++){
10718ccd4a63SDavid du Colombier while((d = *dp) != nil){
10728ccd4a63SDavid du Colombier *dp = d->next;
10738ccd4a63SDavid du Colombier drawfreedimage(d);
10748ccd4a63SDavid du Colombier }
10758ccd4a63SDavid du Colombier dp++;
10768ccd4a63SDavid du Colombier }
10778ccd4a63SDavid du Colombier sdraw.client[cl->slot] = 0;
10788ccd4a63SDavid du Colombier drawflush(); /* to erase visible, now dead windows */
10798ccd4a63SDavid du Colombier free(cl);
10808ccd4a63SDavid du Colombier }
10818ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
10828ccd4a63SDavid du Colombier poperror();
10838ccd4a63SDavid du Colombier }
10848ccd4a63SDavid du Colombier
10858ccd4a63SDavid du Colombier long
drawread(Chan * c,void * a,long n,vlong off)10868ccd4a63SDavid du Colombier drawread(Chan *c, void *a, long n, vlong off)
10878ccd4a63SDavid du Colombier {
10888ccd4a63SDavid du Colombier int index, m;
10898ccd4a63SDavid du Colombier ulong red, green, blue;
10908ccd4a63SDavid du Colombier Client *cl;
10918ccd4a63SDavid du Colombier uchar *p;
10928ccd4a63SDavid du Colombier Refresh *r;
10938ccd4a63SDavid du Colombier DImage *di;
10948ccd4a63SDavid du Colombier Memimage *i;
10958ccd4a63SDavid du Colombier ulong offset = off;
10968ccd4a63SDavid du Colombier char buf[16];
10978ccd4a63SDavid du Colombier
10988ccd4a63SDavid du Colombier if(c->qid.type & QTDIR)
10998ccd4a63SDavid du Colombier return devdirread(c, a, n, 0, 0, drawgen);
11008ccd4a63SDavid du Colombier cl = drawclient(c);
11018ccd4a63SDavid du Colombier qlock(&sdraw.lk);
11028ccd4a63SDavid du Colombier if(waserror()){
11038ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
11048ccd4a63SDavid du Colombier nexterror();
11058ccd4a63SDavid du Colombier }
11068ccd4a63SDavid du Colombier switch(QID(c->qid)){
11078ccd4a63SDavid du Colombier case Qctl:
11088ccd4a63SDavid du Colombier if(n < 12*12)
11098ccd4a63SDavid du Colombier error(Eshortread);
11108ccd4a63SDavid du Colombier if(cl->infoid < 0)
11118ccd4a63SDavid du Colombier error(Enodrawimage);
11128ccd4a63SDavid du Colombier if(cl->infoid == 0){
11138ccd4a63SDavid du Colombier i = screenimage;
11148ccd4a63SDavid du Colombier if(i == nil)
11158ccd4a63SDavid du Colombier error(Enodrawimage);
11168ccd4a63SDavid du Colombier }else{
11178ccd4a63SDavid du Colombier di = drawlookup(cl, cl->infoid, 1);
11188ccd4a63SDavid du Colombier if(di == nil)
11198ccd4a63SDavid du Colombier error(Enodrawimage);
11208ccd4a63SDavid du Colombier i = di->image;
11218ccd4a63SDavid du Colombier }
11228ccd4a63SDavid du Colombier n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ",
11238ccd4a63SDavid du Colombier cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl,
11248ccd4a63SDavid du Colombier i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
11258ccd4a63SDavid du Colombier i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
11268ccd4a63SDavid du Colombier cl->infoid = -1;
11278ccd4a63SDavid du Colombier break;
11288ccd4a63SDavid du Colombier
11298ccd4a63SDavid du Colombier case Qcolormap:
11308ccd4a63SDavid du Colombier drawactive(1); /* to restore map from backup */
11318ccd4a63SDavid du Colombier p = malloc(4*12*256+1);
11328ccd4a63SDavid du Colombier if(p == 0)
11338ccd4a63SDavid du Colombier error(Enomem);
11348ccd4a63SDavid du Colombier m = 0;
11358ccd4a63SDavid du Colombier for(index = 0; index < 256; index++){
11368ccd4a63SDavid du Colombier getcolor(index, &red, &green, &blue);
11378ccd4a63SDavid du Colombier m += sprint((char*)p+m, "%11d %11lud %11lud %11lud\n", index, red>>24, green>>24, blue>>24);
11388ccd4a63SDavid du Colombier }
11398ccd4a63SDavid du Colombier n = readstr(offset, a, n, (char*)p);
11408ccd4a63SDavid du Colombier free(p);
11418ccd4a63SDavid du Colombier break;
11428ccd4a63SDavid du Colombier
11438ccd4a63SDavid du Colombier case Qdata:
11448ccd4a63SDavid du Colombier if(cl->readdata == nil)
11458ccd4a63SDavid du Colombier error("no draw data");
11468ccd4a63SDavid du Colombier if(n < cl->nreaddata)
11478ccd4a63SDavid du Colombier error(Eshortread);
11488ccd4a63SDavid du Colombier n = cl->nreaddata;
11498ccd4a63SDavid du Colombier memmove(a, cl->readdata, cl->nreaddata);
11508ccd4a63SDavid du Colombier free(cl->readdata);
11518ccd4a63SDavid du Colombier cl->readdata = nil;
11528ccd4a63SDavid du Colombier break;
11538ccd4a63SDavid du Colombier
11548ccd4a63SDavid du Colombier case Qrefresh:
11558ccd4a63SDavid du Colombier if(n < 5*4)
11568ccd4a63SDavid du Colombier error(Ebadarg);
11578ccd4a63SDavid du Colombier for(;;){
11588ccd4a63SDavid du Colombier if(cl->refreshme || cl->refresh)
11598ccd4a63SDavid du Colombier break;
11608ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
11618ccd4a63SDavid du Colombier if(waserror()){
11628ccd4a63SDavid du Colombier qlock(&sdraw.lk); /* restore lock for waserror() above */
11638ccd4a63SDavid du Colombier nexterror();
11648ccd4a63SDavid du Colombier }
11658ccd4a63SDavid du Colombier sleep(&cl->refrend, drawrefactive, cl);
11668ccd4a63SDavid du Colombier poperror();
11678ccd4a63SDavid du Colombier qlock(&sdraw.lk);
11688ccd4a63SDavid du Colombier }
11698ccd4a63SDavid du Colombier p = a;
11708ccd4a63SDavid du Colombier while(cl->refresh && n>=5*4){
11718ccd4a63SDavid du Colombier r = cl->refresh;
11728ccd4a63SDavid du Colombier BPLONG(p+0*4, r->dimage->id);
11738ccd4a63SDavid du Colombier BPLONG(p+1*4, r->r.min.x);
11748ccd4a63SDavid du Colombier BPLONG(p+2*4, r->r.min.y);
11758ccd4a63SDavid du Colombier BPLONG(p+3*4, r->r.max.x);
11768ccd4a63SDavid du Colombier BPLONG(p+4*4, r->r.max.y);
11778ccd4a63SDavid du Colombier cl->refresh = r->next;
11788ccd4a63SDavid du Colombier free(r);
11798ccd4a63SDavid du Colombier p += 5*4;
11808ccd4a63SDavid du Colombier n -= 5*4;
11818ccd4a63SDavid du Colombier }
11828ccd4a63SDavid du Colombier cl->refreshme = 0;
11838ccd4a63SDavid du Colombier n = p-(uchar*)a;
11848ccd4a63SDavid du Colombier }
11858ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
11868ccd4a63SDavid du Colombier poperror();
11878ccd4a63SDavid du Colombier return n;
11888ccd4a63SDavid du Colombier }
11898ccd4a63SDavid du Colombier
11908ccd4a63SDavid du Colombier void
drawwakeall(void)11918ccd4a63SDavid du Colombier drawwakeall(void)
11928ccd4a63SDavid du Colombier {
11938ccd4a63SDavid du Colombier Client *cl;
11948ccd4a63SDavid du Colombier int i;
11958ccd4a63SDavid du Colombier
11968ccd4a63SDavid du Colombier for(i=0; i<sdraw.nclient; i++){
11978ccd4a63SDavid du Colombier cl = sdraw.client[i];
11988ccd4a63SDavid du Colombier if(cl && (cl->refreshme || cl->refresh))
11998ccd4a63SDavid du Colombier wakeup(&cl->refrend);
12008ccd4a63SDavid du Colombier }
12018ccd4a63SDavid du Colombier }
12028ccd4a63SDavid du Colombier
12038ccd4a63SDavid du Colombier static long
drawwrite(Chan * c,void * a,long n,vlong offset)12048ccd4a63SDavid du Colombier drawwrite(Chan *c, void *a, long n, vlong offset)
12058ccd4a63SDavid du Colombier {
12068ccd4a63SDavid du Colombier char buf[128], *fields[4], *q;
12078ccd4a63SDavid du Colombier Client *cl;
12088ccd4a63SDavid du Colombier int i, m, red, green, blue, x;
12098ccd4a63SDavid du Colombier
12108ccd4a63SDavid du Colombier USED(offset);
12118ccd4a63SDavid du Colombier
12128ccd4a63SDavid du Colombier if(c->qid.type & QTDIR)
12138ccd4a63SDavid du Colombier error(Eisdir);
12148ccd4a63SDavid du Colombier cl = drawclient(c);
12158ccd4a63SDavid du Colombier qlock(&sdraw.lk);
12168ccd4a63SDavid du Colombier if(waserror()){
12178ccd4a63SDavid du Colombier drawwakeall();
12188ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
12198ccd4a63SDavid du Colombier nexterror();
12208ccd4a63SDavid du Colombier }
12218ccd4a63SDavid du Colombier switch(QID(c->qid)){
12228ccd4a63SDavid du Colombier case Qctl:
12238ccd4a63SDavid du Colombier if(n != 4)
12248ccd4a63SDavid du Colombier error("unknown draw control request");
12258ccd4a63SDavid du Colombier cl->infoid = BGLONG((uchar*)a);
12268ccd4a63SDavid du Colombier break;
12278ccd4a63SDavid du Colombier
12288ccd4a63SDavid du Colombier case Qcolormap:
12298ccd4a63SDavid du Colombier drawactive(1); /* to restore map from backup */
12308ccd4a63SDavid du Colombier m = n;
12318ccd4a63SDavid du Colombier n = 0;
12328ccd4a63SDavid du Colombier while(m > 0){
12338ccd4a63SDavid du Colombier x = m;
12348ccd4a63SDavid du Colombier if(x > sizeof(buf)-1)
12358ccd4a63SDavid du Colombier x = sizeof(buf)-1;
12368ccd4a63SDavid du Colombier q = memccpy(buf, a, '\n', x);
12378ccd4a63SDavid du Colombier if(q == 0)
12388ccd4a63SDavid du Colombier break;
12398ccd4a63SDavid du Colombier i = q-buf;
12408ccd4a63SDavid du Colombier n += i;
12418ccd4a63SDavid du Colombier a = (char*)a + i;
12428ccd4a63SDavid du Colombier m -= i;
12438ccd4a63SDavid du Colombier *q = 0;
12448ccd4a63SDavid du Colombier if(tokenize(buf, fields, nelem(fields)) != 4)
12458ccd4a63SDavid du Colombier error(Ebadarg);
12468ccd4a63SDavid du Colombier i = strtoul(fields[0], 0, 0);
12478ccd4a63SDavid du Colombier red = strtoul(fields[1], 0, 0);
12488ccd4a63SDavid du Colombier green = strtoul(fields[2], 0, 0);
12498ccd4a63SDavid du Colombier blue = strtoul(fields[3], &q, 0);
12508ccd4a63SDavid du Colombier if(fields[3] == q)
12518ccd4a63SDavid du Colombier error(Ebadarg);
12528ccd4a63SDavid du Colombier if(red>255 || green>255 || blue>255 || i<0 || i>255)
12538ccd4a63SDavid du Colombier error(Ebadarg);
12548ccd4a63SDavid du Colombier red |= red<<8;
12558ccd4a63SDavid du Colombier red |= red<<16;
12568ccd4a63SDavid du Colombier green |= green<<8;
12578ccd4a63SDavid du Colombier green |= green<<16;
12588ccd4a63SDavid du Colombier blue |= blue<<8;
12598ccd4a63SDavid du Colombier blue |= blue<<16;
12608ccd4a63SDavid du Colombier setcolor(i, red, green, blue);
12618ccd4a63SDavid du Colombier }
12628ccd4a63SDavid du Colombier break;
12638ccd4a63SDavid du Colombier
12648ccd4a63SDavid du Colombier case Qdata:
12658ccd4a63SDavid du Colombier drawmesg(cl, a, n);
12668ccd4a63SDavid du Colombier drawwakeall();
12678ccd4a63SDavid du Colombier break;
12688ccd4a63SDavid du Colombier
12698ccd4a63SDavid du Colombier default:
12708ccd4a63SDavid du Colombier error(Ebadusefd);
12718ccd4a63SDavid du Colombier }
12728ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
12738ccd4a63SDavid du Colombier poperror();
12748ccd4a63SDavid du Colombier return n;
12758ccd4a63SDavid du Colombier }
12768ccd4a63SDavid du Colombier
12778ccd4a63SDavid du Colombier uchar*
drawcoord(uchar * p,uchar * maxp,int oldx,int * newx)12788ccd4a63SDavid du Colombier drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
12798ccd4a63SDavid du Colombier {
12808ccd4a63SDavid du Colombier int b, x;
12818ccd4a63SDavid du Colombier
12828ccd4a63SDavid du Colombier if(p >= maxp)
12838ccd4a63SDavid du Colombier error(Eshortdraw);
12848ccd4a63SDavid du Colombier b = *p++;
12858ccd4a63SDavid du Colombier x = b & 0x7F;
12868ccd4a63SDavid du Colombier if(b & 0x80){
12878ccd4a63SDavid du Colombier if(p+1 >= maxp)
12888ccd4a63SDavid du Colombier error(Eshortdraw);
12898ccd4a63SDavid du Colombier x |= *p++ << 7;
12908ccd4a63SDavid du Colombier x |= *p++ << 15;
12918ccd4a63SDavid du Colombier if(x & (1<<22))
12928ccd4a63SDavid du Colombier x |= ~0<<23;
12938ccd4a63SDavid du Colombier }else{
12948ccd4a63SDavid du Colombier if(b & 0x40)
12958ccd4a63SDavid du Colombier x |= ~0<<7;
12968ccd4a63SDavid du Colombier x += oldx;
12978ccd4a63SDavid du Colombier }
12988ccd4a63SDavid du Colombier *newx = x;
12998ccd4a63SDavid du Colombier return p;
13008ccd4a63SDavid du Colombier }
13018ccd4a63SDavid du Colombier
13028ccd4a63SDavid du Colombier static void
printmesg(char * fmt,uchar * a,int plsprnt)13038ccd4a63SDavid du Colombier printmesg(char *fmt, uchar *a, int plsprnt)
13048ccd4a63SDavid du Colombier {
13058ccd4a63SDavid du Colombier char buf[256];
13068ccd4a63SDavid du Colombier char *p, *q;
13078ccd4a63SDavid du Colombier int s;
13088ccd4a63SDavid du Colombier
13098ccd4a63SDavid du Colombier if(1|| plsprnt==0){
13108ccd4a63SDavid du Colombier SET(s);
13118ccd4a63SDavid du Colombier SET(q);
13128ccd4a63SDavid du Colombier SET(p);
13138ccd4a63SDavid du Colombier USED(fmt);
13148ccd4a63SDavid du Colombier USED(a);
1315*14093dc2SDavid du Colombier p = buf;
13168ccd4a63SDavid du Colombier USED(p);
13178ccd4a63SDavid du Colombier USED(q);
13188ccd4a63SDavid du Colombier USED(s);
13198ccd4a63SDavid du Colombier return;
13208ccd4a63SDavid du Colombier }
13218ccd4a63SDavid du Colombier q = buf;
13228ccd4a63SDavid du Colombier *q++ = *a++;
13238ccd4a63SDavid du Colombier for(p=fmt; *p; p++){
13248ccd4a63SDavid du Colombier switch(*p){
13258ccd4a63SDavid du Colombier case 'l':
13268ccd4a63SDavid du Colombier q += sprint(q, " %ld", (long)BGLONG(a));
13278ccd4a63SDavid du Colombier a += 4;
13288ccd4a63SDavid du Colombier break;
13298ccd4a63SDavid du Colombier case 'L':
13308ccd4a63SDavid du Colombier q += sprint(q, " %.8lux", (ulong)BGLONG(a));
13318ccd4a63SDavid du Colombier a += 4;
13328ccd4a63SDavid du Colombier break;
13338ccd4a63SDavid du Colombier case 'R':
13348ccd4a63SDavid du Colombier q += sprint(q, " [%d %d %d %d]", BGLONG(a), BGLONG(a+4), BGLONG(a+8), BGLONG(a+12));
13358ccd4a63SDavid du Colombier a += 16;
13368ccd4a63SDavid du Colombier break;
13378ccd4a63SDavid du Colombier case 'P':
13388ccd4a63SDavid du Colombier q += sprint(q, " [%d %d]", BGLONG(a), BGLONG(a+4));
13398ccd4a63SDavid du Colombier a += 8;
13408ccd4a63SDavid du Colombier break;
13418ccd4a63SDavid du Colombier case 'b':
13428ccd4a63SDavid du Colombier q += sprint(q, " %d", *a++);
13438ccd4a63SDavid du Colombier break;
13448ccd4a63SDavid du Colombier case 's':
13458ccd4a63SDavid du Colombier q += sprint(q, " %d", BGSHORT(a));
13468ccd4a63SDavid du Colombier a += 2;
13478ccd4a63SDavid du Colombier break;
13488ccd4a63SDavid du Colombier case 'S':
13498ccd4a63SDavid du Colombier q += sprint(q, " %.4ux", BGSHORT(a));
13508ccd4a63SDavid du Colombier a += 2;
13518ccd4a63SDavid du Colombier break;
13528ccd4a63SDavid du Colombier }
13538ccd4a63SDavid du Colombier }
13548ccd4a63SDavid du Colombier *q++ = '\n';
13558ccd4a63SDavid du Colombier *q = 0;
13568ccd4a63SDavid du Colombier iprint("%.*s", (int)(q-buf), buf);
13578ccd4a63SDavid du Colombier }
13588ccd4a63SDavid du Colombier
13598ccd4a63SDavid du Colombier void
drawmesg(Client * client,void * av,int n)13608ccd4a63SDavid du Colombier drawmesg(Client *client, void *av, int n)
13618ccd4a63SDavid du Colombier {
13628ccd4a63SDavid du Colombier int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
13638ccd4a63SDavid du Colombier uchar *u, *a, refresh;
13648ccd4a63SDavid du Colombier char *fmt;
13658ccd4a63SDavid du Colombier ulong value, chan;
13668ccd4a63SDavid du Colombier Rectangle r, clipr;
13678ccd4a63SDavid du Colombier Point p, q, *pp, sp;
13688ccd4a63SDavid du Colombier Memimage *i, *dst, *src, *mask;
13698ccd4a63SDavid du Colombier Memimage *l, **lp;
13708ccd4a63SDavid du Colombier Memscreen *scrn;
13718ccd4a63SDavid du Colombier DImage *font, *ll, *di, *ddst, *dsrc;
13728ccd4a63SDavid du Colombier DName *dn;
13738ccd4a63SDavid du Colombier DScreen *dscrn;
13748ccd4a63SDavid du Colombier FChar *fc;
13758ccd4a63SDavid du Colombier Refx *refx;
13768ccd4a63SDavid du Colombier CScreen *cs;
13778ccd4a63SDavid du Colombier Refreshfn reffn;
13788ccd4a63SDavid du Colombier
13798ccd4a63SDavid du Colombier a = av;
13808ccd4a63SDavid du Colombier m = 0;
13818ccd4a63SDavid du Colombier fmt = nil;
13828ccd4a63SDavid du Colombier if(waserror()){
13838ccd4a63SDavid du Colombier if(fmt) printmesg(fmt, a, 1);
13848ccd4a63SDavid du Colombier /* iprint("error: %s\n", up->errstr); */
13858ccd4a63SDavid du Colombier nexterror();
13868ccd4a63SDavid du Colombier }
13878ccd4a63SDavid du Colombier while((n-=m) > 0){
13888ccd4a63SDavid du Colombier USED(fmt);
13898ccd4a63SDavid du Colombier a += m;
13908ccd4a63SDavid du Colombier switch(*a){
13918ccd4a63SDavid du Colombier default:
13928ccd4a63SDavid du Colombier error("bad draw command");
13938ccd4a63SDavid du Colombier /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */
13948ccd4a63SDavid du Colombier case 'b':
13958ccd4a63SDavid du Colombier printmesg(fmt="LLbLbRRL", a, 0);
13968ccd4a63SDavid du Colombier m = 1+4+4+1+4+1+4*4+4*4+4;
13978ccd4a63SDavid du Colombier if(n < m)
13988ccd4a63SDavid du Colombier error(Eshortdraw);
13998ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
14008ccd4a63SDavid du Colombier scrnid = BGSHORT(a+5);
14018ccd4a63SDavid du Colombier refresh = a[9];
14028ccd4a63SDavid du Colombier chan = BGLONG(a+10);
14038ccd4a63SDavid du Colombier repl = a[14];
14048ccd4a63SDavid du Colombier drawrectangle(&r, a+15);
14058ccd4a63SDavid du Colombier drawrectangle(&clipr, a+31);
14068ccd4a63SDavid du Colombier value = BGLONG(a+47);
14078ccd4a63SDavid du Colombier if(drawlookup(client, dstid, 0))
14088ccd4a63SDavid du Colombier error(Eimageexists);
14098ccd4a63SDavid du Colombier if(scrnid){
14108ccd4a63SDavid du Colombier dscrn = drawlookupscreen(client, scrnid, &cs);
14118ccd4a63SDavid du Colombier scrn = dscrn->screen;
14128ccd4a63SDavid du Colombier if(repl || chan!=scrn->image->chan)
14138ccd4a63SDavid du Colombier error("image parameters incompatible with screen");
1414ec59a3ddSDavid du Colombier reffn = 0;
14158ccd4a63SDavid du Colombier switch(refresh){
14168ccd4a63SDavid du Colombier case Refbackup:
14178ccd4a63SDavid du Colombier break;
14188ccd4a63SDavid du Colombier case Refnone:
14198ccd4a63SDavid du Colombier reffn = memlnorefresh;
14208ccd4a63SDavid du Colombier break;
14218ccd4a63SDavid du Colombier case Refmesg:
14228ccd4a63SDavid du Colombier reffn = drawrefresh;
14238ccd4a63SDavid du Colombier break;
14248ccd4a63SDavid du Colombier default:
14258ccd4a63SDavid du Colombier error("unknown refresh method");
14268ccd4a63SDavid du Colombier }
14278ccd4a63SDavid du Colombier l = memlalloc(scrn, r, reffn, 0, value);
14288ccd4a63SDavid du Colombier if(l == 0)
14298ccd4a63SDavid du Colombier error(Edrawmem);
14308ccd4a63SDavid du Colombier addflush(l->layer->screenr);
14318ccd4a63SDavid du Colombier l->clipr = clipr;
14328ccd4a63SDavid du Colombier rectclip(&l->clipr, r);
14338ccd4a63SDavid du Colombier if(drawinstall(client, dstid, l, dscrn) == 0){
14348ccd4a63SDavid du Colombier memldelete(l);
14358ccd4a63SDavid du Colombier error(Edrawmem);
14368ccd4a63SDavid du Colombier }
14378ccd4a63SDavid du Colombier dscrn->ref++;
14388ccd4a63SDavid du Colombier if(reffn){
14398ccd4a63SDavid du Colombier refx = nil;
14408ccd4a63SDavid du Colombier if(reffn == drawrefresh){
14418ccd4a63SDavid du Colombier refx = malloc(sizeof(Refx));
14428ccd4a63SDavid du Colombier if(refx == 0){
14438ccd4a63SDavid du Colombier drawuninstall(client, dstid);
14448ccd4a63SDavid du Colombier error(Edrawmem);
14458ccd4a63SDavid du Colombier }
14468ccd4a63SDavid du Colombier refx->client = client;
14478ccd4a63SDavid du Colombier refx->dimage = drawlookup(client, dstid, 1);
14488ccd4a63SDavid du Colombier }
14498ccd4a63SDavid du Colombier memlsetrefresh(l, reffn, refx);
14508ccd4a63SDavid du Colombier }
14518ccd4a63SDavid du Colombier continue;
14528ccd4a63SDavid du Colombier }
14538ccd4a63SDavid du Colombier i = allocmemimage(r, chan);
14548ccd4a63SDavid du Colombier if(i == 0)
14558ccd4a63SDavid du Colombier error(Edrawmem);
14568ccd4a63SDavid du Colombier if(repl)
14578ccd4a63SDavid du Colombier i->flags |= Frepl;
14588ccd4a63SDavid du Colombier i->clipr = clipr;
14598ccd4a63SDavid du Colombier if(!repl)
14608ccd4a63SDavid du Colombier rectclip(&i->clipr, r);
14618ccd4a63SDavid du Colombier if(drawinstall(client, dstid, i, 0) == 0){
14628ccd4a63SDavid du Colombier freememimage(i);
14638ccd4a63SDavid du Colombier error(Edrawmem);
14648ccd4a63SDavid du Colombier }
14658ccd4a63SDavid du Colombier memfillcolor(i, value);
14668ccd4a63SDavid du Colombier continue;
14678ccd4a63SDavid du Colombier
14688ccd4a63SDavid du Colombier /* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */
14698ccd4a63SDavid du Colombier case 'A':
14708ccd4a63SDavid du Colombier printmesg(fmt="LLLb", a, 1);
14718ccd4a63SDavid du Colombier m = 1+4+4+4+1;
14728ccd4a63SDavid du Colombier if(n < m)
14738ccd4a63SDavid du Colombier error(Eshortdraw);
14748ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
14758ccd4a63SDavid du Colombier if(dstid == 0)
14768ccd4a63SDavid du Colombier error(Ebadarg);
14778ccd4a63SDavid du Colombier if(drawlookupdscreen(dstid))
14788ccd4a63SDavid du Colombier error(Escreenexists);
14798ccd4a63SDavid du Colombier ddst = drawlookup(client, BGLONG(a+5), 1);
14808ccd4a63SDavid du Colombier dsrc = drawlookup(client, BGLONG(a+9), 1);
14818ccd4a63SDavid du Colombier if(ddst==0 || dsrc==0)
14828ccd4a63SDavid du Colombier error(Enodrawimage);
14838ccd4a63SDavid du Colombier if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0)
14848ccd4a63SDavid du Colombier error(Edrawmem);
14858ccd4a63SDavid du Colombier continue;
14868ccd4a63SDavid du Colombier
14878ccd4a63SDavid du Colombier /* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */
14888ccd4a63SDavid du Colombier case 'c':
14898ccd4a63SDavid du Colombier printmesg(fmt="LbR", a, 0);
14908ccd4a63SDavid du Colombier m = 1+4+1+4*4;
14918ccd4a63SDavid du Colombier if(n < m)
14928ccd4a63SDavid du Colombier error(Eshortdraw);
14938ccd4a63SDavid du Colombier ddst = drawlookup(client, BGLONG(a+1), 1);
14948ccd4a63SDavid du Colombier if(ddst == nil)
14958ccd4a63SDavid du Colombier error(Enodrawimage);
14968ccd4a63SDavid du Colombier if(ddst->name)
14978ccd4a63SDavid du Colombier error("can't change repl/clipr of shared image");
14988ccd4a63SDavid du Colombier dst = ddst->image;
14998ccd4a63SDavid du Colombier if(a[5])
15008ccd4a63SDavid du Colombier dst->flags |= Frepl;
15018ccd4a63SDavid du Colombier drawrectangle(&dst->clipr, a+6);
15028ccd4a63SDavid du Colombier continue;
15038ccd4a63SDavid du Colombier
15048ccd4a63SDavid du Colombier /* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */
15058ccd4a63SDavid du Colombier case 'd':
15068ccd4a63SDavid du Colombier printmesg(fmt="LLLRPP", a, 0);
15078ccd4a63SDavid du Colombier m = 1+4+4+4+4*4+2*4+2*4;
15088ccd4a63SDavid du Colombier if(n < m)
15098ccd4a63SDavid du Colombier error(Eshortdraw);
15108ccd4a63SDavid du Colombier dst = drawimage(client, a+1);
15118ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
15128ccd4a63SDavid du Colombier src = drawimage(client, a+5);
15138ccd4a63SDavid du Colombier mask = drawimage(client, a+9);
15148ccd4a63SDavid du Colombier drawrectangle(&r, a+13);
15158ccd4a63SDavid du Colombier drawpoint(&p, a+29);
15168ccd4a63SDavid du Colombier drawpoint(&q, a+37);
15178ccd4a63SDavid du Colombier op = drawclientop(client);
15188ccd4a63SDavid du Colombier memdraw(dst, r, src, p, mask, q, op);
15198ccd4a63SDavid du Colombier dstflush(dstid, dst, r);
15208ccd4a63SDavid du Colombier continue;
15218ccd4a63SDavid du Colombier
15228ccd4a63SDavid du Colombier /* toggle debugging: 'D' val[1] */
15238ccd4a63SDavid du Colombier case 'D':
15248ccd4a63SDavid du Colombier printmesg(fmt="b", a, 0);
15258ccd4a63SDavid du Colombier m = 1+1;
15268ccd4a63SDavid du Colombier if(n < m)
15278ccd4a63SDavid du Colombier error(Eshortdraw);
15288ccd4a63SDavid du Colombier drawdebug = a[1];
15298ccd4a63SDavid du Colombier continue;
15308ccd4a63SDavid du Colombier
15318ccd4a63SDavid du Colombier /* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/
15328ccd4a63SDavid du Colombier case 'e':
15338ccd4a63SDavid du Colombier case 'E':
15348ccd4a63SDavid du Colombier printmesg(fmt="LLPlllPll", a, 0);
15358ccd4a63SDavid du Colombier m = 1+4+4+2*4+4+4+4+2*4+2*4;
15368ccd4a63SDavid du Colombier if(n < m)
15378ccd4a63SDavid du Colombier error(Eshortdraw);
15388ccd4a63SDavid du Colombier dst = drawimage(client, a+1);
15398ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
15408ccd4a63SDavid du Colombier src = drawimage(client, a+5);
15418ccd4a63SDavid du Colombier drawpoint(&p, a+9);
15428ccd4a63SDavid du Colombier e0 = BGLONG(a+17);
15438ccd4a63SDavid du Colombier e1 = BGLONG(a+21);
15448ccd4a63SDavid du Colombier if(e0<0 || e1<0)
15458ccd4a63SDavid du Colombier error("invalid ellipse semidiameter");
15468ccd4a63SDavid du Colombier j = BGLONG(a+25);
15478ccd4a63SDavid du Colombier if(j < 0)
15488ccd4a63SDavid du Colombier error("negative ellipse thickness");
15498ccd4a63SDavid du Colombier drawpoint(&sp, a+29);
15508ccd4a63SDavid du Colombier c = j;
15518ccd4a63SDavid du Colombier if(*a == 'E')
15528ccd4a63SDavid du Colombier c = -1;
15538ccd4a63SDavid du Colombier ox = BGLONG(a+37);
15548ccd4a63SDavid du Colombier oy = BGLONG(a+41);
15558ccd4a63SDavid du Colombier op = drawclientop(client);
15568ccd4a63SDavid du Colombier /* high bit indicates arc angles are present */
1557ec59a3ddSDavid du Colombier if(ox & (1U<<31)){
15588ccd4a63SDavid du Colombier if((ox & (1<<30)) == 0)
1559ec59a3ddSDavid du Colombier ox &= ~(1U<<31);
15608ccd4a63SDavid du Colombier memarc(dst, p, e0, e1, c, src, sp, ox, oy, op);
15618ccd4a63SDavid du Colombier }else
15628ccd4a63SDavid du Colombier memellipse(dst, p, e0, e1, c, src, sp, op);
15638ccd4a63SDavid du Colombier dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
15648ccd4a63SDavid du Colombier continue;
15658ccd4a63SDavid du Colombier
15668ccd4a63SDavid du Colombier /* free: 'f' id[4] */
15678ccd4a63SDavid du Colombier case 'f':
15688ccd4a63SDavid du Colombier printmesg(fmt="L", a, 1);
15698ccd4a63SDavid du Colombier m = 1+4;
15708ccd4a63SDavid du Colombier if(n < m)
15718ccd4a63SDavid du Colombier error(Eshortdraw);
15728ccd4a63SDavid du Colombier ll = drawlookup(client, BGLONG(a+1), 0);
15738ccd4a63SDavid du Colombier if(ll && ll->dscreen && ll->dscreen->owner != client)
15748ccd4a63SDavid du Colombier ll->dscreen->owner->refreshme = 1;
15758ccd4a63SDavid du Colombier drawuninstall(client, BGLONG(a+1));
15768ccd4a63SDavid du Colombier continue;
15778ccd4a63SDavid du Colombier
15788ccd4a63SDavid du Colombier /* free screen: 'F' id[4] */
15798ccd4a63SDavid du Colombier case 'F':
15808ccd4a63SDavid du Colombier printmesg(fmt="L", a, 1);
15818ccd4a63SDavid du Colombier m = 1+4;
15828ccd4a63SDavid du Colombier if(n < m)
15838ccd4a63SDavid du Colombier error(Eshortdraw);
15848ccd4a63SDavid du Colombier drawlookupscreen(client, BGLONG(a+1), &cs);
15858ccd4a63SDavid du Colombier drawuninstallscreen(client, cs);
15868ccd4a63SDavid du Colombier continue;
15878ccd4a63SDavid du Colombier
15888ccd4a63SDavid du Colombier /* initialize font: 'i' fontid[4] nchars[4] ascent[1] */
15898ccd4a63SDavid du Colombier case 'i':
15908ccd4a63SDavid du Colombier printmesg(fmt="Llb", a, 1);
15918ccd4a63SDavid du Colombier m = 1+4+4+1;
15928ccd4a63SDavid du Colombier if(n < m)
15938ccd4a63SDavid du Colombier error(Eshortdraw);
15948ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
15958ccd4a63SDavid du Colombier if(dstid == 0)
15968ccd4a63SDavid du Colombier error("can't use display as font");
15978ccd4a63SDavid du Colombier font = drawlookup(client, dstid, 1);
15988ccd4a63SDavid du Colombier if(font == 0)
15998ccd4a63SDavid du Colombier error(Enodrawimage);
16008ccd4a63SDavid du Colombier if(font->image->layer)
16018ccd4a63SDavid du Colombier error("can't use window as font");
16028ccd4a63SDavid du Colombier ni = BGLONG(a+5);
16038ccd4a63SDavid du Colombier if(ni<=0 || ni>4096)
16048ccd4a63SDavid du Colombier error("bad font size (4096 chars max)");
16058ccd4a63SDavid du Colombier free(font->fchar); /* should we complain if non-zero? */
16068ccd4a63SDavid du Colombier font->fchar = malloc(ni*sizeof(FChar));
16078ccd4a63SDavid du Colombier if(font->fchar == 0)
16088ccd4a63SDavid du Colombier error("no memory for font");
16098ccd4a63SDavid du Colombier memset(font->fchar, 0, ni*sizeof(FChar));
16108ccd4a63SDavid du Colombier font->nfchar = ni;
16118ccd4a63SDavid du Colombier font->ascent = a[9];
16128ccd4a63SDavid du Colombier continue;
16138ccd4a63SDavid du Colombier
16148ccd4a63SDavid du Colombier /* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
16158ccd4a63SDavid du Colombier case 'l':
16168ccd4a63SDavid du Colombier printmesg(fmt="LLSRPbb", a, 0);
16178ccd4a63SDavid du Colombier m = 1+4+4+2+4*4+2*4+1+1;
16188ccd4a63SDavid du Colombier if(n < m)
16198ccd4a63SDavid du Colombier error(Eshortdraw);
16208ccd4a63SDavid du Colombier font = drawlookup(client, BGLONG(a+1), 1);
16218ccd4a63SDavid du Colombier if(font == 0)
16228ccd4a63SDavid du Colombier error(Enodrawimage);
16238ccd4a63SDavid du Colombier if(font->nfchar == 0)
16248ccd4a63SDavid du Colombier error(Enotfont);
16258ccd4a63SDavid du Colombier src = drawimage(client, a+5);
16268ccd4a63SDavid du Colombier ci = BGSHORT(a+9);
16278ccd4a63SDavid du Colombier if(ci >= font->nfchar)
16288ccd4a63SDavid du Colombier error(Eindex);
16298ccd4a63SDavid du Colombier drawrectangle(&r, a+11);
16308ccd4a63SDavid du Colombier drawpoint(&p, a+27);
16318ccd4a63SDavid du Colombier memdraw(font->image, r, src, p, memopaque, p, S);
16328ccd4a63SDavid du Colombier fc = &font->fchar[ci];
16338ccd4a63SDavid du Colombier fc->minx = r.min.x;
16348ccd4a63SDavid du Colombier fc->maxx = r.max.x;
16358ccd4a63SDavid du Colombier fc->miny = r.min.y;
16368ccd4a63SDavid du Colombier fc->maxy = r.max.y;
16378ccd4a63SDavid du Colombier fc->left = a[35];
16388ccd4a63SDavid du Colombier fc->width = a[36];
16398ccd4a63SDavid du Colombier continue;
16408ccd4a63SDavid du Colombier
16418ccd4a63SDavid du Colombier /* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */
16428ccd4a63SDavid du Colombier case 'L':
16438ccd4a63SDavid du Colombier printmesg(fmt="LPPlllLP", a, 0);
16448ccd4a63SDavid du Colombier m = 1+4+2*4+2*4+4+4+4+4+2*4;
16458ccd4a63SDavid du Colombier if(n < m)
16468ccd4a63SDavid du Colombier error(Eshortdraw);
16478ccd4a63SDavid du Colombier dst = drawimage(client, a+1);
16488ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
16498ccd4a63SDavid du Colombier drawpoint(&p, a+5);
16508ccd4a63SDavid du Colombier drawpoint(&q, a+13);
16518ccd4a63SDavid du Colombier e0 = BGLONG(a+21);
16528ccd4a63SDavid du Colombier e1 = BGLONG(a+25);
16538ccd4a63SDavid du Colombier j = BGLONG(a+29);
16548ccd4a63SDavid du Colombier if(j < 0)
16558ccd4a63SDavid du Colombier error("negative line width");
16568ccd4a63SDavid du Colombier src = drawimage(client, a+33);
16578ccd4a63SDavid du Colombier drawpoint(&sp, a+37);
16588ccd4a63SDavid du Colombier op = drawclientop(client);
16598ccd4a63SDavid du Colombier memline(dst, p, q, e0, e1, j, src, sp, op);
16608ccd4a63SDavid du Colombier /* avoid memlinebbox if possible */
16618ccd4a63SDavid du Colombier if(dstid==0 || dst->layer!=nil){
16628ccd4a63SDavid du Colombier /* BUG: this is terribly inefficient: update maximal containing rect*/
16638ccd4a63SDavid du Colombier r = memlinebbox(p, q, e0, e1, j);
16648ccd4a63SDavid du Colombier dstflush(dstid, dst, insetrect(r, -(1+1+j)));
16658ccd4a63SDavid du Colombier }
16668ccd4a63SDavid du Colombier continue;
16678ccd4a63SDavid du Colombier
16688ccd4a63SDavid du Colombier /* create image mask: 'm' newid[4] id[4] */
16698ccd4a63SDavid du Colombier /*
16708ccd4a63SDavid du Colombier *
16718ccd4a63SDavid du Colombier case 'm':
16728ccd4a63SDavid du Colombier printmesg("LL", a, 0);
16738ccd4a63SDavid du Colombier m = 4+4;
16748ccd4a63SDavid du Colombier if(n < m)
16758ccd4a63SDavid du Colombier error(Eshortdraw);
16768ccd4a63SDavid du Colombier break;
16778ccd4a63SDavid du Colombier *
16788ccd4a63SDavid du Colombier */
16798ccd4a63SDavid du Colombier
16808ccd4a63SDavid du Colombier /* attach to a named image: 'n' dstid[4] j[1] name[j] */
16818ccd4a63SDavid du Colombier case 'n':
16828ccd4a63SDavid du Colombier printmesg(fmt="Lz", a, 0);
16838ccd4a63SDavid du Colombier m = 1+4+1;
16848ccd4a63SDavid du Colombier if(n < m)
16858ccd4a63SDavid du Colombier error(Eshortdraw);
16868ccd4a63SDavid du Colombier j = a[5];
16878ccd4a63SDavid du Colombier if(j == 0) /* give me a non-empty name please */
16888ccd4a63SDavid du Colombier error(Eshortdraw);
16898ccd4a63SDavid du Colombier m += j;
16908ccd4a63SDavid du Colombier if(n < m)
16918ccd4a63SDavid du Colombier error(Eshortdraw);
16928ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
16938ccd4a63SDavid du Colombier if(drawlookup(client, dstid, 0))
16948ccd4a63SDavid du Colombier error(Eimageexists);
16958ccd4a63SDavid du Colombier dn = drawlookupname(j, (char*)a+6);
16968ccd4a63SDavid du Colombier if(dn == nil)
16978ccd4a63SDavid du Colombier error(Enoname);
16988ccd4a63SDavid du Colombier if(drawinstall(client, dstid, dn->dimage->image, 0) == 0)
16998ccd4a63SDavid du Colombier error(Edrawmem);
17008ccd4a63SDavid du Colombier di = drawlookup(client, dstid, 0);
17018ccd4a63SDavid du Colombier if(di == 0)
17028ccd4a63SDavid du Colombier error("draw: can't happen");
17038ccd4a63SDavid du Colombier di->vers = dn->vers;
17048ccd4a63SDavid du Colombier di->name = smalloc(j+1);
17058ccd4a63SDavid du Colombier di->fromname = dn->dimage;
17068ccd4a63SDavid du Colombier di->fromname->ref++;
17078ccd4a63SDavid du Colombier memmove(di->name, a+6, j);
17088ccd4a63SDavid du Colombier di->name[j] = 0;
17098ccd4a63SDavid du Colombier client->infoid = dstid;
17108ccd4a63SDavid du Colombier continue;
17118ccd4a63SDavid du Colombier
17128ccd4a63SDavid du Colombier /* name an image: 'N' dstid[4] in[1] j[1] name[j] */
17138ccd4a63SDavid du Colombier case 'N':
17148ccd4a63SDavid du Colombier printmesg(fmt="Lbz", a, 0);
17158ccd4a63SDavid du Colombier m = 1+4+1+1;
17168ccd4a63SDavid du Colombier if(n < m)
17178ccd4a63SDavid du Colombier error(Eshortdraw);
17188ccd4a63SDavid du Colombier c = a[5];
17198ccd4a63SDavid du Colombier j = a[6];
17208ccd4a63SDavid du Colombier if(j == 0) /* give me a non-empty name please */
17218ccd4a63SDavid du Colombier error(Eshortdraw);
17228ccd4a63SDavid du Colombier m += j;
17238ccd4a63SDavid du Colombier if(n < m)
17248ccd4a63SDavid du Colombier error(Eshortdraw);
17258ccd4a63SDavid du Colombier di = drawlookup(client, BGLONG(a+1), 0);
17268ccd4a63SDavid du Colombier if(di == 0)
17278ccd4a63SDavid du Colombier error(Enodrawimage);
17288ccd4a63SDavid du Colombier if(di->name)
17298ccd4a63SDavid du Colombier error(Enamed);
17308ccd4a63SDavid du Colombier if(c)
17318ccd4a63SDavid du Colombier drawaddname(client, di, j, (char*)a+7);
17328ccd4a63SDavid du Colombier else{
17338ccd4a63SDavid du Colombier dn = drawlookupname(j, (char*)a+7);
17348ccd4a63SDavid du Colombier if(dn == nil)
17358ccd4a63SDavid du Colombier error(Enoname);
17368ccd4a63SDavid du Colombier if(dn->dimage != di)
17378ccd4a63SDavid du Colombier error(Ewrongname);
17388ccd4a63SDavid du Colombier drawdelname(dn);
17398ccd4a63SDavid du Colombier }
17408ccd4a63SDavid du Colombier continue;
17418ccd4a63SDavid du Colombier
17428ccd4a63SDavid du Colombier /* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */
17438ccd4a63SDavid du Colombier case 'o':
17448ccd4a63SDavid du Colombier printmesg(fmt="LPP", a, 0);
17458ccd4a63SDavid du Colombier m = 1+4+2*4+2*4;
17468ccd4a63SDavid du Colombier if(n < m)
17478ccd4a63SDavid du Colombier error(Eshortdraw);
17488ccd4a63SDavid du Colombier dst = drawimage(client, a+1);
17498ccd4a63SDavid du Colombier if(dst->layer){
17508ccd4a63SDavid du Colombier drawpoint(&p, a+5);
17518ccd4a63SDavid du Colombier drawpoint(&q, a+13);
17528ccd4a63SDavid du Colombier r = dst->layer->screenr;
17538ccd4a63SDavid du Colombier ni = memlorigin(dst, p, q);
17548ccd4a63SDavid du Colombier if(ni < 0)
17558ccd4a63SDavid du Colombier error("image origin failed");
17568ccd4a63SDavid du Colombier if(ni > 0){
17578ccd4a63SDavid du Colombier addflush(r);
17588ccd4a63SDavid du Colombier addflush(dst->layer->screenr);
17598ccd4a63SDavid du Colombier ll = drawlookup(client, BGLONG(a+1), 1);
17608ccd4a63SDavid du Colombier drawrefreshscreen(ll, client);
17618ccd4a63SDavid du Colombier }
17628ccd4a63SDavid du Colombier }
17638ccd4a63SDavid du Colombier continue;
17648ccd4a63SDavid du Colombier
17658ccd4a63SDavid du Colombier /* set compositing operator for next draw operation: 'O' op */
17668ccd4a63SDavid du Colombier case 'O':
17678ccd4a63SDavid du Colombier printmesg(fmt="b", a, 0);
17688ccd4a63SDavid du Colombier m = 1+1;
17698ccd4a63SDavid du Colombier if(n < m)
17708ccd4a63SDavid du Colombier error(Eshortdraw);
17718ccd4a63SDavid du Colombier client->op = a[1];
17728ccd4a63SDavid du Colombier continue;
17738ccd4a63SDavid du Colombier
17748ccd4a63SDavid 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] */
17758ccd4a63SDavid 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] */
17768ccd4a63SDavid du Colombier case 'p':
17778ccd4a63SDavid du Colombier case 'P':
17788ccd4a63SDavid du Colombier printmesg(fmt="LslllLPP", a, 0);
17798ccd4a63SDavid du Colombier m = 1+4+2+4+4+4+4+2*4;
17808ccd4a63SDavid du Colombier if(n < m)
17818ccd4a63SDavid du Colombier error(Eshortdraw);
17828ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
17838ccd4a63SDavid du Colombier dst = drawimage(client, a+1);
17848ccd4a63SDavid du Colombier ni = BGSHORT(a+5);
17858ccd4a63SDavid du Colombier if(ni < 0)
17868ccd4a63SDavid du Colombier error("negative count in polygon");
17878ccd4a63SDavid du Colombier e0 = BGLONG(a+7);
17888ccd4a63SDavid du Colombier e1 = BGLONG(a+11);
17898ccd4a63SDavid du Colombier j = 0;
17908ccd4a63SDavid du Colombier if(*a == 'p'){
17918ccd4a63SDavid du Colombier j = BGLONG(a+15);
17928ccd4a63SDavid du Colombier if(j < 0)
17938ccd4a63SDavid du Colombier error("negative polygon line width");
17948ccd4a63SDavid du Colombier }
17958ccd4a63SDavid du Colombier src = drawimage(client, a+19);
17968ccd4a63SDavid du Colombier drawpoint(&sp, a+23);
17978ccd4a63SDavid du Colombier drawpoint(&p, a+31);
17988ccd4a63SDavid du Colombier ni++;
17998ccd4a63SDavid du Colombier pp = malloc(ni*sizeof(Point));
18008ccd4a63SDavid du Colombier if(pp == nil)
18018ccd4a63SDavid du Colombier error(Enomem);
18028ccd4a63SDavid du Colombier doflush = 0;
18038ccd4a63SDavid du Colombier if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data))
18048ccd4a63SDavid du Colombier doflush = 1; /* simplify test in loop */
18058ccd4a63SDavid du Colombier ox = oy = 0;
18068ccd4a63SDavid du Colombier esize = 0;
18078ccd4a63SDavid du Colombier u = a+m;
18088ccd4a63SDavid du Colombier for(y=0; y<ni; y++){
18098ccd4a63SDavid du Colombier q = p;
18108ccd4a63SDavid du Colombier oesize = esize;
18118ccd4a63SDavid du Colombier u = drawcoord(u, a+n, ox, &p.x);
18128ccd4a63SDavid du Colombier u = drawcoord(u, a+n, oy, &p.y);
18138ccd4a63SDavid du Colombier ox = p.x;
18148ccd4a63SDavid du Colombier oy = p.y;
18158ccd4a63SDavid du Colombier if(doflush){
18168ccd4a63SDavid du Colombier esize = j;
18178ccd4a63SDavid du Colombier if(*a == 'p'){
18188ccd4a63SDavid du Colombier if(y == 0){
18198ccd4a63SDavid du Colombier c = memlineendsize(e0);
18208ccd4a63SDavid du Colombier if(c > esize)
18218ccd4a63SDavid du Colombier esize = c;
18228ccd4a63SDavid du Colombier }
18238ccd4a63SDavid du Colombier if(y == ni-1){
18248ccd4a63SDavid du Colombier c = memlineendsize(e1);
18258ccd4a63SDavid du Colombier if(c > esize)
18268ccd4a63SDavid du Colombier esize = c;
18278ccd4a63SDavid du Colombier }
18288ccd4a63SDavid du Colombier }
18298ccd4a63SDavid du Colombier if(*a=='P' && e0!=1 && e0 !=~0)
18308ccd4a63SDavid du Colombier r = dst->clipr;
18318ccd4a63SDavid du Colombier else if(y > 0){
18328ccd4a63SDavid du Colombier r = Rect(q.x-oesize, q.y-oesize, q.x+oesize+1, q.y+oesize+1);
18338ccd4a63SDavid du Colombier combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
18348ccd4a63SDavid du Colombier }
18358ccd4a63SDavid du Colombier if(rectclip(&r, dst->clipr)) /* should perhaps be an arg to dstflush */
18368ccd4a63SDavid du Colombier dstflush(dstid, dst, r);
18378ccd4a63SDavid du Colombier }
18388ccd4a63SDavid du Colombier pp[y] = p;
18398ccd4a63SDavid du Colombier }
18408ccd4a63SDavid du Colombier if(y == 1)
18418ccd4a63SDavid du Colombier dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
18428ccd4a63SDavid du Colombier op = drawclientop(client);
18438ccd4a63SDavid du Colombier if(*a == 'p')
18448ccd4a63SDavid du Colombier mempoly(dst, pp, ni, e0, e1, j, src, sp, op);
18458ccd4a63SDavid du Colombier else
18468ccd4a63SDavid du Colombier memfillpoly(dst, pp, ni, e0, src, sp, op);
18478ccd4a63SDavid du Colombier free(pp);
18488ccd4a63SDavid du Colombier m = u-a;
18498ccd4a63SDavid du Colombier continue;
18508ccd4a63SDavid du Colombier
18518ccd4a63SDavid du Colombier /* read: 'r' id[4] R[4*4] */
18528ccd4a63SDavid du Colombier case 'r':
18538ccd4a63SDavid du Colombier printmesg(fmt="LR", a, 0);
18548ccd4a63SDavid du Colombier m = 1+4+4*4;
18558ccd4a63SDavid du Colombier if(n < m)
18568ccd4a63SDavid du Colombier error(Eshortdraw);
18578ccd4a63SDavid du Colombier i = drawimage(client, a+1);
18588ccd4a63SDavid du Colombier drawrectangle(&r, a+5);
18598ccd4a63SDavid du Colombier if(!rectinrect(r, i->r))
18608ccd4a63SDavid du Colombier error(Ereadoutside);
18618ccd4a63SDavid du Colombier c = bytesperline(r, i->depth);
18628ccd4a63SDavid du Colombier c *= Dy(r);
18638ccd4a63SDavid du Colombier free(client->readdata);
18648ccd4a63SDavid du Colombier client->readdata = mallocz(c, 0);
18658ccd4a63SDavid du Colombier if(client->readdata == nil)
18668ccd4a63SDavid du Colombier error("readimage malloc failed");
18678ccd4a63SDavid du Colombier client->nreaddata = memunload(i, r, client->readdata, c);
18688ccd4a63SDavid du Colombier if(client->nreaddata < 0){
18698ccd4a63SDavid du Colombier free(client->readdata);
18708ccd4a63SDavid du Colombier client->readdata = nil;
18718ccd4a63SDavid du Colombier error("bad readimage call");
18728ccd4a63SDavid du Colombier }
18738ccd4a63SDavid du Colombier continue;
18748ccd4a63SDavid du Colombier
18758ccd4a63SDavid du Colombier /* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */
18768ccd4a63SDavid 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]) */
18778ccd4a63SDavid du Colombier case 's':
18788ccd4a63SDavid du Colombier case 'x':
18798ccd4a63SDavid du Colombier printmesg(fmt="LLLPRPs", a, 0);
18808ccd4a63SDavid du Colombier m = 1+4+4+4+2*4+4*4+2*4+2;
18818ccd4a63SDavid du Colombier if(*a == 'x')
18828ccd4a63SDavid du Colombier m += 4+2*4;
18838ccd4a63SDavid du Colombier if(n < m)
18848ccd4a63SDavid du Colombier error(Eshortdraw);
18858ccd4a63SDavid du Colombier
18868ccd4a63SDavid du Colombier dst = drawimage(client, a+1);
18878ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
18888ccd4a63SDavid du Colombier src = drawimage(client, a+5);
18898ccd4a63SDavid du Colombier font = drawlookup(client, BGLONG(a+9), 1);
18908ccd4a63SDavid du Colombier if(font == 0)
18918ccd4a63SDavid du Colombier error(Enodrawimage);
18928ccd4a63SDavid du Colombier if(font->nfchar == 0)
18938ccd4a63SDavid du Colombier error(Enotfont);
18948ccd4a63SDavid du Colombier drawpoint(&p, a+13);
18958ccd4a63SDavid du Colombier drawrectangle(&r, a+21);
18968ccd4a63SDavid du Colombier drawpoint(&sp, a+37);
18978ccd4a63SDavid du Colombier ni = BGSHORT(a+45);
18988ccd4a63SDavid du Colombier u = a+m;
18998ccd4a63SDavid du Colombier m += ni*2;
19008ccd4a63SDavid du Colombier if(n < m)
19018ccd4a63SDavid du Colombier error(Eshortdraw);
19028ccd4a63SDavid du Colombier clipr = dst->clipr;
19038ccd4a63SDavid du Colombier dst->clipr = r;
19048ccd4a63SDavid du Colombier op = drawclientop(client);
1905ec59a3ddSDavid du Colombier l = dst;
19068ccd4a63SDavid du Colombier if(*a == 'x'){
19078ccd4a63SDavid du Colombier /* paint background */
19088ccd4a63SDavid du Colombier l = drawimage(client, a+47);
19098ccd4a63SDavid du Colombier drawpoint(&q, a+51);
19108ccd4a63SDavid du Colombier r.min.x = p.x;
19118ccd4a63SDavid du Colombier r.min.y = p.y-font->ascent;
19128ccd4a63SDavid du Colombier r.max.x = p.x;
19138ccd4a63SDavid du Colombier r.max.y = r.min.y+Dy(font->image->r);
19148ccd4a63SDavid du Colombier j = ni;
19158ccd4a63SDavid du Colombier while(--j >= 0){
19168ccd4a63SDavid du Colombier ci = BGSHORT(u);
19178ccd4a63SDavid du Colombier if(ci<0 || ci>=font->nfchar){
19188ccd4a63SDavid du Colombier dst->clipr = clipr;
19198ccd4a63SDavid du Colombier error(Eindex);
19208ccd4a63SDavid du Colombier }
19218ccd4a63SDavid du Colombier r.max.x += font->fchar[ci].width;
19228ccd4a63SDavid du Colombier u += 2;
19238ccd4a63SDavid du Colombier }
19248ccd4a63SDavid du Colombier memdraw(dst, r, l, q, memopaque, ZP, op);
19258ccd4a63SDavid du Colombier u -= 2*ni;
19268ccd4a63SDavid du Colombier }
19278ccd4a63SDavid du Colombier q = p;
19288ccd4a63SDavid du Colombier while(--ni >= 0){
19298ccd4a63SDavid du Colombier ci = BGSHORT(u);
19308ccd4a63SDavid du Colombier if(ci<0 || ci>=font->nfchar){
19318ccd4a63SDavid du Colombier dst->clipr = clipr;
19328ccd4a63SDavid du Colombier error(Eindex);
19338ccd4a63SDavid du Colombier }
1934ec59a3ddSDavid du Colombier q = drawchar(dst, l, q, src, &sp, font, ci, op);
19358ccd4a63SDavid du Colombier u += 2;
19368ccd4a63SDavid du Colombier }
19378ccd4a63SDavid du Colombier dst->clipr = clipr;
19388ccd4a63SDavid du Colombier p.y -= font->ascent;
19398ccd4a63SDavid du Colombier dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
19408ccd4a63SDavid du Colombier continue;
19418ccd4a63SDavid du Colombier
19428ccd4a63SDavid du Colombier /* use public screen: 'S' id[4] chan[4] */
19438ccd4a63SDavid du Colombier case 'S':
19448ccd4a63SDavid du Colombier printmesg(fmt="Ll", a, 0);
19458ccd4a63SDavid du Colombier m = 1+4+4;
19468ccd4a63SDavid du Colombier if(n < m)
19478ccd4a63SDavid du Colombier error(Eshortdraw);
19488ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
19498ccd4a63SDavid du Colombier if(dstid == 0)
19508ccd4a63SDavid du Colombier error(Ebadarg);
19518ccd4a63SDavid du Colombier dscrn = drawlookupdscreen(dstid);
19528ccd4a63SDavid du Colombier if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client))
19538ccd4a63SDavid du Colombier error(Enodrawscreen);
19548ccd4a63SDavid du Colombier if(dscrn->screen->image->chan != BGLONG(a+5))
19558ccd4a63SDavid du Colombier error("inconsistent chan");
19568ccd4a63SDavid du Colombier if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0)
19578ccd4a63SDavid du Colombier error(Edrawmem);
19588ccd4a63SDavid du Colombier continue;
19598ccd4a63SDavid du Colombier
19608ccd4a63SDavid du Colombier /* top or bottom windows: 't' top[1] nw[2] n*id[4] */
19618ccd4a63SDavid du Colombier case 't':
19628ccd4a63SDavid du Colombier printmesg(fmt="bsL", a, 0);
19638ccd4a63SDavid du Colombier m = 1+1+2;
19648ccd4a63SDavid du Colombier if(n < m)
19658ccd4a63SDavid du Colombier error(Eshortdraw);
19668ccd4a63SDavid du Colombier nw = BGSHORT(a+2);
19678ccd4a63SDavid du Colombier if(nw < 0)
19688ccd4a63SDavid du Colombier error(Ebadarg);
19698ccd4a63SDavid du Colombier if(nw == 0)
19708ccd4a63SDavid du Colombier continue;
19718ccd4a63SDavid du Colombier m += nw*4;
19728ccd4a63SDavid du Colombier if(n < m)
19738ccd4a63SDavid du Colombier error(Eshortdraw);
19748ccd4a63SDavid du Colombier lp = malloc(nw*sizeof(Memimage*));
19758ccd4a63SDavid du Colombier if(lp == 0)
19768ccd4a63SDavid du Colombier error(Enomem);
19778ccd4a63SDavid du Colombier if(waserror()){
19788ccd4a63SDavid du Colombier free(lp);
19798ccd4a63SDavid du Colombier nexterror();
19808ccd4a63SDavid du Colombier }
19818ccd4a63SDavid du Colombier for(j=0; j<nw; j++)
19828ccd4a63SDavid du Colombier lp[j] = drawimage(client, a+1+1+2+j*4);
19838ccd4a63SDavid du Colombier if(lp[0]->layer == 0)
19848ccd4a63SDavid du Colombier error("images are not windows");
19858ccd4a63SDavid du Colombier for(j=1; j<nw; j++)
19868ccd4a63SDavid du Colombier if(lp[j]->layer->screen != lp[0]->layer->screen)
19878ccd4a63SDavid du Colombier error("images not on same screen");
19888ccd4a63SDavid du Colombier if(a[1])
19898ccd4a63SDavid du Colombier memltofrontn(lp, nw);
19908ccd4a63SDavid du Colombier else
19918ccd4a63SDavid du Colombier memltorearn(lp, nw);
19928ccd4a63SDavid du Colombier if(lp[0]->layer->screen->image->data == screenimage->data)
19938ccd4a63SDavid du Colombier for(j=0; j<nw; j++)
19948ccd4a63SDavid du Colombier addflush(lp[j]->layer->screenr);
19958ccd4a63SDavid du Colombier ll = drawlookup(client, BGLONG(a+1+1+2), 1);
19968ccd4a63SDavid du Colombier drawrefreshscreen(ll, client);
19978ccd4a63SDavid du Colombier poperror();
19988ccd4a63SDavid du Colombier free(lp);
19998ccd4a63SDavid du Colombier continue;
20008ccd4a63SDavid du Colombier
20018ccd4a63SDavid du Colombier /* visible: 'v' */
20028ccd4a63SDavid du Colombier case 'v':
20038ccd4a63SDavid du Colombier printmesg(fmt="", a, 0);
20048ccd4a63SDavid du Colombier m = 1;
20058ccd4a63SDavid du Colombier drawflush();
20068ccd4a63SDavid du Colombier continue;
20078ccd4a63SDavid du Colombier
20088ccd4a63SDavid du Colombier /* write: 'y' id[4] R[4*4] data[x*1] */
20098ccd4a63SDavid du Colombier /* write from compressed data: 'Y' id[4] R[4*4] data[x*1] */
20108ccd4a63SDavid du Colombier case 'y':
20118ccd4a63SDavid du Colombier case 'Y':
20128ccd4a63SDavid du Colombier printmesg(fmt="LR", a, 0);
20138ccd4a63SDavid du Colombier // iprint("load %c\n", *a);
20148ccd4a63SDavid du Colombier m = 1+4+4*4;
20158ccd4a63SDavid du Colombier if(n < m)
20168ccd4a63SDavid du Colombier error(Eshortdraw);
20178ccd4a63SDavid du Colombier dstid = BGLONG(a+1);
20188ccd4a63SDavid du Colombier dst = drawimage(client, a+1);
20198ccd4a63SDavid du Colombier drawrectangle(&r, a+5);
20208ccd4a63SDavid du Colombier if(!rectinrect(r, dst->r))
20218ccd4a63SDavid du Colombier error(Ewriteoutside);
20228ccd4a63SDavid du Colombier y = memload(dst, r, a+m, n-m, *a=='Y');
20238ccd4a63SDavid du Colombier if(y < 0)
20248ccd4a63SDavid du Colombier error("bad writeimage call");
20258ccd4a63SDavid du Colombier dstflush(dstid, dst, r);
20268ccd4a63SDavid du Colombier m += y;
20278ccd4a63SDavid du Colombier continue;
20288ccd4a63SDavid du Colombier }
20298ccd4a63SDavid du Colombier }
20308ccd4a63SDavid du Colombier poperror();
20318ccd4a63SDavid du Colombier }
20328ccd4a63SDavid du Colombier
20338ccd4a63SDavid du Colombier Dev drawdevtab = {
20348ccd4a63SDavid du Colombier 'i',
20358ccd4a63SDavid du Colombier "draw",
20368ccd4a63SDavid du Colombier
20378ccd4a63SDavid du Colombier devreset,
20388ccd4a63SDavid du Colombier devinit,
20398ccd4a63SDavid du Colombier devshutdown,
20408ccd4a63SDavid du Colombier drawattach,
20418ccd4a63SDavid du Colombier drawwalk,
20428ccd4a63SDavid du Colombier drawstat,
20438ccd4a63SDavid du Colombier drawopen,
20448ccd4a63SDavid du Colombier devcreate,
20458ccd4a63SDavid du Colombier drawclose,
20468ccd4a63SDavid du Colombier drawread,
20478ccd4a63SDavid du Colombier devbread,
20488ccd4a63SDavid du Colombier drawwrite,
20498ccd4a63SDavid du Colombier devbwrite,
20508ccd4a63SDavid du Colombier devremove,
20518ccd4a63SDavid du Colombier devwstat,
20528ccd4a63SDavid du Colombier };
20538ccd4a63SDavid du Colombier
20548ccd4a63SDavid du Colombier /*
20558ccd4a63SDavid du Colombier * On 8 bit displays, load the default color map
20568ccd4a63SDavid du Colombier */
20578ccd4a63SDavid du Colombier void
drawcmap(void)20588ccd4a63SDavid du Colombier drawcmap(void)
20598ccd4a63SDavid du Colombier {
20608ccd4a63SDavid du Colombier int r, g, b, cr, cg, cb, v;
20618ccd4a63SDavid du Colombier int num, den;
20628ccd4a63SDavid du Colombier int i, j;
20638ccd4a63SDavid du Colombier
20648ccd4a63SDavid du Colombier drawactive(1); /* to restore map from backup */
20658ccd4a63SDavid du Colombier for(r=0,i=0; r!=4; r++)
20668ccd4a63SDavid du Colombier for(v=0; v!=4; v++,i+=16){
20678ccd4a63SDavid du Colombier for(g=0,j=v-r; g!=4; g++)
20688ccd4a63SDavid du Colombier for(b=0;b!=4;b++,j++){
20698ccd4a63SDavid du Colombier den = r;
20708ccd4a63SDavid du Colombier if(g > den)
20718ccd4a63SDavid du Colombier den = g;
20728ccd4a63SDavid du Colombier if(b > den)
20738ccd4a63SDavid du Colombier den = b;
20748ccd4a63SDavid du Colombier if(den == 0) /* divide check -- pick grey shades */
20758ccd4a63SDavid du Colombier cr = cg = cb = v*17;
20768ccd4a63SDavid du Colombier else{
20778ccd4a63SDavid du Colombier num = 17*(4*den+v);
20788ccd4a63SDavid du Colombier cr = r*num/den;
20798ccd4a63SDavid du Colombier cg = g*num/den;
20808ccd4a63SDavid du Colombier cb = b*num/den;
20818ccd4a63SDavid du Colombier }
20828ccd4a63SDavid du Colombier setcolor(i+(j&15),
20838ccd4a63SDavid du Colombier cr*0x01010101, cg*0x01010101, cb*0x01010101);
20848ccd4a63SDavid du Colombier }
20858ccd4a63SDavid du Colombier }
20868ccd4a63SDavid du Colombier }
20878ccd4a63SDavid du Colombier
20888ccd4a63SDavid du Colombier void
drawblankscreen(int blank)20898ccd4a63SDavid du Colombier drawblankscreen(int blank)
20908ccd4a63SDavid du Colombier {
20918ccd4a63SDavid du Colombier int i, nc;
20928ccd4a63SDavid du Colombier ulong *p;
20938ccd4a63SDavid du Colombier
20948ccd4a63SDavid du Colombier if(blank == sdraw.blanked)
20958ccd4a63SDavid du Colombier return;
20968ccd4a63SDavid du Colombier if(!canqlock(&sdraw.lk))
20978ccd4a63SDavid du Colombier return;
20988ccd4a63SDavid du Colombier if(!initscreenimage()){
20998ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
21008ccd4a63SDavid du Colombier return;
21018ccd4a63SDavid du Colombier }
21028ccd4a63SDavid du Colombier p = sdraw.savemap;
21038ccd4a63SDavid du Colombier nc = screenimage->depth > 8 ? 256 : 1<<screenimage->depth;
21048ccd4a63SDavid du Colombier
21058ccd4a63SDavid du Colombier /*
21068ccd4a63SDavid du Colombier * blankscreen uses the hardware to blank the screen
21078ccd4a63SDavid du Colombier * when possible. to help in cases when it is not possible,
21088ccd4a63SDavid du Colombier * we set the color map to be all black.
21098ccd4a63SDavid du Colombier */
21108ccd4a63SDavid du Colombier if(blank == 0){ /* turn screen on */
21118ccd4a63SDavid du Colombier for(i=0; i<nc; i++, p+=3)
21128ccd4a63SDavid du Colombier setcolor(i, p[0], p[1], p[2]);
21138ccd4a63SDavid du Colombier // blankscreen(0);
21148ccd4a63SDavid du Colombier }else{ /* turn screen off */
21158ccd4a63SDavid du Colombier // blankscreen(1);
21168ccd4a63SDavid du Colombier for(i=0; i<nc; i++, p+=3){
21178ccd4a63SDavid du Colombier getcolor(i, &p[0], &p[1], &p[2]);
21188ccd4a63SDavid du Colombier setcolor(i, 0, 0, 0);
21198ccd4a63SDavid du Colombier }
21208ccd4a63SDavid du Colombier }
21218ccd4a63SDavid du Colombier sdraw.blanked = blank;
21228ccd4a63SDavid du Colombier qunlock(&sdraw.lk);
21238ccd4a63SDavid du Colombier }
21248ccd4a63SDavid du Colombier
21258ccd4a63SDavid du Colombier /*
21268ccd4a63SDavid du Colombier * record activity on screen, changing blanking as appropriate
21278ccd4a63SDavid du Colombier */
21288ccd4a63SDavid du Colombier void
drawactive(int active)21298ccd4a63SDavid du Colombier drawactive(int active)
21308ccd4a63SDavid du Colombier {
21318ccd4a63SDavid du Colombier /*
21328ccd4a63SDavid du Colombier if(active){
21338ccd4a63SDavid du Colombier drawblankscreen(0);
21348ccd4a63SDavid du Colombier sdraw.blanktime = MACHP(0)->ticks;
21358ccd4a63SDavid du Colombier }else{
21368ccd4a63SDavid du Colombier if(blanktime && sdraw.blanktime && TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60 >= blanktime)
21378ccd4a63SDavid du Colombier drawblankscreen(1);
21388ccd4a63SDavid du Colombier }
21398ccd4a63SDavid du Colombier */
21408ccd4a63SDavid du Colombier }
21418ccd4a63SDavid du Colombier
21428ccd4a63SDavid du Colombier int
drawidletime(void)21438ccd4a63SDavid du Colombier drawidletime(void)
21448ccd4a63SDavid du Colombier {
21458ccd4a63SDavid du Colombier return 0;
21468ccd4a63SDavid du Colombier /* return TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60; */
21478ccd4a63SDavid du Colombier }
21488ccd4a63SDavid du Colombier
2149