1 #include "lib9.h" 2 #include "draw.h" 3 #include "kernel.h" 4 5 typedef struct Memimage Memimage; 6 7 static int screenid; 8 9 Screen* 10 allocscreen(Image *image, Image *fill, int public) 11 { 12 uchar *a; 13 Screen *s; 14 int id, try; 15 Display *d; 16 17 d = image->display; 18 if(d != fill->display){ 19 kwerrstr("allocscreen: image and fill on different displays"); 20 return 0; 21 } 22 s = malloc(sizeof(Screen)); 23 if(s == 0) 24 return 0; 25 SET(id); 26 for(try=0; try<25; try++){ 27 /* loop until find a free id */ 28 a = bufimage(d, 1+4+4+4+1); 29 if(a == 0){ 30 free(s); 31 return 0; 32 } 33 id = ++screenid; 34 a[0] = 'A'; 35 BPLONG(a+1, id); 36 BPLONG(a+5, image->id); 37 BPLONG(a+9, fill->id); 38 a[13] = public; 39 if(flushimage(d, 0) != -1) 40 break; 41 } 42 s->display = d; 43 s->id = id; 44 s->image = image; 45 // assert(s->image && s->image->chan != 0); 46 47 s->fill = fill; 48 return s; 49 } 50 51 Screen* 52 publicscreen(Display *d, int id, ulong chan) 53 { 54 uchar *a; 55 Screen *s; 56 57 s = malloc(sizeof(Screen)); 58 if(s == 0) 59 return 0; 60 a = bufimage(d, 1+4+4); 61 if(a == 0){ 62 Error: 63 free(s); 64 return 0; 65 } 66 a[0] = 'S'; 67 BPLONG(a+1, id); 68 BPLONG(a+5, chan); 69 if(flushimage(d, 0) < 0) 70 goto Error; 71 72 s->display = d; 73 s->id = id; 74 s->image = 0; 75 s->fill = 0; 76 return s; 77 } 78 79 int 80 freescreen(Screen *s) 81 { 82 uchar *a; 83 Display *d; 84 85 if(s == 0) 86 return 0; 87 d = s->display; 88 a = bufimage(d, 1+4); 89 if(a == 0) 90 return -1; 91 a[0] = 'F'; 92 BPLONG(a+1, s->id); 93 /* 94 * flush(1) because screen is likely holding last reference to 95 * window, and want it to disappear visually. 96 */ 97 if(flushimage(d, 1) < 0) 98 return -1; 99 free(s); 100 return 1; 101 } 102 103 Image* 104 allocwindow(Screen *s, Rectangle r, int ref, ulong val) 105 { 106 return _allocwindow(nil, s, r, ref, val); 107 } 108 109 Image* 110 _allocwindow(Image *i, Screen *s, Rectangle r, int ref, ulong val) 111 { 112 Display *d; 113 114 d = s->display; 115 i = _allocimage(i, d, r, s->image->chan, 0, val, s->id, ref); 116 if(i == 0) 117 return 0; 118 i->screen = s; 119 i->next = s->display->windows; 120 s->display->windows = i; 121 return i; 122 } 123 124 static 125 void 126 topbottom(Image **w, int n, int top) 127 { 128 int i; 129 uchar *b; 130 Display *d; 131 132 if(n<0 || n>(Displaybufsize-100)/4){ 133 _drawprint(2, "top/bottom: ridiculous number of windows\n"); 134 return; 135 } 136 if(n==0) 137 return; 138 /* check that all images are on the same display; only it can check the screens */ 139 d = w[0]->display; 140 for(i=1; i<n; i++) 141 if(w[i]->display != d){ 142 _drawprint(2, "top/bottom: windows not on same display\n"); 143 return; 144 } 145 b = bufimage(d, 1+1+2+4*n); 146 if (b == 0) { 147 _drawprint(2, "top/bottom: no bufimage\n"); 148 return; 149 } 150 b[0] = 't'; 151 b[1] = top; 152 BPSHORT(b+2, n); 153 for(i=0; i<n; i++) 154 BPLONG(b+4+4*i, w[i]->id); 155 } 156 157 void 158 bottomwindow(Image *w) 159 { 160 topbottom(&w, 1, 0); 161 } 162 163 void 164 topwindow(Image *w) 165 { 166 topbottom(&w, 1, 1); 167 } 168 169 void 170 bottomnwindows(Image **w, int n) 171 { 172 topbottom(w, n, 0); 173 } 174 175 void 176 topnwindows(Image **w, int n) 177 { 178 topbottom(w, n, 1); 179 } 180 181 int 182 originwindow(Image *w, Point log, Point scr) 183 { 184 uchar *b; 185 Point delta; 186 187 flushimage(w->display, 0); 188 b = bufimage(w->display, 1+4+2*4+2*4); 189 if(b == nil) 190 return 0; 191 b[0] = 'o'; 192 BPLONG(b+1, w->id); 193 BPLONG(b+5, log.x); 194 BPLONG(b+9, log.y); 195 BPLONG(b+13, scr.x); 196 BPLONG(b+17, scr.y); 197 if(flushimage(w->display, 1) < 0) 198 return -1; 199 delta = subpt(log, w->r.min); 200 w->r = rectaddpt(w->r, delta); 201 w->clipr = rectaddpt(w->clipr, delta); 202 return 1; 203 } 204