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