17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "../port/error.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier #define Image IMAGE
97dd7cddfSDavid du Colombier #include <draw.h>
107dd7cddfSDavid du Colombier #include <memdraw.h>
117dd7cddfSDavid du Colombier #include <memlayer.h>
127dd7cddfSDavid du Colombier #include <cursor.h>
137dd7cddfSDavid du Colombier #include "screen.h"
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier enum
167dd7cddfSDavid du Colombier {
177dd7cddfSDavid du Colombier Qtopdir = 0,
187dd7cddfSDavid du Colombier Qnew,
194de34a7eSDavid du Colombier Qwinname,
207dd7cddfSDavid du Colombier Q3rd,
217dd7cddfSDavid du Colombier Q2nd,
227dd7cddfSDavid du Colombier Qcolormap,
237dd7cddfSDavid du Colombier Qctl,
247dd7cddfSDavid du Colombier Qdata,
257dd7cddfSDavid du Colombier Qrefresh,
267dd7cddfSDavid du Colombier };
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier /*
297dd7cddfSDavid du Colombier * Qid path is:
307dd7cddfSDavid du Colombier * 4 bits of file type (qids above)
317dd7cddfSDavid du Colombier * 24 bits of mux slot number +1; 0 means not attached to client
327dd7cddfSDavid du Colombier */
337dd7cddfSDavid du Colombier #define QSHIFT 4 /* location in qid of client # */
347dd7cddfSDavid du Colombier
359a747e4fSDavid du Colombier #define QID(q) ((((ulong)(q).path)&0x0000000F)>>0)
369a747e4fSDavid du Colombier #define CLIENTPATH(q) ((((ulong)q)&0x7FFFFFF0)>>QSHIFT)
377dd7cddfSDavid du Colombier #define CLIENT(q) CLIENTPATH((q).path)
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier #define NHASH (1<<5)
407dd7cddfSDavid du Colombier #define HASHMASK (NHASH-1)
419a747e4fSDavid du Colombier #define IOUNIT (64*1024)
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier typedef struct Client Client;
447dd7cddfSDavid du Colombier typedef struct Draw Draw;
457dd7cddfSDavid du Colombier typedef struct DImage DImage;
467dd7cddfSDavid du Colombier typedef struct DScreen DScreen;
477dd7cddfSDavid du Colombier typedef struct CScreen CScreen;
487dd7cddfSDavid du Colombier typedef struct FChar FChar;
497dd7cddfSDavid du Colombier typedef struct Refresh Refresh;
507dd7cddfSDavid du Colombier typedef struct Refx Refx;
517dd7cddfSDavid du Colombier typedef struct DName DName;
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier ulong blanktime = 30; /* in minutes; a half hour */
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier struct Draw
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier int clientid;
587dd7cddfSDavid du Colombier int nclient;
597dd7cddfSDavid du Colombier Client** client;
607dd7cddfSDavid du Colombier int nname;
617dd7cddfSDavid du Colombier DName* name;
627dd7cddfSDavid du Colombier int vers;
637dd7cddfSDavid du Colombier int softscreen;
647dd7cddfSDavid du Colombier int blanked; /* screen turned off */
657dd7cddfSDavid du Colombier ulong blanktime; /* time of last operation */
667dd7cddfSDavid du Colombier ulong savemap[3*256];
677dd7cddfSDavid du Colombier };
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier struct Client
707dd7cddfSDavid du Colombier {
717dd7cddfSDavid du Colombier Ref r;
727dd7cddfSDavid du Colombier DImage* dimage[NHASH];
737dd7cddfSDavid du Colombier CScreen* cscreen;
747dd7cddfSDavid du Colombier Refresh* refresh;
757dd7cddfSDavid du Colombier Rendez refrend;
767dd7cddfSDavid du Colombier uchar* readdata;
777dd7cddfSDavid du Colombier int nreaddata;
787dd7cddfSDavid du Colombier int busy;
797dd7cddfSDavid du Colombier int clientid;
807dd7cddfSDavid du Colombier int slot;
817dd7cddfSDavid du Colombier int refreshme;
827dd7cddfSDavid du Colombier int infoid;
836a9fc400SDavid du Colombier int op;
847dd7cddfSDavid du Colombier };
857dd7cddfSDavid du Colombier
867dd7cddfSDavid du Colombier struct Refresh
877dd7cddfSDavid du Colombier {
887dd7cddfSDavid du Colombier DImage* dimage;
897dd7cddfSDavid du Colombier Rectangle r;
907dd7cddfSDavid du Colombier Refresh* next;
917dd7cddfSDavid du Colombier };
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier struct Refx
947dd7cddfSDavid du Colombier {
957dd7cddfSDavid du Colombier Client* client;
967dd7cddfSDavid du Colombier DImage* dimage;
977dd7cddfSDavid du Colombier };
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier struct DName
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier char *name;
1027dd7cddfSDavid du Colombier Client *client;
1037dd7cddfSDavid du Colombier DImage* dimage;
1047dd7cddfSDavid du Colombier int vers;
1057dd7cddfSDavid du Colombier };
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier struct FChar
1087dd7cddfSDavid du Colombier {
1097dd7cddfSDavid du Colombier int minx; /* left edge of bits */
1107dd7cddfSDavid du Colombier int maxx; /* right edge of bits */
1117dd7cddfSDavid du Colombier uchar miny; /* first non-zero scan-line */
1127dd7cddfSDavid du Colombier uchar maxy; /* last non-zero scan-line + 1 */
1137dd7cddfSDavid du Colombier schar left; /* offset of baseline */
1147dd7cddfSDavid du Colombier uchar width; /* width of baseline */
1157dd7cddfSDavid du Colombier };
1167dd7cddfSDavid du Colombier
1177dd7cddfSDavid du Colombier /*
1187dd7cddfSDavid du Colombier * Reference counts in DImages:
1197dd7cddfSDavid du Colombier * one per open by original client
1207dd7cddfSDavid du Colombier * one per screen image or fill
1217dd7cddfSDavid du Colombier * one per image derived from this one by name
1227dd7cddfSDavid du Colombier */
1237dd7cddfSDavid du Colombier struct DImage
1247dd7cddfSDavid du Colombier {
1257dd7cddfSDavid du Colombier int id;
1267dd7cddfSDavid du Colombier int ref;
1277dd7cddfSDavid du Colombier char *name;
1287dd7cddfSDavid du Colombier int vers;
1297dd7cddfSDavid du Colombier Memimage* image;
1307dd7cddfSDavid du Colombier int ascent;
1317dd7cddfSDavid du Colombier int nfchar;
1327dd7cddfSDavid du Colombier FChar* fchar;
1337dd7cddfSDavid du Colombier DScreen* dscreen; /* 0 if not a window */
1347dd7cddfSDavid du Colombier DImage* fromname; /* image this one is derived from, by name */
1357dd7cddfSDavid du Colombier DImage* next;
1367dd7cddfSDavid du Colombier };
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier struct CScreen
1397dd7cddfSDavid du Colombier {
1407dd7cddfSDavid du Colombier DScreen* dscreen;
1417dd7cddfSDavid du Colombier CScreen* next;
1427dd7cddfSDavid du Colombier };
1437dd7cddfSDavid du Colombier
1447dd7cddfSDavid du Colombier struct DScreen
1457dd7cddfSDavid du Colombier {
1467dd7cddfSDavid du Colombier int id;
1477dd7cddfSDavid du Colombier int public;
1487dd7cddfSDavid du Colombier int ref;
1497dd7cddfSDavid du Colombier DImage *dimage;
1507dd7cddfSDavid du Colombier DImage *dfill;
1517dd7cddfSDavid du Colombier Memscreen* screen;
1527dd7cddfSDavid du Colombier Client* owner;
1537dd7cddfSDavid du Colombier DScreen* next;
1547dd7cddfSDavid du Colombier };
1557dd7cddfSDavid du Colombier
1567dd7cddfSDavid du Colombier static Draw sdraw;
1574de34a7eSDavid du Colombier QLock drawlock;
1584de34a7eSDavid du Colombier
1597dd7cddfSDavid du Colombier static Memimage *screenimage;
1604de34a7eSDavid du Colombier static DImage* screendimage;
1614de34a7eSDavid du Colombier static char screenname[40];
1624de34a7eSDavid du Colombier static int screennameid;
1634de34a7eSDavid du Colombier
1647dd7cddfSDavid du Colombier static Rectangle flushrect;
1657dd7cddfSDavid du Colombier static int waste;
1667dd7cddfSDavid du Colombier static DScreen* dscreen;
1677dd7cddfSDavid du Colombier extern void flushmemscreen(Rectangle);
1687dd7cddfSDavid du Colombier void drawmesg(Client*, void*, int);
1697dd7cddfSDavid du Colombier void drawuninstall(Client*, int);
1707dd7cddfSDavid du Colombier void drawfreedimage(DImage*);
1717dd7cddfSDavid du Colombier Client* drawclientofpath(ulong);
1724de34a7eSDavid du Colombier DImage* allocdimage(Memimage*);
1737dd7cddfSDavid du Colombier
1747dd7cddfSDavid du Colombier static char Enodrawimage[] = "unknown id for draw image";
1757dd7cddfSDavid du Colombier static char Enodrawscreen[] = "unknown id for draw screen";
1767dd7cddfSDavid du Colombier static char Eshortdraw[] = "short draw message";
1777dd7cddfSDavid du Colombier static char Eshortread[] = "draw read too short";
1787dd7cddfSDavid du Colombier static char Eimageexists[] = "image id in use";
1797dd7cddfSDavid du Colombier static char Escreenexists[] = "screen id in use";
1807dd7cddfSDavid du Colombier static char Edrawmem[] = "image memory allocation failed";
1817dd7cddfSDavid du Colombier static char Ereadoutside[] = "readimage outside image";
1827dd7cddfSDavid du Colombier static char Ewriteoutside[] = "writeimage outside image";
1837dd7cddfSDavid du Colombier static char Enotfont[] = "image not a font";
1847dd7cddfSDavid du Colombier static char Eindex[] = "character index out of range";
1857dd7cddfSDavid du Colombier static char Enoclient[] = "no such draw client";
1867dd7cddfSDavid du Colombier static char Edepth[] = "image has bad depth";
1877dd7cddfSDavid du Colombier static char Enameused[] = "image name in use";
1887dd7cddfSDavid du Colombier static char Enoname[] = "no image with that name";
1897dd7cddfSDavid du Colombier static char Eoldname[] = "named image no longer valid";
1907dd7cddfSDavid du Colombier static char Enamed[] = "image already has name";
1917dd7cddfSDavid du Colombier static char Ewrongname[] = "wrong name for image";
1927dd7cddfSDavid du Colombier
1934de34a7eSDavid du Colombier static void
dlock(void)1944de34a7eSDavid du Colombier dlock(void)
1954de34a7eSDavid du Colombier {
1964de34a7eSDavid du Colombier qlock(&drawlock);
1974de34a7eSDavid du Colombier }
1984de34a7eSDavid du Colombier
1994de34a7eSDavid du Colombier static int
candlock(void)2004de34a7eSDavid du Colombier candlock(void)
2014de34a7eSDavid du Colombier {
2024de34a7eSDavid du Colombier return canqlock(&drawlock);
2034de34a7eSDavid du Colombier }
2044de34a7eSDavid du Colombier
2054de34a7eSDavid du Colombier static void
dunlock(void)2064de34a7eSDavid du Colombier dunlock(void)
2074de34a7eSDavid du Colombier {
2084de34a7eSDavid du Colombier qunlock(&drawlock);
2094de34a7eSDavid du Colombier }
2104de34a7eSDavid du Colombier
2117dd7cddfSDavid du Colombier static int
drawgen(Chan * c,char *,Dirtab *,int,int s,Dir * dp)2129a747e4fSDavid du Colombier drawgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
2137dd7cddfSDavid du Colombier {
2147dd7cddfSDavid du Colombier int t;
2157dd7cddfSDavid du Colombier Qid q;
2167dd7cddfSDavid du Colombier ulong path;
2177dd7cddfSDavid du Colombier Client *cl;
2187dd7cddfSDavid du Colombier
2197dd7cddfSDavid du Colombier q.vers = 0;
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier if(s == DEVDOTDOT){
2227dd7cddfSDavid du Colombier switch(QID(c->qid)){
2237dd7cddfSDavid du Colombier case Qtopdir:
2247dd7cddfSDavid du Colombier case Q2nd:
2259a747e4fSDavid du Colombier mkqid(&q, Qtopdir, 0, QTDIR);
2269a747e4fSDavid du Colombier devdir(c, q, "#i", 0, eve, 0500, dp);
2277dd7cddfSDavid du Colombier break;
2287dd7cddfSDavid du Colombier case Q3rd:
2297dd7cddfSDavid du Colombier cl = drawclientofpath(c->qid.path);
2307dd7cddfSDavid du Colombier if(cl == nil)
2314e3613abSDavid du Colombier strncpy(up->genbuf, "??", sizeof up->genbuf);
2327dd7cddfSDavid du Colombier else
2334e3613abSDavid du Colombier snprint(up->genbuf, sizeof up->genbuf,
2344e3613abSDavid du Colombier "%d", cl->clientid);
2359a747e4fSDavid du Colombier mkqid(&q, Q2nd, 0, QTDIR);
2369a747e4fSDavid du Colombier devdir(c, q, up->genbuf, 0, eve, 0500, dp);
2377dd7cddfSDavid du Colombier break;
2387dd7cddfSDavid du Colombier default:
2399a747e4fSDavid du Colombier panic("drawwalk %llux", c->qid.path);
2407dd7cddfSDavid du Colombier }
2417dd7cddfSDavid du Colombier return 1;
2427dd7cddfSDavid du Colombier }
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier /*
2457dd7cddfSDavid du Colombier * Top level directory contains the name of the device.
2467dd7cddfSDavid du Colombier */
2479a747e4fSDavid du Colombier t = QID(c->qid);
2489a747e4fSDavid du Colombier if(t == Qtopdir){
2497dd7cddfSDavid du Colombier switch(s){
2507dd7cddfSDavid du Colombier case 0:
2519a747e4fSDavid du Colombier mkqid(&q, Q2nd, 0, QTDIR);
2527dd7cddfSDavid du Colombier devdir(c, q, "draw", 0, eve, 0555, dp);
2537dd7cddfSDavid du Colombier break;
2544de34a7eSDavid du Colombier case 1:
255*6bbfed0dSDavid du Colombier mkqid(&q, Qwinname, 0, QTFILE);
2564de34a7eSDavid du Colombier devdir(c, q, "winname", 0, eve, 0444, dp);
2574de34a7eSDavid du Colombier break;
2587dd7cddfSDavid du Colombier default:
2597dd7cddfSDavid du Colombier return -1;
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier return 1;
2627dd7cddfSDavid du Colombier }
2637dd7cddfSDavid du Colombier
264*6bbfed0dSDavid du Colombier if(t == Qwinname){
265*6bbfed0dSDavid du Colombier mkqid(&q, Qwinname, 0, QTFILE);
266*6bbfed0dSDavid du Colombier devdir(c, q, "winname", 0, eve, 0444, dp);
267*6bbfed0dSDavid du Colombier return 1;
268*6bbfed0dSDavid du Colombier }
269*6bbfed0dSDavid du Colombier
2707dd7cddfSDavid du Colombier /*
2717dd7cddfSDavid du Colombier * Second level contains "new" plus all the clients.
2727dd7cddfSDavid du Colombier */
2737dd7cddfSDavid du Colombier if(t == Q2nd || t == Qnew){
2747dd7cddfSDavid du Colombier if(s == 0){
2759a747e4fSDavid du Colombier mkqid(&q, Qnew, 0, QTFILE);
2769a747e4fSDavid du Colombier devdir(c, q, "new", 0, eve, 0666, dp);
2777dd7cddfSDavid du Colombier }
2787dd7cddfSDavid du Colombier else if(s <= sdraw.nclient){
2797dd7cddfSDavid du Colombier cl = sdraw.client[s-1];
2807dd7cddfSDavid du Colombier if(cl == 0)
2817dd7cddfSDavid du Colombier return 0;
2824e3613abSDavid du Colombier snprint(up->genbuf, sizeof up->genbuf, "%d",
2834e3613abSDavid du Colombier cl->clientid);
2849a747e4fSDavid du Colombier mkqid(&q, (s<<QSHIFT)|Q3rd, 0, QTDIR);
2859a747e4fSDavid du Colombier devdir(c, q, up->genbuf, 0, eve, 0555, dp);
2867dd7cddfSDavid du Colombier return 1;
2877dd7cddfSDavid du Colombier }
2887dd7cddfSDavid du Colombier else
2897dd7cddfSDavid du Colombier return -1;
2907dd7cddfSDavid du Colombier return 1;
2917dd7cddfSDavid du Colombier }
2927dd7cddfSDavid du Colombier
2937dd7cddfSDavid du Colombier /*
2947dd7cddfSDavid du Colombier * Third level.
2957dd7cddfSDavid du Colombier */
2969a747e4fSDavid du Colombier path = c->qid.path&~((1<<QSHIFT)-1); /* slot component */
2977dd7cddfSDavid du Colombier q.vers = c->qid.vers;
2989a747e4fSDavid du Colombier q.type = QTFILE;
2997dd7cddfSDavid du Colombier switch(s){
3007dd7cddfSDavid du Colombier case 0:
3019a747e4fSDavid du Colombier q.path = path|Qcolormap;
3027dd7cddfSDavid du Colombier devdir(c, q, "colormap", 0, eve, 0600, dp);
3037dd7cddfSDavid du Colombier break;
3047dd7cddfSDavid du Colombier case 1:
3059a747e4fSDavid du Colombier q.path = path|Qctl;
3067dd7cddfSDavid du Colombier devdir(c, q, "ctl", 0, eve, 0600, dp);
3077dd7cddfSDavid du Colombier break;
3087dd7cddfSDavid du Colombier case 2:
3099a747e4fSDavid du Colombier q.path = path|Qdata;
3107dd7cddfSDavid du Colombier devdir(c, q, "data", 0, eve, 0600, dp);
3117dd7cddfSDavid du Colombier break;
3127dd7cddfSDavid du Colombier case 3:
3139a747e4fSDavid du Colombier q.path = path|Qrefresh;
3147dd7cddfSDavid du Colombier devdir(c, q, "refresh", 0, eve, 0400, dp);
3157dd7cddfSDavid du Colombier break;
3167dd7cddfSDavid du Colombier default:
3177dd7cddfSDavid du Colombier return -1;
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier return 1;
3207dd7cddfSDavid du Colombier }
3217dd7cddfSDavid du Colombier
3227dd7cddfSDavid du Colombier static
3237dd7cddfSDavid du Colombier int
drawrefactive(void * a)3247dd7cddfSDavid du Colombier drawrefactive(void *a)
3257dd7cddfSDavid du Colombier {
3267dd7cddfSDavid du Colombier Client *c;
3277dd7cddfSDavid du Colombier
3287dd7cddfSDavid du Colombier c = a;
3297dd7cddfSDavid du Colombier return c->refreshme || c->refresh!=0;
3307dd7cddfSDavid du Colombier }
3317dd7cddfSDavid du Colombier
3327dd7cddfSDavid du Colombier static
3337dd7cddfSDavid du Colombier void
drawrefreshscreen(DImage * l,Client * client)3347dd7cddfSDavid du Colombier drawrefreshscreen(DImage *l, Client *client)
3357dd7cddfSDavid du Colombier {
3367dd7cddfSDavid du Colombier while(l != nil && l->dscreen == nil)
3377dd7cddfSDavid du Colombier l = l->fromname;
3387dd7cddfSDavid du Colombier if(l != nil && l->dscreen->owner != client)
3397dd7cddfSDavid du Colombier l->dscreen->owner->refreshme = 1;
3407dd7cddfSDavid du Colombier }
3417dd7cddfSDavid du Colombier
3427dd7cddfSDavid du Colombier static
3437dd7cddfSDavid du Colombier void
drawrefresh(Memimage *,Rectangle r,void * v)3449a747e4fSDavid du Colombier drawrefresh(Memimage*, Rectangle r, void *v)
3457dd7cddfSDavid du Colombier {
3467dd7cddfSDavid du Colombier Refx *x;
3477dd7cddfSDavid du Colombier DImage *d;
3487dd7cddfSDavid du Colombier Client *c;
3497dd7cddfSDavid du Colombier Refresh *ref;
3507dd7cddfSDavid du Colombier
3517dd7cddfSDavid du Colombier if(v == 0)
3527dd7cddfSDavid du Colombier return;
3537dd7cddfSDavid du Colombier x = v;
3547dd7cddfSDavid du Colombier c = x->client;
3557dd7cddfSDavid du Colombier d = x->dimage;
3567dd7cddfSDavid du Colombier for(ref=c->refresh; ref; ref=ref->next)
3577dd7cddfSDavid du Colombier if(ref->dimage == d){
3587dd7cddfSDavid du Colombier combinerect(&ref->r, r);
3597dd7cddfSDavid du Colombier return;
3607dd7cddfSDavid du Colombier }
3617dd7cddfSDavid du Colombier ref = malloc(sizeof(Refresh));
3627dd7cddfSDavid du Colombier if(ref){
3637dd7cddfSDavid du Colombier ref->dimage = d;
3647dd7cddfSDavid du Colombier ref->r = r;
3657dd7cddfSDavid du Colombier ref->next = c->refresh;
3667dd7cddfSDavid du Colombier c->refresh = ref;
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier }
3697dd7cddfSDavid du Colombier
3707dd7cddfSDavid du Colombier static void
addflush(Rectangle r)3717dd7cddfSDavid du Colombier addflush(Rectangle r)
3727dd7cddfSDavid du Colombier {
3737dd7cddfSDavid du Colombier int abb, ar, anbb;
3747dd7cddfSDavid du Colombier Rectangle nbb;
3757dd7cddfSDavid du Colombier
3767dd7cddfSDavid du Colombier if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))
3777dd7cddfSDavid du Colombier return;
3787dd7cddfSDavid du Colombier
3797dd7cddfSDavid du Colombier if(flushrect.min.x >= flushrect.max.x){
3807dd7cddfSDavid du Colombier flushrect = r;
3817dd7cddfSDavid du Colombier waste = 0;
3827dd7cddfSDavid du Colombier return;
3837dd7cddfSDavid du Colombier }
3847dd7cddfSDavid du Colombier nbb = flushrect;
3857dd7cddfSDavid du Colombier combinerect(&nbb, r);
3867dd7cddfSDavid du Colombier ar = Dx(r)*Dy(r);
3877dd7cddfSDavid du Colombier abb = Dx(flushrect)*Dy(flushrect);
3887dd7cddfSDavid du Colombier anbb = Dx(nbb)*Dy(nbb);
3897dd7cddfSDavid du Colombier /*
3907dd7cddfSDavid du Colombier * Area of new waste is area of new bb minus area of old bb,
3917dd7cddfSDavid du Colombier * less the area of the new segment, which we assume is not waste.
3927dd7cddfSDavid du Colombier * This could be negative, but that's OK.
3937dd7cddfSDavid du Colombier */
3947dd7cddfSDavid du Colombier waste += anbb-abb - ar;
3957dd7cddfSDavid du Colombier if(waste < 0)
3967dd7cddfSDavid du Colombier waste = 0;
3977dd7cddfSDavid du Colombier /*
3987dd7cddfSDavid du Colombier * absorb if:
3997dd7cddfSDavid du Colombier * total area is small
4007dd7cddfSDavid du Colombier * waste is less than half total area
4017dd7cddfSDavid du Colombier * rectangles touch
4027dd7cddfSDavid du Colombier */
4037dd7cddfSDavid du Colombier if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){
4047dd7cddfSDavid du Colombier flushrect = nbb;
4057dd7cddfSDavid du Colombier return;
4067dd7cddfSDavid du Colombier }
4077dd7cddfSDavid du Colombier /* emit current state */
4089a747e4fSDavid du Colombier if(flushrect.min.x < flushrect.max.x)
4097dd7cddfSDavid du Colombier flushmemscreen(flushrect);
4107dd7cddfSDavid du Colombier flushrect = r;
4117dd7cddfSDavid du Colombier waste = 0;
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier
4147dd7cddfSDavid du Colombier static
4157dd7cddfSDavid du Colombier void
dstflush(int dstid,Memimage * dst,Rectangle r)4167dd7cddfSDavid du Colombier dstflush(int dstid, Memimage *dst, Rectangle r)
4177dd7cddfSDavid du Colombier {
4187dd7cddfSDavid du Colombier Memlayer *l;
4197dd7cddfSDavid du Colombier
4207dd7cddfSDavid du Colombier if(dstid == 0){
4217dd7cddfSDavid du Colombier combinerect(&flushrect, r);
4227dd7cddfSDavid du Colombier return;
4237dd7cddfSDavid du Colombier }
4246a9fc400SDavid du Colombier /* how can this happen? -rsc, dec 12 2002 */
4256a9fc400SDavid du Colombier if(dst == 0){
4266a9fc400SDavid du Colombier print("nil dstflush\n");
4276a9fc400SDavid du Colombier return;
4286a9fc400SDavid du Colombier }
4297dd7cddfSDavid du Colombier l = dst->layer;
4307dd7cddfSDavid du Colombier if(l == nil)
4317dd7cddfSDavid du Colombier return;
4327dd7cddfSDavid du Colombier do{
4337dd7cddfSDavid du Colombier if(l->screen->image->data != screenimage->data)
4347dd7cddfSDavid du Colombier return;
4357dd7cddfSDavid du Colombier r = rectaddpt(r, l->delta);
4367dd7cddfSDavid du Colombier l = l->screen->image->layer;
4377dd7cddfSDavid du Colombier }while(l);
4387dd7cddfSDavid du Colombier addflush(r);
4397dd7cddfSDavid du Colombier }
4407dd7cddfSDavid du Colombier
4417dd7cddfSDavid du Colombier void
drawflush(void)4427dd7cddfSDavid du Colombier drawflush(void)
4437dd7cddfSDavid du Colombier {
4449a747e4fSDavid du Colombier if(flushrect.min.x < flushrect.max.x)
4457dd7cddfSDavid du Colombier flushmemscreen(flushrect);
4467dd7cddfSDavid du Colombier flushrect = Rect(10000, 10000, -10000, -10000);
4477dd7cddfSDavid du Colombier }
4487dd7cddfSDavid du Colombier
4497dd7cddfSDavid du Colombier static
4507dd7cddfSDavid du Colombier int
drawcmp(char * a,char * b,int n)4517dd7cddfSDavid du Colombier drawcmp(char *a, char *b, int n)
4527dd7cddfSDavid du Colombier {
4537dd7cddfSDavid du Colombier if(strlen(a) != n)
4547dd7cddfSDavid du Colombier return 1;
4557dd7cddfSDavid du Colombier return memcmp(a, b, n);
4567dd7cddfSDavid du Colombier }
4577dd7cddfSDavid du Colombier
4587dd7cddfSDavid du Colombier DName*
drawlookupname(int n,char * str)4597dd7cddfSDavid du Colombier drawlookupname(int n, char *str)
4607dd7cddfSDavid du Colombier {
4617dd7cddfSDavid du Colombier DName *name, *ename;
4627dd7cddfSDavid du Colombier
4637dd7cddfSDavid du Colombier name = sdraw.name;
4647dd7cddfSDavid du Colombier ename = &name[sdraw.nname];
4657dd7cddfSDavid du Colombier for(; name<ename; name++)
4667dd7cddfSDavid du Colombier if(drawcmp(name->name, str, n) == 0)
4677dd7cddfSDavid du Colombier return name;
4687dd7cddfSDavid du Colombier return 0;
4697dd7cddfSDavid du Colombier }
4707dd7cddfSDavid du Colombier
4717dd7cddfSDavid du Colombier int
drawgoodname(DImage * d)4727dd7cddfSDavid du Colombier drawgoodname(DImage *d)
4737dd7cddfSDavid du Colombier {
4747dd7cddfSDavid du Colombier DName *n;
4757dd7cddfSDavid du Colombier
4767dd7cddfSDavid du Colombier /* if window, validate the screen's own images */
4777dd7cddfSDavid du Colombier if(d->dscreen)
4787dd7cddfSDavid du Colombier if(drawgoodname(d->dscreen->dimage) == 0
4797dd7cddfSDavid du Colombier || drawgoodname(d->dscreen->dfill) == 0)
4807dd7cddfSDavid du Colombier return 0;
4817dd7cddfSDavid du Colombier if(d->name == nil)
4827dd7cddfSDavid du Colombier return 1;
4837dd7cddfSDavid du Colombier n = drawlookupname(strlen(d->name), d->name);
4847dd7cddfSDavid du Colombier if(n==nil || n->vers!=d->vers)
4857dd7cddfSDavid du Colombier return 0;
4867dd7cddfSDavid du Colombier return 1;
4877dd7cddfSDavid du Colombier }
4887dd7cddfSDavid du Colombier
4897dd7cddfSDavid du Colombier DImage*
drawlookup(Client * client,int id,int checkname)4907dd7cddfSDavid du Colombier drawlookup(Client *client, int id, int checkname)
4917dd7cddfSDavid du Colombier {
4927dd7cddfSDavid du Colombier DImage *d;
4937dd7cddfSDavid du Colombier
4947dd7cddfSDavid du Colombier d = client->dimage[id&HASHMASK];
4957dd7cddfSDavid du Colombier while(d){
4967dd7cddfSDavid du Colombier if(d->id == id){
4977dd7cddfSDavid du Colombier if(checkname && !drawgoodname(d))
4987dd7cddfSDavid du Colombier error(Eoldname);
4997dd7cddfSDavid du Colombier return d;
5007dd7cddfSDavid du Colombier }
5017dd7cddfSDavid du Colombier d = d->next;
5027dd7cddfSDavid du Colombier }
5037dd7cddfSDavid du Colombier return 0;
5047dd7cddfSDavid du Colombier }
5057dd7cddfSDavid du Colombier
5067dd7cddfSDavid du Colombier DScreen*
drawlookupdscreen(int id)5077dd7cddfSDavid du Colombier drawlookupdscreen(int id)
5087dd7cddfSDavid du Colombier {
5097dd7cddfSDavid du Colombier DScreen *s;
5107dd7cddfSDavid du Colombier
5117dd7cddfSDavid du Colombier s = dscreen;
5127dd7cddfSDavid du Colombier while(s){
5137dd7cddfSDavid du Colombier if(s->id == id)
5147dd7cddfSDavid du Colombier return s;
5157dd7cddfSDavid du Colombier s = s->next;
5167dd7cddfSDavid du Colombier }
5177dd7cddfSDavid du Colombier return 0;
5187dd7cddfSDavid du Colombier }
5197dd7cddfSDavid du Colombier
5207dd7cddfSDavid du Colombier DScreen*
drawlookupscreen(Client * client,int id,CScreen ** cs)5217dd7cddfSDavid du Colombier drawlookupscreen(Client *client, int id, CScreen **cs)
5227dd7cddfSDavid du Colombier {
5237dd7cddfSDavid du Colombier CScreen *s;
5247dd7cddfSDavid du Colombier
5257dd7cddfSDavid du Colombier s = client->cscreen;
5267dd7cddfSDavid du Colombier while(s){
5277dd7cddfSDavid du Colombier if(s->dscreen->id == id){
5287dd7cddfSDavid du Colombier *cs = s;
5297dd7cddfSDavid du Colombier return s->dscreen;
5307dd7cddfSDavid du Colombier }
5317dd7cddfSDavid du Colombier s = s->next;
5327dd7cddfSDavid du Colombier }
5337dd7cddfSDavid du Colombier error(Enodrawscreen);
5347dd7cddfSDavid du Colombier return 0;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier
5374de34a7eSDavid du Colombier DImage*
allocdimage(Memimage * i)5384de34a7eSDavid du Colombier allocdimage(Memimage *i)
5397dd7cddfSDavid du Colombier {
5407dd7cddfSDavid du Colombier DImage *d;
5417dd7cddfSDavid du Colombier
5427dd7cddfSDavid du Colombier d = malloc(sizeof(DImage));
5437dd7cddfSDavid du Colombier if(d == 0)
5447dd7cddfSDavid du Colombier return 0;
5457dd7cddfSDavid du Colombier d->ref = 1;
5467dd7cddfSDavid du Colombier d->name = 0;
5477dd7cddfSDavid du Colombier d->vers = 0;
5487dd7cddfSDavid du Colombier d->image = i;
5497dd7cddfSDavid du Colombier d->nfchar = 0;
5507dd7cddfSDavid du Colombier d->fchar = 0;
5517dd7cddfSDavid du Colombier d->fromname = 0;
5524de34a7eSDavid du Colombier return d;
5534de34a7eSDavid du Colombier }
5544de34a7eSDavid du Colombier
5554de34a7eSDavid du Colombier Memimage*
drawinstall(Client * client,int id,Memimage * i,DScreen * dscreen)5564de34a7eSDavid du Colombier drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
5574de34a7eSDavid du Colombier {
5584de34a7eSDavid du Colombier DImage *d;
5594de34a7eSDavid du Colombier
5604de34a7eSDavid du Colombier d = allocdimage(i);
5614de34a7eSDavid du Colombier if(d == 0)
5624de34a7eSDavid du Colombier return 0;
5634de34a7eSDavid du Colombier d->id = id;
5647dd7cddfSDavid du Colombier d->dscreen = dscreen;
5657dd7cddfSDavid du Colombier d->next = client->dimage[id&HASHMASK];
5667dd7cddfSDavid du Colombier client->dimage[id&HASHMASK] = d;
5677dd7cddfSDavid du Colombier return i;
5687dd7cddfSDavid du Colombier }
5697dd7cddfSDavid du Colombier
5707dd7cddfSDavid du Colombier Memscreen*
drawinstallscreen(Client * client,DScreen * d,int id,DImage * dimage,DImage * dfill,int public)5717dd7cddfSDavid du Colombier drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public)
5727dd7cddfSDavid du Colombier {
5737dd7cddfSDavid du Colombier Memscreen *s;
5747dd7cddfSDavid du Colombier CScreen *c;
5757dd7cddfSDavid du Colombier
5767dd7cddfSDavid du Colombier c = malloc(sizeof(CScreen));
5777dd7cddfSDavid du Colombier if(dimage && dimage->image && dimage->image->chan == 0)
5787dd7cddfSDavid du Colombier panic("bad image %p in drawinstallscreen", dimage->image);
5797dd7cddfSDavid du Colombier
5807dd7cddfSDavid du Colombier if(c == 0)
5817dd7cddfSDavid du Colombier return 0;
5827dd7cddfSDavid du Colombier if(d == 0){
5837dd7cddfSDavid du Colombier d = malloc(sizeof(DScreen));
5847dd7cddfSDavid du Colombier if(d == 0){
5857dd7cddfSDavid du Colombier free(c);
5867dd7cddfSDavid du Colombier return 0;
5877dd7cddfSDavid du Colombier }
5887dd7cddfSDavid du Colombier s = malloc(sizeof(Memscreen));
5897dd7cddfSDavid du Colombier if(s == 0){
5907dd7cddfSDavid du Colombier free(c);
5917dd7cddfSDavid du Colombier free(d);
5927dd7cddfSDavid du Colombier return 0;
5937dd7cddfSDavid du Colombier }
5947dd7cddfSDavid du Colombier s->frontmost = 0;
5957dd7cddfSDavid du Colombier s->rearmost = 0;
5967dd7cddfSDavid du Colombier d->dimage = dimage;
5977dd7cddfSDavid du Colombier if(dimage){
5987dd7cddfSDavid du Colombier s->image = dimage->image;
5997dd7cddfSDavid du Colombier dimage->ref++;
6007dd7cddfSDavid du Colombier }
6017dd7cddfSDavid du Colombier d->dfill = dfill;
6027dd7cddfSDavid du Colombier if(dfill){
6037dd7cddfSDavid du Colombier s->fill = dfill->image;
6047dd7cddfSDavid du Colombier dfill->ref++;
6057dd7cddfSDavid du Colombier }
6067dd7cddfSDavid du Colombier d->ref = 0;
6077dd7cddfSDavid du Colombier d->id = id;
6087dd7cddfSDavid du Colombier d->screen = s;
6097dd7cddfSDavid du Colombier d->public = public;
6107dd7cddfSDavid du Colombier d->next = dscreen;
6117dd7cddfSDavid du Colombier d->owner = client;
6127dd7cddfSDavid du Colombier dscreen = d;
6137dd7cddfSDavid du Colombier }
6147dd7cddfSDavid du Colombier c->dscreen = d;
6157dd7cddfSDavid du Colombier d->ref++;
6167dd7cddfSDavid du Colombier c->next = client->cscreen;
6177dd7cddfSDavid du Colombier client->cscreen = c;
6187dd7cddfSDavid du Colombier return d->screen;
6197dd7cddfSDavid du Colombier }
6207dd7cddfSDavid du Colombier
6217dd7cddfSDavid du Colombier void
drawdelname(DName * name)6227dd7cddfSDavid du Colombier drawdelname(DName *name)
6237dd7cddfSDavid du Colombier {
6247dd7cddfSDavid du Colombier int i;
6257dd7cddfSDavid du Colombier
6267dd7cddfSDavid du Colombier i = name-sdraw.name;
6277dd7cddfSDavid du Colombier memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
6287dd7cddfSDavid du Colombier sdraw.nname--;
6297dd7cddfSDavid du Colombier }
6307dd7cddfSDavid du Colombier
6317dd7cddfSDavid du Colombier void
drawfreedscreen(DScreen * this)6327dd7cddfSDavid du Colombier drawfreedscreen(DScreen *this)
6337dd7cddfSDavid du Colombier {
6347dd7cddfSDavid du Colombier DScreen *ds, *next;
6357dd7cddfSDavid du Colombier
6367dd7cddfSDavid du Colombier this->ref--;
6377dd7cddfSDavid du Colombier if(this->ref < 0)
6387dd7cddfSDavid du Colombier print("negative ref in drawfreedscreen\n");
6397dd7cddfSDavid du Colombier if(this->ref > 0)
6407dd7cddfSDavid du Colombier return;
6417dd7cddfSDavid du Colombier ds = dscreen;
6427dd7cddfSDavid du Colombier if(ds == this){
6437dd7cddfSDavid du Colombier dscreen = this->next;
6447dd7cddfSDavid du Colombier goto Found;
6457dd7cddfSDavid du Colombier }
6467dd7cddfSDavid du Colombier while(next = ds->next){ /* assign = */
6477dd7cddfSDavid du Colombier if(next == this){
6487dd7cddfSDavid du Colombier ds->next = this->next;
6497dd7cddfSDavid du Colombier goto Found;
6507dd7cddfSDavid du Colombier }
6517dd7cddfSDavid du Colombier ds = next;
6527dd7cddfSDavid du Colombier }
6537dd7cddfSDavid du Colombier error(Enodrawimage);
6547dd7cddfSDavid du Colombier
6557dd7cddfSDavid du Colombier Found:
6567dd7cddfSDavid du Colombier if(this->dimage)
6577dd7cddfSDavid du Colombier drawfreedimage(this->dimage);
6587dd7cddfSDavid du Colombier if(this->dfill)
6597dd7cddfSDavid du Colombier drawfreedimage(this->dfill);
6607dd7cddfSDavid du Colombier free(this->screen);
6617dd7cddfSDavid du Colombier free(this);
6627dd7cddfSDavid du Colombier }
6637dd7cddfSDavid du Colombier
6647dd7cddfSDavid du Colombier void
drawfreedimage(DImage * dimage)6657dd7cddfSDavid du Colombier drawfreedimage(DImage *dimage)
6667dd7cddfSDavid du Colombier {
6677dd7cddfSDavid du Colombier int i;
6687dd7cddfSDavid du Colombier Memimage *l;
6697dd7cddfSDavid du Colombier DScreen *ds;
6707dd7cddfSDavid du Colombier
6717dd7cddfSDavid du Colombier dimage->ref--;
6727dd7cddfSDavid du Colombier if(dimage->ref < 0)
6737dd7cddfSDavid du Colombier print("negative ref in drawfreedimage\n");
6747dd7cddfSDavid du Colombier if(dimage->ref > 0)
6757dd7cddfSDavid du Colombier return;
6767dd7cddfSDavid du Colombier
6777dd7cddfSDavid du Colombier /* any names? */
6787dd7cddfSDavid du Colombier for(i=0; i<sdraw.nname; )
6797dd7cddfSDavid du Colombier if(sdraw.name[i].dimage == dimage)
6807dd7cddfSDavid du Colombier drawdelname(sdraw.name+i);
6817dd7cddfSDavid du Colombier else
6827dd7cddfSDavid du Colombier i++;
6837dd7cddfSDavid du Colombier if(dimage->fromname){ /* acquired by name; owned by someone else*/
6847dd7cddfSDavid du Colombier drawfreedimage(dimage->fromname);
6857dd7cddfSDavid du Colombier goto Return;
6867dd7cddfSDavid du Colombier }
6874de34a7eSDavid du Colombier // if(dimage->image == screenimage) /* don't free the display */
6884de34a7eSDavid du Colombier // goto Return;
6897dd7cddfSDavid du Colombier ds = dimage->dscreen;
6907dd7cddfSDavid du Colombier if(ds){
6917dd7cddfSDavid du Colombier l = dimage->image;
6927dd7cddfSDavid du Colombier if(l->data == screenimage->data)
6937dd7cddfSDavid du Colombier addflush(l->layer->screenr);
6947dd7cddfSDavid du Colombier if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
6957dd7cddfSDavid du Colombier free(l->layer->refreshptr);
6967dd7cddfSDavid du Colombier l->layer->refreshptr = nil;
6977dd7cddfSDavid du Colombier if(drawgoodname(dimage))
6987dd7cddfSDavid du Colombier memldelete(l);
6997dd7cddfSDavid du Colombier else
7007dd7cddfSDavid du Colombier memlfree(l);
7017dd7cddfSDavid du Colombier drawfreedscreen(ds);
7027dd7cddfSDavid du Colombier }else
7037dd7cddfSDavid du Colombier freememimage(dimage->image);
7047dd7cddfSDavid du Colombier Return:
7057dd7cddfSDavid du Colombier free(dimage->fchar);
7067dd7cddfSDavid du Colombier free(dimage);
7077dd7cddfSDavid du Colombier }
7087dd7cddfSDavid du Colombier
7097dd7cddfSDavid du Colombier void
drawuninstallscreen(Client * client,CScreen * this)7107dd7cddfSDavid du Colombier drawuninstallscreen(Client *client, CScreen *this)
7117dd7cddfSDavid du Colombier {
7127dd7cddfSDavid du Colombier CScreen *cs, *next;
7137dd7cddfSDavid du Colombier
7147dd7cddfSDavid du Colombier cs = client->cscreen;
7157dd7cddfSDavid du Colombier if(cs == this){
7167dd7cddfSDavid du Colombier client->cscreen = this->next;
7177dd7cddfSDavid du Colombier drawfreedscreen(this->dscreen);
7187dd7cddfSDavid du Colombier free(this);
7197dd7cddfSDavid du Colombier return;
7207dd7cddfSDavid du Colombier }
7217dd7cddfSDavid du Colombier while(next = cs->next){ /* assign = */
7227dd7cddfSDavid du Colombier if(next == this){
7237dd7cddfSDavid du Colombier cs->next = this->next;
7247dd7cddfSDavid du Colombier drawfreedscreen(this->dscreen);
7257dd7cddfSDavid du Colombier free(this);
7267dd7cddfSDavid du Colombier return;
7277dd7cddfSDavid du Colombier }
7287dd7cddfSDavid du Colombier cs = next;
7297dd7cddfSDavid du Colombier }
7307dd7cddfSDavid du Colombier }
7317dd7cddfSDavid du Colombier
7327dd7cddfSDavid du Colombier void
drawuninstall(Client * client,int id)7337dd7cddfSDavid du Colombier drawuninstall(Client *client, int id)
7347dd7cddfSDavid du Colombier {
7357dd7cddfSDavid du Colombier DImage *d, *next;
7367dd7cddfSDavid du Colombier
7377dd7cddfSDavid du Colombier d = client->dimage[id&HASHMASK];
7387dd7cddfSDavid du Colombier if(d == 0)
7397dd7cddfSDavid du Colombier error(Enodrawimage);
7407dd7cddfSDavid du Colombier if(d->id == id){
7417dd7cddfSDavid du Colombier client->dimage[id&HASHMASK] = d->next;
7427dd7cddfSDavid du Colombier drawfreedimage(d);
7437dd7cddfSDavid du Colombier return;
7447dd7cddfSDavid du Colombier }
7457dd7cddfSDavid du Colombier while(next = d->next){ /* assign = */
7467dd7cddfSDavid du Colombier if(next->id == id){
7477dd7cddfSDavid du Colombier d->next = next->next;
7487dd7cddfSDavid du Colombier drawfreedimage(next);
7497dd7cddfSDavid du Colombier return;
7507dd7cddfSDavid du Colombier }
7517dd7cddfSDavid du Colombier d = next;
7527dd7cddfSDavid du Colombier }
7537dd7cddfSDavid du Colombier error(Enodrawimage);
7547dd7cddfSDavid du Colombier }
7557dd7cddfSDavid du Colombier
7567dd7cddfSDavid du Colombier void
drawaddname(Client * client,DImage * di,int n,char * str)7577dd7cddfSDavid du Colombier drawaddname(Client *client, DImage *di, int n, char *str)
7587dd7cddfSDavid du Colombier {
7597dd7cddfSDavid du Colombier DName *name, *ename, *new, *t;
7607dd7cddfSDavid du Colombier
7617dd7cddfSDavid du Colombier name = sdraw.name;
7627dd7cddfSDavid du Colombier ename = &name[sdraw.nname];
7637dd7cddfSDavid du Colombier for(; name<ename; name++)
7647dd7cddfSDavid du Colombier if(drawcmp(name->name, str, n) == 0)
7657dd7cddfSDavid du Colombier error(Enameused);
7667dd7cddfSDavid du Colombier t = smalloc((sdraw.nname+1)*sizeof(DName));
7677dd7cddfSDavid du Colombier memmove(t, sdraw.name, sdraw.nname*sizeof(DName));
7687dd7cddfSDavid du Colombier free(sdraw.name);
7697dd7cddfSDavid du Colombier sdraw.name = t;
7707dd7cddfSDavid du Colombier new = &sdraw.name[sdraw.nname++];
7717dd7cddfSDavid du Colombier new->name = smalloc(n+1);
7727dd7cddfSDavid du Colombier memmove(new->name, str, n);
7737dd7cddfSDavid du Colombier new->name[n] = 0;
7747dd7cddfSDavid du Colombier new->dimage = di;
7757dd7cddfSDavid du Colombier new->client = client;
7767dd7cddfSDavid du Colombier new->vers = ++sdraw.vers;
7777dd7cddfSDavid du Colombier }
7787dd7cddfSDavid du Colombier
7797dd7cddfSDavid du Colombier Client*
drawnewclient(void)7807dd7cddfSDavid du Colombier drawnewclient(void)
7817dd7cddfSDavid du Colombier {
7827dd7cddfSDavid du Colombier Client *cl, **cp;
7837dd7cddfSDavid du Colombier int i;
7847dd7cddfSDavid du Colombier
7857dd7cddfSDavid du Colombier for(i=0; i<sdraw.nclient; i++){
7867dd7cddfSDavid du Colombier cl = sdraw.client[i];
7877dd7cddfSDavid du Colombier if(cl == 0)
7887dd7cddfSDavid du Colombier break;
7897dd7cddfSDavid du Colombier }
7907dd7cddfSDavid du Colombier if(i == sdraw.nclient){
7917dd7cddfSDavid du Colombier cp = malloc((sdraw.nclient+1)*sizeof(Client*));
7927dd7cddfSDavid du Colombier if(cp == 0)
7937dd7cddfSDavid du Colombier return 0;
7947dd7cddfSDavid du Colombier memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*));
7957dd7cddfSDavid du Colombier free(sdraw.client);
7967dd7cddfSDavid du Colombier sdraw.client = cp;
7977dd7cddfSDavid du Colombier sdraw.nclient++;
7987dd7cddfSDavid du Colombier cp[i] = 0;
7997dd7cddfSDavid du Colombier }
8007dd7cddfSDavid du Colombier cl = malloc(sizeof(Client));
8017dd7cddfSDavid du Colombier if(cl == 0)
8027dd7cddfSDavid du Colombier return 0;
8037dd7cddfSDavid du Colombier memset(cl, 0, sizeof(Client));
8047dd7cddfSDavid du Colombier cl->slot = i;
8057dd7cddfSDavid du Colombier cl->clientid = ++sdraw.clientid;
8066a9fc400SDavid du Colombier cl->op = SoverD;
8077dd7cddfSDavid du Colombier sdraw.client[i] = cl;
8087dd7cddfSDavid du Colombier return cl;
8097dd7cddfSDavid du Colombier }
8107dd7cddfSDavid du Colombier
8116a9fc400SDavid du Colombier static int
drawclientop(Client * cl)8126a9fc400SDavid du Colombier drawclientop(Client *cl)
8136a9fc400SDavid du Colombier {
8146a9fc400SDavid du Colombier int op;
8156a9fc400SDavid du Colombier
8166a9fc400SDavid du Colombier op = cl->op;
8176a9fc400SDavid du Colombier cl->op = SoverD;
8186a9fc400SDavid du Colombier return op;
8196a9fc400SDavid du Colombier }
8206a9fc400SDavid du Colombier
8217dd7cddfSDavid du Colombier int
drawhasclients(void)8227dd7cddfSDavid du Colombier drawhasclients(void)
8237dd7cddfSDavid du Colombier {
824223a736eSDavid du Colombier /*
825223a736eSDavid du Colombier * if draw has ever been used, we can't resize the frame buffer,
826223a736eSDavid du Colombier * even if all clients have exited (nclients is cumulative); it's too
827223a736eSDavid du Colombier * hard to make work.
828223a736eSDavid du Colombier */
8297dd7cddfSDavid du Colombier return sdraw.nclient != 0;
8307dd7cddfSDavid du Colombier }
8317dd7cddfSDavid du Colombier
8327dd7cddfSDavid du Colombier Client*
drawclientofpath(ulong path)8337dd7cddfSDavid du Colombier drawclientofpath(ulong path)
8347dd7cddfSDavid du Colombier {
8357dd7cddfSDavid du Colombier Client *cl;
8367dd7cddfSDavid du Colombier int slot;
8377dd7cddfSDavid du Colombier
8387dd7cddfSDavid du Colombier slot = CLIENTPATH(path);
8397dd7cddfSDavid du Colombier if(slot == 0)
8407dd7cddfSDavid du Colombier return nil;
8417dd7cddfSDavid du Colombier cl = sdraw.client[slot-1];
8427dd7cddfSDavid du Colombier if(cl==0 || cl->clientid==0)
8437dd7cddfSDavid du Colombier return nil;
8447dd7cddfSDavid du Colombier return cl;
8457dd7cddfSDavid du Colombier }
8467dd7cddfSDavid du Colombier
8477dd7cddfSDavid du Colombier
8487dd7cddfSDavid du Colombier Client*
drawclient(Chan * c)8497dd7cddfSDavid du Colombier drawclient(Chan *c)
8507dd7cddfSDavid du Colombier {
8517dd7cddfSDavid du Colombier Client *client;
8527dd7cddfSDavid du Colombier
8537dd7cddfSDavid du Colombier client = drawclientofpath(c->qid.path);
8547dd7cddfSDavid du Colombier if(client == nil)
8557dd7cddfSDavid du Colombier error(Enoclient);
8567dd7cddfSDavid du Colombier return client;
8577dd7cddfSDavid du Colombier }
8587dd7cddfSDavid du Colombier
8597dd7cddfSDavid du Colombier Memimage*
drawimage(Client * client,uchar * a)8607dd7cddfSDavid du Colombier drawimage(Client *client, uchar *a)
8617dd7cddfSDavid du Colombier {
8627dd7cddfSDavid du Colombier DImage *d;
8637dd7cddfSDavid du Colombier
8647dd7cddfSDavid du Colombier d = drawlookup(client, BGLONG(a), 1);
8657dd7cddfSDavid du Colombier if(d == nil)
8667dd7cddfSDavid du Colombier error(Enodrawimage);
8677dd7cddfSDavid du Colombier return d->image;
8687dd7cddfSDavid du Colombier }
8697dd7cddfSDavid du Colombier
8707dd7cddfSDavid du Colombier void
drawrectangle(Rectangle * r,uchar * a)8717dd7cddfSDavid du Colombier drawrectangle(Rectangle *r, uchar *a)
8727dd7cddfSDavid du Colombier {
8737dd7cddfSDavid du Colombier r->min.x = BGLONG(a+0*4);
8747dd7cddfSDavid du Colombier r->min.y = BGLONG(a+1*4);
8757dd7cddfSDavid du Colombier r->max.x = BGLONG(a+2*4);
8767dd7cddfSDavid du Colombier r->max.y = BGLONG(a+3*4);
8777dd7cddfSDavid du Colombier }
8787dd7cddfSDavid du Colombier
8797dd7cddfSDavid du Colombier void
drawpoint(Point * p,uchar * a)8807dd7cddfSDavid du Colombier drawpoint(Point *p, uchar *a)
8817dd7cddfSDavid du Colombier {
8827dd7cddfSDavid du Colombier p->x = BGLONG(a+0*4);
8837dd7cddfSDavid du Colombier p->y = BGLONG(a+1*4);
8847dd7cddfSDavid du Colombier }
8857dd7cddfSDavid du Colombier
8867dd7cddfSDavid du Colombier Point
drawchar(Memimage * dst,Memimage * rdst,Point p,Memimage * src,Point * sp,DImage * font,int index,int op)8871ee3cffaSDavid du Colombier drawchar(Memimage *dst, Memimage *rdst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
8887dd7cddfSDavid du Colombier {
8897dd7cddfSDavid du Colombier FChar *fc;
8907dd7cddfSDavid du Colombier Rectangle r;
8917dd7cddfSDavid du Colombier Point sp1;
8921ee3cffaSDavid du Colombier static Memimage *tmp;
8937dd7cddfSDavid du Colombier
8947dd7cddfSDavid du Colombier fc = &font->fchar[index];
8957dd7cddfSDavid du Colombier r.min.x = p.x+fc->left;
8967dd7cddfSDavid du Colombier r.min.y = p.y-(font->ascent-fc->miny);
8977dd7cddfSDavid du Colombier r.max.x = r.min.x+(fc->maxx-fc->minx);
8987dd7cddfSDavid du Colombier r.max.y = r.min.y+(fc->maxy-fc->miny);
8997dd7cddfSDavid du Colombier sp1.x = sp->x+fc->left;
9007dd7cddfSDavid du Colombier sp1.y = sp->y+fc->miny;
9011ee3cffaSDavid du Colombier
9021ee3cffaSDavid du Colombier /*
9031ee3cffaSDavid du Colombier * If we're drawing greyscale fonts onto a VGA screen,
9041ee3cffaSDavid du Colombier * it's very costly to read the screen memory to do the
9051ee3cffaSDavid du Colombier * alpha blending inside memdraw. If this is really a stringbg,
9061ee3cffaSDavid du Colombier * then rdst is the bg image (in main memory) which we can
9071ee3cffaSDavid du Colombier * refer to for the underlying dst pixels instead of reading dst
9081ee3cffaSDavid du Colombier * directly.
9091ee3cffaSDavid du Colombier */
9101ee3cffaSDavid du Colombier if(ishwimage(dst) && !ishwimage(rdst) && font->image->depth > 1){
9111ee3cffaSDavid du Colombier if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){
9121ee3cffaSDavid du Colombier if(tmp)
9131ee3cffaSDavid du Colombier freememimage(tmp);
9141ee3cffaSDavid du Colombier tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan);
9151ee3cffaSDavid du Colombier if(tmp == nil)
9161ee3cffaSDavid du Colombier goto fallback;
9171ee3cffaSDavid du Colombier }
9181ee3cffaSDavid du Colombier memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S);
9191ee3cffaSDavid du Colombier memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op);
9201ee3cffaSDavid du Colombier memdraw(dst, r, tmp, ZP, memopaque, ZP, S);
9211ee3cffaSDavid du Colombier }else{
9221ee3cffaSDavid du Colombier fallback:
9236a9fc400SDavid du Colombier memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
9241ee3cffaSDavid du Colombier }
9251ee3cffaSDavid du Colombier
9267dd7cddfSDavid du Colombier p.x += fc->width;
9277dd7cddfSDavid du Colombier sp->x += fc->width;
9287dd7cddfSDavid du Colombier return p;
9297dd7cddfSDavid du Colombier }
9307dd7cddfSDavid du Colombier
9314de34a7eSDavid du Colombier static DImage*
makescreenimage(void)9324de34a7eSDavid du Colombier makescreenimage(void)
9337dd7cddfSDavid du Colombier {
9347dd7cddfSDavid du Colombier int width, depth;
9357dd7cddfSDavid du Colombier ulong chan;
9364de34a7eSDavid du Colombier DImage *di;
9374de34a7eSDavid du Colombier Memdata *md;
9384de34a7eSDavid du Colombier Memimage *i;
9397dd7cddfSDavid du Colombier Rectangle r;
9407dd7cddfSDavid du Colombier
9414de34a7eSDavid du Colombier md = malloc(sizeof *md);
9424de34a7eSDavid du Colombier if(md == nil)
9434de34a7eSDavid du Colombier return nil;
9444de34a7eSDavid du Colombier md->allocd = 1;
9454de34a7eSDavid du Colombier md->base = nil;
9464de34a7eSDavid du Colombier md->bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen);
9474de34a7eSDavid du Colombier if(md->bdata == nil){
9484de34a7eSDavid du Colombier free(md);
9494de34a7eSDavid du Colombier return nil;
9504de34a7eSDavid du Colombier }
9514de34a7eSDavid du Colombier md->ref = 1;
9524de34a7eSDavid du Colombier i = allocmemimaged(r, chan, md);
9534de34a7eSDavid du Colombier if(i == nil){
9544de34a7eSDavid du Colombier free(md);
9554de34a7eSDavid du Colombier return nil;
9564de34a7eSDavid du Colombier }
9574de34a7eSDavid du Colombier i->width = width;
9584de34a7eSDavid du Colombier i->clipr = r;
9594de34a7eSDavid du Colombier
9604de34a7eSDavid du Colombier di = allocdimage(i);
9614de34a7eSDavid du Colombier if(di == nil){
9624de34a7eSDavid du Colombier freememimage(i); /* frees md */
9634de34a7eSDavid du Colombier return nil;
9644de34a7eSDavid du Colombier }
9654de34a7eSDavid du Colombier if(!waserror()){
9664de34a7eSDavid du Colombier snprint(screenname, sizeof screenname, "noborder.screen.%d", ++screennameid);
9674de34a7eSDavid du Colombier drawaddname(nil, di, strlen(screenname), screenname);
9684de34a7eSDavid du Colombier poperror();
9694de34a7eSDavid du Colombier }
9704de34a7eSDavid du Colombier return di;
9714de34a7eSDavid du Colombier }
9724de34a7eSDavid du Colombier
9734de34a7eSDavid du Colombier static int
initscreenimage(void)9744de34a7eSDavid du Colombier initscreenimage(void)
9754de34a7eSDavid du Colombier {
9767dd7cddfSDavid du Colombier if(screenimage != nil)
9777dd7cddfSDavid du Colombier return 1;
9787dd7cddfSDavid du Colombier
9794de34a7eSDavid du Colombier screendimage = makescreenimage();
9804de34a7eSDavid du Colombier if(screendimage == nil)
9817dd7cddfSDavid du Colombier return 0;
9824de34a7eSDavid du Colombier screenimage = screendimage->image;
9834de34a7eSDavid du Colombier // iprint("initscreenimage %p %p\n", screendimage, screenimage);
9844de34a7eSDavid du Colombier mouseresize();
9857dd7cddfSDavid du Colombier return 1;
9867dd7cddfSDavid du Colombier }
9877dd7cddfSDavid du Colombier
9887dd7cddfSDavid du Colombier void
deletescreenimage(void)9897dd7cddfSDavid du Colombier deletescreenimage(void)
9907dd7cddfSDavid du Colombier {
9914de34a7eSDavid du Colombier dlock();
9924de34a7eSDavid du Colombier if(screenimage){
9934de34a7eSDavid du Colombier /* will be freed via screendimage; disable */
9944de34a7eSDavid du Colombier screenimage->clipr = ZR;
9957dd7cddfSDavid du Colombier screenimage = nil;
9964de34a7eSDavid du Colombier }
9974de34a7eSDavid du Colombier if(screendimage){
9984de34a7eSDavid du Colombier drawfreedimage(screendimage);
9994de34a7eSDavid du Colombier screendimage = nil;
10004de34a7eSDavid du Colombier }
10014de34a7eSDavid du Colombier dunlock();
10024de34a7eSDavid du Colombier }
10034de34a7eSDavid du Colombier
10044de34a7eSDavid du Colombier void
resetscreenimage(void)10054de34a7eSDavid du Colombier resetscreenimage(void)
10064de34a7eSDavid du Colombier {
10074de34a7eSDavid du Colombier dlock();
10084de34a7eSDavid du Colombier initscreenimage();
10094de34a7eSDavid du Colombier dunlock();
10107dd7cddfSDavid du Colombier }
10117dd7cddfSDavid du Colombier
10126a9fc400SDavid du Colombier static Chan*
drawattach(char * spec)10137dd7cddfSDavid du Colombier drawattach(char *spec)
10147dd7cddfSDavid du Colombier {
10154de34a7eSDavid du Colombier dlock();
10167dd7cddfSDavid du Colombier if(!initscreenimage()){
10174de34a7eSDavid du Colombier dunlock();
10187dd7cddfSDavid du Colombier error("no frame buffer");
10197dd7cddfSDavid du Colombier }
10204de34a7eSDavid du Colombier dunlock();
10217dd7cddfSDavid du Colombier return devattach('i', spec);
10227dd7cddfSDavid du Colombier }
10237dd7cddfSDavid du Colombier
10246a9fc400SDavid du Colombier static Walkqid*
drawwalk(Chan * c,Chan * nc,char ** name,int nname)10259a747e4fSDavid du Colombier drawwalk(Chan *c, Chan *nc, char **name, int nname)
10267dd7cddfSDavid du Colombier {
10274de34a7eSDavid du Colombier if(screenimage == nil)
10287dd7cddfSDavid du Colombier error("no frame buffer");
10299a747e4fSDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, drawgen);
10307dd7cddfSDavid du Colombier }
10317dd7cddfSDavid du Colombier
10329a747e4fSDavid du Colombier static int
drawstat(Chan * c,uchar * db,int n)10339a747e4fSDavid du Colombier drawstat(Chan *c, uchar *db, int n)
10347dd7cddfSDavid du Colombier {
10359a747e4fSDavid du Colombier return devstat(c, db, n, 0, 0, drawgen);
10367dd7cddfSDavid du Colombier }
10377dd7cddfSDavid du Colombier
10387dd7cddfSDavid du Colombier static Chan*
drawopen(Chan * c,int omode)10397dd7cddfSDavid du Colombier drawopen(Chan *c, int omode)
10407dd7cddfSDavid du Colombier {
10417dd7cddfSDavid du Colombier Client *cl;
10424de34a7eSDavid du Colombier DName *dn;
10434de34a7eSDavid du Colombier DImage *di;
10447dd7cddfSDavid du Colombier
10459a747e4fSDavid du Colombier if(c->qid.type & QTDIR){
10469a747e4fSDavid du Colombier c = devopen(c, omode, 0, 0, drawgen);
10479a747e4fSDavid du Colombier c->iounit = IOUNIT;
10489a747e4fSDavid du Colombier }
10497dd7cddfSDavid du Colombier
10504de34a7eSDavid du Colombier dlock();
10517dd7cddfSDavid du Colombier if(waserror()){
10524de34a7eSDavid du Colombier dunlock();
10537dd7cddfSDavid du Colombier nexterror();
10547dd7cddfSDavid du Colombier }
10557dd7cddfSDavid du Colombier
10567dd7cddfSDavid du Colombier if(QID(c->qid) == Qnew){
10577dd7cddfSDavid du Colombier cl = drawnewclient();
10587dd7cddfSDavid du Colombier if(cl == 0)
10597dd7cddfSDavid du Colombier error(Enodev);
10607dd7cddfSDavid du Colombier c->qid.path = Qctl|((cl->slot+1)<<QSHIFT);
10617dd7cddfSDavid du Colombier }
10627dd7cddfSDavid du Colombier
10637dd7cddfSDavid du Colombier switch(QID(c->qid)){
10644de34a7eSDavid du Colombier case Qwinname:
10654de34a7eSDavid du Colombier break;
10664de34a7eSDavid du Colombier
10677dd7cddfSDavid du Colombier case Qnew:
10687dd7cddfSDavid du Colombier break;
10697dd7cddfSDavid du Colombier
10707dd7cddfSDavid du Colombier case Qctl:
10717dd7cddfSDavid du Colombier cl = drawclient(c);
10727dd7cddfSDavid du Colombier if(cl->busy)
10737dd7cddfSDavid du Colombier error(Einuse);
10747dd7cddfSDavid du Colombier cl->busy = 1;
10757dd7cddfSDavid du Colombier flushrect = Rect(10000, 10000, -10000, -10000);
10764de34a7eSDavid du Colombier dn = drawlookupname(strlen(screenname), screenname);
10774de34a7eSDavid du Colombier if(dn == 0)
10784de34a7eSDavid du Colombier error("draw: cannot happen 2");
10794de34a7eSDavid du Colombier if(drawinstall(cl, 0, dn->dimage->image, 0) == 0)
10804de34a7eSDavid du Colombier error(Edrawmem);
10814de34a7eSDavid du Colombier di = drawlookup(cl, 0, 0);
10824de34a7eSDavid du Colombier if(di == 0)
10834de34a7eSDavid du Colombier error("draw: cannot happen 1");
10844de34a7eSDavid du Colombier di->vers = dn->vers;
10854de34a7eSDavid du Colombier di->name = smalloc(strlen(screenname)+1);
10864de34a7eSDavid du Colombier strcpy(di->name, screenname);
10874de34a7eSDavid du Colombier di->fromname = dn->dimage;
10884de34a7eSDavid du Colombier di->fromname->ref++;
10897dd7cddfSDavid du Colombier incref(&cl->r);
10907dd7cddfSDavid du Colombier break;
10914de34a7eSDavid du Colombier
10927dd7cddfSDavid du Colombier case Qcolormap:
10937dd7cddfSDavid du Colombier case Qdata:
10947dd7cddfSDavid du Colombier case Qrefresh:
10957dd7cddfSDavid du Colombier cl = drawclient(c);
10967dd7cddfSDavid du Colombier incref(&cl->r);
10977dd7cddfSDavid du Colombier break;
10987dd7cddfSDavid du Colombier }
10994de34a7eSDavid du Colombier dunlock();
11007dd7cddfSDavid du Colombier poperror();
11017dd7cddfSDavid du Colombier c->mode = openmode(omode);
11027dd7cddfSDavid du Colombier c->flag |= COPEN;
11037dd7cddfSDavid du Colombier c->offset = 0;
11049a747e4fSDavid du Colombier c->iounit = IOUNIT;
11057dd7cddfSDavid du Colombier return c;
11067dd7cddfSDavid du Colombier }
11077dd7cddfSDavid du Colombier
11087dd7cddfSDavid du Colombier static void
drawclose(Chan * c)11097dd7cddfSDavid du Colombier drawclose(Chan *c)
11107dd7cddfSDavid du Colombier {
11117dd7cddfSDavid du Colombier int i;
11127dd7cddfSDavid du Colombier DImage *d, **dp;
11137dd7cddfSDavid du Colombier Client *cl;
11147dd7cddfSDavid du Colombier Refresh *r;
11157dd7cddfSDavid du Colombier
11169a747e4fSDavid du Colombier if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */
11177dd7cddfSDavid du Colombier return;
11184de34a7eSDavid du Colombier dlock();
11197dd7cddfSDavid du Colombier if(waserror()){
11204de34a7eSDavid du Colombier dunlock();
11217dd7cddfSDavid du Colombier nexterror();
11227dd7cddfSDavid du Colombier }
11237dd7cddfSDavid du Colombier
11247dd7cddfSDavid du Colombier cl = drawclient(c);
11257dd7cddfSDavid du Colombier if(QID(c->qid) == Qctl)
11267dd7cddfSDavid du Colombier cl->busy = 0;
11277dd7cddfSDavid du Colombier if((c->flag&COPEN) && (decref(&cl->r)==0)){
11287dd7cddfSDavid du Colombier while(r = cl->refresh){ /* assign = */
11297dd7cddfSDavid du Colombier cl->refresh = r->next;
11307dd7cddfSDavid du Colombier free(r);
11317dd7cddfSDavid du Colombier }
11327dd7cddfSDavid du Colombier /* free names */
11337dd7cddfSDavid du Colombier for(i=0; i<sdraw.nname; )
11347dd7cddfSDavid du Colombier if(sdraw.name[i].client == cl)
11357dd7cddfSDavid du Colombier drawdelname(sdraw.name+i);
11367dd7cddfSDavid du Colombier else
11377dd7cddfSDavid du Colombier i++;
11387dd7cddfSDavid du Colombier while(cl->cscreen)
11397dd7cddfSDavid du Colombier drawuninstallscreen(cl, cl->cscreen);
11407dd7cddfSDavid du Colombier /* all screens are freed, so now we can free images */
11417dd7cddfSDavid du Colombier dp = cl->dimage;
11427dd7cddfSDavid du Colombier for(i=0; i<NHASH; i++){
11437dd7cddfSDavid du Colombier while((d = *dp) != nil){
11447dd7cddfSDavid du Colombier *dp = d->next;
11457dd7cddfSDavid du Colombier drawfreedimage(d);
11467dd7cddfSDavid du Colombier }
11477dd7cddfSDavid du Colombier dp++;
11487dd7cddfSDavid du Colombier }
11497dd7cddfSDavid du Colombier sdraw.client[cl->slot] = 0;
11507dd7cddfSDavid du Colombier drawflush(); /* to erase visible, now dead windows */
11517dd7cddfSDavid du Colombier free(cl);
11527dd7cddfSDavid du Colombier }
11534de34a7eSDavid du Colombier dunlock();
11547dd7cddfSDavid du Colombier poperror();
11557dd7cddfSDavid du Colombier }
11567dd7cddfSDavid du Colombier
11577dd7cddfSDavid du Colombier long
drawread(Chan * c,void * a,long n,vlong off)11587dd7cddfSDavid du Colombier drawread(Chan *c, void *a, long n, vlong off)
11597dd7cddfSDavid du Colombier {
11607dd7cddfSDavid du Colombier int index, m;
11617dd7cddfSDavid du Colombier ulong red, green, blue;
11627dd7cddfSDavid du Colombier Client *cl;
11637dd7cddfSDavid du Colombier uchar *p;
11647dd7cddfSDavid du Colombier Refresh *r;
11657dd7cddfSDavid du Colombier DImage *di;
11667dd7cddfSDavid du Colombier Memimage *i;
11677dd7cddfSDavid du Colombier ulong offset = off;
11687dd7cddfSDavid du Colombier char buf[16];
11697dd7cddfSDavid du Colombier
11709a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
11717dd7cddfSDavid du Colombier return devdirread(c, a, n, 0, 0, drawgen);
11724de34a7eSDavid du Colombier if(QID(c->qid) == Qwinname)
11734de34a7eSDavid du Colombier return readstr(off, a, n, screenname);
11744de34a7eSDavid du Colombier
11757dd7cddfSDavid du Colombier cl = drawclient(c);
11764de34a7eSDavid du Colombier dlock();
11777dd7cddfSDavid du Colombier if(waserror()){
11784de34a7eSDavid du Colombier dunlock();
11797dd7cddfSDavid du Colombier nexterror();
11807dd7cddfSDavid du Colombier }
11817dd7cddfSDavid du Colombier switch(QID(c->qid)){
11827dd7cddfSDavid du Colombier case Qctl:
11837dd7cddfSDavid du Colombier if(n < 12*12)
11847dd7cddfSDavid du Colombier error(Eshortread);
11857dd7cddfSDavid du Colombier if(cl->infoid < 0)
11867dd7cddfSDavid du Colombier error(Enodrawimage);
11877dd7cddfSDavid du Colombier if(cl->infoid == 0){
11887dd7cddfSDavid du Colombier i = screenimage;
11897dd7cddfSDavid du Colombier if(i == nil)
11907dd7cddfSDavid du Colombier error(Enodrawimage);
11917dd7cddfSDavid du Colombier }else{
11927dd7cddfSDavid du Colombier di = drawlookup(cl, cl->infoid, 1);
11937dd7cddfSDavid du Colombier if(di == nil)
11947dd7cddfSDavid du Colombier error(Enodrawimage);
11957dd7cddfSDavid du Colombier i = di->image;
11967dd7cddfSDavid du Colombier }
11974e3613abSDavid du Colombier n = snprint(a, n,
11984e3613abSDavid du Colombier "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ",
11994e3613abSDavid du Colombier cl->clientid, cl->infoid, chantostr(buf, i->chan),
12004e3613abSDavid du Colombier (i->flags&Frepl)==Frepl,
12017dd7cddfSDavid du Colombier i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
12024e3613abSDavid du Colombier i->clipr.min.x, i->clipr.min.y, i->clipr.max.x,
12034e3613abSDavid du Colombier i->clipr.max.y);
12047dd7cddfSDavid du Colombier cl->infoid = -1;
12057dd7cddfSDavid du Colombier break;
12067dd7cddfSDavid du Colombier
12077dd7cddfSDavid du Colombier case Qcolormap:
12087dd7cddfSDavid du Colombier drawactive(1); /* to restore map from backup */
12097dd7cddfSDavid du Colombier p = malloc(4*12*256+1);
12107dd7cddfSDavid du Colombier if(p == 0)
12117dd7cddfSDavid du Colombier error(Enomem);
12127dd7cddfSDavid du Colombier m = 0;
12137dd7cddfSDavid du Colombier for(index = 0; index < 256; index++){
12147dd7cddfSDavid du Colombier getcolor(index, &red, &green, &blue);
12154e3613abSDavid du Colombier m += snprint((char*)p+m, 4*12*256+1 - m,
12164e3613abSDavid du Colombier "%11d %11lud %11lud %11lud\n", index,
12174e3613abSDavid du Colombier red>>24, green>>24, blue>>24);
12187dd7cddfSDavid du Colombier }
12197dd7cddfSDavid du Colombier n = readstr(offset, a, n, (char*)p);
12207dd7cddfSDavid du Colombier free(p);
12217dd7cddfSDavid du Colombier break;
12227dd7cddfSDavid du Colombier
12237dd7cddfSDavid du Colombier case Qdata:
12247dd7cddfSDavid du Colombier if(cl->readdata == nil)
12257dd7cddfSDavid du Colombier error("no draw data");
12267dd7cddfSDavid du Colombier if(n < cl->nreaddata)
12277dd7cddfSDavid du Colombier error(Eshortread);
12287dd7cddfSDavid du Colombier n = cl->nreaddata;
12297dd7cddfSDavid du Colombier memmove(a, cl->readdata, cl->nreaddata);
12307dd7cddfSDavid du Colombier free(cl->readdata);
12317dd7cddfSDavid du Colombier cl->readdata = nil;
12327dd7cddfSDavid du Colombier break;
12337dd7cddfSDavid du Colombier
12347dd7cddfSDavid du Colombier case Qrefresh:
12357dd7cddfSDavid du Colombier if(n < 5*4)
12367dd7cddfSDavid du Colombier error(Ebadarg);
12377dd7cddfSDavid du Colombier for(;;){
12387dd7cddfSDavid du Colombier if(cl->refreshme || cl->refresh)
12397dd7cddfSDavid du Colombier break;
12404de34a7eSDavid du Colombier dunlock();
12417dd7cddfSDavid du Colombier if(waserror()){
12424de34a7eSDavid du Colombier dlock(); /* restore lock for waserror() above */
12437dd7cddfSDavid du Colombier nexterror();
12447dd7cddfSDavid du Colombier }
12457dd7cddfSDavid du Colombier sleep(&cl->refrend, drawrefactive, cl);
12467dd7cddfSDavid du Colombier poperror();
12474de34a7eSDavid du Colombier dlock();
12487dd7cddfSDavid du Colombier }
12497dd7cddfSDavid du Colombier p = a;
12507dd7cddfSDavid du Colombier while(cl->refresh && n>=5*4){
12517dd7cddfSDavid du Colombier r = cl->refresh;
12527dd7cddfSDavid du Colombier BPLONG(p+0*4, r->dimage->id);
12537dd7cddfSDavid du Colombier BPLONG(p+1*4, r->r.min.x);
12547dd7cddfSDavid du Colombier BPLONG(p+2*4, r->r.min.y);
12557dd7cddfSDavid du Colombier BPLONG(p+3*4, r->r.max.x);
12567dd7cddfSDavid du Colombier BPLONG(p+4*4, r->r.max.y);
12577dd7cddfSDavid du Colombier cl->refresh = r->next;
12587dd7cddfSDavid du Colombier free(r);
12597dd7cddfSDavid du Colombier p += 5*4;
12607dd7cddfSDavid du Colombier n -= 5*4;
12617dd7cddfSDavid du Colombier }
12627dd7cddfSDavid du Colombier cl->refreshme = 0;
12637dd7cddfSDavid du Colombier n = p-(uchar*)a;
12644de34a7eSDavid du Colombier break;
12657dd7cddfSDavid du Colombier }
12664de34a7eSDavid du Colombier dunlock();
12677dd7cddfSDavid du Colombier poperror();
12687dd7cddfSDavid du Colombier return n;
12697dd7cddfSDavid du Colombier }
12707dd7cddfSDavid du Colombier
12717dd7cddfSDavid du Colombier void
drawwakeall(void)12727dd7cddfSDavid du Colombier drawwakeall(void)
12737dd7cddfSDavid du Colombier {
12747dd7cddfSDavid du Colombier Client *cl;
12757dd7cddfSDavid du Colombier int i;
12767dd7cddfSDavid du Colombier
12777dd7cddfSDavid du Colombier for(i=0; i<sdraw.nclient; i++){
12787dd7cddfSDavid du Colombier cl = sdraw.client[i];
12797dd7cddfSDavid du Colombier if(cl && (cl->refreshme || cl->refresh))
12807dd7cddfSDavid du Colombier wakeup(&cl->refrend);
12817dd7cddfSDavid du Colombier }
12827dd7cddfSDavid du Colombier }
12837dd7cddfSDavid du Colombier
12847dd7cddfSDavid du Colombier static long
drawwrite(Chan * c,void * a,long n,vlong)12859a747e4fSDavid du Colombier drawwrite(Chan *c, void *a, long n, vlong)
12867dd7cddfSDavid du Colombier {
12877dd7cddfSDavid du Colombier char buf[128], *fields[4], *q;
12887dd7cddfSDavid du Colombier Client *cl;
12897dd7cddfSDavid du Colombier int i, m, red, green, blue, x;
12907dd7cddfSDavid du Colombier
12919a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
12927dd7cddfSDavid du Colombier error(Eisdir);
12937dd7cddfSDavid du Colombier cl = drawclient(c);
12944de34a7eSDavid du Colombier dlock();
12957dd7cddfSDavid du Colombier if(waserror()){
12967dd7cddfSDavid du Colombier drawwakeall();
12974de34a7eSDavid du Colombier dunlock();
12987dd7cddfSDavid du Colombier nexterror();
12997dd7cddfSDavid du Colombier }
13007dd7cddfSDavid du Colombier switch(QID(c->qid)){
13017dd7cddfSDavid du Colombier case Qctl:
13027dd7cddfSDavid du Colombier if(n != 4)
13037dd7cddfSDavid du Colombier error("unknown draw control request");
13047dd7cddfSDavid du Colombier cl->infoid = BGLONG((uchar*)a);
13057dd7cddfSDavid du Colombier break;
13067dd7cddfSDavid du Colombier
13077dd7cddfSDavid du Colombier case Qcolormap:
13087dd7cddfSDavid du Colombier drawactive(1); /* to restore map from backup */
13097dd7cddfSDavid du Colombier m = n;
13107dd7cddfSDavid du Colombier n = 0;
13117dd7cddfSDavid du Colombier while(m > 0){
13127dd7cddfSDavid du Colombier x = m;
13137dd7cddfSDavid du Colombier if(x > sizeof(buf)-1)
13147dd7cddfSDavid du Colombier x = sizeof(buf)-1;
13157dd7cddfSDavid du Colombier q = memccpy(buf, a, '\n', x);
13167dd7cddfSDavid du Colombier if(q == 0)
13177dd7cddfSDavid du Colombier break;
13187dd7cddfSDavid du Colombier i = q-buf;
13197dd7cddfSDavid du Colombier n += i;
13207dd7cddfSDavid du Colombier a = (char*)a + i;
13217dd7cddfSDavid du Colombier m -= i;
13227dd7cddfSDavid du Colombier *q = 0;
13239a747e4fSDavid du Colombier if(tokenize(buf, fields, nelem(fields)) != 4)
13247dd7cddfSDavid du Colombier error(Ebadarg);
13257dd7cddfSDavid du Colombier i = strtoul(fields[0], 0, 0);
13267dd7cddfSDavid du Colombier red = strtoul(fields[1], 0, 0);
13277dd7cddfSDavid du Colombier green = strtoul(fields[2], 0, 0);
13287dd7cddfSDavid du Colombier blue = strtoul(fields[3], &q, 0);
13297dd7cddfSDavid du Colombier if(fields[3] == q)
13307dd7cddfSDavid du Colombier error(Ebadarg);
13317dd7cddfSDavid du Colombier if(red>255 || green>255 || blue>255 || i<0 || i>255)
13327dd7cddfSDavid du Colombier error(Ebadarg);
13337dd7cddfSDavid du Colombier red |= red<<8;
13347dd7cddfSDavid du Colombier red |= red<<16;
13357dd7cddfSDavid du Colombier green |= green<<8;
13367dd7cddfSDavid du Colombier green |= green<<16;
13377dd7cddfSDavid du Colombier blue |= blue<<8;
13387dd7cddfSDavid du Colombier blue |= blue<<16;
13397dd7cddfSDavid du Colombier setcolor(i, red, green, blue);
13407dd7cddfSDavid du Colombier }
13417dd7cddfSDavid du Colombier break;
13427dd7cddfSDavid du Colombier
13437dd7cddfSDavid du Colombier case Qdata:
13447dd7cddfSDavid du Colombier drawmesg(cl, a, n);
13457dd7cddfSDavid du Colombier drawwakeall();
13467dd7cddfSDavid du Colombier break;
13477dd7cddfSDavid du Colombier
13487dd7cddfSDavid du Colombier default:
13497dd7cddfSDavid du Colombier error(Ebadusefd);
13507dd7cddfSDavid du Colombier }
13514de34a7eSDavid du Colombier dunlock();
13527dd7cddfSDavid du Colombier poperror();
13537dd7cddfSDavid du Colombier return n;
13547dd7cddfSDavid du Colombier }
13557dd7cddfSDavid du Colombier
13567dd7cddfSDavid du Colombier uchar*
drawcoord(uchar * p,uchar * maxp,int oldx,int * newx)13577dd7cddfSDavid du Colombier drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
13587dd7cddfSDavid du Colombier {
13597dd7cddfSDavid du Colombier int b, x;
13607dd7cddfSDavid du Colombier
13617dd7cddfSDavid du Colombier if(p >= maxp)
13627dd7cddfSDavid du Colombier error(Eshortdraw);
13637dd7cddfSDavid du Colombier b = *p++;
13647dd7cddfSDavid du Colombier x = b & 0x7F;
13657dd7cddfSDavid du Colombier if(b & 0x80){
13667dd7cddfSDavid du Colombier if(p+1 >= maxp)
13677dd7cddfSDavid du Colombier error(Eshortdraw);
13687dd7cddfSDavid du Colombier x |= *p++ << 7;
13697dd7cddfSDavid du Colombier x |= *p++ << 15;
13707dd7cddfSDavid du Colombier if(x & (1<<22))
13717dd7cddfSDavid du Colombier x |= ~0<<23;
13727dd7cddfSDavid du Colombier }else{
13737dd7cddfSDavid du Colombier if(b & 0x40)
13747dd7cddfSDavid du Colombier x |= ~0<<7;
13757dd7cddfSDavid du Colombier x += oldx;
13767dd7cddfSDavid du Colombier }
13777dd7cddfSDavid du Colombier *newx = x;
13787dd7cddfSDavid du Colombier return p;
13797dd7cddfSDavid du Colombier }
13807dd7cddfSDavid du Colombier
13817dd7cddfSDavid du Colombier static void
printmesg(char * fmt,uchar * a,int plsprnt)13827dd7cddfSDavid du Colombier printmesg(char *fmt, uchar *a, int plsprnt)
13837dd7cddfSDavid du Colombier {
13847dd7cddfSDavid du Colombier char buf[256];
13857dd7cddfSDavid du Colombier char *p, *q;
13864e3613abSDavid du Colombier int s, left;
13877dd7cddfSDavid du Colombier
13887dd7cddfSDavid du Colombier if(1|| plsprnt==0){
13897dd7cddfSDavid du Colombier SET(s,q,p);
13907dd7cddfSDavid du Colombier USED(fmt, a, buf, p, q, s);
13917dd7cddfSDavid du Colombier return;
13927dd7cddfSDavid du Colombier }
13937dd7cddfSDavid du Colombier q = buf;
13947dd7cddfSDavid du Colombier *q++ = *a++;
13957dd7cddfSDavid du Colombier for(p=fmt; *p; p++){
13964e3613abSDavid du Colombier left = sizeof buf - 2 - (q - buf); /* 2 for \n\0 */
13977dd7cddfSDavid du Colombier switch(*p){
13987dd7cddfSDavid du Colombier case 'l':
13994e3613abSDavid du Colombier q += snprint(q, left, " %ld", (long)BGLONG(a));
14007dd7cddfSDavid du Colombier a += 4;
14017dd7cddfSDavid du Colombier break;
14027dd7cddfSDavid du Colombier case 'L':
14034e3613abSDavid du Colombier q += snprint(q, left, " %.8lux", (ulong)BGLONG(a));
14047dd7cddfSDavid du Colombier a += 4;
14057dd7cddfSDavid du Colombier break;
14067dd7cddfSDavid du Colombier case 'R':
14074e3613abSDavid du Colombier q += snprint(q, left, " [%d %d %d %d]", BGLONG(a),
14084e3613abSDavid du Colombier BGLONG(a+4), BGLONG(a+8), BGLONG(a+12));
14097dd7cddfSDavid du Colombier a += 16;
14107dd7cddfSDavid du Colombier break;
14117dd7cddfSDavid du Colombier case 'P':
14124e3613abSDavid du Colombier q += snprint(q, left, " [%d %d]", BGLONG(a), BGLONG(a+4));
14137dd7cddfSDavid du Colombier a += 8;
14147dd7cddfSDavid du Colombier break;
14157dd7cddfSDavid du Colombier case 'b':
14164e3613abSDavid du Colombier q += snprint(q, left, " %d", *a++);
14177dd7cddfSDavid du Colombier break;
14187dd7cddfSDavid du Colombier case 's':
14194e3613abSDavid du Colombier q += snprint(q, left, " %d", BGSHORT(a));
14207dd7cddfSDavid du Colombier a += 2;
14217dd7cddfSDavid du Colombier break;
14227dd7cddfSDavid du Colombier case 'S':
14234e3613abSDavid du Colombier q += snprint(q, left, " %.4ux", BGSHORT(a));
14247dd7cddfSDavid du Colombier a += 2;
14257dd7cddfSDavid du Colombier break;
14267dd7cddfSDavid du Colombier }
14277dd7cddfSDavid du Colombier }
14287dd7cddfSDavid du Colombier *q++ = '\n';
14297dd7cddfSDavid du Colombier *q = 0;
14307dd7cddfSDavid du Colombier iprint("%.*s", (int)(q-buf), buf);
14317dd7cddfSDavid du Colombier }
14327dd7cddfSDavid du Colombier
14337dd7cddfSDavid du Colombier void
drawmesg(Client * client,void * av,int n)14347dd7cddfSDavid du Colombier drawmesg(Client *client, void *av, int n)
14357dd7cddfSDavid du Colombier {
14366a9fc400SDavid du Colombier int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
14377dd7cddfSDavid du Colombier uchar *u, *a, refresh;
14387dd7cddfSDavid du Colombier char *fmt;
14397dd7cddfSDavid du Colombier ulong value, chan;
14407dd7cddfSDavid du Colombier Rectangle r, clipr;
14417dd7cddfSDavid du Colombier Point p, q, *pp, sp;
14421ee3cffaSDavid du Colombier Memimage *i, *bg, *dst, *src, *mask;
14437dd7cddfSDavid du Colombier Memimage *l, **lp;
14447dd7cddfSDavid du Colombier Memscreen *scrn;
14457dd7cddfSDavid du Colombier DImage *font, *ll, *di, *ddst, *dsrc;
14467dd7cddfSDavid du Colombier DName *dn;
14477dd7cddfSDavid du Colombier DScreen *dscrn;
14487dd7cddfSDavid du Colombier FChar *fc;
14497dd7cddfSDavid du Colombier Refx *refx;
14507dd7cddfSDavid du Colombier CScreen *cs;
14517dd7cddfSDavid du Colombier Refreshfn reffn;
14527dd7cddfSDavid du Colombier
14537dd7cddfSDavid du Colombier a = av;
14547dd7cddfSDavid du Colombier m = 0;
14557dd7cddfSDavid du Colombier fmt = nil;
14567dd7cddfSDavid du Colombier if(waserror()){
14577dd7cddfSDavid du Colombier if(fmt) printmesg(fmt, a, 1);
14589a747e4fSDavid du Colombier /* iprint("error: %s\n", up->errstr); */
14597dd7cddfSDavid du Colombier nexterror();
14607dd7cddfSDavid du Colombier }
14617dd7cddfSDavid du Colombier while((n-=m) > 0){
14627dd7cddfSDavid du Colombier USED(fmt);
14637dd7cddfSDavid du Colombier a += m;
14647dd7cddfSDavid du Colombier switch(*a){
14657dd7cddfSDavid du Colombier default:
14667dd7cddfSDavid du Colombier error("bad draw command");
14677dd7cddfSDavid du Colombier /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */
14687dd7cddfSDavid du Colombier case 'b':
14697dd7cddfSDavid du Colombier printmesg(fmt="LLbLbRRL", a, 0);
14707dd7cddfSDavid du Colombier m = 1+4+4+1+4+1+4*4+4*4+4;
14717dd7cddfSDavid du Colombier if(n < m)
14727dd7cddfSDavid du Colombier error(Eshortdraw);
14737dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
14747dd7cddfSDavid du Colombier scrnid = BGSHORT(a+5);
14757dd7cddfSDavid du Colombier refresh = a[9];
14767dd7cddfSDavid du Colombier chan = BGLONG(a+10);
14777dd7cddfSDavid du Colombier repl = a[14];
14787dd7cddfSDavid du Colombier drawrectangle(&r, a+15);
14797dd7cddfSDavid du Colombier drawrectangle(&clipr, a+31);
14807dd7cddfSDavid du Colombier value = BGLONG(a+47);
14817dd7cddfSDavid du Colombier if(drawlookup(client, dstid, 0))
14827dd7cddfSDavid du Colombier error(Eimageexists);
14837dd7cddfSDavid du Colombier if(scrnid){
14847dd7cddfSDavid du Colombier dscrn = drawlookupscreen(client, scrnid, &cs);
14857dd7cddfSDavid du Colombier scrn = dscrn->screen;
14867dd7cddfSDavid du Colombier if(repl || chan!=scrn->image->chan)
14877dd7cddfSDavid du Colombier error("image parameters incompatible with screen");
14887dd7cddfSDavid du Colombier reffn = nil;
14897dd7cddfSDavid du Colombier switch(refresh){
14907dd7cddfSDavid du Colombier case Refbackup:
14917dd7cddfSDavid du Colombier break;
14927dd7cddfSDavid du Colombier case Refnone:
14937dd7cddfSDavid du Colombier reffn = memlnorefresh;
14947dd7cddfSDavid du Colombier break;
14957dd7cddfSDavid du Colombier case Refmesg:
14967dd7cddfSDavid du Colombier reffn = drawrefresh;
14977dd7cddfSDavid du Colombier break;
14987dd7cddfSDavid du Colombier default:
14997dd7cddfSDavid du Colombier error("unknown refresh method");
15007dd7cddfSDavid du Colombier }
15017dd7cddfSDavid du Colombier l = memlalloc(scrn, r, reffn, 0, value);
15027dd7cddfSDavid du Colombier if(l == 0)
15037dd7cddfSDavid du Colombier error(Edrawmem);
15047dd7cddfSDavid du Colombier addflush(l->layer->screenr);
15057dd7cddfSDavid du Colombier l->clipr = clipr;
15067dd7cddfSDavid du Colombier rectclip(&l->clipr, r);
15077dd7cddfSDavid du Colombier if(drawinstall(client, dstid, l, dscrn) == 0){
15087dd7cddfSDavid du Colombier memldelete(l);
15097dd7cddfSDavid du Colombier error(Edrawmem);
15107dd7cddfSDavid du Colombier }
15117dd7cddfSDavid du Colombier dscrn->ref++;
15127dd7cddfSDavid du Colombier if(reffn){
15137dd7cddfSDavid du Colombier refx = nil;
15147dd7cddfSDavid du Colombier if(reffn == drawrefresh){
15157dd7cddfSDavid du Colombier refx = malloc(sizeof(Refx));
15167dd7cddfSDavid du Colombier if(refx == 0){
15177dd7cddfSDavid du Colombier drawuninstall(client, dstid);
15187dd7cddfSDavid du Colombier error(Edrawmem);
15197dd7cddfSDavid du Colombier }
15207dd7cddfSDavid du Colombier refx->client = client;
15217dd7cddfSDavid du Colombier refx->dimage = drawlookup(client, dstid, 1);
15227dd7cddfSDavid du Colombier }
15237dd7cddfSDavid du Colombier memlsetrefresh(l, reffn, refx);
15247dd7cddfSDavid du Colombier }
15257dd7cddfSDavid du Colombier continue;
15267dd7cddfSDavid du Colombier }
15277dd7cddfSDavid du Colombier i = allocmemimage(r, chan);
152880ee5cbfSDavid du Colombier if(i == 0)
15297dd7cddfSDavid du Colombier error(Edrawmem);
15307dd7cddfSDavid du Colombier if(repl)
15317dd7cddfSDavid du Colombier i->flags |= Frepl;
15327dd7cddfSDavid du Colombier i->clipr = clipr;
15337dd7cddfSDavid du Colombier if(!repl)
15347dd7cddfSDavid du Colombier rectclip(&i->clipr, r);
15357dd7cddfSDavid du Colombier if(drawinstall(client, dstid, i, 0) == 0){
15367dd7cddfSDavid du Colombier freememimage(i);
15377dd7cddfSDavid du Colombier error(Edrawmem);
15387dd7cddfSDavid du Colombier }
15397dd7cddfSDavid du Colombier memfillcolor(i, value);
15407dd7cddfSDavid du Colombier continue;
15417dd7cddfSDavid du Colombier
15427dd7cddfSDavid du Colombier /* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */
15437dd7cddfSDavid du Colombier case 'A':
15447dd7cddfSDavid du Colombier printmesg(fmt="LLLb", a, 1);
15457dd7cddfSDavid du Colombier m = 1+4+4+4+1;
15467dd7cddfSDavid du Colombier if(n < m)
15477dd7cddfSDavid du Colombier error(Eshortdraw);
15487dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
15497dd7cddfSDavid du Colombier if(dstid == 0)
15507dd7cddfSDavid du Colombier error(Ebadarg);
15517dd7cddfSDavid du Colombier if(drawlookupdscreen(dstid))
15527dd7cddfSDavid du Colombier error(Escreenexists);
15537dd7cddfSDavid du Colombier ddst = drawlookup(client, BGLONG(a+5), 1);
15547dd7cddfSDavid du Colombier dsrc = drawlookup(client, BGLONG(a+9), 1);
15557dd7cddfSDavid du Colombier if(ddst==0 || dsrc==0)
15567dd7cddfSDavid du Colombier error(Enodrawimage);
15577dd7cddfSDavid du Colombier if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0)
15587dd7cddfSDavid du Colombier error(Edrawmem);
15597dd7cddfSDavid du Colombier continue;
15607dd7cddfSDavid du Colombier
15617dd7cddfSDavid du Colombier /* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */
15627dd7cddfSDavid du Colombier case 'c':
15637dd7cddfSDavid du Colombier printmesg(fmt="LbR", a, 0);
15647dd7cddfSDavid du Colombier m = 1+4+1+4*4;
15657dd7cddfSDavid du Colombier if(n < m)
15667dd7cddfSDavid du Colombier error(Eshortdraw);
15677dd7cddfSDavid du Colombier ddst = drawlookup(client, BGLONG(a+1), 1);
15687dd7cddfSDavid du Colombier if(ddst == nil)
15697dd7cddfSDavid du Colombier error(Enodrawimage);
15707dd7cddfSDavid du Colombier if(ddst->name)
15718cd4f5a6SDavid du Colombier error("cannot change repl/clipr of shared image");
15727dd7cddfSDavid du Colombier dst = ddst->image;
15737dd7cddfSDavid du Colombier if(a[5])
15747dd7cddfSDavid du Colombier dst->flags |= Frepl;
15757dd7cddfSDavid du Colombier drawrectangle(&dst->clipr, a+6);
15767dd7cddfSDavid du Colombier continue;
15777dd7cddfSDavid du Colombier
15787dd7cddfSDavid du Colombier /* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */
15797dd7cddfSDavid du Colombier case 'd':
15807dd7cddfSDavid du Colombier printmesg(fmt="LLLRPP", a, 0);
15817dd7cddfSDavid du Colombier m = 1+4+4+4+4*4+2*4+2*4;
15827dd7cddfSDavid du Colombier if(n < m)
15837dd7cddfSDavid du Colombier error(Eshortdraw);
15847dd7cddfSDavid du Colombier dst = drawimage(client, a+1);
15857dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
15867dd7cddfSDavid du Colombier src = drawimage(client, a+5);
15877dd7cddfSDavid du Colombier mask = drawimage(client, a+9);
15887dd7cddfSDavid du Colombier drawrectangle(&r, a+13);
15897dd7cddfSDavid du Colombier drawpoint(&p, a+29);
15907dd7cddfSDavid du Colombier drawpoint(&q, a+37);
15916a9fc400SDavid du Colombier op = drawclientop(client);
15926a9fc400SDavid du Colombier memdraw(dst, r, src, p, mask, q, op);
15937dd7cddfSDavid du Colombier dstflush(dstid, dst, r);
15947dd7cddfSDavid du Colombier continue;
15957dd7cddfSDavid du Colombier
15967dd7cddfSDavid du Colombier /* toggle debugging: 'D' val[1] */
15977dd7cddfSDavid du Colombier case 'D':
15987dd7cddfSDavid du Colombier printmesg(fmt="b", a, 0);
15997dd7cddfSDavid du Colombier m = 1+1;
16007dd7cddfSDavid du Colombier if(n < m)
16017dd7cddfSDavid du Colombier error(Eshortdraw);
16027dd7cddfSDavid du Colombier drawdebug = a[1];
16037dd7cddfSDavid du Colombier continue;
16047dd7cddfSDavid du Colombier
16057dd7cddfSDavid du Colombier /* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/
16067dd7cddfSDavid du Colombier case 'e':
16077dd7cddfSDavid du Colombier case 'E':
16087dd7cddfSDavid du Colombier printmesg(fmt="LLPlllPll", a, 0);
16097dd7cddfSDavid du Colombier m = 1+4+4+2*4+4+4+4+2*4+2*4;
16107dd7cddfSDavid du Colombier if(n < m)
16117dd7cddfSDavid du Colombier error(Eshortdraw);
16127dd7cddfSDavid du Colombier dst = drawimage(client, a+1);
16137dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
16147dd7cddfSDavid du Colombier src = drawimage(client, a+5);
16157dd7cddfSDavid du Colombier drawpoint(&p, a+9);
16167dd7cddfSDavid du Colombier e0 = BGLONG(a+17);
16177dd7cddfSDavid du Colombier e1 = BGLONG(a+21);
16187dd7cddfSDavid du Colombier if(e0<0 || e1<0)
16197dd7cddfSDavid du Colombier error("invalid ellipse semidiameter");
16207dd7cddfSDavid du Colombier j = BGLONG(a+25);
16217dd7cddfSDavid du Colombier if(j < 0)
16227dd7cddfSDavid du Colombier error("negative ellipse thickness");
16237dd7cddfSDavid du Colombier drawpoint(&sp, a+29);
16247dd7cddfSDavid du Colombier c = j;
16257dd7cddfSDavid du Colombier if(*a == 'E')
16267dd7cddfSDavid du Colombier c = -1;
16277dd7cddfSDavid du Colombier ox = BGLONG(a+37);
16287dd7cddfSDavid du Colombier oy = BGLONG(a+41);
16296a9fc400SDavid du Colombier op = drawclientop(client);
16307dd7cddfSDavid du Colombier /* high bit indicates arc angles are present */
16317dd7cddfSDavid du Colombier if(ox & (1<<31)){
16327dd7cddfSDavid du Colombier if((ox & (1<<30)) == 0)
16337dd7cddfSDavid du Colombier ox &= ~(1<<31);
16346a9fc400SDavid du Colombier memarc(dst, p, e0, e1, c, src, sp, ox, oy, op);
16357dd7cddfSDavid du Colombier }else
16366a9fc400SDavid du Colombier memellipse(dst, p, e0, e1, c, src, sp, op);
16377dd7cddfSDavid du Colombier dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
16387dd7cddfSDavid du Colombier continue;
16397dd7cddfSDavid du Colombier
16407dd7cddfSDavid du Colombier /* free: 'f' id[4] */
16417dd7cddfSDavid du Colombier case 'f':
16427dd7cddfSDavid du Colombier printmesg(fmt="L", a, 1);
16437dd7cddfSDavid du Colombier m = 1+4;
16447dd7cddfSDavid du Colombier if(n < m)
16457dd7cddfSDavid du Colombier error(Eshortdraw);
16467dd7cddfSDavid du Colombier ll = drawlookup(client, BGLONG(a+1), 0);
16477dd7cddfSDavid du Colombier if(ll && ll->dscreen && ll->dscreen->owner != client)
16487dd7cddfSDavid du Colombier ll->dscreen->owner->refreshme = 1;
16497dd7cddfSDavid du Colombier drawuninstall(client, BGLONG(a+1));
16507dd7cddfSDavid du Colombier continue;
16517dd7cddfSDavid du Colombier
16527dd7cddfSDavid du Colombier /* free screen: 'F' id[4] */
16537dd7cddfSDavid du Colombier case 'F':
16547dd7cddfSDavid du Colombier printmesg(fmt="L", a, 1);
16557dd7cddfSDavid du Colombier m = 1+4;
16567dd7cddfSDavid du Colombier if(n < m)
16577dd7cddfSDavid du Colombier error(Eshortdraw);
16587dd7cddfSDavid du Colombier drawlookupscreen(client, BGLONG(a+1), &cs);
16597dd7cddfSDavid du Colombier drawuninstallscreen(client, cs);
16607dd7cddfSDavid du Colombier continue;
16617dd7cddfSDavid du Colombier
16627dd7cddfSDavid du Colombier /* initialize font: 'i' fontid[4] nchars[4] ascent[1] */
16637dd7cddfSDavid du Colombier case 'i':
16647dd7cddfSDavid du Colombier printmesg(fmt="Llb", a, 1);
16657dd7cddfSDavid du Colombier m = 1+4+4+1;
16667dd7cddfSDavid du Colombier if(n < m)
16677dd7cddfSDavid du Colombier error(Eshortdraw);
16687dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
16697dd7cddfSDavid du Colombier if(dstid == 0)
16708cd4f5a6SDavid du Colombier error("cannot use display as font");
16717dd7cddfSDavid du Colombier font = drawlookup(client, dstid, 1);
16727dd7cddfSDavid du Colombier if(font == 0)
16737dd7cddfSDavid du Colombier error(Enodrawimage);
16747dd7cddfSDavid du Colombier if(font->image->layer)
16758cd4f5a6SDavid du Colombier error("cannot use window as font");
16767dd7cddfSDavid du Colombier ni = BGLONG(a+5);
16779a747e4fSDavid du Colombier if(ni<=0 || ni>4096)
16789a747e4fSDavid du Colombier error("bad font size (4096 chars max)");
16799a747e4fSDavid du Colombier free(font->fchar); /* should we complain if non-zero? */
16807dd7cddfSDavid du Colombier font->fchar = malloc(ni*sizeof(FChar));
16817dd7cddfSDavid du Colombier if(font->fchar == 0)
16827dd7cddfSDavid du Colombier error("no memory for font");
16837dd7cddfSDavid du Colombier memset(font->fchar, 0, ni*sizeof(FChar));
16847dd7cddfSDavid du Colombier font->nfchar = ni;
16857dd7cddfSDavid du Colombier font->ascent = a[9];
16867dd7cddfSDavid du Colombier continue;
16877dd7cddfSDavid du Colombier
16887dd7cddfSDavid du Colombier /* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
16897dd7cddfSDavid du Colombier case 'l':
16907dd7cddfSDavid du Colombier printmesg(fmt="LLSRPbb", a, 0);
16917dd7cddfSDavid du Colombier m = 1+4+4+2+4*4+2*4+1+1;
16927dd7cddfSDavid du Colombier if(n < m)
16937dd7cddfSDavid du Colombier error(Eshortdraw);
16947dd7cddfSDavid du Colombier font = drawlookup(client, BGLONG(a+1), 1);
16957dd7cddfSDavid du Colombier if(font == 0)
16967dd7cddfSDavid du Colombier error(Enodrawimage);
16977dd7cddfSDavid du Colombier if(font->nfchar == 0)
16987dd7cddfSDavid du Colombier error(Enotfont);
16997dd7cddfSDavid du Colombier src = drawimage(client, a+5);
17007dd7cddfSDavid du Colombier ci = BGSHORT(a+9);
17017dd7cddfSDavid du Colombier if(ci >= font->nfchar)
17027dd7cddfSDavid du Colombier error(Eindex);
17037dd7cddfSDavid du Colombier drawrectangle(&r, a+11);
17047dd7cddfSDavid du Colombier drawpoint(&p, a+27);
17056a9fc400SDavid du Colombier memdraw(font->image, r, src, p, memopaque, p, S);
17067dd7cddfSDavid du Colombier fc = &font->fchar[ci];
17077dd7cddfSDavid du Colombier fc->minx = r.min.x;
17087dd7cddfSDavid du Colombier fc->maxx = r.max.x;
17097dd7cddfSDavid du Colombier fc->miny = r.min.y;
17107dd7cddfSDavid du Colombier fc->maxy = r.max.y;
17117dd7cddfSDavid du Colombier fc->left = a[35];
17127dd7cddfSDavid du Colombier fc->width = a[36];
17137dd7cddfSDavid du Colombier continue;
17147dd7cddfSDavid du Colombier
17157dd7cddfSDavid du Colombier /* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */
17167dd7cddfSDavid du Colombier case 'L':
17177dd7cddfSDavid du Colombier printmesg(fmt="LPPlllLP", a, 0);
17187dd7cddfSDavid du Colombier m = 1+4+2*4+2*4+4+4+4+4+2*4;
17197dd7cddfSDavid du Colombier if(n < m)
17207dd7cddfSDavid du Colombier error(Eshortdraw);
17217dd7cddfSDavid du Colombier dst = drawimage(client, a+1);
17227dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
17237dd7cddfSDavid du Colombier drawpoint(&p, a+5);
17247dd7cddfSDavid du Colombier drawpoint(&q, a+13);
17257dd7cddfSDavid du Colombier e0 = BGLONG(a+21);
17267dd7cddfSDavid du Colombier e1 = BGLONG(a+25);
17277dd7cddfSDavid du Colombier j = BGLONG(a+29);
17287dd7cddfSDavid du Colombier if(j < 0)
17297dd7cddfSDavid du Colombier error("negative line width");
17307dd7cddfSDavid du Colombier src = drawimage(client, a+33);
17317dd7cddfSDavid du Colombier drawpoint(&sp, a+37);
17326a9fc400SDavid du Colombier op = drawclientop(client);
17336a9fc400SDavid du Colombier memline(dst, p, q, e0, e1, j, src, sp, op);
17347dd7cddfSDavid du Colombier /* avoid memlinebbox if possible */
17357dd7cddfSDavid du Colombier if(dstid==0 || dst->layer!=nil){
17367dd7cddfSDavid du Colombier /* BUG: this is terribly inefficient: update maximal containing rect*/
17377dd7cddfSDavid du Colombier r = memlinebbox(p, q, e0, e1, j);
17387dd7cddfSDavid du Colombier dstflush(dstid, dst, insetrect(r, -(1+1+j)));
17397dd7cddfSDavid du Colombier }
17407dd7cddfSDavid du Colombier continue;
17417dd7cddfSDavid du Colombier
17427dd7cddfSDavid du Colombier /* create image mask: 'm' newid[4] id[4] */
17437dd7cddfSDavid du Colombier /*
17447dd7cddfSDavid du Colombier *
17457dd7cddfSDavid du Colombier case 'm':
17467dd7cddfSDavid du Colombier printmesg("LL", a, 0);
17477dd7cddfSDavid du Colombier m = 4+4;
17487dd7cddfSDavid du Colombier if(n < m)
17497dd7cddfSDavid du Colombier error(Eshortdraw);
17507dd7cddfSDavid du Colombier break;
17517dd7cddfSDavid du Colombier *
17527dd7cddfSDavid du Colombier */
17537dd7cddfSDavid du Colombier
17547dd7cddfSDavid du Colombier /* attach to a named image: 'n' dstid[4] j[1] name[j] */
17557dd7cddfSDavid du Colombier case 'n':
17567dd7cddfSDavid du Colombier printmesg(fmt="Lz", a, 0);
17577dd7cddfSDavid du Colombier m = 1+4+1;
17587dd7cddfSDavid du Colombier if(n < m)
17597dd7cddfSDavid du Colombier error(Eshortdraw);
17607dd7cddfSDavid du Colombier j = a[5];
17617dd7cddfSDavid du Colombier if(j == 0) /* give me a non-empty name please */
17627dd7cddfSDavid du Colombier error(Eshortdraw);
17637dd7cddfSDavid du Colombier m += j;
17647dd7cddfSDavid du Colombier if(n < m)
17657dd7cddfSDavid du Colombier error(Eshortdraw);
17667dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
17677dd7cddfSDavid du Colombier if(drawlookup(client, dstid, 0))
17687dd7cddfSDavid du Colombier error(Eimageexists);
17697dd7cddfSDavid du Colombier dn = drawlookupname(j, (char*)a+6);
17707dd7cddfSDavid du Colombier if(dn == nil)
17717dd7cddfSDavid du Colombier error(Enoname);
17727dd7cddfSDavid du Colombier if(drawinstall(client, dstid, dn->dimage->image, 0) == 0)
17737dd7cddfSDavid du Colombier error(Edrawmem);
17747dd7cddfSDavid du Colombier di = drawlookup(client, dstid, 0);
17757dd7cddfSDavid du Colombier if(di == 0)
17768cd4f5a6SDavid du Colombier error("draw: cannot happen");
17777dd7cddfSDavid du Colombier di->vers = dn->vers;
17787dd7cddfSDavid du Colombier di->name = smalloc(j+1);
17797dd7cddfSDavid du Colombier di->fromname = dn->dimage;
17807dd7cddfSDavid du Colombier di->fromname->ref++;
17817dd7cddfSDavid du Colombier memmove(di->name, a+6, j);
17827dd7cddfSDavid du Colombier di->name[j] = 0;
17837dd7cddfSDavid du Colombier client->infoid = dstid;
17847dd7cddfSDavid du Colombier continue;
17857dd7cddfSDavid du Colombier
17867dd7cddfSDavid du Colombier /* name an image: 'N' dstid[4] in[1] j[1] name[j] */
17877dd7cddfSDavid du Colombier case 'N':
17887dd7cddfSDavid du Colombier printmesg(fmt="Lbz", a, 0);
17897dd7cddfSDavid du Colombier m = 1+4+1+1;
17907dd7cddfSDavid du Colombier if(n < m)
17917dd7cddfSDavid du Colombier error(Eshortdraw);
17927dd7cddfSDavid du Colombier c = a[5];
17937dd7cddfSDavid du Colombier j = a[6];
17947dd7cddfSDavid du Colombier if(j == 0) /* give me a non-empty name please */
17957dd7cddfSDavid du Colombier error(Eshortdraw);
17967dd7cddfSDavid du Colombier m += j;
17977dd7cddfSDavid du Colombier if(n < m)
17987dd7cddfSDavid du Colombier error(Eshortdraw);
17997dd7cddfSDavid du Colombier di = drawlookup(client, BGLONG(a+1), 0);
18007dd7cddfSDavid du Colombier if(di == 0)
18017dd7cddfSDavid du Colombier error(Enodrawimage);
18027dd7cddfSDavid du Colombier if(di->name)
18037dd7cddfSDavid du Colombier error(Enamed);
18047dd7cddfSDavid du Colombier if(c)
18057dd7cddfSDavid du Colombier drawaddname(client, di, j, (char*)a+7);
18067dd7cddfSDavid du Colombier else{
18077dd7cddfSDavid du Colombier dn = drawlookupname(j, (char*)a+7);
18087dd7cddfSDavid du Colombier if(dn == nil)
18097dd7cddfSDavid du Colombier error(Enoname);
18107dd7cddfSDavid du Colombier if(dn->dimage != di)
18117dd7cddfSDavid du Colombier error(Ewrongname);
18127dd7cddfSDavid du Colombier drawdelname(dn);
18137dd7cddfSDavid du Colombier }
18147dd7cddfSDavid du Colombier continue;
18157dd7cddfSDavid du Colombier
18167dd7cddfSDavid du Colombier /* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */
18177dd7cddfSDavid du Colombier case 'o':
18187dd7cddfSDavid du Colombier printmesg(fmt="LPP", a, 0);
18197dd7cddfSDavid du Colombier m = 1+4+2*4+2*4;
18207dd7cddfSDavid du Colombier if(n < m)
18217dd7cddfSDavid du Colombier error(Eshortdraw);
18227dd7cddfSDavid du Colombier dst = drawimage(client, a+1);
18237dd7cddfSDavid du Colombier if(dst->layer){
18247dd7cddfSDavid du Colombier drawpoint(&p, a+5);
18257dd7cddfSDavid du Colombier drawpoint(&q, a+13);
18267dd7cddfSDavid du Colombier r = dst->layer->screenr;
18277dd7cddfSDavid du Colombier ni = memlorigin(dst, p, q);
18287dd7cddfSDavid du Colombier if(ni < 0)
18297dd7cddfSDavid du Colombier error("image origin failed");
18307dd7cddfSDavid du Colombier if(ni > 0){
18317dd7cddfSDavid du Colombier addflush(r);
18327dd7cddfSDavid du Colombier addflush(dst->layer->screenr);
18337dd7cddfSDavid du Colombier ll = drawlookup(client, BGLONG(a+1), 1);
18347dd7cddfSDavid du Colombier drawrefreshscreen(ll, client);
18357dd7cddfSDavid du Colombier }
18367dd7cddfSDavid du Colombier }
18377dd7cddfSDavid du Colombier continue;
18387dd7cddfSDavid du Colombier
18396a9fc400SDavid du Colombier /* set compositing operator for next draw operation: 'O' op */
18406a9fc400SDavid du Colombier case 'O':
18416a9fc400SDavid du Colombier printmesg(fmt="b", a, 0);
18426a9fc400SDavid du Colombier m = 1+1;
18436a9fc400SDavid du Colombier if(n < m)
18446a9fc400SDavid du Colombier error(Eshortdraw);
18456a9fc400SDavid du Colombier client->op = a[1];
18466a9fc400SDavid du Colombier continue;
18476a9fc400SDavid du Colombier
18487dd7cddfSDavid 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] */
18497dd7cddfSDavid 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] */
18507dd7cddfSDavid du Colombier case 'p':
18517dd7cddfSDavid du Colombier case 'P':
18527dd7cddfSDavid du Colombier printmesg(fmt="LslllLPP", a, 0);
18537dd7cddfSDavid du Colombier m = 1+4+2+4+4+4+4+2*4;
18547dd7cddfSDavid du Colombier if(n < m)
18557dd7cddfSDavid du Colombier error(Eshortdraw);
18567dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
18577dd7cddfSDavid du Colombier dst = drawimage(client, a+1);
18587dd7cddfSDavid du Colombier ni = BGSHORT(a+5);
18597dd7cddfSDavid du Colombier if(ni < 0)
18607dd7cddfSDavid du Colombier error("negative count in polygon");
18617dd7cddfSDavid du Colombier e0 = BGLONG(a+7);
18627dd7cddfSDavid du Colombier e1 = BGLONG(a+11);
18637dd7cddfSDavid du Colombier j = 0;
18647dd7cddfSDavid du Colombier if(*a == 'p'){
18657dd7cddfSDavid du Colombier j = BGLONG(a+15);
18667dd7cddfSDavid du Colombier if(j < 0)
18677dd7cddfSDavid du Colombier error("negative polygon line width");
18687dd7cddfSDavid du Colombier }
18697dd7cddfSDavid du Colombier src = drawimage(client, a+19);
18707dd7cddfSDavid du Colombier drawpoint(&sp, a+23);
18717dd7cddfSDavid du Colombier drawpoint(&p, a+31);
18727dd7cddfSDavid du Colombier ni++;
18737dd7cddfSDavid du Colombier pp = malloc(ni*sizeof(Point));
18747dd7cddfSDavid du Colombier if(pp == nil)
18757dd7cddfSDavid du Colombier error(Enomem);
18767dd7cddfSDavid du Colombier doflush = 0;
18777dd7cddfSDavid du Colombier if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data))
18787dd7cddfSDavid du Colombier doflush = 1; /* simplify test in loop */
18797dd7cddfSDavid du Colombier ox = oy = 0;
18806a9fc400SDavid du Colombier esize = 0;
18817dd7cddfSDavid du Colombier u = a+m;
18827dd7cddfSDavid du Colombier for(y=0; y<ni; y++){
18836a9fc400SDavid du Colombier q = p;
18846a9fc400SDavid du Colombier oesize = esize;
18857dd7cddfSDavid du Colombier u = drawcoord(u, a+n, ox, &p.x);
18867dd7cddfSDavid du Colombier u = drawcoord(u, a+n, oy, &p.y);
18877dd7cddfSDavid du Colombier ox = p.x;
18887dd7cddfSDavid du Colombier oy = p.y;
18897dd7cddfSDavid du Colombier if(doflush){
18907dd7cddfSDavid du Colombier esize = j;
18917dd7cddfSDavid du Colombier if(*a == 'p'){
18927dd7cddfSDavid du Colombier if(y == 0){
18937dd7cddfSDavid du Colombier c = memlineendsize(e0);
18947dd7cddfSDavid du Colombier if(c > esize)
18957dd7cddfSDavid du Colombier esize = c;
18967dd7cddfSDavid du Colombier }
18977dd7cddfSDavid du Colombier if(y == ni-1){
18987dd7cddfSDavid du Colombier c = memlineendsize(e1);
18997dd7cddfSDavid du Colombier if(c > esize)
19007dd7cddfSDavid du Colombier esize = c;
19017dd7cddfSDavid du Colombier }
19027dd7cddfSDavid du Colombier }
19037dd7cddfSDavid du Colombier if(*a=='P' && e0!=1 && e0 !=~0)
19047dd7cddfSDavid du Colombier r = dst->clipr;
19056a9fc400SDavid du Colombier else if(y > 0){
19066a9fc400SDavid du Colombier r = Rect(q.x-oesize, q.y-oesize, q.x+oesize+1, q.y+oesize+1);
19076a9fc400SDavid du Colombier combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
19086a9fc400SDavid du Colombier }
19096a9fc400SDavid du Colombier if(rectclip(&r, dst->clipr)) /* should perhaps be an arg to dstflush */
19107dd7cddfSDavid du Colombier dstflush(dstid, dst, r);
19117dd7cddfSDavid du Colombier }
19127dd7cddfSDavid du Colombier pp[y] = p;
19137dd7cddfSDavid du Colombier }
19146a9fc400SDavid du Colombier if(y == 1)
19156a9fc400SDavid du Colombier dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
19166a9fc400SDavid du Colombier op = drawclientop(client);
19177dd7cddfSDavid du Colombier if(*a == 'p')
19186a9fc400SDavid du Colombier mempoly(dst, pp, ni, e0, e1, j, src, sp, op);
19197dd7cddfSDavid du Colombier else
19206a9fc400SDavid du Colombier memfillpoly(dst, pp, ni, e0, src, sp, op);
19217dd7cddfSDavid du Colombier free(pp);
19227dd7cddfSDavid du Colombier m = u-a;
19237dd7cddfSDavid du Colombier continue;
19247dd7cddfSDavid du Colombier
19257dd7cddfSDavid du Colombier /* read: 'r' id[4] R[4*4] */
19267dd7cddfSDavid du Colombier case 'r':
19277dd7cddfSDavid du Colombier printmesg(fmt="LR", a, 0);
19287dd7cddfSDavid du Colombier m = 1+4+4*4;
19297dd7cddfSDavid du Colombier if(n < m)
19307dd7cddfSDavid du Colombier error(Eshortdraw);
19317dd7cddfSDavid du Colombier i = drawimage(client, a+1);
19327dd7cddfSDavid du Colombier drawrectangle(&r, a+5);
19337dd7cddfSDavid du Colombier if(!rectinrect(r, i->r))
19347dd7cddfSDavid du Colombier error(Ereadoutside);
19357dd7cddfSDavid du Colombier c = bytesperline(r, i->depth);
19367dd7cddfSDavid du Colombier c *= Dy(r);
19377dd7cddfSDavid du Colombier free(client->readdata);
19387dd7cddfSDavid du Colombier client->readdata = mallocz(c, 0);
19397dd7cddfSDavid du Colombier if(client->readdata == nil)
19407dd7cddfSDavid du Colombier error("readimage malloc failed");
194180ee5cbfSDavid du Colombier client->nreaddata = memunload(i, r, client->readdata, c);
19427dd7cddfSDavid du Colombier if(client->nreaddata < 0){
19437dd7cddfSDavid du Colombier free(client->readdata);
19447dd7cddfSDavid du Colombier client->readdata = nil;
19457dd7cddfSDavid du Colombier error("bad readimage call");
19467dd7cddfSDavid du Colombier }
19477dd7cddfSDavid du Colombier continue;
19487dd7cddfSDavid du Colombier
19497dd7cddfSDavid du Colombier /* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */
19507dd7cddfSDavid 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]) */
19517dd7cddfSDavid du Colombier case 's':
19527dd7cddfSDavid du Colombier case 'x':
19537dd7cddfSDavid du Colombier printmesg(fmt="LLLPRPs", a, 0);
19547dd7cddfSDavid du Colombier m = 1+4+4+4+2*4+4*4+2*4+2;
19557dd7cddfSDavid du Colombier if(*a == 'x')
19567dd7cddfSDavid du Colombier m += 4+2*4;
19577dd7cddfSDavid du Colombier if(n < m)
19587dd7cddfSDavid du Colombier error(Eshortdraw);
19597dd7cddfSDavid du Colombier
19607dd7cddfSDavid du Colombier dst = drawimage(client, a+1);
19617dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
19627dd7cddfSDavid du Colombier src = drawimage(client, a+5);
19637dd7cddfSDavid du Colombier font = drawlookup(client, BGLONG(a+9), 1);
19647dd7cddfSDavid du Colombier if(font == 0)
19657dd7cddfSDavid du Colombier error(Enodrawimage);
19667dd7cddfSDavid du Colombier if(font->nfchar == 0)
19677dd7cddfSDavid du Colombier error(Enotfont);
19687dd7cddfSDavid du Colombier drawpoint(&p, a+13);
19697dd7cddfSDavid du Colombier drawrectangle(&r, a+21);
19707dd7cddfSDavid du Colombier drawpoint(&sp, a+37);
19717dd7cddfSDavid du Colombier ni = BGSHORT(a+45);
19727dd7cddfSDavid du Colombier u = a+m;
19737dd7cddfSDavid du Colombier m += ni*2;
19747dd7cddfSDavid du Colombier if(n < m)
19757dd7cddfSDavid du Colombier error(Eshortdraw);
19767dd7cddfSDavid du Colombier clipr = dst->clipr;
19777dd7cddfSDavid du Colombier dst->clipr = r;
19786a9fc400SDavid du Colombier op = drawclientop(client);
19791ee3cffaSDavid du Colombier bg = dst;
19807dd7cddfSDavid du Colombier if(*a == 'x'){
19817dd7cddfSDavid du Colombier /* paint background */
19821ee3cffaSDavid du Colombier bg = drawimage(client, a+47);
19837dd7cddfSDavid du Colombier drawpoint(&q, a+51);
19847dd7cddfSDavid du Colombier r.min.x = p.x;
19857dd7cddfSDavid du Colombier r.min.y = p.y-font->ascent;
19867dd7cddfSDavid du Colombier r.max.x = p.x;
19877dd7cddfSDavid du Colombier r.max.y = r.min.y+Dy(font->image->r);
19887dd7cddfSDavid du Colombier j = ni;
19897dd7cddfSDavid du Colombier while(--j >= 0){
19907dd7cddfSDavid du Colombier ci = BGSHORT(u);
19917dd7cddfSDavid du Colombier if(ci<0 || ci>=font->nfchar){
19927dd7cddfSDavid du Colombier dst->clipr = clipr;
19937dd7cddfSDavid du Colombier error(Eindex);
19947dd7cddfSDavid du Colombier }
19957dd7cddfSDavid du Colombier r.max.x += font->fchar[ci].width;
19967dd7cddfSDavid du Colombier u += 2;
19977dd7cddfSDavid du Colombier }
19981ee3cffaSDavid du Colombier memdraw(dst, r, bg, q, memopaque, ZP, op);
19997dd7cddfSDavid du Colombier u -= 2*ni;
20007dd7cddfSDavid du Colombier }
20017dd7cddfSDavid du Colombier q = p;
20027dd7cddfSDavid du Colombier while(--ni >= 0){
20037dd7cddfSDavid du Colombier ci = BGSHORT(u);
20047dd7cddfSDavid du Colombier if(ci<0 || ci>=font->nfchar){
20057dd7cddfSDavid du Colombier dst->clipr = clipr;
20067dd7cddfSDavid du Colombier error(Eindex);
20077dd7cddfSDavid du Colombier }
20081ee3cffaSDavid du Colombier q = drawchar(dst, bg, q, src, &sp, font, ci, op);
20097dd7cddfSDavid du Colombier u += 2;
20107dd7cddfSDavid du Colombier }
20117dd7cddfSDavid du Colombier dst->clipr = clipr;
20127dd7cddfSDavid du Colombier p.y -= font->ascent;
20137dd7cddfSDavid du Colombier dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
20147dd7cddfSDavid du Colombier continue;
20157dd7cddfSDavid du Colombier
20167dd7cddfSDavid du Colombier /* use public screen: 'S' id[4] chan[4] */
20177dd7cddfSDavid du Colombier case 'S':
20187dd7cddfSDavid du Colombier printmesg(fmt="Ll", a, 0);
20197dd7cddfSDavid du Colombier m = 1+4+4;
20207dd7cddfSDavid du Colombier if(n < m)
20217dd7cddfSDavid du Colombier error(Eshortdraw);
20227dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
20237dd7cddfSDavid du Colombier if(dstid == 0)
20247dd7cddfSDavid du Colombier error(Ebadarg);
20257dd7cddfSDavid du Colombier dscrn = drawlookupdscreen(dstid);
20267dd7cddfSDavid du Colombier if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client))
20277dd7cddfSDavid du Colombier error(Enodrawscreen);
20287dd7cddfSDavid du Colombier if(dscrn->screen->image->chan != BGLONG(a+5))
20297dd7cddfSDavid du Colombier error("inconsistent chan");
20307dd7cddfSDavid du Colombier if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0)
20317dd7cddfSDavid du Colombier error(Edrawmem);
20327dd7cddfSDavid du Colombier continue;
20337dd7cddfSDavid du Colombier
20347dd7cddfSDavid du Colombier /* top or bottom windows: 't' top[1] nw[2] n*id[4] */
20357dd7cddfSDavid du Colombier case 't':
20367dd7cddfSDavid du Colombier printmesg(fmt="bsL", a, 0);
20377dd7cddfSDavid du Colombier m = 1+1+2;
20387dd7cddfSDavid du Colombier if(n < m)
20397dd7cddfSDavid du Colombier error(Eshortdraw);
20407dd7cddfSDavid du Colombier nw = BGSHORT(a+2);
20417dd7cddfSDavid du Colombier if(nw < 0)
20427dd7cddfSDavid du Colombier error(Ebadarg);
20437dd7cddfSDavid du Colombier if(nw == 0)
20447dd7cddfSDavid du Colombier continue;
20457dd7cddfSDavid du Colombier m += nw*4;
20467dd7cddfSDavid du Colombier if(n < m)
20477dd7cddfSDavid du Colombier error(Eshortdraw);
20487dd7cddfSDavid du Colombier lp = malloc(nw*sizeof(Memimage*));
20497dd7cddfSDavid du Colombier if(lp == 0)
20507dd7cddfSDavid du Colombier error(Enomem);
20517dd7cddfSDavid du Colombier if(waserror()){
20527dd7cddfSDavid du Colombier free(lp);
20537dd7cddfSDavid du Colombier nexterror();
20547dd7cddfSDavid du Colombier }
20557dd7cddfSDavid du Colombier for(j=0; j<nw; j++)
20567dd7cddfSDavid du Colombier lp[j] = drawimage(client, a+1+1+2+j*4);
20577dd7cddfSDavid du Colombier if(lp[0]->layer == 0)
20587dd7cddfSDavid du Colombier error("images are not windows");
20597dd7cddfSDavid du Colombier for(j=1; j<nw; j++)
20607dd7cddfSDavid du Colombier if(lp[j]->layer->screen != lp[0]->layer->screen)
20617dd7cddfSDavid du Colombier error("images not on same screen");
20627dd7cddfSDavid du Colombier if(a[1])
20637dd7cddfSDavid du Colombier memltofrontn(lp, nw);
20647dd7cddfSDavid du Colombier else
20657dd7cddfSDavid du Colombier memltorearn(lp, nw);
20667dd7cddfSDavid du Colombier if(lp[0]->layer->screen->image->data == screenimage->data)
20677dd7cddfSDavid du Colombier for(j=0; j<nw; j++)
20687dd7cddfSDavid du Colombier addflush(lp[j]->layer->screenr);
20697dd7cddfSDavid du Colombier ll = drawlookup(client, BGLONG(a+1+1+2), 1);
20707dd7cddfSDavid du Colombier drawrefreshscreen(ll, client);
20717dd7cddfSDavid du Colombier poperror();
20727dd7cddfSDavid du Colombier free(lp);
20737dd7cddfSDavid du Colombier continue;
20747dd7cddfSDavid du Colombier
20757dd7cddfSDavid du Colombier /* visible: 'v' */
20767dd7cddfSDavid du Colombier case 'v':
20777dd7cddfSDavid du Colombier printmesg(fmt="", a, 0);
20787dd7cddfSDavid du Colombier m = 1;
20797dd7cddfSDavid du Colombier drawflush();
20807dd7cddfSDavid du Colombier continue;
20817dd7cddfSDavid du Colombier
20827dd7cddfSDavid du Colombier /* write: 'y' id[4] R[4*4] data[x*1] */
20837dd7cddfSDavid du Colombier /* write from compressed data: 'Y' id[4] R[4*4] data[x*1] */
20847dd7cddfSDavid du Colombier case 'y':
20857dd7cddfSDavid du Colombier case 'Y':
20867dd7cddfSDavid du Colombier printmesg(fmt="LR", a, 0);
20877dd7cddfSDavid du Colombier // iprint("load %c\n", *a);
20887dd7cddfSDavid du Colombier m = 1+4+4*4;
20897dd7cddfSDavid du Colombier if(n < m)
20907dd7cddfSDavid du Colombier error(Eshortdraw);
20917dd7cddfSDavid du Colombier dstid = BGLONG(a+1);
20927dd7cddfSDavid du Colombier dst = drawimage(client, a+1);
20937dd7cddfSDavid du Colombier drawrectangle(&r, a+5);
20947dd7cddfSDavid du Colombier if(!rectinrect(r, dst->r))
20957dd7cddfSDavid du Colombier error(Ewriteoutside);
20967dd7cddfSDavid du Colombier y = memload(dst, r, a+m, n-m, *a=='Y');
20977dd7cddfSDavid du Colombier if(y < 0)
20987dd7cddfSDavid du Colombier error("bad writeimage call");
20997dd7cddfSDavid du Colombier dstflush(dstid, dst, r);
21007dd7cddfSDavid du Colombier m += y;
21017dd7cddfSDavid du Colombier continue;
21027dd7cddfSDavid du Colombier }
21037dd7cddfSDavid du Colombier }
21047dd7cddfSDavid du Colombier poperror();
21057dd7cddfSDavid du Colombier }
21067dd7cddfSDavid du Colombier
21077dd7cddfSDavid du Colombier Dev drawdevtab = {
21087dd7cddfSDavid du Colombier 'i',
21097dd7cddfSDavid du Colombier "draw",
21107dd7cddfSDavid du Colombier
21117dd7cddfSDavid du Colombier devreset,
21127dd7cddfSDavid du Colombier devinit,
21139a747e4fSDavid du Colombier devshutdown,
21147dd7cddfSDavid du Colombier drawattach,
21157dd7cddfSDavid du Colombier drawwalk,
21167dd7cddfSDavid du Colombier drawstat,
21177dd7cddfSDavid du Colombier drawopen,
21187dd7cddfSDavid du Colombier devcreate,
21197dd7cddfSDavid du Colombier drawclose,
21207dd7cddfSDavid du Colombier drawread,
21217dd7cddfSDavid du Colombier devbread,
21227dd7cddfSDavid du Colombier drawwrite,
21237dd7cddfSDavid du Colombier devbwrite,
21247dd7cddfSDavid du Colombier devremove,
21257dd7cddfSDavid du Colombier devwstat,
21267dd7cddfSDavid du Colombier };
21277dd7cddfSDavid du Colombier
21287dd7cddfSDavid du Colombier /*
21297dd7cddfSDavid du Colombier * On 8 bit displays, load the default color map
21307dd7cddfSDavid du Colombier */
21317dd7cddfSDavid du Colombier void
drawcmap(void)21327dd7cddfSDavid du Colombier drawcmap(void)
21337dd7cddfSDavid du Colombier {
21347dd7cddfSDavid du Colombier int r, g, b, cr, cg, cb, v;
21357dd7cddfSDavid du Colombier int num, den;
21367dd7cddfSDavid du Colombier int i, j;
21377dd7cddfSDavid du Colombier
21387dd7cddfSDavid du Colombier drawactive(1); /* to restore map from backup */
21397dd7cddfSDavid du Colombier for(r=0,i=0; r!=4; r++)
21407dd7cddfSDavid du Colombier for(v=0; v!=4; v++,i+=16){
21417dd7cddfSDavid du Colombier for(g=0,j=v-r; g!=4; g++)
21427dd7cddfSDavid du Colombier for(b=0;b!=4;b++,j++){
21437dd7cddfSDavid du Colombier den = r;
21447dd7cddfSDavid du Colombier if(g > den)
21457dd7cddfSDavid du Colombier den = g;
21467dd7cddfSDavid du Colombier if(b > den)
21477dd7cddfSDavid du Colombier den = b;
21487dd7cddfSDavid du Colombier if(den == 0) /* divide check -- pick grey shades */
21497dd7cddfSDavid du Colombier cr = cg = cb = v*17;
21507dd7cddfSDavid du Colombier else{
21517dd7cddfSDavid du Colombier num = 17*(4*den+v);
21527dd7cddfSDavid du Colombier cr = r*num/den;
21537dd7cddfSDavid du Colombier cg = g*num/den;
21547dd7cddfSDavid du Colombier cb = b*num/den;
21557dd7cddfSDavid du Colombier }
21567dd7cddfSDavid du Colombier setcolor(i+(j&15),
21577dd7cddfSDavid du Colombier cr*0x01010101, cg*0x01010101, cb*0x01010101);
21587dd7cddfSDavid du Colombier }
21597dd7cddfSDavid du Colombier }
21607dd7cddfSDavid du Colombier }
21617dd7cddfSDavid du Colombier
21627dd7cddfSDavid du Colombier void
drawblankscreen(int blank)21637dd7cddfSDavid du Colombier drawblankscreen(int blank)
21647dd7cddfSDavid du Colombier {
21657dd7cddfSDavid du Colombier int i, nc;
21667dd7cddfSDavid du Colombier ulong *p;
21677dd7cddfSDavid du Colombier
21687dd7cddfSDavid du Colombier if(blank == sdraw.blanked)
21697dd7cddfSDavid du Colombier return;
21704de34a7eSDavid du Colombier if(!candlock())
21717dd7cddfSDavid du Colombier return;
2172cb8c047aSDavid du Colombier if(screenimage == nil){
21734de34a7eSDavid du Colombier dunlock();
21747dd7cddfSDavid du Colombier return;
21757dd7cddfSDavid du Colombier }
21767dd7cddfSDavid du Colombier p = sdraw.savemap;
21777dd7cddfSDavid du Colombier nc = screenimage->depth > 8 ? 256 : 1<<screenimage->depth;
21787dd7cddfSDavid du Colombier
21797dd7cddfSDavid du Colombier /*
21807dd7cddfSDavid du Colombier * blankscreen uses the hardware to blank the screen
21817dd7cddfSDavid du Colombier * when possible. to help in cases when it is not possible,
21827dd7cddfSDavid du Colombier * we set the color map to be all black.
21837dd7cddfSDavid du Colombier */
21847dd7cddfSDavid du Colombier if(blank == 0){ /* turn screen on */
21857dd7cddfSDavid du Colombier for(i=0; i<nc; i++, p+=3)
21867dd7cddfSDavid du Colombier setcolor(i, p[0], p[1], p[2]);
21877dd7cddfSDavid du Colombier blankscreen(0);
21887dd7cddfSDavid du Colombier }else{ /* turn screen off */
21897dd7cddfSDavid du Colombier blankscreen(1);
21907dd7cddfSDavid du Colombier for(i=0; i<nc; i++, p+=3){
21917dd7cddfSDavid du Colombier getcolor(i, &p[0], &p[1], &p[2]);
21927dd7cddfSDavid du Colombier setcolor(i, 0, 0, 0);
21937dd7cddfSDavid du Colombier }
21947dd7cddfSDavid du Colombier }
21957dd7cddfSDavid du Colombier sdraw.blanked = blank;
21964de34a7eSDavid du Colombier dunlock();
21977dd7cddfSDavid du Colombier }
21987dd7cddfSDavid du Colombier
21997dd7cddfSDavid du Colombier /*
22007dd7cddfSDavid du Colombier * record activity on screen, changing blanking as appropriate
22017dd7cddfSDavid du Colombier */
22027dd7cddfSDavid du Colombier void
drawactive(int active)22037dd7cddfSDavid du Colombier drawactive(int active)
22047dd7cddfSDavid du Colombier {
22057dd7cddfSDavid du Colombier if(active){
22067dd7cddfSDavid du Colombier drawblankscreen(0);
22076a9fc400SDavid du Colombier sdraw.blanktime = MACHP(0)->ticks;
22087dd7cddfSDavid du Colombier }else{
22096a9fc400SDavid du Colombier if(blanktime && sdraw.blanktime && TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60 >= blanktime)
22107dd7cddfSDavid du Colombier drawblankscreen(1);
22117dd7cddfSDavid du Colombier }
22127dd7cddfSDavid du Colombier }
22136a9fc400SDavid du Colombier
22146a9fc400SDavid du Colombier int
drawidletime(void)22156a9fc400SDavid du Colombier drawidletime(void)
22166a9fc400SDavid du Colombier {
22176a9fc400SDavid du Colombier return TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60;
22186a9fc400SDavid du Colombier }
2219