#include <lib9.h>#include <kern.h>#include <draw.h>#include <memdraw.h>#include <memlayer.h>#include <cursor.h>#include <ninep.h>#include <ninepserver.h>#include "dat.h"#include "fns.h"#include "fsys.h" typedef struct DImage DImage;typedef struct DName DName;typedef struct CScreen CScreen;typedef struct DScreen DScreen;typedef struct FChar FChar;typedef struct Refresh Refresh;typedef struct Refx Refx; #define NHASH (1<<5)#define HASHMASK (NHASH-1) struct DClient{ int r; // Ref DImage* dimage[NHASH]; CScreen* cscreen; Refresh* refresh;// Rendez refrend; Draw *draw; uchar* readdata; int nreaddata; int busy; int clientid; int slot; int refreshme; int infoid; int op;}; struct Refresh{ DImage* dimage; Rectangle r; Refresh* next;}; struct Refx{ DClient* client; DImage* dimage;}; struct FChar{ int minx; /* left edge of bits */ int maxx; /* right edge of bits */ uchar miny; /* first non-zero scan-line */ uchar maxy; /* last non-zero scan-line + 1 */ schar left; /* offset of baseline */ uchar width; /* width of baseline */}; struct DImage{ int id; int ref; char *name; int vers; Memimage* image; int ascent; int nfchar; FChar* fchar; DScreen* dscreen; /* 0 if not a window */ DImage* fromname; /* image this one is derived from, by name */ DImage* next;}; struct DName{ char *name; DClient *client; DImage* dimage; int vers;}; struct CScreen{ DScreen* dscreen; CScreen* next;}; struct DScreen{ int id; int public; int ref; DImage *dimage; DImage *dfill; Memscreen* screen; DClient* owner; DScreen* next;}; struct Draw{ Window* window; DImage* screendimage; Rectangle flushrect; int waste; DScreen* dscreen;}; static void drawfreedimage(Draw*, DImage*);static int drawgoodname(DImage*);static void drawflush(Draw*);static DClient* drawlookupclient(int); int nclient = 0;int ndname = 0;DName* dname = nil;int vers = 0; /* used by libmemdraw */intiprint(char* fmt, ...){ int n; va_list args; va_start(args, fmt); n = vfprint(2, fmt, args); va_end(args); return n;} staticvoiddrawrefreshscreen(DImage *l, DClient *client){ while(l != nil && l->dscreen == nil) l = l->fromname; if(l != nil && l->dscreen->owner != client) l->dscreen->owner->refreshme = 1;} staticvoiddrawrefresh(Memimage *l, Rectangle r, void *v){ Refx *x; DImage *d; DClient *c; Refresh *ref; USED(l); if(v == 0) return; x = v; c = x->client; d = x->dimage; for(ref=c->refresh; ref; ref=ref->next) if(ref->dimage == d){ combinerect(&ref->r, r); return; } ref = mallocz(sizeof(Refresh), 1); if(ref){ ref->dimage = d; ref->r = r; ref->next = c->refresh; c->refresh = ref; }} staticvoidaddflush(Draw *d, Rectangle r){ int abb, ar, anbb; Rectangle nbb; Memimage *screenimage; screenimage = d->window->screenimage; if(!rectclip(&r, screenimage->r)) return; if(d->flushrect.min.x >= d->flushrect.max.x){ d->flushrect = r; d->waste = 0; return; } nbb = d->flushrect; combinerect(&nbb, r); ar = Dx(r)*Dy(r); abb = Dx(d->flushrect)*Dy(d->flushrect); anbb = Dx(nbb)*Dy(nbb); /* * Area of new waste is area of new bb minus area of old bb, * less the area of the new segment, which we assume is not waste. * This could be negative, but that's OK. */ d->waste += anbb-abb - ar; if(d->waste < 0) d->waste = 0; /* * absorb if: * total area is small * waste is less than half total area * rectangles touch */ if(anbb<=1024 || d->waste*2<anbb || rectXrect(d->flushrect, r)){ d->flushrect = nbb; return; } /* emit current state */ if(d->flushrect.min.x < d->flushrect.max.x) xflushmemscreen(d->window, d->flushrect); d->flushrect = r; d->waste = 0;} staticvoiddstflush(Draw *d, Memimage *dst, Rectangle r){ Memimage *screenimage; Memlayer *l; screenimage = d->window->screenimage; if(dst == screenimage){ combinerect(&d->flushrect, r); return; } /* how can this happen? -rsc, dec 12 2002 */ if(dst == 0){ fprint(2, "nil dstflush\n"); return; } l = dst->layer; if(l == nil) return; do{ if(l->screen->image->data != screenimage->data) return; r = rectaddpt(r, l->delta); l = l->screen->image->layer; }while(l); addflush(d, r);} staticvoiddrawflush(Draw *d){ if(d->flushrect.min.x < d->flushrect.max.x) xflushmemscreen(d->window, d->flushrect); d->flushrect = Rect(10000, 10000, -10000, -10000);} staticintdrawcmp(char *a, char *b, int n){ if(strlen(a) != n) return 1; return memcmp(a, b, n);} staticDName*drawlookupname(int n, char *str){ DName *name, *ename; name = dname; ename = &name[ndname]; for(; name<ename; name++) if(drawcmp(name->name, str, n) == 0) return name; return 0;} staticintdrawgoodname(DImage *d){ DName *n; /* if window, validate the screen's own images */ if(d->dscreen) if(drawgoodname(d->dscreen->dimage) == 0 || drawgoodname(d->dscreen->dfill) == 0) return 0; if(d->name == nil) return 1; n = drawlookupname(strlen(d->name), d->name); if(n==nil || n->vers!=d->vers) return 0; return 1;} staticDImage*drawlookup(DClient *client, int id, int checkname){ DImage *d; d = client->dimage[id&HASHMASK]; while(d){ if(d->id == id){ if(checkname && !drawgoodname(d)) return 0; /* BUG: error(Eoldname); */ return d; } d = d->next; } return 0;} staticDScreen*drawlookupdscreen(Draw *draw, int id){ DScreen *s; s = draw->dscreen; while(s){ if(s->id == id) return s; s = s->next; } return 0;} staticDScreen*drawlookupscreen(DClient *client, int id, CScreen **cs){ CScreen *s; s = client->cscreen; while(s){ if(s->dscreen->id == id){ *cs = s; return s->dscreen; } s = s->next; } /* caller must check! */ /* BUG: error(Enodrawscreen); */ return 0;} staticDImage*allocdimage(Memimage *i){ DImage *d; d = malloc(sizeof(DImage)); if(d == 0) return 0; d->ref = 1; d->name = 0; d->vers = 0; d->image = i; d->nfchar = 0; d->fchar = 0; d->fromname = 0; return d;} staticMemimage*drawinstall(DClient *client, int id, Memimage *i, DScreen *dscreen){ DImage *d; d = allocdimage(i); if(d == 0) return 0; d->id = id; d->dscreen = dscreen; d->next = client->dimage[id&HASHMASK]; client->dimage[id&HASHMASK] = d; return i;} staticMemscreen*drawinstallscreen(DClient *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public){ Memscreen *s; CScreen *c; c = malloc(sizeof(CScreen)); if(dimage && dimage->image && dimage->image->chan == 0) fatal("bad image %p in drawinstallscreen", dimage->image); if(c == 0) return 0; if(d == 0){ d = malloc(sizeof(DScreen)); if(d == 0){ free(c); return 0; } s = malloc(sizeof(Memscreen)); if(s == 0){ free(c); free(d); return 0; } s->frontmost = 0; s->rearmost = 0; d->dimage = dimage; if(dimage){ s->image = dimage->image; dimage->ref++; } d->dfill = dfill; if(dfill){ s->fill = dfill->image; dfill->ref++; } d->ref = 0; d->id = id; d->screen = s; d->public = public; d->next = client->draw->dscreen; d->owner = client; client->draw->dscreen = d; } c->dscreen = d; d->ref++; c->next = client->cscreen; client->cscreen = c; return d->screen;} staticvoiddrawdelname(DName *name){ int i; i = name-dname; memmove(name, name+1, (ndname-(i+1))*sizeof(DName)); ndname--;} staticvoiddrawfreedscreen(Draw *d, DScreen *this){ DScreen *ds, *next; this->ref--; if(this->ref < 0) fprint(2, "negative ref in drawfreedscreen\n"); if(this->ref > 0) return; ds = d->dscreen; if(ds == this){ d->dscreen = this->next; goto Found; } while(next = ds->next){ /* assign = */ if(next == this){ ds->next = this->next; goto Found; } ds = next; } /* BUG: error(Enodrawimage); */ return; Found: if(this->dimage) drawfreedimage(d, this->dimage); if(this->dfill) drawfreedimage(d, this->dfill); free(this->screen); free(this);} staticvoiddrawfreedimage(Draw *d, DImage *dimage){ int i; Memimage *l, *screenimage; DScreen *ds; dimage->ref--; if(dimage->ref < 0) fprint(2, "negative ref in drawfreedimage\n"); if(dimage->ref > 0)Lines 1–500 of 1992. Load more
#include <lib9.h> #include <kern.h> #include <draw.h> #include <memdraw.h> #include <memlayer.h> #include <cursor.h> #include <ninep.h> #include <ninepserver.h> #include "dat.h" #include "fns.h" #include "fsys.h" typedef struct DImage DImage; typedef struct DName DName; typedef struct CScreen CScreen; typedef struct DScreen DScreen; typedef struct FChar FChar; typedef struct Refresh Refresh; typedef struct Refx Refx; #define NHASH (1<<5) #define HASHMASK (NHASH-1) struct DClient { int r; // Ref DImage* dimage[NHASH]; CScreen* cscreen; Refresh* refresh; // Rendez refrend; Draw *draw; uchar* readdata; int nreaddata; int busy; int clientid; int slot; int refreshme; int infoid; int op; }; struct Refresh { DImage* dimage; Rectangle r; Refresh* next; }; struct Refx { DClient* client; DImage* dimage; }; struct FChar { int minx; /* left edge of bits */ int maxx; /* right edge of bits */ uchar miny; /* first non-zero scan-line */ uchar maxy; /* last non-zero scan-line + 1 */ schar left; /* offset of baseline */ uchar width; /* width of baseline */ }; struct DImage { int id; int ref; char *name; int vers; Memimage* image; int ascent; int nfchar; FChar* fchar; DScreen* dscreen; /* 0 if not a window */ DImage* fromname; /* image this one is derived from, by name */ DImage* next; }; struct DName { char *name; DClient *client; DImage* dimage; int vers; }; struct CScreen { DScreen* dscreen; CScreen* next; }; struct DScreen { int id; int public; int ref; DImage *dimage; DImage *dfill; Memscreen* screen; DClient* owner; DScreen* next; }; struct Draw { Window* window; DImage* screendimage; Rectangle flushrect; int waste; DScreen* dscreen; }; static void drawfreedimage(Draw*, DImage*); static int drawgoodname(DImage*); static void drawflush(Draw*); static DClient* drawlookupclient(int); int nclient = 0; int ndname = 0; DName* dname = nil; int vers = 0; /* used by libmemdraw */ int iprint(char* fmt, ...) { int n; va_list args; va_start(args, fmt); n = vfprint(2, fmt, args); va_end(args); return n; } static void drawrefreshscreen(DImage *l, DClient *client) { while(l != nil && l->dscreen == nil) l = l->fromname; if(l != nil && l->dscreen->owner != client) l->dscreen->owner->refreshme = 1; } static void drawrefresh(Memimage *l, Rectangle r, void *v) { Refx *x; DImage *d; DClient *c; Refresh *ref; USED(l); if(v == 0) return; x = v; c = x->client; d = x->dimage; for(ref=c->refresh; ref; ref=ref->next) if(ref->dimage == d){ combinerect(&ref->r, r); return; } ref = mallocz(sizeof(Refresh), 1); if(ref){ ref->dimage = d; ref->r = r; ref->next = c->refresh; c->refresh = ref; } } static void addflush(Draw *d, Rectangle r) { int abb, ar, anbb; Rectangle nbb; Memimage *screenimage; screenimage = d->window->screenimage; if(!rectclip(&r, screenimage->r)) return; if(d->flushrect.min.x >= d->flushrect.max.x){ d->flushrect = r; d->waste = 0; return; } nbb = d->flushrect; combinerect(&nbb, r); ar = Dx(r)*Dy(r); abb = Dx(d->flushrect)*Dy(d->flushrect); anbb = Dx(nbb)*Dy(nbb); /* * Area of new waste is area of new bb minus area of old bb, * less the area of the new segment, which we assume is not waste. * This could be negative, but that's OK. */ d->waste += anbb-abb - ar; if(d->waste < 0) d->waste = 0; /* * absorb if: * total area is small * waste is less than half total area * rectangles touch */ if(anbb<=1024 || d->waste*2<anbb || rectXrect(d->flushrect, r)){ d->flushrect = nbb; return; } /* emit current state */ if(d->flushrect.min.x < d->flushrect.max.x) xflushmemscreen(d->window, d->flushrect); d->flushrect = r; d->waste = 0; } static void dstflush(Draw *d, Memimage *dst, Rectangle r) { Memimage *screenimage; Memlayer *l; screenimage = d->window->screenimage; if(dst == screenimage){ combinerect(&d->flushrect, r); return; } /* how can this happen? -rsc, dec 12 2002 */ if(dst == 0){ fprint(2, "nil dstflush\n"); return; } l = dst->layer; if(l == nil) return; do{ if(l->screen->image->data != screenimage->data) return; r = rectaddpt(r, l->delta); l = l->screen->image->layer; }while(l); addflush(d, r); } static void drawflush(Draw *d) { if(d->flushrect.min.x < d->flushrect.max.x) xflushmemscreen(d->window, d->flushrect); d->flushrect = Rect(10000, 10000, -10000, -10000); } static int drawcmp(char *a, char *b, int n) { if(strlen(a) != n) return 1; return memcmp(a, b, n); } static DName* drawlookupname(int n, char *str) { DName *name, *ename; name = dname; ename = &name[ndname]; for(; name<ename; name++) if(drawcmp(name->name, str, n) == 0) return name; return 0; } static int drawgoodname(DImage *d) { DName *n; /* if window, validate the screen's own images */ if(d->dscreen) if(drawgoodname(d->dscreen->dimage) == 0 || drawgoodname(d->dscreen->dfill) == 0) return 0; if(d->name == nil) return 1; n = drawlookupname(strlen(d->name), d->name); if(n==nil || n->vers!=d->vers) return 0; return 1; } static DImage* drawlookup(DClient *client, int id, int checkname) { DImage *d; d = client->dimage[id&HASHMASK]; while(d){ if(d->id == id){ if(checkname && !drawgoodname(d)) return 0; /* BUG: error(Eoldname); */ return d; } d = d->next; } return 0; } static DScreen* drawlookupdscreen(Draw *draw, int id) { DScreen *s; s = draw->dscreen; while(s){ if(s->id == id) return s; s = s->next; } return 0; } static DScreen* drawlookupscreen(DClient *client, int id, CScreen **cs) { CScreen *s; s = client->cscreen; while(s){ if(s->dscreen->id == id){ *cs = s; return s->dscreen; } s = s->next; } /* caller must check! */ /* BUG: error(Enodrawscreen); */ return 0; } static DImage* allocdimage(Memimage *i) { DImage *d; d = malloc(sizeof(DImage)); if(d == 0) return 0; d->ref = 1; d->name = 0; d->vers = 0; d->image = i; d->nfchar = 0; d->fchar = 0; d->fromname = 0; return d; } static Memimage* drawinstall(DClient *client, int id, Memimage *i, DScreen *dscreen) { DImage *d; d = allocdimage(i); if(d == 0) return 0; d->id = id; d->dscreen = dscreen; d->next = client->dimage[id&HASHMASK]; client->dimage[id&HASHMASK] = d; return i; } static Memscreen* drawinstallscreen(DClient *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public) { Memscreen *s; CScreen *c; c = malloc(sizeof(CScreen)); if(dimage && dimage->image && dimage->image->chan == 0) fatal("bad image %p in drawinstallscreen", dimage->image); if(c == 0) return 0; if(d == 0){ d = malloc(sizeof(DScreen)); if(d == 0){ free(c); return 0; } s = malloc(sizeof(Memscreen)); if(s == 0){ free(c); free(d); return 0; } s->frontmost = 0; s->rearmost = 0; d->dimage = dimage; if(dimage){ s->image = dimage->image; dimage->ref++; } d->dfill = dfill; if(dfill){ s->fill = dfill->image; dfill->ref++; } d->ref = 0; d->id = id; d->screen = s; d->public = public; d->next = client->draw->dscreen; d->owner = client; client->draw->dscreen = d; } c->dscreen = d; d->ref++; c->next = client->cscreen; client->cscreen = c; return d->screen; } static void drawdelname(DName *name) { int i; i = name-dname; memmove(name, name+1, (ndname-(i+1))*sizeof(DName)); ndname--; } static void drawfreedscreen(Draw *d, DScreen *this) { DScreen *ds, *next; this->ref--; if(this->ref < 0) fprint(2, "negative ref in drawfreedscreen\n"); if(this->ref > 0) return; ds = d->dscreen; if(ds == this){ d->dscreen = this->next; goto Found; } while(next = ds->next){ /* assign = */ if(next == this){ ds->next = this->next; goto Found; } ds = next; } /* BUG: error(Enodrawimage); */ return; Found: if(this->dimage) drawfreedimage(d, this->dimage); if(this->dfill) drawfreedimage(d, this->dfill); free(this->screen); free(this); } static void drawfreedimage(Draw *d, DImage *dimage) { int i; Memimage *l, *screenimage; DScreen *ds; dimage->ref--; if(dimage->ref < 0) fprint(2, "negative ref in drawfreedimage\n"); if(dimage->ref > 0)