]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vnc/screen.c
devdraw: simplify drawgen()
[plan9front.git] / sys / src / cmd / vnc / screen.c
1 #include        <u.h>
2 #include        <libc.h>
3 #include        "compat.h"
4 #include        "kbd.h"
5 #include        "error.h"
6
7 #define Image   IMAGE
8 #include        <draw.h>
9 #include        <memdraw.h>
10 #include        <cursor.h>
11 #include        "screen.h"
12
13 enum
14 {
15         CURSORDIM = 16
16 };
17
18 Memimage        *gscreen;
19 Point           ZP;
20 int             cursorver;
21 Point           cursorpos;
22
23 static Memimage         *back;
24 static Memimage         *conscol;
25 static Memimage         *curscol;
26 static Point            curpos;
27 static Memsubfont       *memdefont;
28 static Rectangle        flushr;
29 static Rectangle        window;
30 static int              h;
31 static int              w;
32
33 static Rectangle        cursorr;
34 static Point            offscreen;
35 static uchar            cursset[CURSORDIM*CURSORDIM/8];
36 static uchar            cursclr[CURSORDIM*CURSORDIM/8];
37 static int              cursdrawvers = -1;
38 static Memimage         *cursorset;
39 static Memimage         *cursorclear;
40 static Cursor           screencursor;
41
42 void
43 screeninit(int x, int y, char *chanstr)
44 {
45         char buf[128];
46         Rectangle r;
47         int chan;
48
49         cursorver = 0;
50
51         memimageinit();
52         chan = strtochan(chanstr);
53         if(chan == 0)
54                 error("bad screen channel string");
55
56         r = Rect(0, 0, x, y);
57         gscreen = allocmemimage(r, chan);
58         if(gscreen == nil){
59                 snprint(buf, sizeof buf, "can't allocate screen image: %r");
60                 error(buf);
61         }
62
63         offscreen = Pt(x + 100, y + 100);
64         cursorr = Rect(0, 0, CURSORDIM, CURSORDIM);
65         cursorset = allocmemimage(cursorr, GREY8);
66         cursorclear = allocmemimage(cursorr, GREY1);
67         if(cursorset == nil || cursorclear == nil){
68                 freememimage(gscreen);
69                 freememimage(cursorset);
70                 freememimage(cursorclear);
71                 gscreen = nil;
72                 cursorset = nil;
73                 cursorclear = nil;
74                 snprint(buf, sizeof buf, "can't allocate cursor images: %r");
75                 error(buf);
76         }
77
78         /* a lot of work to get a grey color */
79         curscol = allocmemimage(Rect(0,0,1,1), RGBA32);
80         curscol->flags |= Frepl;
81         curscol->clipr = gscreen->r;
82         memfillcolor(curscol, 0xff0000ff);
83
84         screenwin();
85
86         setcursor(&arrow);
87 }
88
89 void
90 screenwin(void)
91 {
92         Point p;
93         char *greet;
94         Memimage *grey;
95
96         qlock(&drawlock);
97         back = memwhite;
98         conscol = memblack;
99         memfillcolor(gscreen, 0x888844FF);
100         
101         memdefont = getmemdefont();
102         h = memdefont->height;
103
104         window = insetrect(gscreen->clipr, 20);
105         memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S);
106         window = insetrect(window, 4);
107         memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
108
109         /* a lot of work to get a grey color */
110         grey = allocmemimage(Rect(0,0,1,1), CMAP8);
111         grey->flags |= Frepl;
112         grey->clipr = gscreen->r;
113         memfillcolor(grey, 0xAAAAAAFF);
114         memimagedraw(gscreen, Rect(window.min.x, window.min.y,
115                         window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S);
116         freememimage(grey);
117         window = insetrect(window, 5);
118
119         greet = " Plan 9 Console ";
120         p = addpt(window.min, Pt(10, 0));
121         memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
122         window.min.y += h+6;
123         curpos = window.min;
124         window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
125         flushmemscreen(gscreen->r);
126         qunlock(&drawlock);
127 }
128
129 uchar*
130 attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
131 {
132         *r = gscreen->clipr;
133         *d = gscreen->depth;
134         *chan = gscreen->chan;
135         *width = gscreen->width;
136         *softscreen = 1;
137
138         return gscreen->data->bdata;
139 }
140
141 void
142 getcolor(ulong , ulong* pr, ulong* pg, ulong* pb)
143 {
144         *pr = 0;
145         *pg = 0;
146         *pb = 0;
147 }
148
149 int
150 setcolor(ulong , ulong , ulong , ulong )
151 {
152         return 0;
153 }
154
155 /*
156  * called with cursor unlocked, drawlock locked
157  */
158 void
159 cursordraw(Memimage *dst, Rectangle r)
160 {
161         static uchar set[CURSORDIM*CURSORDIM], clr[CURSORDIM*CURSORDIM/8];
162         static int ver = -1;
163         int i, j, n;
164
165         lock(&cursor);
166         if(ver != cursorver){
167                 n = 0;
168                 for(i = 0; i < CURSORDIM*CURSORDIM/8; i += CURSORDIM/8){
169                         for(j = 0; j < CURSORDIM; j++){
170                                 if(cursset[i + (j >> 3)] & (1 << (7 - (j & 7))))
171                                         set[n] = 0xaa;
172                                 else
173                                         set[n] = 0;
174                                 n++;
175                         }
176                 }
177                 memmove(clr, cursclr, CURSORDIM*CURSORDIM/8);
178                 ver = cursorver;
179                 unlock(&cursor);
180                 loadmemimage(cursorset, cursorr, set, CURSORDIM*CURSORDIM);
181                 loadmemimage(cursorclear, cursorr, clr, CURSORDIM*CURSORDIM/8);
182         }else
183                 unlock(&cursor);
184         memimagedraw(dst, r, memwhite, ZP, cursorclear, ZP, SoverD);
185         memimagedraw(dst, r, curscol, ZP, cursorset, ZP, SoverD);
186 }
187
188 /*
189  * called with cursor locked, drawlock possibly unlocked
190  */
191 Rectangle
192 cursorrect(void)
193 {
194         Rectangle r;
195
196         r.min.x = cursorpos.x + cursor.offset.x;
197         r.min.y = cursorpos.y + cursor.offset.y;
198         r.max.x = r.min.x + CURSORDIM;
199         r.max.y = r.min.y + CURSORDIM;
200         return r;
201 }
202
203 /*
204  * called with cursor locked, drawlock possibly unlocked
205  */
206 void
207 setcursor(Cursor* curs)
208 {
209         cursorver++;
210         memmove(cursset, curs->set, CURSORDIM*CURSORDIM/8);
211         memmove(cursclr, curs->clr, CURSORDIM*CURSORDIM/8);
212 }
213
214 void
215 cursoron(void)
216 {
217         cursorpos = mousexy();
218 }
219
220 void
221 cursoroff(void)
222 {
223         cursorpos = offscreen;
224 }
225
226 void
227 blankscreen(int blank)
228 {
229         USED(blank);
230 }
231
232 static void
233 screenflush(void)
234 {
235         flushmemscreen(flushr);
236         flushr = Rect(10000, 10000, -10000, -10000);
237 }
238
239 static void
240 addflush(Rectangle r)
241 {
242         if(flushr.min.x >= flushr.max.x)
243                 flushr = r;
244         else
245                 combinerect(&flushr, r);
246 }
247
248 static void
249 scroll(void)
250 {
251         int o;
252         Point p;
253         Rectangle r;
254
255         o = 8*h;
256         r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
257         p = Pt(window.min.x, window.min.y+o);
258         memimagedraw(gscreen, r, gscreen, p, nil, p, S);
259         r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
260         memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
261         flushmemscreen(gscreen->clipr);
262
263         curpos.y -= o;
264 }
265
266 static void
267 screenputc(char *buf)
268 {
269         Point p;
270         int w, pos;
271         Rectangle r;
272         static int *xp;
273         static int xbuf[256];
274
275         if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
276                 xp = xbuf;
277
278         switch(buf[0]){
279         case '\n':
280                 if(curpos.y+h >= window.max.y)
281                         scroll();
282                 curpos.y += h;
283                 screenputc("\r");
284                 break;
285         case '\r':
286                 xp = xbuf;
287                 curpos.x = window.min.x;
288                 break;
289         case '\t':
290                 p = memsubfontwidth(memdefont, " ");
291                 w = p.x;
292                 *xp++ = curpos.x;
293                 pos = (curpos.x-window.min.x)/w;
294                 pos = 8-(pos%8);
295                 r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
296                 memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
297                 addflush(r);
298                 curpos.x += pos*w;
299                 break;
300         case '\b':
301                 if(xp <= xbuf)
302                         break;
303                 xp--;
304                 r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
305                 memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
306                 addflush(r);
307                 curpos.x = *xp;
308                 break;
309         case '\0':
310                 break;
311         default:
312                 p = memsubfontwidth(memdefont, buf);
313                 w = p.x;
314
315                 if(curpos.x >= window.max.x-w)
316                         screenputc("\n");
317
318                 *xp++ = curpos.x;
319                 r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
320                 memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
321                 memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
322                 addflush(r);
323                 curpos.x += w;
324         }
325 }
326
327 void
328 screenputs(char *s, int n)
329 {
330         static char rb[UTFmax+1];
331         static int nrb;
332         char *e;
333
334         qlock(&drawlock);
335         e = s + n;
336         while(s < e){
337                 rb[nrb++] = *s++;
338                 if(nrb >= UTFmax || fullrune(rb, nrb)){
339                         rb[nrb] = 0;
340                         screenputc(rb);
341                         nrb = 0;
342                 }
343         }
344         screenflush();
345         qunlock(&drawlock);
346 }