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