xref: /plan9/sys/src/cmd/vnc/draw.c (revision 6bbfed0d85c6d7248503ef0614d0f1e40438b735)
19a747e4fSDavid du Colombier #include "vnc.h"
29a747e4fSDavid du Colombier #include "vncv.h"
39a747e4fSDavid du Colombier 
49a747e4fSDavid du Colombier static struct {
59a747e4fSDavid du Colombier 	char	*name;
69a747e4fSDavid du Colombier 	int	num;
79a747e4fSDavid du Colombier } enctab[] = {
89a747e4fSDavid du Colombier 	"copyrect",	EncCopyRect,
99a747e4fSDavid du Colombier 	"corre",	EncCorre,
109a747e4fSDavid du Colombier 	"hextile",	EncHextile,
119a747e4fSDavid du Colombier 	"raw",		EncRaw,
129a747e4fSDavid du Colombier 	"rre",		EncRre,
139a747e4fSDavid du Colombier 	"mousewarp",	EncMouseWarp,
149a747e4fSDavid du Colombier };
159a747e4fSDavid du Colombier 
169a747e4fSDavid du Colombier static	uchar	*pixbuf;
179a747e4fSDavid du Colombier static	uchar	*linebuf;
189a747e4fSDavid du Colombier static	int	vpixb;
199a747e4fSDavid du Colombier static	int	pixb;
209a747e4fSDavid du Colombier static	void	(*pixcp)(uchar*, uchar*);
219a747e4fSDavid du Colombier 
229a747e4fSDavid du Colombier static void
vncrdcolor(Vnc * v,uchar * color)239a747e4fSDavid du Colombier vncrdcolor(Vnc *v, uchar *color)
249a747e4fSDavid du Colombier {
259a747e4fSDavid du Colombier 	vncrdbytes(v, color, vpixb);
269a747e4fSDavid du Colombier 
279a747e4fSDavid du Colombier 	if(cvtpixels)
289a747e4fSDavid du Colombier 		(*cvtpixels)(color, color, 1);
299a747e4fSDavid du Colombier }
309a747e4fSDavid du Colombier 
319a747e4fSDavid du Colombier void
sendencodings(Vnc * v)329a747e4fSDavid du Colombier sendencodings(Vnc *v)
339a747e4fSDavid du Colombier {
349a747e4fSDavid du Colombier 	char *f[10];
359a747e4fSDavid du Colombier 	int enc[10], nenc, i, j, nf;
369a747e4fSDavid du Colombier 
379a747e4fSDavid du Colombier 	nf = tokenize(encodings, f, nelem(f));
389a747e4fSDavid du Colombier 	nenc = 0;
399a747e4fSDavid du Colombier 	for(i=0; i<nf; i++){
409a747e4fSDavid du Colombier 		for(j=0; j<nelem(enctab); j++)
419a747e4fSDavid du Colombier 			if(strcmp(f[i], enctab[j].name) == 0)
429a747e4fSDavid du Colombier 				break;
439a747e4fSDavid du Colombier 		if(j == nelem(enctab)){
449a747e4fSDavid du Colombier 			print("warning: unknown encoding %s\n", f[i]);
459a747e4fSDavid du Colombier 			continue;
469a747e4fSDavid du Colombier 		}
479a747e4fSDavid du Colombier 		enc[nenc++] = enctab[j].num;
489a747e4fSDavid du Colombier 	}
499a747e4fSDavid du Colombier 
509a747e4fSDavid du Colombier 	vnclock(v);
519a747e4fSDavid du Colombier 	vncwrchar(v, MSetEnc);
529a747e4fSDavid du Colombier 	vncwrchar(v, 0);
539a747e4fSDavid du Colombier 	vncwrshort(v, nenc);
549a747e4fSDavid du Colombier 	for(i=0; i<nenc; i++)
559a747e4fSDavid du Colombier 		vncwrlong(v, enc[i]);
569a747e4fSDavid du Colombier 	vncflush(v);
579a747e4fSDavid du Colombier 	vncunlock(v);
589a747e4fSDavid du Colombier }
599a747e4fSDavid du Colombier 
609a747e4fSDavid du Colombier void
requestupdate(Vnc * v,int incremental)619a747e4fSDavid du Colombier requestupdate(Vnc *v, int incremental)
629a747e4fSDavid du Colombier {
639a747e4fSDavid du Colombier 	int x, y;
649a747e4fSDavid du Colombier 
659a747e4fSDavid du Colombier 	lockdisplay(display);
669a747e4fSDavid du Colombier 	x = Dx(screen->r);
679a747e4fSDavid du Colombier 	y = Dy(screen->r);
689a747e4fSDavid du Colombier 	unlockdisplay(display);
699a747e4fSDavid du Colombier 	if(x > v->dim.x)
709a747e4fSDavid du Colombier 		x = v->dim.x;
719a747e4fSDavid du Colombier 	if(y > v->dim.y)
729a747e4fSDavid du Colombier 		y = v->dim.y;
739a747e4fSDavid du Colombier 	vnclock(v);
749a747e4fSDavid du Colombier 	vncwrchar(v, MFrameReq);
759a747e4fSDavid du Colombier 	vncwrchar(v, incremental);
769a747e4fSDavid du Colombier 	vncwrrect(v, Rpt(ZP, Pt(x, y)));
779a747e4fSDavid du Colombier 	vncflush(v);
789a747e4fSDavid du Colombier 	vncunlock(v);
799a747e4fSDavid du Colombier }
809a747e4fSDavid du Colombier 
819a747e4fSDavid du Colombier static Rectangle
clippixbuf(Rectangle r,int maxx,int maxy)829a747e4fSDavid du Colombier clippixbuf(Rectangle r, int maxx, int maxy)
839a747e4fSDavid du Colombier {
849a747e4fSDavid du Colombier 	int y, h, stride1, stride2;
859a747e4fSDavid du Colombier 
869a747e4fSDavid du Colombier 	if(r.min.x > maxx || r.min.y > maxy){
879a747e4fSDavid du Colombier 		r.max.x = 0;
889a747e4fSDavid du Colombier 		return r;
899a747e4fSDavid du Colombier 	}
909a747e4fSDavid du Colombier 	if(r.max.y > maxy)
919a747e4fSDavid du Colombier 		r.max.y = maxy;
929a747e4fSDavid du Colombier 	if(r.max.x <= maxx)
939a747e4fSDavid du Colombier 		return r;
949a747e4fSDavid du Colombier 
959a747e4fSDavid du Colombier 	stride2 = Dx(r) * pixb;
969a747e4fSDavid du Colombier 	r.max.x = maxx;
979a747e4fSDavid du Colombier 	stride1 = Dx(r) * pixb;
989a747e4fSDavid du Colombier 	h = Dy(r);
999a747e4fSDavid du Colombier 	for(y = 0; y < h; y++)
1009a747e4fSDavid du Colombier 		memmove(&pixbuf[y * stride1], &pixbuf[y * stride2], stride1);
1019a747e4fSDavid du Colombier 
1029a747e4fSDavid du Colombier 	return r;
1039a747e4fSDavid du Colombier }
1049a747e4fSDavid du Colombier 
1059a747e4fSDavid du Colombier /* must be called with display locked */
1069a747e4fSDavid du Colombier static void
updatescreen(Rectangle r)1079a747e4fSDavid du Colombier updatescreen(Rectangle r)
1089a747e4fSDavid du Colombier {
109*6bbfed0dSDavid du Colombier 	Image* img;
1109a747e4fSDavid du Colombier 	int b, bb;
1119a747e4fSDavid du Colombier 
1129a747e4fSDavid du Colombier 	lockdisplay(display);
1139a747e4fSDavid du Colombier 	if(r.max.x > Dx(screen->r) || r.max.y > Dy(screen->r)){
1149a747e4fSDavid du Colombier 		r = clippixbuf(r, Dx(screen->r), Dy(screen->r));
1159a747e4fSDavid du Colombier 		if(r.max.x == 0){
1169a747e4fSDavid du Colombier 			unlockdisplay(display);
1179a747e4fSDavid du Colombier 			return;
1189a747e4fSDavid du Colombier 		}
1199a747e4fSDavid du Colombier 	}
1209a747e4fSDavid du Colombier 
1219a747e4fSDavid du Colombier 	/*
1229a747e4fSDavid du Colombier 	 * assume load image fails only because of resize
1239a747e4fSDavid du Colombier 	 */
124*6bbfed0dSDavid du Colombier 	img = allocimage(display, r, screen->chan, 0, DNofill);
125*6bbfed0dSDavid du Colombier 	if(img == nil)
126*6bbfed0dSDavid du Colombier 		sysfatal("updatescreen: %r");
1279a747e4fSDavid du Colombier 	b = Dx(r) * pixb * Dy(r);
128*6bbfed0dSDavid du Colombier 	bb = loadimage(img, r, pixbuf, b);
1299a747e4fSDavid du Colombier 	if(bb != b && verbose)
1309a747e4fSDavid du Colombier 		fprint(2, "loadimage %d on %R for %R returned %d: %r\n", b, rectaddpt(r, screen->r.min), screen->r, bb);
131*6bbfed0dSDavid du Colombier 	draw(screen, rectaddpt(r, screen->r.min), img, nil, r.min);
132*6bbfed0dSDavid du Colombier 	freeimage(img);
1339a747e4fSDavid du Colombier 	unlockdisplay(display);
1349a747e4fSDavid du Colombier }
1359a747e4fSDavid du Colombier 
1369a747e4fSDavid du Colombier static void
fillrect(Rectangle r,int stride,uchar * color)1379a747e4fSDavid du Colombier fillrect(Rectangle r, int stride, uchar *color)
1389a747e4fSDavid du Colombier {
1399a747e4fSDavid du Colombier 	int x, xe, y, off;
1409a747e4fSDavid du Colombier 
1419a747e4fSDavid du Colombier 	y = r.min.y;
1429a747e4fSDavid du Colombier 	off = y * stride;
1439a747e4fSDavid du Colombier 	for(; y < r.max.y; y++){
1449a747e4fSDavid du Colombier 		xe = off + r.max.x * pixb;
1459a747e4fSDavid du Colombier 		for(x = off + r.min.x * pixb; x < xe; x += pixb)
1469a747e4fSDavid du Colombier 			(*pixcp)(&pixbuf[x], color);
1479a747e4fSDavid du Colombier 		off += stride;
1489a747e4fSDavid du Colombier 	}
1499a747e4fSDavid du Colombier }
1509a747e4fSDavid du Colombier 
1519a747e4fSDavid du Colombier static void
loadbuf(Vnc * v,Rectangle r,int stride)1529a747e4fSDavid du Colombier loadbuf(Vnc *v, Rectangle r, int stride)
1539a747e4fSDavid du Colombier {
1549a747e4fSDavid du Colombier 	int off, y;
1559a747e4fSDavid du Colombier 
1569a747e4fSDavid du Colombier 	if(cvtpixels){
1579a747e4fSDavid du Colombier 		y = r.min.y;
1589a747e4fSDavid du Colombier 		off = y * stride;
1599a747e4fSDavid du Colombier 		for(; y < r.max.y; y++){
1609a747e4fSDavid du Colombier 			vncrdbytes(v, linebuf, Dx(r) * vpixb);
1619a747e4fSDavid du Colombier 			(*cvtpixels)(&pixbuf[off + r.min.x * pixb], linebuf, Dx(r));
1629a747e4fSDavid du Colombier 			off += stride;
1639a747e4fSDavid du Colombier 		}
1649a747e4fSDavid du Colombier 	}else{
1659a747e4fSDavid du Colombier 		y = r.min.y;
1669a747e4fSDavid du Colombier 		off = y * stride;
1679a747e4fSDavid du Colombier 		for(; y < r.max.y; y++){
1689a747e4fSDavid du Colombier 			vncrdbytes(v, &pixbuf[off + r.min.x * pixb], Dx(r) * pixb);
1699a747e4fSDavid du Colombier 			off += stride;
1709a747e4fSDavid du Colombier 		}
1719a747e4fSDavid du Colombier 	}
1729a747e4fSDavid du Colombier }
1739a747e4fSDavid du Colombier 
1749a747e4fSDavid du Colombier static Rectangle
hexrect(ushort u)1759a747e4fSDavid du Colombier hexrect(ushort u)
1769a747e4fSDavid du Colombier {
1779a747e4fSDavid du Colombier 	int x, y, w, h;
1789a747e4fSDavid du Colombier 
1799a747e4fSDavid du Colombier 	x = u>>12;
1809a747e4fSDavid du Colombier 	y = (u>>8)&15;
1819a747e4fSDavid du Colombier 	w = ((u>>4)&15)+1;
1829a747e4fSDavid du Colombier 	h = (u&15)+1;
1839a747e4fSDavid du Colombier 
1849a747e4fSDavid du Colombier 	return Rect(x, y, x+w, y+h);
1859a747e4fSDavid du Colombier }
1869a747e4fSDavid du Colombier 
1879a747e4fSDavid du Colombier 
1889a747e4fSDavid du Colombier static void
dohextile(Vnc * v,Rectangle r,int stride)1899a747e4fSDavid du Colombier dohextile(Vnc *v, Rectangle r, int stride)
1909a747e4fSDavid du Colombier {
1919a747e4fSDavid du Colombier 	ulong bg, fg, c;
1929a747e4fSDavid du Colombier 	int enc, nsub, sx, sy, w, h, th, tw;
1939a747e4fSDavid du Colombier 	Rectangle sr, ssr;
1949a747e4fSDavid du Colombier 
1959a747e4fSDavid du Colombier 	fg = bg = 0;
1969a747e4fSDavid du Colombier 	h = Dy(r);
1979a747e4fSDavid du Colombier 	w = Dx(r);
1989a747e4fSDavid du Colombier 	for(sy = 0; sy < h; sy += HextileDim){
1999a747e4fSDavid du Colombier 		th = h - sy;
2009a747e4fSDavid du Colombier 		if(th > HextileDim)
2019a747e4fSDavid du Colombier 			th = HextileDim;
2029a747e4fSDavid du Colombier 		for(sx = 0; sx < w; sx += HextileDim){
2039a747e4fSDavid du Colombier 			tw = w - sx;
2049a747e4fSDavid du Colombier 			if(tw > HextileDim)
2059a747e4fSDavid du Colombier 				tw = HextileDim;
2069a747e4fSDavid du Colombier 
2079a747e4fSDavid du Colombier 			sr = Rect(sx, sy, sx + tw, sy + th);
2089a747e4fSDavid du Colombier 			enc = vncrdchar(v);
2099a747e4fSDavid du Colombier 			if(enc & HextileRaw){
2109a747e4fSDavid du Colombier 				loadbuf(v, sr, stride);
2119a747e4fSDavid du Colombier 				continue;
2129a747e4fSDavid du Colombier 			}
2139a747e4fSDavid du Colombier 
2149a747e4fSDavid du Colombier 			if(enc & HextileBack)
2159a747e4fSDavid du Colombier 				vncrdcolor(v, (uchar*)&bg);
2169a747e4fSDavid du Colombier 			fillrect(sr, stride, (uchar*)&bg);
2179a747e4fSDavid du Colombier 
2189a747e4fSDavid du Colombier 			if(enc & HextileFore)
2199a747e4fSDavid du Colombier 				vncrdcolor(v, (uchar*)&fg);
2209a747e4fSDavid du Colombier 
2219a747e4fSDavid du Colombier 			if(enc & HextileRects){
2229a747e4fSDavid du Colombier 				nsub = vncrdchar(v);
2239a747e4fSDavid du Colombier 				(*pixcp)((uchar*)&c, (uchar*)&fg);
2249a747e4fSDavid du Colombier 				while(nsub-- > 0){
2259a747e4fSDavid du Colombier 					if(enc & HextileCols)
2269a747e4fSDavid du Colombier 						vncrdcolor(v, (uchar*)&c);
2279a747e4fSDavid du Colombier 					ssr = rectaddpt(hexrect(vncrdshort(v)), sr.min);
2289a747e4fSDavid du Colombier 					fillrect(ssr, stride, (uchar*)&c);
2299a747e4fSDavid du Colombier 				}
2309a747e4fSDavid du Colombier 			}
2319a747e4fSDavid du Colombier 		}
2329a747e4fSDavid du Colombier 	}
2339a747e4fSDavid du Colombier }
2349a747e4fSDavid du Colombier 
2359a747e4fSDavid du Colombier static void
dorectangle(Vnc * v)2369a747e4fSDavid du Colombier dorectangle(Vnc *v)
2379a747e4fSDavid du Colombier {
2389a747e4fSDavid du Colombier 	ulong type;
2399a747e4fSDavid du Colombier 	long n, stride;
2409a747e4fSDavid du Colombier 	ulong color;
2419a747e4fSDavid du Colombier 	Point p;
2429a747e4fSDavid du Colombier 	Rectangle r, subr, maxr;
2439a747e4fSDavid du Colombier 
2449a747e4fSDavid du Colombier 	r = vncrdrect(v);
245e42359ddSDavid du Colombier 	if(r.min.x == r.max.x || r.min.y == r.max.y)
246e42359ddSDavid du Colombier 		return;
247e42359ddSDavid du Colombier 	if(!rectinrect(r, Rpt(ZP, v->dim)))
2489a747e4fSDavid du Colombier 		sysfatal("bad rectangle from server: %R not in %R", r, Rpt(ZP, v->dim));
2499a747e4fSDavid du Colombier 	stride = Dx(r) * pixb;
2509a747e4fSDavid du Colombier 	type = vncrdlong(v);
2519a747e4fSDavid du Colombier 	switch(type){
2529a747e4fSDavid du Colombier 	default:
2539a747e4fSDavid du Colombier 		sysfatal("bad rectangle encoding from server");
2549a747e4fSDavid du Colombier 		break;
2559a747e4fSDavid du Colombier 	case EncRaw:
2569a747e4fSDavid du Colombier 		loadbuf(v, Rpt(ZP, Pt(Dx(r), Dy(r))), stride);
2579a747e4fSDavid du Colombier 		updatescreen(r);
2589a747e4fSDavid du Colombier 		break;
2599a747e4fSDavid du Colombier 
2609a747e4fSDavid du Colombier 	case EncCopyRect:
2619a747e4fSDavid du Colombier 		p = vncrdpoint(v);
2629a747e4fSDavid du Colombier 		lockdisplay(display);
2639a747e4fSDavid du Colombier 		p = addpt(p, screen->r.min);
2649a747e4fSDavid du Colombier 		r = rectaddpt(r, screen->r.min);
2659a747e4fSDavid du Colombier 		draw(screen, r, screen, nil, p);
2669a747e4fSDavid du Colombier 		unlockdisplay(display);
2679a747e4fSDavid du Colombier 		break;
2689a747e4fSDavid du Colombier 
2699a747e4fSDavid du Colombier 	case EncRre:
2709a747e4fSDavid du Colombier 	case EncCorre:
2719a747e4fSDavid du Colombier 		maxr = Rpt(ZP, Pt(Dx(r), Dy(r)));
2729a747e4fSDavid du Colombier 		n = vncrdlong(v);
2739a747e4fSDavid du Colombier 		vncrdcolor(v, (uchar*)&color);
2749a747e4fSDavid du Colombier 		fillrect(maxr, stride, (uchar*)&color);
2759a747e4fSDavid du Colombier 		while(n-- > 0){
2769a747e4fSDavid du Colombier 			vncrdcolor(v, (uchar*)&color);
2779a747e4fSDavid du Colombier 			if(type == EncRre)
2789a747e4fSDavid du Colombier 				subr = vncrdrect(v);
2799a747e4fSDavid du Colombier 			else
2809a747e4fSDavid du Colombier 				subr = vncrdcorect(v);
2819a747e4fSDavid du Colombier 			if(!rectinrect(subr, maxr))
2829a747e4fSDavid du Colombier 				sysfatal("bad encoding from server");
2839a747e4fSDavid du Colombier 			fillrect(subr, stride, (uchar*)&color);
2849a747e4fSDavid du Colombier 		}
2859a747e4fSDavid du Colombier 		updatescreen(r);
2869a747e4fSDavid du Colombier 		break;
2879a747e4fSDavid du Colombier 
2889a747e4fSDavid du Colombier 	case EncHextile:
2899a747e4fSDavid du Colombier 		dohextile(v, r, stride);
2909a747e4fSDavid du Colombier 		updatescreen(r);
2919a747e4fSDavid du Colombier 		break;
292d9306527SDavid du Colombier 
2939a747e4fSDavid du Colombier 	case EncMouseWarp:
2949a747e4fSDavid du Colombier 		mousewarp(r.min);
2959a747e4fSDavid du Colombier 		break;
2969a747e4fSDavid du Colombier 	}
2979a747e4fSDavid du Colombier }
2989a747e4fSDavid du Colombier 
2999a747e4fSDavid du Colombier static void
pixcp8(uchar * dst,uchar * src)3009a747e4fSDavid du Colombier pixcp8(uchar *dst, uchar *src)
3019a747e4fSDavid du Colombier {
3029a747e4fSDavid du Colombier 	*dst = *src;
3039a747e4fSDavid du Colombier }
3049a747e4fSDavid du Colombier 
3059a747e4fSDavid du Colombier static void
pixcp16(uchar * dst,uchar * src)3069a747e4fSDavid du Colombier pixcp16(uchar *dst, uchar *src)
3079a747e4fSDavid du Colombier {
3089a747e4fSDavid du Colombier 	*(ushort*)dst = *(ushort*)src;
3099a747e4fSDavid du Colombier }
3109a747e4fSDavid du Colombier 
3119a747e4fSDavid du Colombier static void
pixcp32(uchar * dst,uchar * src)3129a747e4fSDavid du Colombier pixcp32(uchar *dst, uchar *src)
3139a747e4fSDavid du Colombier {
3149a747e4fSDavid du Colombier 	*(ulong*)dst = *(ulong*)src;
3159a747e4fSDavid du Colombier }
3169a747e4fSDavid du Colombier 
3179a747e4fSDavid du Colombier static void
pixcp24(uchar * dst,uchar * src)3189a747e4fSDavid du Colombier pixcp24(uchar *dst, uchar *src)
3199a747e4fSDavid du Colombier {
3209a747e4fSDavid du Colombier 	dst[0] = src[0];
3219a747e4fSDavid du Colombier 	dst[1] = src[1];
3229a747e4fSDavid du Colombier 	dst[2] = src[2];
3239a747e4fSDavid du Colombier }
3249a747e4fSDavid du Colombier 
3259a747e4fSDavid du Colombier static int
calcpixb(int bpp)3269a747e4fSDavid du Colombier calcpixb(int bpp)
3279a747e4fSDavid du Colombier {
3289a747e4fSDavid du Colombier 	if(bpp / 8 * 8 != bpp)
3299a747e4fSDavid du Colombier 		sysfatal("can't handle your screen");
3309a747e4fSDavid du Colombier 	return bpp / 8;
3319a747e4fSDavid du Colombier }
3329a747e4fSDavid du Colombier 
3339a747e4fSDavid du Colombier void
readfromserver(Vnc * v)3349a747e4fSDavid du Colombier readfromserver(Vnc *v)
3359a747e4fSDavid du Colombier {
3369a747e4fSDavid du Colombier 	uchar type;
3379a747e4fSDavid du Colombier 	uchar junk[100];
3389a747e4fSDavid du Colombier 	long n;
3399a747e4fSDavid du Colombier 
3409a747e4fSDavid du Colombier 	vpixb = calcpixb(v->bpp);
3419a747e4fSDavid du Colombier 	pixb = calcpixb(screen->depth);
3429a747e4fSDavid du Colombier 	switch(pixb){
343d9306527SDavid du Colombier 	case 1:
344d9306527SDavid du Colombier 		pixcp = pixcp8;
345d9306527SDavid du Colombier 		break;
346d9306527SDavid du Colombier 	case 2:
347d9306527SDavid du Colombier 		pixcp = pixcp16;
348d9306527SDavid du Colombier 		break;
349d9306527SDavid du Colombier 	case 3:
350d9306527SDavid du Colombier 		pixcp = pixcp24;
351d9306527SDavid du Colombier 		break;
352d9306527SDavid du Colombier 	case 4:
353d9306527SDavid du Colombier 		pixcp = pixcp32;
354d9306527SDavid du Colombier 		break;
3559a747e4fSDavid du Colombier 	default:
356d9306527SDavid du Colombier 		sysfatal("can't handle your screen: bad depth %d", pixb);
3579a747e4fSDavid du Colombier 	}
3589a747e4fSDavid du Colombier 	linebuf = malloc(v->dim.x * vpixb);
3599a747e4fSDavid du Colombier 	pixbuf = malloc(v->dim.x * pixb * v->dim.y);
3609a747e4fSDavid du Colombier 	if(linebuf == nil || pixbuf == nil)
3619a747e4fSDavid du Colombier 		sysfatal("can't allocate pix decompression storage");
3629a747e4fSDavid du Colombier 	for(;;){
3639a747e4fSDavid du Colombier 		type = vncrdchar(v);
3649a747e4fSDavid du Colombier 		switch(type){
3659a747e4fSDavid du Colombier 		default:
3669a747e4fSDavid du Colombier 			sysfatal("bad message from server");
3679a747e4fSDavid du Colombier 			break;
3689a747e4fSDavid du Colombier 		case MFrameUpdate:
3699a747e4fSDavid du Colombier 			vncrdchar(v);
3709a747e4fSDavid du Colombier 			n = vncrdshort(v);
3719a747e4fSDavid du Colombier 			while(n-- > 0)
3729a747e4fSDavid du Colombier 				dorectangle(v);
3739a747e4fSDavid du Colombier 			flushimage(display, 1);
3749a747e4fSDavid du Colombier 			requestupdate(v, 1);
3759a747e4fSDavid du Colombier 			break;
3769a747e4fSDavid du Colombier 
3779a747e4fSDavid du Colombier 		case MSetCmap:
3789a747e4fSDavid du Colombier 			vncrdbytes(v, junk, 3);
3799a747e4fSDavid du Colombier 			n = vncrdshort(v);
3809a747e4fSDavid du Colombier 			vncgobble(v, n*3*2);
3819a747e4fSDavid du Colombier 			break;
3829a747e4fSDavid du Colombier 
3839a747e4fSDavid du Colombier 		case MBell:
384f8e525acSDavid du Colombier 			break;
385f8e525acSDavid du Colombier 
386f8e525acSDavid du Colombier 		case MSAck:
3879a747e4fSDavid du Colombier 			break;
3889a747e4fSDavid du Colombier 
3899a747e4fSDavid du Colombier 		case MSCut:
3909a747e4fSDavid du Colombier 			vncrdbytes(v, junk, 3);
3919a747e4fSDavid du Colombier 			n = vncrdlong(v);
3929a747e4fSDavid du Colombier 			writesnarf(v, n);
3939a747e4fSDavid du Colombier 			break;
3949a747e4fSDavid du Colombier 		}
3959a747e4fSDavid du Colombier 	}
3969a747e4fSDavid du Colombier }
397