Blame


1 76193d7c 2003-09-30 devnull #include <u.h>
2 76193d7c 2003-09-30 devnull #include <libc.h>
3 76193d7c 2003-09-30 devnull #include <draw.h>
4 76193d7c 2003-09-30 devnull
5 76193d7c 2003-09-30 devnull Display *display;
6 76193d7c 2003-09-30 devnull Font *font;
7 76193d7c 2003-09-30 devnull Image *screen;
8 76193d7c 2003-09-30 devnull int _drawdebug;
9 76193d7c 2003-09-30 devnull
10 76193d7c 2003-09-30 devnull static char deffontname[] = "*default*";
11 76193d7c 2003-09-30 devnull Screen *_screen;
12 76193d7c 2003-09-30 devnull
13 b20f06ab 2004-12-26 devnull int debuglockdisplay = 1;
14 74dc60da 2006-06-25 devnull char *winsize;
15 76193d7c 2003-09-30 devnull
16 abe4cd41 2005-07-27 devnull /*
17 76193d7c 2003-09-30 devnull static void
18 76193d7c 2003-09-30 devnull drawshutdown(void)
19 76193d7c 2003-09-30 devnull {
20 76193d7c 2003-09-30 devnull Display *d;
21 76193d7c 2003-09-30 devnull
22 76193d7c 2003-09-30 devnull d = display;
23 76193d7c 2003-09-30 devnull if(d){
24 76193d7c 2003-09-30 devnull display = nil;
25 76193d7c 2003-09-30 devnull closedisplay(d);
26 76193d7c 2003-09-30 devnull }
27 76193d7c 2003-09-30 devnull }
28 abe4cd41 2005-07-27 devnull */
29 76193d7c 2003-09-30 devnull
30 76193d7c 2003-09-30 devnull int
31 74dc60da 2006-06-25 devnull geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref)
32 76193d7c 2003-09-30 devnull {
33 76193d7c 2003-09-30 devnull Subfont *df;
34 76193d7c 2003-09-30 devnull char buf[128];
35 76193d7c 2003-09-30 devnull
36 74dc60da 2006-06-25 devnull if(label == nil)
37 74dc60da 2006-06-25 devnull label = argv0;
38 74dc60da 2006-06-25 devnull display = _initdisplay(error, label);
39 76193d7c 2003-09-30 devnull if(display == nil)
40 76193d7c 2003-09-30 devnull return -1;
41 76193d7c 2003-09-30 devnull
42 76193d7c 2003-09-30 devnull /*
43 76193d7c 2003-09-30 devnull * Set up default font
44 76193d7c 2003-09-30 devnull */
45 76193d7c 2003-09-30 devnull df = getdefont(display);
46 76193d7c 2003-09-30 devnull display->defaultsubfont = df;
47 76193d7c 2003-09-30 devnull if(df == nil){
48 76193d7c 2003-09-30 devnull fprint(2, "imageinit: can't open default subfont: %r\n");
49 76193d7c 2003-09-30 devnull Error:
50 76193d7c 2003-09-30 devnull closedisplay(display);
51 76193d7c 2003-09-30 devnull display = nil;
52 76193d7c 2003-09-30 devnull return -1;
53 76193d7c 2003-09-30 devnull }
54 76193d7c 2003-09-30 devnull if(fontname == nil)
55 74dc60da 2006-06-25 devnull fontname = getenv("font");
56 76193d7c 2003-09-30 devnull
57 76193d7c 2003-09-30 devnull /*
58 76193d7c 2003-09-30 devnull * Build fonts with caches==depth of screen, for speed.
59 76193d7c 2003-09-30 devnull * If conversion were faster, we'd use 0 and save memory.
60 76193d7c 2003-09-30 devnull */
61 76193d7c 2003-09-30 devnull if(fontname == nil){
62 76193d7c 2003-09-30 devnull snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
63 76193d7c 2003-09-30 devnull df->n-1, deffontname);
64 74dc60da 2006-06-25 devnull //BUG: Need something better for this installsubfont("*default*", df);
65 76193d7c 2003-09-30 devnull font = buildfont(display, buf, deffontname);
66 76193d7c 2003-09-30 devnull if(font == nil){
67 74dc60da 2006-06-25 devnull fprint(2, "imageinit: can't open default font: %r\n");
68 76193d7c 2003-09-30 devnull goto Error;
69 76193d7c 2003-09-30 devnull }
70 76193d7c 2003-09-30 devnull }else{
71 76193d7c 2003-09-30 devnull font = openfont(display, fontname); /* BUG: grey fonts */
72 76193d7c 2003-09-30 devnull if(font == nil){
73 74dc60da 2006-06-25 devnull fprint(2, "imageinit: can't open font %s: %r\n", fontname);
74 76193d7c 2003-09-30 devnull goto Error;
75 76193d7c 2003-09-30 devnull }
76 76193d7c 2003-09-30 devnull }
77 76193d7c 2003-09-30 devnull display->defaultfont = font;
78 76193d7c 2003-09-30 devnull
79 670dd11a 2005-03-18 devnull _screen = allocscreen(display->image, display->white, 0);
80 74dc60da 2006-06-25 devnull display->screenimage = display->image; /* _allocwindow wants screenimage->chan */
81 670dd11a 2005-03-18 devnull screen = _allocwindow(nil, _screen, display->image->r, Refnone, DWhite);
82 74dc60da 2006-06-25 devnull if(screen == nil){
83 74dc60da 2006-06-25 devnull fprint(2, "_allocwindow: %r\n");
84 74dc60da 2006-06-25 devnull goto Error;
85 74dc60da 2006-06-25 devnull }
86 670dd11a 2005-03-18 devnull display->screenimage = screen;
87 7ba8aa0c 2005-07-24 devnull draw(screen, screen->r, display->white, nil, ZP);
88 670dd11a 2005-03-18 devnull flushimage(display, 1);
89 670dd11a 2005-03-18 devnull
90 abe4cd41 2005-07-27 devnull /*
91 abe4cd41 2005-07-27 devnull * I don't see any reason to go away gracefully,
92 abe4cd41 2005-07-27 devnull * and if some other proc exits holding the display
93 abe4cd41 2005-07-27 devnull * lock, this atexit call never finishes.
94 abe4cd41 2005-07-27 devnull *
95 abe4cd41 2005-07-27 devnull * atexit(drawshutdown);
96 abe4cd41 2005-07-27 devnull */
97 76193d7c 2003-09-30 devnull return 1;
98 74dc60da 2006-06-25 devnull }
99 74dc60da 2006-06-25 devnull
100 74dc60da 2006-06-25 devnull int
101 74dc60da 2006-06-25 devnull initdraw(void (*error)(Display*, char*), char *fontname, char *label)
102 74dc60da 2006-06-25 devnull {
103 74dc60da 2006-06-25 devnull return geninitdraw("/dev", error, fontname, label, "/dev", Refnone);
104 74dc60da 2006-06-25 devnull }
105 74dc60da 2006-06-25 devnull
106 74dc60da 2006-06-25 devnull extern int _freeimage1(Image*);
107 74dc60da 2006-06-25 devnull
108 74dc60da 2006-06-25 devnull static Image*
109 74dc60da 2006-06-25 devnull getimage0(Display *d, Image *image)
110 74dc60da 2006-06-25 devnull {
111 74dc60da 2006-06-25 devnull char info[12*12+1];
112 74dc60da 2006-06-25 devnull uchar *a;
113 74dc60da 2006-06-25 devnull int n;
114 74dc60da 2006-06-25 devnull
115 74dc60da 2006-06-25 devnull /*
116 74dc60da 2006-06-25 devnull * If there's an old screen, it has id 0. The 'J' request below
117 74dc60da 2006-06-25 devnull * will try to install the new screen as id 0, so the old one
118 74dc60da 2006-06-25 devnull * must be freed first.
119 74dc60da 2006-06-25 devnull */
120 74dc60da 2006-06-25 devnull if(image){
121 74dc60da 2006-06-25 devnull _freeimage1(image);
122 74dc60da 2006-06-25 devnull memset(image, 0, sizeof(Image));
123 74dc60da 2006-06-25 devnull }
124 74dc60da 2006-06-25 devnull
125 74dc60da 2006-06-25 devnull a = bufimage(d, 2);
126 74dc60da 2006-06-25 devnull a[0] = 'J';
127 74dc60da 2006-06-25 devnull a[1] = 'I';
128 74dc60da 2006-06-25 devnull if(flushimage(d, 0) < 0){
129 74dc60da 2006-06-25 devnull fprint(2, "cannot read screen info: %r\n");
130 74dc60da 2006-06-25 devnull return nil;
131 74dc60da 2006-06-25 devnull }
132 74dc60da 2006-06-25 devnull
133 74dc60da 2006-06-25 devnull n = _displayrddraw(d, info, sizeof info);
134 74dc60da 2006-06-25 devnull if(n != 12*12){
135 74dc60da 2006-06-25 devnull fprint(2, "short screen info\n");
136 74dc60da 2006-06-25 devnull return nil;
137 74dc60da 2006-06-25 devnull }
138 74dc60da 2006-06-25 devnull
139 74dc60da 2006-06-25 devnull if(image == nil){
140 74dc60da 2006-06-25 devnull image = mallocz(sizeof(Image), 1);
141 74dc60da 2006-06-25 devnull if(image == nil){
142 74dc60da 2006-06-25 devnull fprint(2, "cannot allocate image: %r\n");
143 74dc60da 2006-06-25 devnull return nil;
144 74dc60da 2006-06-25 devnull }
145 74dc60da 2006-06-25 devnull }
146 74dc60da 2006-06-25 devnull
147 74dc60da 2006-06-25 devnull image->display = d;
148 74dc60da 2006-06-25 devnull image->id = 0;
149 74dc60da 2006-06-25 devnull image->chan = strtochan(info+2*12);
150 74dc60da 2006-06-25 devnull image->depth = chantodepth(image->chan);
151 74dc60da 2006-06-25 devnull image->repl = atoi(info+3*12);
152 74dc60da 2006-06-25 devnull image->r.min.x = atoi(info+4*12);
153 74dc60da 2006-06-25 devnull image->r.min.y = atoi(info+5*12);
154 74dc60da 2006-06-25 devnull image->r.max.x = atoi(info+6*12);
155 74dc60da 2006-06-25 devnull image->r.max.y = atoi(info+7*12);
156 74dc60da 2006-06-25 devnull image->clipr.min.x = atoi(info+8*12);
157 74dc60da 2006-06-25 devnull image->clipr.min.y = atoi(info+9*12);
158 74dc60da 2006-06-25 devnull image->clipr.max.x = atoi(info+10*12);
159 74dc60da 2006-06-25 devnull image->clipr.max.y = atoi(info+11*12);
160 74dc60da 2006-06-25 devnull return image;
161 74dc60da 2006-06-25 devnull }
162 74dc60da 2006-06-25 devnull
163 74dc60da 2006-06-25 devnull /*
164 74dc60da 2006-06-25 devnull * Attach, or possibly reattach, to window.
165 74dc60da 2006-06-25 devnull * If reattaching, maintain value of screen pointer.
166 74dc60da 2006-06-25 devnull */
167 74dc60da 2006-06-25 devnull int
168 74dc60da 2006-06-25 devnull getwindow(Display *d, int ref)
169 74dc60da 2006-06-25 devnull {
170 74dc60da 2006-06-25 devnull Image *i, *oi;
171 74dc60da 2006-06-25 devnull
172 74dc60da 2006-06-25 devnull /* XXX check for destroyed? */
173 74dc60da 2006-06-25 devnull
174 74dc60da 2006-06-25 devnull /*
175 74dc60da 2006-06-25 devnull * Libdraw promises not to change the value of "screen",
176 74dc60da 2006-06-25 devnull * so we have to reuse the image structure
177 74dc60da 2006-06-25 devnull * memory we already have.
178 74dc60da 2006-06-25 devnull */
179 74dc60da 2006-06-25 devnull oi = d->image;
180 74dc60da 2006-06-25 devnull i = getimage0(d, oi);
181 74dc60da 2006-06-25 devnull if(i == nil)
182 74dc60da 2006-06-25 devnull sysfatal("getwindow failed");
183 74dc60da 2006-06-25 devnull d->image = i;
184 74dc60da 2006-06-25 devnull /* fprint(2, "getwindow %p -> %p\n", oi, i); */
185 74dc60da 2006-06-25 devnull
186 74dc60da 2006-06-25 devnull freescreen(_screen);
187 74dc60da 2006-06-25 devnull _screen = allocscreen(i, d->white, 0);
188 74dc60da 2006-06-25 devnull _freeimage1(screen);
189 74dc60da 2006-06-25 devnull screen = _allocwindow(screen, _screen, i->r, ref, DWhite);
190 74dc60da 2006-06-25 devnull d->screenimage = screen;
191 74dc60da 2006-06-25 devnull return 0;
192 76193d7c 2003-09-30 devnull }
193 76193d7c 2003-09-30 devnull
194 74dc60da 2006-06-25 devnull Display*
195 74dc60da 2006-06-25 devnull _initdisplay(void (*error)(Display*, char*), char *label)
196 74dc60da 2006-06-25 devnull {
197 74dc60da 2006-06-25 devnull Display *disp;
198 74dc60da 2006-06-25 devnull Image *image;
199 74dc60da 2006-06-25 devnull
200 74dc60da 2006-06-25 devnull fmtinstall('P', Pfmt);
201 74dc60da 2006-06-25 devnull fmtinstall('R', Rfmt);
202 74dc60da 2006-06-25 devnull
203 74dc60da 2006-06-25 devnull disp = mallocz(sizeof(Display), 1);
204 74dc60da 2006-06-25 devnull if(disp == nil){
205 74dc60da 2006-06-25 devnull Error1:
206 74dc60da 2006-06-25 devnull return nil;
207 74dc60da 2006-06-25 devnull }
208 74dc60da 2006-06-25 devnull disp->srvfd = -1;
209 74dc60da 2006-06-25 devnull image = nil;
210 74dc60da 2006-06-25 devnull if(0){
211 74dc60da 2006-06-25 devnull Error2:
212 74dc60da 2006-06-25 devnull free(image);
213 74dc60da 2006-06-25 devnull free(disp);
214 74dc60da 2006-06-25 devnull goto Error1;
215 74dc60da 2006-06-25 devnull }
216 74dc60da 2006-06-25 devnull disp->bufsize = 65500;
217 74dc60da 2006-06-25 devnull disp->buf = malloc(disp->bufsize+5); /* +5 for flush message */
218 74dc60da 2006-06-25 devnull disp->bufp = disp->buf;
219 74dc60da 2006-06-25 devnull disp->error = error;
220 74dc60da 2006-06-25 devnull qlock(&disp->qlock);
221 74dc60da 2006-06-25 devnull
222 74dc60da 2006-06-25 devnull if(disp->buf == nil)
223 74dc60da 2006-06-25 devnull goto Error2;
224 74dc60da 2006-06-25 devnull if(0){
225 74dc60da 2006-06-25 devnull Error3:
226 74dc60da 2006-06-25 devnull free(disp->buf);
227 74dc60da 2006-06-25 devnull goto Error2;
228 74dc60da 2006-06-25 devnull }
229 74dc60da 2006-06-25 devnull
230 74dc60da 2006-06-25 devnull if(_displaymux(disp) < 0
231 74dc60da 2006-06-25 devnull || _displayconnect(disp) < 0
232 74dc60da 2006-06-25 devnull || _displayinit(disp, label, winsize) < 0)
233 74dc60da 2006-06-25 devnull goto Error3;
234 74dc60da 2006-06-25 devnull if(0){
235 74dc60da 2006-06-25 devnull Error4:
236 74dc60da 2006-06-25 devnull close(disp->srvfd);
237 74dc60da 2006-06-25 devnull goto Error3;
238 74dc60da 2006-06-25 devnull }
239 74dc60da 2006-06-25 devnull
240 74dc60da 2006-06-25 devnull image = getimage0(disp, nil);
241 74dc60da 2006-06-25 devnull if(image == nil)
242 74dc60da 2006-06-25 devnull goto Error4;
243 74dc60da 2006-06-25 devnull
244 74dc60da 2006-06-25 devnull disp->image = image;
245 74dc60da 2006-06-25 devnull disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);
246 74dc60da 2006-06-25 devnull disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);
247 74dc60da 2006-06-25 devnull if(disp->white == nil || disp->black == nil){
248 74dc60da 2006-06-25 devnull free(disp->white);
249 74dc60da 2006-06-25 devnull free(disp->black);
250 74dc60da 2006-06-25 devnull goto Error4;
251 74dc60da 2006-06-25 devnull }
252 74dc60da 2006-06-25 devnull
253 74dc60da 2006-06-25 devnull disp->opaque = disp->white;
254 74dc60da 2006-06-25 devnull disp->transparent = disp->black;
255 74dc60da 2006-06-25 devnull
256 74dc60da 2006-06-25 devnull return disp;
257 74dc60da 2006-06-25 devnull }
258 74dc60da 2006-06-25 devnull
259 76193d7c 2003-09-30 devnull /*
260 76193d7c 2003-09-30 devnull * Call with d unlocked.
261 76193d7c 2003-09-30 devnull * Note that disp->defaultfont and defaultsubfont are not freed here.
262 76193d7c 2003-09-30 devnull */
263 76193d7c 2003-09-30 devnull void
264 76193d7c 2003-09-30 devnull closedisplay(Display *disp)
265 76193d7c 2003-09-30 devnull {
266 76193d7c 2003-09-30 devnull int fd;
267 76193d7c 2003-09-30 devnull char buf[128];
268 76193d7c 2003-09-30 devnull
269 76193d7c 2003-09-30 devnull if(disp == nil)
270 76193d7c 2003-09-30 devnull return;
271 76193d7c 2003-09-30 devnull if(disp == display)
272 76193d7c 2003-09-30 devnull display = nil;
273 76193d7c 2003-09-30 devnull if(disp->oldlabel[0]){
274 76193d7c 2003-09-30 devnull snprint(buf, sizeof buf, "%s/label", disp->windir);
275 76193d7c 2003-09-30 devnull fd = open(buf, OWRITE);
276 76193d7c 2003-09-30 devnull if(fd >= 0){
277 76193d7c 2003-09-30 devnull write(fd, disp->oldlabel, strlen(disp->oldlabel));
278 76193d7c 2003-09-30 devnull close(fd);
279 76193d7c 2003-09-30 devnull }
280 76193d7c 2003-09-30 devnull }
281 76193d7c 2003-09-30 devnull
282 76193d7c 2003-09-30 devnull free(disp->devdir);
283 76193d7c 2003-09-30 devnull free(disp->windir);
284 297cded7 2005-12-29 devnull if(disp->white)
285 297cded7 2005-12-29 devnull freeimage(disp->white);
286 297cded7 2005-12-29 devnull if(disp->black)
287 297cded7 2005-12-29 devnull freeimage(disp->black);
288 74dc60da 2006-06-25 devnull if(disp->srvfd >= 0)
289 74dc60da 2006-06-25 devnull close(disp->srvfd);
290 76193d7c 2003-09-30 devnull free(disp);
291 76193d7c 2003-09-30 devnull }
292 76193d7c 2003-09-30 devnull
293 76193d7c 2003-09-30 devnull void
294 76193d7c 2003-09-30 devnull lockdisplay(Display *disp)
295 76193d7c 2003-09-30 devnull {
296 76193d7c 2003-09-30 devnull if(debuglockdisplay){
297 76193d7c 2003-09-30 devnull /* avoid busy looping; it's rare we collide anyway */
298 76193d7c 2003-09-30 devnull while(!canqlock(&disp->qlock)){
299 76193d7c 2003-09-30 devnull fprint(1, "proc %d waiting for display lock...\n", getpid());
300 76193d7c 2003-09-30 devnull sleep(1000);
301 76193d7c 2003-09-30 devnull }
302 76193d7c 2003-09-30 devnull }else
303 76193d7c 2003-09-30 devnull qlock(&disp->qlock);
304 76193d7c 2003-09-30 devnull }
305 76193d7c 2003-09-30 devnull
306 76193d7c 2003-09-30 devnull void
307 76193d7c 2003-09-30 devnull unlockdisplay(Display *disp)
308 76193d7c 2003-09-30 devnull {
309 76193d7c 2003-09-30 devnull qunlock(&disp->qlock);
310 76193d7c 2003-09-30 devnull }
311 76193d7c 2003-09-30 devnull
312 76193d7c 2003-09-30 devnull void
313 76193d7c 2003-09-30 devnull drawerror(Display *d, char *s)
314 76193d7c 2003-09-30 devnull {
315 76193d7c 2003-09-30 devnull char err[ERRMAX];
316 76193d7c 2003-09-30 devnull
317 76193d7c 2003-09-30 devnull if(d->error)
318 76193d7c 2003-09-30 devnull d->error(d, s);
319 76193d7c 2003-09-30 devnull else{
320 76193d7c 2003-09-30 devnull errstr(err, sizeof err);
321 76193d7c 2003-09-30 devnull fprint(2, "draw: %s: %s\n", s, err);
322 76193d7c 2003-09-30 devnull exits(s);
323 76193d7c 2003-09-30 devnull }
324 76193d7c 2003-09-30 devnull }
325 76193d7c 2003-09-30 devnull
326 76193d7c 2003-09-30 devnull static
327 76193d7c 2003-09-30 devnull int
328 76193d7c 2003-09-30 devnull doflush(Display *d)
329 76193d7c 2003-09-30 devnull {
330 76193d7c 2003-09-30 devnull int n;
331 76193d7c 2003-09-30 devnull
332 76193d7c 2003-09-30 devnull n = d->bufp-d->buf;
333 76193d7c 2003-09-30 devnull if(n <= 0)
334 76193d7c 2003-09-30 devnull return 1;
335 76193d7c 2003-09-30 devnull
336 74dc60da 2006-06-25 devnull if(_displaywrdraw(d, d->buf, n) != n){
337 76193d7c 2003-09-30 devnull if(_drawdebug)
338 76193d7c 2003-09-30 devnull fprint(2, "flushimage fail: d=%p: %r\n", d); /**/
339 76193d7c 2003-09-30 devnull d->bufp = d->buf; /* might as well; chance of continuing */
340 76193d7c 2003-09-30 devnull return -1;
341 76193d7c 2003-09-30 devnull }
342 76193d7c 2003-09-30 devnull d->bufp = d->buf;
343 76193d7c 2003-09-30 devnull return 1;
344 76193d7c 2003-09-30 devnull }
345 76193d7c 2003-09-30 devnull
346 76193d7c 2003-09-30 devnull int
347 76193d7c 2003-09-30 devnull flushimage(Display *d, int visible)
348 76193d7c 2003-09-30 devnull {
349 76193d7c 2003-09-30 devnull if(visible){
350 76193d7c 2003-09-30 devnull *d->bufp++ = 'v'; /* five bytes always reserved for this */
351 76193d7c 2003-09-30 devnull if(d->_isnewdisplay){
352 76193d7c 2003-09-30 devnull BPLONG(d->bufp, d->screenimage->id);
353 76193d7c 2003-09-30 devnull d->bufp += 4;
354 76193d7c 2003-09-30 devnull }
355 76193d7c 2003-09-30 devnull }
356 76193d7c 2003-09-30 devnull return doflush(d);
357 76193d7c 2003-09-30 devnull }
358 76193d7c 2003-09-30 devnull
359 76193d7c 2003-09-30 devnull uchar*
360 76193d7c 2003-09-30 devnull bufimage(Display *d, int n)
361 76193d7c 2003-09-30 devnull {
362 76193d7c 2003-09-30 devnull uchar *p;
363 76193d7c 2003-09-30 devnull
364 148f25d3 2005-11-07 devnull if(n<0 || d == nil || n>d->bufsize){
365 148f25d3 2005-11-07 devnull abort();
366 76193d7c 2003-09-30 devnull werrstr("bad count in bufimage");
367 76193d7c 2003-09-30 devnull return 0;
368 76193d7c 2003-09-30 devnull }
369 76193d7c 2003-09-30 devnull if(d->bufp+n > d->buf+d->bufsize)
370 76193d7c 2003-09-30 devnull if(doflush(d) < 0)
371 76193d7c 2003-09-30 devnull return 0;
372 76193d7c 2003-09-30 devnull p = d->bufp;
373 76193d7c 2003-09-30 devnull d->bufp += n;
374 76193d7c 2003-09-30 devnull return p;
375 76193d7c 2003-09-30 devnull }
376 76193d7c 2003-09-30 devnull