#include <u.h>#include <libc.h>#include <draw.h> typedef struct Memimage Memimage; static int screenid; Screen*allocscreen(Image *image, Image *fill, int public){ uchar *a; Screen *s; int id, try; Display *d; d = image->display; if(d != fill->display){ werrstr("allocscreen: image and fill on different displays"); return 0; } s = malloc(sizeof(Screen)); if(s == 0) return 0; SET(id); for(try=0; try<25; try++){ /* loop until find a free id */ a = bufimage(d, 1+4+4+4+1); if(a == 0){ free(s); return 0; } id = ++screenid; a[0] = 'A'; BPLONG(a+1, id); BPLONG(a+5, image->id); BPLONG(a+9, fill->id); a[13] = public; if(flushimage(d, 0) != -1){ werrstr(""); break; } } s->display = d; s->id = id; s->image = image; assert(s->image && s->image->chan != 0); s->fill = fill; return s;} Screen*publicscreen(Display *d, int id, ulong chan){ uchar *a; Screen *s; s = malloc(sizeof(Screen)); if(s == 0) return 0; a = bufimage(d, 1+4+4); if(a == 0){ Error: free(s); return 0; } a[0] = 'S'; BPLONG(a+1, id); BPLONG(a+5, chan); if(flushimage(d, 0) < 0) goto Error; s->display = d; s->id = id; s->image = 0; s->fill = 0; return s;} intfreescreen(Screen *s){ uchar *a; Display *d; if(s == 0) return 0; d = s->display; a = bufimage(d, 1+4); if(a == 0) return -1; a[0] = 'F'; BPLONG(a+1, s->id); /* * flush(1) because screen is likely holding last reference to * window, and want it to disappear visually. */ if(flushimage(d, 1) < 0) return -1; free(s); return 1;} Image*allocwindow(Screen *s, Rectangle r, int ref, ulong val){ return _allocwindow(nil, s, r, ref, val);} Image*_allocwindow(Image *i, Screen *s, Rectangle r, int ref, ulong val){ Display *d; d = s->display; i = _allocimage(i, d, r, d->screenimage->chan, 0, val, s->id, ref); if(i == 0) return 0; i->screen = s; i->next = s->display->windows; s->display->windows = i; return i;} staticvoidtopbottom(Image **w, int n, int top){ int i; uchar *b; Display *d; if(n < 0){ Ridiculous: fprint(2, "top/bottom: ridiculous number of windows\n"); return; } if(n == 0) return; if(n > (w[0]->display->bufsize-100)/4) goto Ridiculous; /* * this used to check that all images were on the same screen. * we don't know the screen associated with images we acquired * by name. instead, check that all images are on the same display. * the display will check that they are all on the same screen. */ d = w[0]->display; for(i=1; i<n; i++) if(w[i]->display != d){ fprint(2, "top/bottom: windows not on same screen\n"); return; } if(n==0) return; b = bufimage(d, 1+1+2+4*n); b[0] = 't'; b[1] = top; BPSHORT(b+2, n); for(i=0; i<n; i++) BPLONG(b+4+4*i, w[i]->id);} voidbottomwindow(Image *w){ if(w->screen == 0) return; topbottom(&w, 1, 0);} voidtopwindow(Image *w){ if(w->screen == 0) return; topbottom(&w, 1, 1);} voidbottomnwindows(Image **w, int n){ topbottom(w, n, 0);} voidtopnwindows(Image **w, int n){ topbottom(w, n, 1);} intoriginwindow(Image *w, Point log, Point scr){ uchar *b; Point delta; flushimage(w->display, 0); b = bufimage(w->display, 1+4+2*4+2*4); if(b == nil) return 0; b[0] = 'o'; BPLONG(b+1, w->id); BPLONG(b+5, log.x); BPLONG(b+9, log.y); BPLONG(b+13, scr.x); BPLONG(b+17, scr.y); if(flushimage(w->display, 1) < 0) return -1; delta = subpt(log, w->r.min); w->r = rectaddpt(w->r, delta); w->clipr = rectaddpt(w->clipr, delta); return 1;}
#include <u.h>
#include <libc.h>
#include <draw.h>
typedef struct Memimage Memimage;
static int screenid;
Screen*
allocscreen(Image *image, Image *fill, int public)
{
uchar *a;
Screen *s;
int id, try;
Display *d;
d = image->display;
if(d != fill->display){
werrstr("allocscreen: image and fill on different displays");
return 0;
}
s = malloc(sizeof(Screen));
if(s == 0)
return 0;
SET(id);
for(try=0; try<25; try++){
/* loop until find a free id */
a = bufimage(d, 1+4+4+4+1);
if(a == 0){
free(s);
return 0;
}
id = ++screenid;
a[0] = 'A';
BPLONG(a+1, id);
BPLONG(a+5, image->id);
BPLONG(a+9, fill->id);
a[13] = public;
if(flushimage(d, 0) != -1){
werrstr("");
break;
}
}
s->display = d;
s->id = id;
s->image = image;
assert(s->image && s->image->chan != 0);
s->fill = fill;
return s;
}
Screen*
publicscreen(Display *d, int id, ulong chan)
{
uchar *a;
Screen *s;
s = malloc(sizeof(Screen));
if(s == 0)
return 0;
a = bufimage(d, 1+4+4);
if(a == 0){
Error:
free(s);
return 0;
}
a[0] = 'S';
BPLONG(a+1, id);
BPLONG(a+5, chan);
if(flushimage(d, 0) < 0)
goto Error;
s->display = d;
s->id = id;
s->image = 0;
s->fill = 0;
return s;
}
int
freescreen(Screen *s)
{
uchar *a;
Display *d;
if(s == 0)
return 0;
d = s->display;
a = bufimage(d, 1+4);
if(a == 0)
return -1;
a[0] = 'F';
BPLONG(a+1, s->id);
/*
* flush(1) because screen is likely holding last reference to
* window, and want it to disappear visually.
*/
if(flushimage(d, 1) < 0)
return -1;
free(s);
return 1;
}
Image*
allocwindow(Screen *s, Rectangle r, int ref, ulong val)
{
return _allocwindow(nil, s, r, ref, val);
}
Image*
_allocwindow(Image *i, Screen *s, Rectangle r, int ref, ulong val)
{
Display *d;
d = s->display;
i = _allocimage(i, d, r, d->screenimage->chan, 0, val, s->id, ref);
if(i == 0)
return 0;
i->screen = s;
i->next = s->display->windows;
s->display->windows = i;
return i;
}
static
void
topbottom(Image **w, int n, int top)
{
int i;
uchar *b;
Display *d;
if(n < 0){
Ridiculous:
fprint(2, "top/bottom: ridiculous number of windows\n");
return;
}
if(n == 0)
return;
if(n > (w[0]->display->bufsize-100)/4)
goto Ridiculous;
/*
* this used to check that all images were on the same screen.
* we don't know the screen associated with images we acquired
* by name. instead, check that all images are on the same display.
* the display will check that they are all on the same screen.
*/
d = w[0]->display;
for(i=1; i<n; i++)
if(w[i]->display != d){
fprint(2, "top/bottom: windows not on same screen\n");
return;
}
if(n==0)
return;
b = bufimage(d, 1+1+2+4*n);
b[0] = 't';
b[1] = top;
BPSHORT(b+2, n);
for(i=0; i<n; i++)
BPLONG(b+4+4*i, w[i]->id);
}
void
bottomwindow(Image *w)
{
if(w->screen == 0)
return;
topbottom(&w, 1, 0);
}
void
topwindow(Image *w)
{
if(w->screen == 0)
return;
topbottom(&w, 1, 1);
}
void
bottomnwindows(Image **w, int n)
{
topbottom(w, n, 0);
}
void
topnwindows(Image **w, int n)
{
topbottom(w, n, 1);
}
int
originwindow(Image *w, Point log, Point scr)
{
uchar *b;
Point delta;
flushimage(w->display, 0);
b = bufimage(w->display, 1+4+2*4+2*4);
if(b == nil)
return 0;
b[0] = 'o';
BPLONG(b+1, w->id);
BPLONG(b+5, log.x);
BPLONG(b+9, log.y);
BPLONG(b+13, scr.x);
BPLONG(b+17, scr.y);
if(flushimage(w->display, 1) < 0)
return -1;
delta = subpt(log, w->r.min);
w->r = rectaddpt(w->r, delta);
w->clipr = rectaddpt(w->clipr, delta);
return 1;
}