123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- #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)
- 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;
- }
|