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