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