1 /*
2    rdesktop: A Remote Desktop Protocol client.
3    User interface services - VNC target
4    Copyright (C) Matthew Chapman 1999-2000
5    Copyright (C) 2000 Tim Edmonds
6    Copyright (C) 2001 James "Wez" Weatherall
7    Copyright (C) 2001 Johannes E. Schindelin
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License along
20    with this program; if not, write to the Free Software Foundation, Inc.,
21    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23 
24 
25 #include <stdio.h>
26 #include <time.h>
27 
28 #ifdef WIN32
29 #define close closesocket
30 #define strcasecmp _strcmpi
31 #else
32 #include <unistd.h>
33 #include <sys/time.h>		/* timeval */
34 #include <sys/socket.h>
35 #endif
36 
37 #include "../rdesktop.h"
38 #undef VERSION
39 
40 #ifdef WIN32
41 #define HBITMAP R_HBITMAP
42 #define HCURSOR R_HCURSOR
43 #define WORD R_WORD
44 #endif
45 #include "vnc.h"
46 #ifdef WIN32
47 #undef HBITMAP
48 #undef HCURSOR
49 #undef WORD
50 #endif
51 
52 #include <errno.h>
53 #include <sys/socket.h>
54 extern int ListenOnTCPPort(int port);
55 extern int rfbClientSocket;
56 
57 #include <rfb/rfbregion.h>
58 
59 #define BITSPERBYTES 8
60 #define TOBYTES(bits) ((bits)/BITSPERBYTES)
61 
62 extern int g_width;
63 extern int g_height;
64 extern int keylayout;
65 extern BOOL sendmotion;
66 #ifdef ENABLE_SHADOW
67 extern int client_counter;
68 #endif
69 
70 
71 int rfb_port = 5923;
72 int defer_time = 5;
73 int rfbClientSocket = 0;
74 static rfbScreenInfoPtr server = NULL;
75 static vncBuffer *frameBuffer = NULL;
76 static uint8_t reverseByte[0x100];
77 BOOL g_enable_compose = False;
78 int g_display = 0;
79 
80 /* ignored */
81 BOOL owncolmap = False;
82 BOOL enable_compose = False;
83 
84 void
vncHideCursor()85 vncHideCursor()
86 {
87 	if (server->clientHead)
88 		rfbUndrawCursor(server);
89 }
90 
91 /* -=- mouseLookup
92  * Table converting mouse button number (0-2) to flag
93  */
94 
95 int mouseLookup[3] = {
96 	MOUSE_FLAG_BUTTON1, MOUSE_FLAG_BUTTON3, MOUSE_FLAG_BUTTON2
97 };
98 
99 int clipX, clipY, clipW, clipH;
100 
101 BOOL
vncwinClipRect(int * x,int * y,int * cx,int * cy)102 vncwinClipRect(int *x, int *y, int *cx, int *cy)
103 {
104 	if (*x + *cx > clipX + clipW)
105 		*cx = clipX + clipW - *x;
106 	if (*y + *cy > clipY + clipH)
107 		*cy = clipY + clipH - *y;
108 	if (*x < clipX)
109 	{
110 		*cx -= clipX - *x;
111 		*x = clipX;
112 	}
113 	if (*y < clipY)
114 	{
115 		*cy -= clipY - *y;
116 		*y = clipY;
117 	}
118 	if (*cx < 0 || *cy < 0)
119 		*cx = *cy = 0;
120 	return (*cx > 0 && *cy > 0 && *x < server->width && *y < server->height);
121 }
122 
123 void
xwin_toggle_fullscreen(void)124 xwin_toggle_fullscreen(void)
125 {
126 }
127 
128 static int lastbuttons = 0;
129 
130 #define FIRST_MODIFIER XK_Shift_L
131 #define LAST_MODIFIER XK_Hyper_R
132 
133 static BOOL keystate[LAST_MODIFIER - FIRST_MODIFIER];
134 
135 void
init_keyboard()136 init_keyboard()
137 {
138 	int i;
139 	for (i = 0; i < LAST_MODIFIER - FIRST_MODIFIER; i++)
140 		keystate[i] = 0;
141 
142 	xkeymap_init();
143 }
144 
145 BOOL
get_key_state(unsigned int state,uint32 keysym)146 get_key_state(unsigned int state, uint32 keysym)
147 {
148 	if (keysym >= FIRST_MODIFIER && keysym <= LAST_MODIFIER)
149 		return keystate[keysym - FIRST_MODIFIER];
150 	return 0;
151 }
152 
153 void
vncKey(rfbBool down,rfbKeySym keysym,struct _rfbClientRec * cl)154 vncKey(rfbBool down, rfbKeySym keysym, struct _rfbClientRec *cl)
155 {
156 	uint32 ev_time = time(NULL);
157 	key_translation tr = { 0, 0 };
158 
159 	if (keysym >= FIRST_MODIFIER && keysym <= LAST_MODIFIER)
160 	{
161 		/* TODO: fake local state */
162 		keystate[keysym - FIRST_MODIFIER] = down;
163 	}
164 
165 	if (down)
166 	{
167 		/* TODO: fake local state */
168 		if (handle_special_keys(keysym, 0, ev_time, True))
169 			return;
170 
171 		/* TODO: fake local state */
172 		tr = xkeymap_translate_key(keysym, 0, 0);
173 
174 		if (tr.scancode == 0)
175 			return;
176 
177 		ensure_remote_modifiers(ev_time, tr);
178 
179 		rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
180 	}
181 	else
182 	{
183 		/* todO: fake local state */
184 		if (handle_special_keys(keysym, 0, ev_time, False))
185 			return;
186 
187 		/* todO: fake local state */
188 		tr = xkeymap_translate_key(keysym, 0, 0);
189 
190 		if (tr.scancode == 0)
191 			return;
192 
193 		rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
194 	}
195 }
196 
197 void
vncMouse(int buttonMask,int x,int y,struct _rfbClientRec * cl)198 vncMouse(int buttonMask, int x, int y, struct _rfbClientRec *cl)
199 {
200 	int b;
201 	uint32 ev_time = time(NULL);
202 
203 	rdp_send_input(ev_time, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, x, y);
204 
205 	for (b = 0; b < 3; b++)
206 	{
207 		int bb = 1 << (b);
208 		if (!(lastbuttons & bb) && (buttonMask & bb))
209 		{
210 			rdp_send_input(ev_time, RDP_INPUT_MOUSE,
211 				       (mouseLookup[b]) | MOUSE_FLAG_DOWN, x, y);
212 		}
213 		else if ((lastbuttons & bb) && !(buttonMask & bb))
214 		{
215 			rdp_send_input(ev_time, RDP_INPUT_MOUSE, (mouseLookup[b]), x, y);
216 		}
217 	}
218 	lastbuttons = buttonMask;
219 
220 	/* handle cursor */
221 	rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
222 }
223 
224 
225 void
rdp2vnc_connect(char * server,uint32 flags,char * domain,char * password,char * shell,char * directory)226 rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
227 		char *shell, char *directory)
228 {
229 	struct sockaddr addr;
230 	fd_set fdset;
231 	struct timeval tv;
232 	int rfbListenSock, addrlen = sizeof(addr);
233 
234 	rfbListenSock = rfbListenOnTCPPort(rfb_port);
235 	fprintf(stderr, "Listening on VNC port %d\n", rfb_port);
236 	if (rfbListenSock <= 0)
237 		error("Cannot listen on port %d", rfb_port);
238 	else
239 		while (1)
240 		{
241 			FD_ZERO(&fdset);
242 			FD_SET(rfbListenSock, &fdset);
243 			tv.tv_sec = 5;
244 			tv.tv_usec = 0;
245 			if (select(rfbListenSock + 1, &fdset, NULL, NULL, &tv) > 0)
246 			{
247 				rfbClientSocket = accept(rfbListenSock, &addr, &addrlen);
248 				if (rfbClientSocket < 0)
249 				{
250 					error("Error accepting client (%d: %s.\n",
251 					      errno, strerror(errno));
252 					continue;
253 				}
254 				ui_create_window();
255 				if (!rdp_connect(server, flags, domain, password, shell, directory))
256 				{
257 					error("Error connecting to RDP server.\n");
258 					continue;
259 				}
260 				if (!fork())
261 				{
262 					BOOL deactivated;
263 					uint32_t ext_disc_reason;
264 					printf("Connection successful.\n");
265 					rdp_main_loop(&deactivated, &ext_disc_reason);
266 					printf("Disconnecting...\n");
267 					rdp_disconnect();
268 					ui_destroy_window();
269 					exit(0);
270 				}
271 			}
272 		}
273 }
274 
275 
276 
277 
278 
279 extern char g_title[];
280 BOOL
ui_create_window()281 ui_create_window()
282 {
283 	int i;
284 
285 	for (i = 0; i < 0x100; i++)
286 		reverseByte[i] =
287 			(((i >> 7) & 1)) | (((i >> 6) & 1) << 1) | (((i >> 5) & 1) << 2) |
288 			(((i >> 4) & 1) << 3) | (((i >> 3) & 1) << 4) | (((i >> 2) & 1) << 5) |
289 			(((i >> 1) & 1) << 6) | (((i >> 0) & 1) << 7);
290 
291 	server = rfbGetScreen(0, NULL, g_width, g_height, 8, 1, 1);
292 	server->desktopName = g_title;
293 	server->frameBuffer = (char *) malloc(g_width * g_height);
294 	server->ptrAddEvent = vncMouse;
295 	server->kbdAddEvent = vncKey;
296 #ifdef ENABLE_SHADOW
297 	server->httpPort = 6124 + client_counter;
298 	server->port = 5924 + client_counter;
299 	rfbInitSockets(server);
300 	server->alwaysShared = TRUE;
301 	server->neverShared = FALSE;
302 #else
303 	server->port = -1;
304 	server->alwaysShared = FALSE;
305 	server->neverShared = FALSE;
306 #endif
307 	server->inetdSock = rfbClientSocket;
308 	server->serverFormat.trueColour = FALSE;	/* activate colour maps */
309 	server->deferUpdateTime = defer_time;
310 
311 	frameBuffer = (vncBuffer *) malloc(sizeof(vncBuffer));
312 	frameBuffer->w = g_width;
313 	frameBuffer->h = g_height;
314 	frameBuffer->linew = g_width;
315 	frameBuffer->data = server->frameBuffer;
316 	frameBuffer->owner = FALSE;
317 	frameBuffer->format = &server->serverFormat;
318 
319 	ui_set_clip(0, 0, g_width, g_height);
320 
321 	rfbInitServer(server);
322 #ifndef ENABLE_SHADOW
323 	server->port = rfb_port;
324 #else
325 	fprintf(stderr, "server listening on port %d (socket %d)\n", server->port,
326 		server->listenSock);
327 #endif
328 
329 	init_keyboard();
330 
331 	return (server != NULL);
332 }
333 
334 void
ui_destroy_window()335 ui_destroy_window()
336 {
337 	rfbCloseClient(server->clientHead);
338 }
339 
340 
341 int
ui_select(int rdpSocket)342 ui_select(int rdpSocket)
343 {
344 	fd_set fds;
345 	struct timeval tv;
346 	int n, m = server->maxFd;
347 
348 	if (rdpSocket > m)
349 		m = rdpSocket;
350 	while (1)
351 	{
352 		fds = server->allFds;
353 		FD_SET(rdpSocket, &fds);
354 		tv.tv_sec = defer_time / 1000;
355 		tv.tv_usec = (defer_time % 1000) * 1000;
356 		n = select(m + 1, &fds, NULL, NULL, &tv);
357 		rfbProcessEvents(server, 0);
358 		/* if client is gone, close connection */
359 		if (!server->clientHead)
360 			close(rdpSocket);
361 		if (FD_ISSET(rdpSocket, &fds))
362 			return 1;
363 	}
364 	return 0;
365 }
366 
367 void
ui_move_pointer(int x,int y)368 ui_move_pointer(int x, int y)
369 {
370 	// TODO: Is there a way to send x,y even if cursor encoding is active?
371 	rfbUndrawCursor(server);
372 	server->cursorX = x;
373 	server->cursorY = y;
374 }
375 
376 HBITMAP
ui_create_bitmap(int width,int height,uint8 * data)377 ui_create_bitmap(int width, int height, uint8 * data)
378 {
379 	vncBuffer *buf;
380 
381 	buf = vncNewBuffer(width, height, 8);
382 	memcpy(buf->data, data, width * height);
383 
384 	return (HBITMAP) buf;
385 }
386 
387 void
ui_paint_bitmap(int x,int y,int cx,int cy,int width,int height,uint8 * data)388 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
389 {
390 	vncBuffer *buf;
391 	buf = ui_create_bitmap(width, height, data);
392 	vncCopyBlitFrom(server, x, y, cx, cy, buf, 0, 0);
393 	vncDeleteBuffer(buf);
394 }
395 
396 void
ui_destroy_bitmap(HBITMAP bmp)397 ui_destroy_bitmap(HBITMAP bmp)
398 {
399 	vncDeleteBuffer((vncBuffer *) bmp);
400 }
401 
402 uint8_t
vncLookupColour(rfbColourMap * colourMap,uint8_t * p)403 vncLookupColour(rfbColourMap * colourMap, uint8_t * p)
404 {
405 	uint8_t i, i1 = 0;
406 	uint8_t *cm = colourMap->data.bytes;
407 	uint32_t m, m1 = abs(cm[0] - p[0]) + abs(cm[1] - p[1]) + abs(cm[2] - p[2]);
408 	for (i = 1; i < 255; i++)
409 	{
410 		m = abs(cm[i * 3] - p[0]) + abs(cm[i * 3 + 1] - p[1]) + abs(cm[i * 3 + 2] - p[2]);
411 		if (m < m1)
412 		{
413 			m1 = m;
414 			i1 = i;
415 		}
416 	}
417 	return (i1);
418 }
419 
420 HCURSOR
ui_create_cursor(unsigned int x,unsigned int y,int width,int height,uint8 * mask,uint8 * data)421 ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * mask, uint8 * data)
422 {
423 	int i, j;
424 	uint8_t *d0, *d1;
425 	uint8_t *cdata;
426 	uint8_t white[3] = { 0xff, 0xff, 0xff };
427 	uint8_t black[3] = { 0, 0, 0 };
428 	uint8_t *cur;
429 	rfbCursorPtr cursor;
430 	rfbColourMap *colourMap = &server->colourMap;
431 
432 	cdata = xmalloc(sizeof(uint8_t) * width * height);
433 	d0 = xmalloc(sizeof(uint32_t) * width * height / 4);
434 	d1 = (uint8_t *) mask;
435 	for (j = 0; j < height; j++)
436 		for (i = 0; i < width / 8; i++)
437 		{
438 			d0[j * width / 8 + i] = d1[(height - 1 - j) * width / 8 + i] ^ 0xffffffff;
439 		}
440 	for (j = 0; j < height; j++)
441 	{
442 		for (i = 0; i < width; i++)
443 		{
444 			//strange that the pointer is in 24bit depth when everything
445 			//else is in 8bit palletized.
446 			cur = data + ((height - 1 - j) * width + i) * 3;
447 			if (cur[0] > 0x80 || cur[1] > 0x80 || cur[2] > 0x80)
448 			{
449 				if (!(d0[(j * width + i) / 8] & (0x80 >> (i & 7))))
450 				{
451 					/* text cursor! */
452 					cdata[j * width + i] = vncLookupColour(colourMap, black);
453 					d0[(j * width + i) / 8] |= 0x80 >> (i & 7);
454 				}
455 				else
456 					cdata[j * width + i] = vncLookupColour(colourMap, white);
457 			}
458 			else
459 				cdata[j * width + i] = vncLookupColour(colourMap, cur);
460 		}
461 	}
462 	cursor = (rfbCursorPtr) xmalloc(sizeof(rfbCursor));
463 	cursor->width = width;
464 	cursor->height = height;
465 	cursor->xhot = x;
466 	cursor->yhot = y;
467 	cursor->mask = (char *) d0;
468 	cursor->source = 0;
469 	cursor->richSource = cdata;
470 	cursor->cleanup = 0;	// workaround: this produces a memleak
471 
472 	cursor->backRed = cursor->backGreen = cursor->backBlue = 0xffff;
473 	cursor->foreRed = cursor->foreGreen = cursor->foreBlue = 0;
474 
475 	return (HCURSOR) cursor;
476 }
477 
478 void
ui_set_cursor(HCURSOR cursor)479 ui_set_cursor(HCURSOR cursor)
480 {
481 	/* FALSE means: don't delete old cursor */
482 	rfbSetCursor(server, (rfbCursorPtr) cursor, FALSE);
483 }
484 
485 void
ui_destroy_cursor(HCURSOR cursor)486 ui_destroy_cursor(HCURSOR cursor)
487 {
488 	if (cursor)
489 		rfbFreeCursor((rfbCursorPtr) cursor);
490 }
491 
492 void
ui_set_null_cursor(void)493 ui_set_null_cursor(void)
494 {
495 	rfbSetCursor(server, 0, FALSE);
496 }
497 
498 HGLYPH
ui_create_glyph(int width,int height,uint8 * data)499 ui_create_glyph(int width, int height, uint8 * data)
500 {
501 	int x, y;
502 	vncBuffer *buf;
503 
504 	buf = vncNewBuffer(width, height, 8);
505 
506 	//data is padded to multiple of 16bit line lengths
507 	for (y = 0; y < height; y++)
508 	{
509 		for (x = 0; x < width; x++)
510 		{
511 			int byte = x / 8 + (y * ((width + 7) / 8));
512 			byte = rfbEndianTest ? reverseByte[data[byte]] : data[byte];
513 			byte = (byte >> (x & 7)) & 0x01;
514 			vncSetPixel(buf, x, y, byte ? 0x7f : 0x00);
515 		}
516 	}
517 
518 	return (HGLYPH) buf;
519 }
520 
521 void
ui_destroy_glyph(HGLYPH glyph)522 ui_destroy_glyph(HGLYPH glyph)
523 {
524 	ui_destroy_bitmap((HBITMAP) glyph);
525 }
526 
527 HCOLOURMAP
ui_create_colourmap(COLOURMAP * colours)528 ui_create_colourmap(COLOURMAP * colours)
529 {
530 	int i;
531 	rfbColourMap *map = vncNewColourMap(server, colours->ncolours);
532 	for (i = 0; i < colours->ncolours; i++)
533 	{
534 		vncSetColourMapEntry(map, i, colours->colours[i].red,
535 				     colours->colours[i].green, colours->colours[i].blue);
536 	}
537 	return map;
538 }
539 
540 void
ui_destroy_colourmap(HCOLOURMAP map)541 ui_destroy_colourmap(HCOLOURMAP map)
542 {
543 	vncDeleteColourMap(map);
544 }
545 
546 void
ui_set_colourmap(HCOLOURMAP map)547 ui_set_colourmap(HCOLOURMAP map)
548 {
549 	vncSetColourMap(server, map);
550 }
551 
552 void
ui_set_clip(int x,int y,int cx,int cy)553 ui_set_clip(int x, int y, int cx, int cy)
554 {
555 	clipX = x;
556 	clipY = y;
557 	clipW = cx;
558 	clipH = cy;
559 }
560 
561 void
ui_reset_clip()562 ui_reset_clip()
563 {
564 	clipX = 0;
565 	clipY = 0;
566 	clipW = 64000;
567 	clipH = 64000;
568 }
569 
570 void
ui_bell()571 ui_bell()
572 {
573 	rfbSendBell(server);
574 }
575 
576 void
ui_destblt(uint8 opcode,int x,int y,int cx,int cy)577 ui_destblt(uint8 opcode,
578 	   /* dest */ int x, int y, int cx, int cy)
579 {
580 	int i;
581 	vncBuffer *buf;
582 
583 	switch (opcode)
584 	{
585 		case 0:
586 		case 15:
587 			ui_rect(x, y, cx, cy, 0xff);
588 			break;
589 		case 5:	// invert
590 			buf = vncGetRect(server, x, y, cx, cy);
591 			for (i = 0; i < cx * cy; i++)
592 				((char *) (buf->data))[i] = !((char *) (buf->data))[i];
593 			break;
594 		default:
595 			unimpl("ui_destblt: opcode=%d %d,%d %dx%d\n", opcode, x, y, cx, cy);
596 	}
597 }
598 
599 void
ui_patblt(uint8 opcode,int x,int y,int cx,int cy,BRUSH * brush,int bgcolour,int fgcolour)600 ui_patblt(uint8 opcode,
601 	  /* dest */ int x, int y, int cx, int cy,
602 	  /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
603 {
604 	switch (brush->style)
605 	{
606 		case 0:	/* Solid */
607 			switch (opcode)
608 			{
609 				case ROP2_XOR:
610 					{
611 						int xx, yy;
612 						vncBuffer *fill = vncNewBuffer(cx, cy, 8);
613 						for (yy = 0; yy < cy; yy++)
614 							for (xx = 0; xx < cx; xx++)
615 								vncSetPixel(fill, xx, yy, fgcolour);
616 						if (vncwinClipRect(&x, &y, &cx, &cy))
617 							vncXorBlitFrom(server, x, y, cx, cy, fill,
618 								       0, 0);
619 						break;
620 					}
621 
622 				default:
623 					if (vncwinClipRect(&x, &y, &cx, &cy))
624 						vncSetRect(server, x, y, cx, cy, fgcolour);
625 			}
626 			break;
627 
628 		case 3:	/* Pattern */
629 			{
630 				int xx, yy;
631 				vncBuffer *fill;
632 				fill = (vncBuffer *) ui_create_glyph(8, 8, brush->pattern);
633 
634 				for (yy = 0; yy < 8; yy++)
635 				{
636 					for (xx = 0; xx < 8; xx++)
637 					{
638 						vncSetPixel(fill, xx, yy,
639 							    vncGetPixel(fill, xx,
640 									yy) ? fgcolour : bgcolour);
641 					}
642 				}
643 
644 				if (vncwinClipRect(&x, &y, &cx, &cy))
645 				{
646 					switch (opcode)
647 					{
648 						case ROP2_COPY:
649 							vncCopyBlitFrom(server, x, y, cx, cy, fill,
650 									0, 0);
651 							break;
652 						case ROP2_XOR:
653 							vncXorBlitFrom(server, x, y, cx, cy, fill,
654 								       0, 0);
655 							break;
656 						default:
657 							unimpl("pattern blit (%d,%d) opcode=%d bg=%d fg=%d\n", x, y, opcode, bgcolour, fgcolour);
658 							vncCopyBlitFrom(server, x, y, cx, cy, fill,
659 									0, 0);
660 							break;
661 					}
662 				}
663 
664 				ui_destroy_glyph((HGLYPH) fill);
665 				break;
666 
667 			}
668 		default:
669 			unimpl("brush %d\n", brush->style);
670 	}
671 }
672 
673 void
ui_screenblt(uint8 opcode,int x,int y,int cx,int cy,int srcx,int srcy)674 ui_screenblt(uint8 opcode,
675 	     /* dest */ int x, int y, int cx, int cy,
676 	     /* src */ int srcx, int srcy)
677 {
678 	int ox, oy;
679 
680 	ox = x;
681 	oy = y;
682 	if (vncwinClipRect(&x, &y, &cx, &cy))
683 	{
684 		//if we clipped top or left, we have to adjust srcx,srcy;
685 		srcx += x - ox;
686 		srcy += y - oy;
687 		vncCopyBlit(server, x, y, cx, cy, srcx, srcy);
688 	}
689 }
690 
691 void
ui_memblt(uint8 opcode,int x,int y,int cx,int cy,HBITMAP src,int srcx,int srcy)692 ui_memblt(uint8 opcode,
693 	  /* dest */ int x, int y, int cx, int cy,
694 	  /* src */ HBITMAP src, int srcx, int srcy)
695 {
696 	int ox, oy;
697 	ox = x;
698 	oy = y;
699 
700 	if (vncwinClipRect(&x, &y, &cx, &cy))
701 	{
702 		//if we clipped top or left, we have to adjust srcx,srcy;
703 		srcx += x - ox;
704 		srcy += y - oy;
705 		switch (ROP2_S(opcode))
706 		{
707 			case ROP2_OR:
708 				vncTransBlitFrom(server, x, y, cx, cy, (vncBuffer *) src, srcx,
709 						 srcy, 0x0);
710 				break;
711 			case ROP2_XOR:
712 				vncXorBlitFrom(server, x, y, cx, cy, (vncBuffer *) src, srcx, srcy);
713 				break;
714 			case ROP2_AND:
715 				vncAndBlitFrom(server, x, y, cx, cy, (vncBuffer *) src, srcx, srcy);
716 				break;
717 			case ROP2_COPY:
718 				vncCopyBlitFrom(server, x, y, cx, cy, (vncBuffer *) src, srcx,
719 						srcy);
720 				break;
721 			default:
722 				unimpl("ui_memblt: op%d %d,%d %dx%d\n", opcode, x, y, cx, cy);
723 				vncCopyBlitFrom(server, x, y, cx, cy, (vncBuffer *) src, srcx,
724 						srcy);
725 				break;
726 		}
727 	}
728 }
729 
730 void
ui_triblt(uint8 opcode,int x,int y,int cx,int cy,HBITMAP src,int srcx,int srcy,BRUSH * brush,int bgcolour,int fgcolour)731 ui_triblt(uint8 opcode,
732 	  /* dest */ int x, int y, int cx, int cy,
733 	  /* src */ HBITMAP src, int srcx, int srcy,
734 	  /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
735 {
736 	/* This is potentially difficult to do in general. Until someone
737 	   comes up with a more efficient way of doing it I am using cases. */
738 
739 	switch (opcode)
740 	{
741 		case 0x69:	/* PDSxxn */
742 			ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
743 			ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
744 			break;
745 
746 		case 0xb8:	/* PSDPxax */
747 			ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
748 			ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
749 			ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
750 			break;
751 
752 		default:
753 			unimpl("ui_triblt 1x%x\n", opcode);
754 			ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
755 	}
756 
757 }
758 
759 void
ui_line(uint8 opcode,int startx,int starty,int endx,int endy,PEN * pen)760 ui_line(uint8 opcode,
761 	/* dest */ int startx, int starty, int endx, int endy,
762 	/* pen */ PEN * pen)
763 {
764 	//vncSetRect(server,startx,starty,1+endx-startx,endy-starty,pen->colour);
765 	//unimpl("drawline: pen colour=%d\n",pen->colour);
766 	/* TODO: implement opcodes */
767 	rfbDrawLine(server, startx, starty, endx, endy, pen->colour);
768 }
769 
770 void
ui_rect(int x,int y,int cx,int cy,int colour)771 ui_rect(
772 	       /* dest */ int x, int y, int cx, int cy,
773 	       /* brush */ int colour)
774 {
775 	if (vncwinClipRect(&x, &y, &cx, &cy))
776 	{
777 		vncSetRect(server, x, y, cx, cy, colour);
778 	}
779 }
780 
781 void
ui_draw_glyph(int mixmode,int x,int y,int cx,int cy,HGLYPH glyph,int srcx,int srcy,int bgcolour,int fgcolour)782 ui_draw_glyph(int mixmode,
783 	      /* dest */ int x, int y, int cx, int cy,
784 	      /* src */ HGLYPH glyph, int srcx, int srcy,
785 	      /* colours */ int bgcolour, int fgcolour)
786 {
787 	int xx, yy;
788 	int ox, oy;
789 	vncBuffer *buf = vncDupBuffer(glyph);
790 
791 	x &= 0xffff;
792 	y &= 0xffff;
793 
794 	/* yes, sometimes same fgcolour and bgcolour are sent, but because
795 	 * of transparency, we have to change that! */
796 	if (mixmode == MIX_TRANSPARENT && fgcolour == bgcolour)
797 		bgcolour = fgcolour ^ 0xff;
798 
799 	ox = x;
800 	oy = y;
801 
802 	for (yy = srcy; yy < srcy + cy; yy++)
803 	{
804 		for (xx = srcx; xx < srcx + cx; xx++)
805 		{
806 			vncSetPixel(buf, xx, yy, vncGetPixel(buf, xx, yy) ? fgcolour : bgcolour);
807 		}
808 	}
809 
810 	switch (mixmode)
811 	{
812 		case MIX_TRANSPARENT:
813 			if (vncwinClipRect(&x, &y, &cx, &cy))
814 			{
815 				//if we clipped top or left, we have to adjust srcx,srcy;
816 				srcx += x - ox;
817 				srcy += y - oy;
818 				vncTransBlitFrom(server, x, y, cx, cy, buf, srcx, srcy, bgcolour);
819 			}
820 			break;
821 		case MIX_OPAQUE:
822 			if (vncwinClipRect(&x, &y, &cx, &cy))
823 			{
824 				//if we clipped top or left, we have to adjust srcx,srcy;
825 				srcx += x - ox;
826 				srcy += y - oy;
827 				vncCopyBlitFrom(server, x, y, cx, cy, buf, srcx, srcy);
828 			}
829 			break;
830 
831 		default:
832 			unimpl("mix %d\n", mixmode);
833 	}
834 	vncDeleteBuffer(buf);
835 }
836 
837 #define DO_GLYPH(ttext,idx) \
838 {\
839   glyph = cache_get_font (font, ttext[idx]);\
840   if (!(flags & TEXT2_IMPLICIT_X))\
841     {\
842       offset = ttext[++idx];\
843       if ((offset & 0x80))\
844         offset = ((offset & 0x7f) << 8) | ttext[++idx];\
845       if (flags & TEXT2_VERTICAL)\
846             y += offset;\
847           else\
848             x += offset;\
849     }\
850   if (glyph != NULL)\
851     {\
852       ui_draw_glyph (mixmode, x + (short) glyph->offset,\
853                      y + (short) glyph->baseline,\
854                      glyph->width, glyph->height,\
855                      glyph->pixmap, 0, 0, bgcolour, fgcolour);\
856       if (flags & TEXT2_IMPLICIT_X)\
857         x += glyph->width;\
858     }\
859 }
860 
861 
862 void
ui_draw_text(uint8 font,uint8 flags,int mixmode,int x,int y,int clipx,int clipy,int clipcx,int clipcy,int boxx,int boxy,int boxcx,int boxcy,int bgcolour,int fgcolour,uint8 * text,uint8 length)863 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
864 	     int clipx, int clipy, int clipcx, int clipcy,
865 	     int boxx, int boxy, int boxcx, int boxcy,
866 	     int bgcolour, int fgcolour, uint8 * text, uint8 length)
867 {
868 	FONTGLYPH *glyph;
869 	int i, j, offset;
870 	DATABLOB *entry;
871 
872 	if (boxcx > 1)
873 	{
874 		ui_rect(boxx, boxy, boxcx, boxcy, bgcolour);
875 	}
876 	else if (mixmode == MIX_OPAQUE)
877 	{
878 		ui_rect(clipx, clipy, clipcx, clipcy, bgcolour);
879 	}
880 
881 	/* Paint text, character by character */
882 	for (i = 0; i < length;)
883 	{
884 		switch (text[i])
885 		{
886 			case 0xff:
887 				if (i + 2 < length)
888 					cache_put_text(text[i + 1], &(text[i - text[i + 2]]),
889 						       text[i + 2]);
890 				else
891 				{
892 					error("this shouldn't be happening\n");
893 					break;
894 				}
895 				/* this will move pointer from start to first character after FF command */
896 				length -= i + 3;
897 				text = &(text[i + 3]);
898 				i = 0;
899 				break;
900 
901 			case 0xfe:
902 				entry = cache_get_text(text[i + 1]);
903 				if (entry != NULL)
904 				{
905 					if ((((uint8 *) (entry->data))[1] == 0)
906 					    && (!(flags & TEXT2_IMPLICIT_X)))
907 					{
908 						if (flags & 0x04)	/* vertical text */
909 							y += text[i + 2];
910 						else
911 							x += text[i + 2];
912 					}
913 					if (i + 2 < length)
914 						i += 3;
915 					else
916 						i += 2;
917 					length -= i;
918 					/* this will move pointer from start to first character after FE command */
919 					text = &(text[i]);
920 					i = 0;
921 					for (j = 0; j < entry->size; j++)
922 						DO_GLYPH(((uint8 *) (entry->data)), j);
923 				}
924 				break;
925 			default:
926 				DO_GLYPH(text, i);
927 				i++;
928 				break;
929 		}
930 	}
931 }
932 
933 void
ui_desktop_save(uint32 offset,int x,int y,int cx,int cy)934 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
935 {
936 	vncBuffer *buf;
937 
938 	buf = vncGetRect(server, x, y, cx, cy);
939 	offset *= TOBYTES(server->serverFormat.bitsPerPixel);
940 	cache_put_desktop(offset, cx, cy, cx, TOBYTES(server->serverFormat.bitsPerPixel),
941 			  (buf->data));
942 }
943 
944 void
ui_desktop_restore(uint32 offset,int x,int y,int cx,int cy)945 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
946 {
947 	uint8 *data;
948 	vncBuffer *buf;
949 	int ox, oy, srcx, srcy;
950 
951 	srcx = srcy = 0;
952 	ox = x;
953 	oy = y;
954 
955 	offset *= TOBYTES(server->serverFormat.bitsPerPixel);
956 	data = cache_get_desktop(offset, cx, cy, TOBYTES(server->serverFormat.bitsPerPixel));
957 	if (data == NULL)
958 		return;
959 
960 	buf = vncNewBuffer(cx, cy, 8);
961 	memcpy(buf->data, data, cx * cy * 1);
962 
963 	if (vncwinClipRect(&x, &y, &cx, &cy))
964 	{
965 		srcx += x - ox;
966 		srcy += y - oy;
967 		vncCopyBlitFrom(server, x, y, cx, cy, buf, srcx, srcy);
968 	}
969 	vncDeleteBuffer(buf);
970 }
971 
972 rfbPixelFormat vnc_formats[] = {
973 	/* bpp, depth,BE,TC, rmax, gmax, bmax, rsh, gsh, bsh  */
974 	{8, 8, 1, 0, 7, 7, 3, 0, 3, 6}
975 	,
976 	{16, 16, 1, 1, 31, 63, 31, 0, 5, 10}
977 	,
978 	{32, 24, 1, 1, 255, 255, 255, 0, 8, 16}
979 	,			//non-existant
980 	{32, 32, 1, 1, 2047, 2047, 1023, 0, 11, 22}
981 };
982 
983 rfbPixelFormat *
vncNewFormat(int depth)984 vncNewFormat(int depth)
985 {
986 	return &(vnc_formats[(depth + 1) / 8 - 1]);
987 }
988 
989 vncBuffer *
vncNewBuffer(int w,int h,int depth)990 vncNewBuffer(int w, int h, int depth)
991 {
992 	vncBuffer *b = (vncBuffer *) xmalloc(sizeof(vncBuffer));
993 	b->format = vncNewFormat(depth);
994 	b->data = (void *) xmalloc(w * h * (b->format->bitsPerPixel / 8));
995 	b->owner = 1;
996 	b->w = w;
997 	b->h = h;
998 	b->linew = w;
999 	return b;
1000 }
1001 
1002 vncBuffer *
vncDupBuffer(vncBuffer * b)1003 vncDupBuffer(vncBuffer * b)
1004 {
1005 	vncBuffer *buf = vncNewBuffer(b->w, b->h, b->format->depth);
1006 	memcpy(buf->data, b->data, b->linew * b->h * b->format->bitsPerPixel / 8);
1007 	return buf;
1008 }
1009 
1010 void
vncPrintStats()1011 vncPrintStats()
1012 {
1013 	if (server && server->clientHead)
1014 		rfbPrintStats(server->clientHead);
1015 }
1016 
1017 /* blit */
1018 
1019 #define GETPIXEL(buf,x,y) \
1020      (((uint8_t*)(buf->data))[(x)+((y)*buf->linew)])
1021 #define SETPIXEL(buf,x,y,p) \
1022      (((uint8_t*)(buf->data))[(x)+((y)*buf->linew)] = (uint8_t)p)
1023 
1024 void
vncCopyBlitFromNoEncode(rfbScreenInfoPtr s,int x,int y,int w,int h,vncBuffer * src,int srcx,int srcy)1025 vncCopyBlitFromNoEncode(rfbScreenInfoPtr s, int x, int y, int w, int h,
1026 			vncBuffer * src, int srcx, int srcy)
1027 {
1028 	int xx, yy;
1029 
1030 	vncHideCursor();
1031 
1032 	if (s->serverFormat.bitsPerPixel == src->format->bitsPerPixel
1033 	    && srcx + w <= src->w && srcy + h <= src->h)
1034 	{
1035 		//simple copy
1036 		uint8_t *srcdata, *dstdata;
1037 		srcdata = src->data + (srcy * src->linew + srcx);
1038 		dstdata = s->frameBuffer + (y * s->paddedWidthInBytes + x);
1039 		for (yy = 0; yy < h; yy++)
1040 		{
1041 			memcpy(dstdata, srcdata, w);
1042 			dstdata += s->paddedWidthInBytes;
1043 			srcdata += src->linew;
1044 		}
1045 	}
1046 	else
1047 	{
1048 		// xsrc,ysrc provide tiling copy support.
1049 		for (yy = y; yy < y + h; yy++)
1050 		{
1051 			int ysrc = srcy + yy - y;
1052 			while (ysrc >= src->h)
1053 				ysrc -= src->h;
1054 			for (xx = x; xx < x + w; xx++)
1055 			{
1056 				vncPixel p;
1057 				int xsrc = srcx + xx - x;
1058 				while (xsrc >= src->linew)
1059 					xsrc -= src->linew;
1060 				p = GETPIXEL(src, xsrc, ysrc);
1061 				SETPIXEL(frameBuffer, xx, yy, p);
1062 			}
1063 		}
1064 	}
1065 }
1066 
1067 void
vncCopyBlit(rfbScreenInfoPtr s,int x,int y,int w,int h,int srcx,int srcy)1068 vncCopyBlit(rfbScreenInfoPtr s, int x, int y, int w, int h, int srcx, int srcy)
1069 {
1070 	/* LibVNCServer already knows how to copy the data. */
1071 	rfbDoCopyRect(s, x, y, x + w, y + h, x - srcx, y - srcy);
1072 }
1073 
1074 void
vncCopyBlitFrom(rfbScreenInfoPtr s,int x,int y,int w,int h,vncBuffer * src,int srcx,int srcy)1075 vncCopyBlitFrom(rfbScreenInfoPtr s, int x, int y, int w, int h, vncBuffer * src, int srcx, int srcy)
1076 {
1077 	vncCopyBlitFromNoEncode(s, x, y, w, h, src, srcx, srcy);
1078 	rfbMarkRectAsModified(s, x, y, x + w, y + h);
1079 }
1080 
1081 void
vncTransBlitFrom(rfbScreenInfoPtr s,int x,int y,int w,int h,vncBuffer * src,int srcx,int srcy,int bg)1082 vncTransBlitFrom(rfbScreenInfoPtr s, int x, int y, int w, int h,
1083 		 vncBuffer * src, int srcx, int srcy, int bg)
1084 {
1085 	int xx, yy;
1086 
1087 	vncHideCursor();
1088 
1089 	// xsrc,ysrc provide tiling copy support.
1090 	for (yy = y; yy < y + h; yy++)
1091 	{
1092 		int ysrc = srcy + yy - y;
1093 		while (ysrc >= src->h)
1094 			ysrc -= src->h;
1095 		for (xx = x; xx < x + w; xx++)
1096 		{
1097 			vncPixel p;
1098 			int xsrc = srcx + xx - x;
1099 			while (xsrc >= src->linew)
1100 				xsrc -= src->linew;
1101 			p = GETPIXEL(src, xsrc, ysrc);
1102 			// transparent blit!
1103 			if (p != bg)
1104 				SETPIXEL(frameBuffer, xx, yy, p);
1105 		}
1106 	}
1107 
1108 	rfbMarkRectAsModified(s, x, y, x + w, y + h);
1109 }
1110 
1111 void
vncXorBlitFrom(rfbScreenInfoPtr s,int x,int y,int w,int h,vncBuffer * src,int srcx,int srcy)1112 vncXorBlitFrom(rfbScreenInfoPtr s, int x, int y, int w, int h, vncBuffer * src, int srcx, int srcy)
1113 {
1114 	int xx, yy;
1115 
1116 	vncHideCursor();
1117 
1118 	// xsrc,ysrc provide tiling copy support.
1119 	for (yy = y; yy < y + h; yy++)
1120 	{
1121 		int ysrc = srcy + yy - y;
1122 		while (ysrc >= src->h)
1123 			ysrc -= src->h;
1124 		for (xx = x; xx < x + w; xx++)
1125 		{
1126 			vncPixel p, pp;
1127 			int xsrc = srcx + xx - x;
1128 			while (xsrc >= src->linew)
1129 				xsrc -= src->linew;
1130 			p = GETPIXEL(src, xsrc, ysrc);
1131 			pp = GETPIXEL(frameBuffer, xx, yy);
1132 			// xor blit!
1133 			SETPIXEL(frameBuffer, xx, yy, p ^ pp);
1134 		}
1135 	}
1136 
1137 	rfbMarkRectAsModified(s, x, y, x + w, y + h);
1138 }
1139 
1140 void
vncAndBlitFrom(rfbScreenInfoPtr s,int x,int y,int w,int h,vncBuffer * src,int srcx,int srcy)1141 vncAndBlitFrom(rfbScreenInfoPtr s, int x, int y, int w, int h, vncBuffer * src, int srcx, int srcy)
1142 {
1143 	int xx, yy;
1144 
1145 	vncHideCursor();
1146 
1147 	// xsrc,ysrc provide tiling copy support.
1148 	for (yy = y; yy < y + h; yy++)
1149 	{
1150 		int ysrc = srcy + yy - y;
1151 		while (ysrc >= src->h)
1152 			ysrc -= src->h;
1153 		for (xx = x; xx < x + w; xx++)
1154 		{
1155 			vncPixel p, pp;
1156 			int xsrc = srcx + xx - x;
1157 			while (xsrc >= src->linew)
1158 				xsrc -= src->linew;
1159 			p = GETPIXEL(src, xsrc, ysrc);
1160 			pp = GETPIXEL(frameBuffer, xx, yy);
1161 			// and blit!
1162 			SETPIXEL(frameBuffer, xx, yy, p & pp);
1163 		}
1164 	}
1165 
1166 	rfbMarkRectAsModified(s, x, y, x + w, y + h);
1167 }
1168 
1169 void
vncDeleteBuffer(vncBuffer * b)1170 vncDeleteBuffer(vncBuffer * b)
1171 {
1172 	if (b->owner)
1173 		xfree(b->data);
1174 	xfree(b);
1175 }
1176 
1177 /* cursor */
1178 rfbCursorPtr
vncNewCursor(vncBuffer * mask,vncBuffer * pointer,int hotx,int hoty)1179 vncNewCursor(vncBuffer * mask, vncBuffer * pointer, int hotx, int hoty)
1180 {
1181 	int i, j, w = (mask->w + 7) / 8, mask_size = w * mask->h,
1182 		pointer_size = pointer->w * pointer->h;
1183 	rfbCursorPtr c = (rfbCursorPtr) xmalloc(sizeof(rfbCursor));
1184 
1185 	if (mask->w != pointer->w || mask->h != pointer->h)
1186 		error("ERROR! Mask is %dx%d, Pointer is %dx%d\n",
1187 		      mask->w, mask->h, pointer->w, pointer->h);
1188 
1189 	c->xhot = hotx;
1190 	c->yhot = hoty;
1191 	c->width = mask->w;
1192 	c->height = mask->h;
1193 
1194 	c->mask = (char *) xmalloc(mask_size);
1195 	for (j = 0; j < c->height; j++)
1196 		for (i = 0; i < w; i++)
1197 			c->mask[j * w + i] =
1198 				reverseByte[((unsigned char *) mask->data)[(j) * w + i]];
1199 	vncDeleteBuffer(mask);
1200 
1201 	c->source = 0;
1202 	c->richSource = (char *) xmalloc(pointer_size);
1203 	memcpy(c->richSource, pointer->data, pointer_size);
1204 	vncDeleteBuffer(pointer);
1205 
1206 	return c;
1207 }
1208 
1209 /* No FreeCursor, because the cursors are buffered. We only get a "HANDLE" */
1210 void
vncSetCursor(rfbScreenInfoPtr s,rfbCursorPtr c)1211 vncSetCursor(rfbScreenInfoPtr s, rfbCursorPtr c)
1212 {
1213 	rfbSetCursor(s, c, FALSE);
1214 }
1215 
1216 /* these functions work even if vncBuffer's pixel format is not 1 byte/pixel */
1217 vncPixel
vncGetPixel(vncBuffer * b,int x,int y)1218 vncGetPixel(vncBuffer * b, int x, int y)
1219 {
1220 	unsigned long offset = (x + (y * (b->linew))) * (b->format->bitsPerPixel >> 3);
1221 	return ((uint8_t *) (b->data))[offset];
1222 }
1223 
1224 void
vncSetPixel(vncBuffer * b,int x,int y,vncPixel c)1225 vncSetPixel(vncBuffer * b, int x, int y, vncPixel c)
1226 {
1227 	unsigned long offset = (x + (y * (b->linew))) * (b->format->bitsPerPixel >> 3);
1228 	((uint8_t *) (b->data))[offset] = c;
1229 }
1230 
1231 void
vncSetRect(rfbScreenInfoPtr s,int x,int y,int w,int h,vncPixel c)1232 vncSetRect(rfbScreenInfoPtr s, int x, int y, int w, int h, vncPixel c)
1233 {
1234 	int xx, yy;
1235 
1236 	if (x + w > s->width)
1237 		w = s->width - x;
1238 	if (y + h > s->height)
1239 		h = s->height - y;
1240 	if (w <= 0 || h <= 0)
1241 		return;
1242 
1243 	vncHideCursor();
1244 
1245 	// - Fill the rect in the local framebuffer
1246 	if (s->serverFormat.bitsPerPixel == 8)
1247 	{
1248 		// - Simple 8-bit fill
1249 		uint8_t *dstdata;
1250 		dstdata = s->frameBuffer + (y * s->paddedWidthInBytes + x);
1251 		for (yy = 0; yy < h; yy++)
1252 		{
1253 			memset(dstdata, c, w);
1254 			dstdata += s->paddedWidthInBytes;
1255 		}
1256 	}
1257 	else
1258 	{
1259 		for (yy = y; yy < y + h; yy++)
1260 		{
1261 			for (xx = x; xx < x + w; xx++)
1262 			{
1263 				SETPIXEL(frameBuffer, xx, yy, c);
1264 			}
1265 		}
1266 	}
1267 
1268 	rfbMarkRectAsModified(s, x, y, x + w, y + h);
1269 }
1270 
1271 vncBuffer *
vncGetRect(rfbScreenInfoPtr s,int x,int y,int w,int h)1272 vncGetRect(rfbScreenInfoPtr s, int x, int y, int w, int h)
1273 {
1274 	int xx, yy;
1275 	vncBuffer *b = vncNewBuffer(w, h, s->serverFormat.depth);
1276 
1277 	vncHideCursor();
1278 
1279 	if (s->serverFormat.bitsPerPixel == 8)
1280 	{
1281 		//simple copy
1282 		int srcstep, dststep;
1283 		char *srcdata, *dstdata;
1284 		srcstep = s->paddedWidthInBytes * s->serverFormat.bitsPerPixel / 8;
1285 		dststep = w * s->serverFormat.bitsPerPixel / 8;
1286 		dstdata = b->data;
1287 		srcdata = s->frameBuffer + (y * srcstep + x * s->serverFormat.bitsPerPixel / 8);
1288 		for (yy = 0; yy < h; yy++)
1289 		{
1290 			memcpy(dstdata, srcdata, dststep);
1291 			dstdata += dststep;
1292 			srcdata += srcstep;
1293 		}
1294 	}
1295 	else
1296 	{
1297 		for (yy = y; yy < y + h; yy++)
1298 		{
1299 			for (xx = x; xx < x + w; xx++)
1300 			{
1301 				SETPIXEL(b, xx - x, yy - y, GETPIXEL(frameBuffer, xx, yy));
1302 			}
1303 		}
1304 	}
1305 
1306 	return b;
1307 }
1308 
1309 /* colourmap */
1310 
1311 rfbColourMap *
vncNewColourMap(rfbScreenInfoPtr s,int n)1312 vncNewColourMap(rfbScreenInfoPtr s, int n)
1313 {
1314 	rfbColourMap *m = (rfbColourMap *) xmalloc(sizeof(rfbColourMap));
1315 	m->is16 = FALSE;
1316 	m->count = n;
1317 	m->data.bytes = (uint8_t *) xmalloc(n * 3);
1318 	return m;
1319 }
1320 
1321 void
vncSetColourMapEntry(rfbColourMap * m,int i,vncPixel r,vncPixel g,vncPixel b)1322 vncSetColourMapEntry(rfbColourMap * m, int i, vncPixel r, vncPixel g, vncPixel b)
1323 {
1324 	if (i < m->count)
1325 	{
1326 		m->data.bytes[3 * i + 0] = r;
1327 		m->data.bytes[3 * i + 1] = g;
1328 		m->data.bytes[3 * i + 2] = b;
1329 	}
1330 }
1331 
1332 void
vncDeleteColourMap(rfbColourMap * m)1333 vncDeleteColourMap(rfbColourMap * m)
1334 {
1335 	if (m->data.bytes)
1336 		free(m->data.bytes);
1337 	m->count = 0;
1338 }
1339 
1340 void
vncSetColourMap(rfbScreenInfoPtr s,rfbColourMap * m)1341 vncSetColourMap(rfbScreenInfoPtr s, rfbColourMap * m)
1342 {
1343 	vncDeleteColourMap(&s->colourMap);
1344 	s->colourMap = *m;
1345 	rfbSetClientColourMaps(s, 0, 0);
1346 }
1347 
1348 void
ui_begin_update()1349 ui_begin_update()
1350 {
1351 }
1352 
1353 void
ui_end_update()1354 ui_end_update()
1355 {
1356 }
1357 
1358 void
ui_resize_window()1359 ui_resize_window()
1360 {
1361 	rfbClientIteratorPtr iter;
1362 	rfbClientPtr cl;
1363 
1364 	server->width = g_width;
1365 	server->height = g_height;
1366 	server->frameBuffer = (char *) realloc(server->frameBuffer, g_width * g_height);
1367 	server->paddedWidthInBytes = g_width;
1368 
1369 	iter = rfbGetClientIterator(server);
1370 	while ((cl = rfbClientIteratorNext(iter)))
1371 		if (cl->useNewFBSize)
1372 			cl->newFBSizePending = TRUE;
1373 		else
1374 			rfbLog("Warning: Client %s does not support NewFBSize!\n ", cl->host);
1375 	rfbReleaseClientIterator(iter);
1376 }
1377