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