1 #include <assert.h>
2 #include <string.h>
3 #include <rfb/rfb.h>
4 #include <rfb/rfbclient.h>
5 
6 #include "nacro.h"
7 
8 /* for visual grepping */
9 typedef struct image_t {
10 	int width,height;
11 	char* buffer;
12 } image_t;
13 
14 /* this is a VNC connection */
15 typedef struct private_resource_t {
16 	int listen_port;
17 	rfbScreenInfo* server;
18 	rfbClient* client;
19 
20 	uint32_t keysym;
21 	rfbBool keydown;
22 
23 	int x,y;
24 	int buttons;
25 
26 	char* text_client;
27 	char* text_server;
28 
29 	image_t* grep_image;
30 	int x_origin,y_origin;
31 
32 	enum { SLEEP,VISUALGREP,WAITFORUPDATE } state;
33 	result_t result;
34 } private_resource_t;
35 
36 /* resource management */
37 
38 #define MAX_RESOURCE_COUNT 20
39 
40 static private_resource_t resource_pool[MAX_RESOURCE_COUNT];
41 static int resource_count=0;
42 
get_resource(int resource)43 static private_resource_t* get_resource(int resource)
44 {
45 	if(resource>=MAX_RESOURCE_COUNT || resource<0 || resource_pool[resource].client==0)
46 		return NULL;
47 	return resource_pool+resource;
48 }
49 
get_next_resource(void)50 static private_resource_t* get_next_resource(void)
51 {
52 	if(resource_count<MAX_RESOURCE_COUNT) {
53 		memset(resource_pool+resource_count,0,sizeof(private_resource_t));
54 		resource_count++;
55 		return resource_pool+resource_count-1;
56 	} else {
57 		int i;
58 
59 		for(i=0;i<MAX_RESOURCE_COUNT && resource_pool[i].client;i++);
60 		if(i<MAX_RESOURCE_COUNT)
61 			return resource_pool+i;
62 	}
63 	return NULL;
64 }
65 
free_resource(int resource)66 static void free_resource(int resource)
67 {
68 	private_resource_t* res=get_resource(resource);
69 	if(res)
70 		res->client=NULL;
71 }
72 
73 /* hooks */
74 
got_key(rfbBool down,rfbKeySym keysym,rfbClientRec * cl)75 static void got_key(rfbBool down,rfbKeySym keysym,rfbClientRec* cl)
76 {
77 	private_resource_t* res=(private_resource_t*)cl->screen->screenData;
78 
79 	res->keydown=down;
80 	res->keysym=keysym;
81 	res->result|=RESULT_KEY;
82 }
83 
got_mouse(int buttons,int x,int y,rfbClientRec * cl)84 static void got_mouse(int buttons,int x,int y,rfbClientRec* cl)
85 {
86 	private_resource_t* res=(private_resource_t*)cl->screen->screenData;
87 
88 	res->buttons=buttons;
89 	res->x=x;
90 	res->y=y;
91 	res->result|=RESULT_MOUSE;
92 }
93 
got_text(char * str,int len,rfbClientRec * cl)94 static void got_text(char* str,int len,rfbClientRec* cl)
95 {
96 	private_resource_t* res=(private_resource_t*)cl->screen->screenData;
97 
98 	if (res->text_client)
99 		free(res->text_client);
100 	res->text_client=strdup(str);
101 	res->result|=RESULT_TEXT_CLIENT;
102 }
103 
got_text_from_server(rfbClient * cl,const char * str,int textlen)104 static void got_text_from_server(rfbClient* cl, const char *str, int textlen)
105 {
106 	private_resource_t* res=(private_resource_t*)cl->clientData;
107 
108 	if (res->text_server)
109 		free(res->text_server);
110 	res->text_server=strdup(str);
111 	res->result|=RESULT_TEXT_SERVER;
112 }
113 
malloc_frame_buffer(rfbClient * cl)114 static rfbBool malloc_frame_buffer(rfbClient* cl)
115 {
116 	private_resource_t* res=(private_resource_t*)cl->clientData;
117 
118 	if(!res->server) {
119 		int w=cl->width,h=cl->height;
120 
121 		res->client->frameBuffer=malloc(w*4*h);
122 
123 		res->server=rfbGetScreen(NULL,NULL,w,h,8,3,4);
124 		if(!res->server)
125                   return FALSE;
126 		res->server->screenData=res;
127 		res->server->port=res->listen_port;
128 		res->server->frameBuffer=res->client->frameBuffer;
129 		res->server->kbdAddEvent=got_key;
130 		res->server->ptrAddEvent=got_mouse;
131 		res->server->setXCutText=got_text;
132 		rfbInitServer(res->server);
133 	} else {
134 		/* TODO: realloc if necessary */
135 		/* TODO: resolution change: send NewFBSize */
136 		/* TODO: if the origin is out of bounds, reset to 0 */
137 	}
138 }
139 
do_visual_grep(private_resource_t * res,int x,int y,int w,int h)140 static bool_t do_visual_grep(private_resource_t* res,int x,int y,int w,int h)
141 {
142 	rfbClient* cl;
143 	image_t* image;
144 	int x_start,y_start,x_end=x+w-1,y_end=y+h-1;
145 	bool_t found=0;
146 
147 	if(res==0 || (cl=res->client)==0 || (image=res->grep_image)==0)
148 		return 0;
149 
150 	x_start=x-image->width;
151 	y_start=y-image->height;
152 	if(x_start<0) x_start=0;
153 	if(y_start<0) y_start=0;
154 	if(x_end+image->width>cl->width) x_end=cl->width-image->width;
155 	if(y_end+image->height>cl->height) y_end=cl->height-image->height;
156 
157 	/* find image and set x_origin,y_origin if found */
158 	for(y=y_start;y<y_end;y++)
159 		for(x=x_start;x<x_end;x++) {
160 			bool_t matching=1;
161 			int i,j;
162 			for(j=0;matching && j<image->height;j++)
163 				for(i=0;matching && i<image->width;i++)
164 					if(memcmp(cl->frameBuffer+4*(x+i+cl->width*(y+j)),image->buffer+4*(i+image->width*j),3))
165 						matching=0;
166 			if(matching) {
167 				private_resource_t* res=(private_resource_t*)cl->clientData;
168 				res->x_origin=x;
169 				res->y_origin=y;
170 				return -1;
171 			}
172 		}
173 	return 0;
174 }
175 
got_frame_buffer(rfbClient * cl,int x,int y,int w,int h)176 static void got_frame_buffer(rfbClient* cl,int x,int y,int w,int h)
177 {
178 	private_resource_t* res=(private_resource_t*)cl->clientData;
179 
180 	assert(res->server);
181 
182 	if(res->grep_image && do_visual_grep(res,x,y,w,h)) {
183 		res->result|=RESULT_FOUNDIMAGE;
184 	}
185 	if(res->server) {
186 		rfbMarkRectAsModified(res->server,x,y,x+w,y+h);
187 	}
188 
189 	res->result|=RESULT_SCREEN;
190 }
191 
192 /* init/shutdown functions */
193 
initvnc(const char * server,int server_port,int listen_port)194 resource_t initvnc(const char* server,int server_port,int listen_port)
195 {
196 	private_resource_t* res=get_next_resource();
197 	int dummy=0;
198 
199 	if(res==0)
200 		return -1;
201 
202 	/* remember for later */
203 	res->listen_port=listen_port;
204 
205 	res->text_client = NULL;
206 	res->text_server = NULL;
207 
208 	res->client=rfbGetClient(8,3,4);
209 	res->client->clientData=(void*)res;
210 	res->client->GotFrameBufferUpdate=got_frame_buffer;
211 	res->client->MallocFrameBuffer=malloc_frame_buffer;
212 	res->client->GotXCutText=got_text_from_server;
213 	res->client->serverHost=strdup(server);
214 	res->client->serverPort=server_port;
215 	res->client->appData.encodingsString="raw";
216 	if(!rfbInitClient(res->client,&dummy,NULL)) {
217 		res->client=NULL;
218 		return -1;
219 	}
220 	return res-resource_pool;
221 }
222 
closevnc(resource_t resource)223 void closevnc(resource_t resource)
224 {
225 	private_resource_t* res=get_resource(resource);
226 	if(res==0)
227 		return;
228 
229 	if(res->server)
230 		rfbScreenCleanup(res->server);
231 
232 	assert(res->client);
233 
234 	rfbClientCleanup(res->client);
235 
236 	res->client=NULL;
237 }
238 
239 /* PNM (image) helpers */
240 
savepnm(resource_t resource,const char * filename,int x1,int y1,int x2,int y2)241 bool_t savepnm(resource_t resource,const char* filename,int x1,int y1,int x2,int y2)
242 {
243 	private_resource_t* res=get_resource(resource);
244 	int i,j,w,h;
245 	uint32_t* buffer;
246 	FILE* f;
247 
248 	if(res==0 || res->client==0)
249 		return 0;
250 	assert(res->client->format.depth==24);
251 
252 	w=res->client->width;
253 	h=res->client->height;
254 	buffer=(uint32_t*)res->client->frameBuffer;
255 
256 	if(res==0 || x1>x2 || y1>y2 || x1<0 || x2>=w || y1<0 || y2>=h)
257 		return FALSE;
258 
259 	f=fopen(filename,"wb");
260 
261 	if(f==0)
262 		return FALSE;
263 
264 	fprintf(f,"P6\n%d %d\n255\n",1+x2-x1,1+y2-y1);
265 	for(j=y1;j<=y2;j++)
266 		for(i=x1;i<=x2;i++) {
267 			fwrite(buffer+i+j*w,3,1,f);
268 		}
269 	if(fclose(f))
270 		return FALSE;
271 	return TRUE;
272 }
273 
loadpnm(const char * filename)274 static image_t* loadpnm(const char* filename)
275 {
276 	FILE* f=fopen(filename,"rb");
277 	char buffer[1024];
278 	int i,j,w,h;
279 	image_t* image;
280 
281 	if(f==0)
282 		return NULL;
283 
284 	if(!fgets(buffer,1024,f) || strcmp("P6\n",buffer)) {
285 		fclose(f);
286 		return NULL;
287 	}
288 
289 	do {
290 		fgets(buffer,1024,f);
291 		if(feof(f)) {
292 			fclose(f);
293 			return NULL;
294 		}
295 	} while(buffer[0]=='#');
296 
297 	if( sscanf(buffer,"%d %d",&w,&h)!=2
298 			|| !fgets(buffer,1024,f) || strcmp("255\n",buffer)) {
299 		fclose(f);
300 		return NULL;
301 	}
302 
303 	image=(image_t*)malloc(sizeof(image_t));
304 	image->width=w;
305 	image->height=h;
306 	image->buffer=malloc(w*4*h);
307 	if(!image->buffer) {
308 		fclose(f);
309 		free(image);
310 		return NULL;
311 	}
312 
313 	for(j=0;j<h;j++)
314 		for(i=0;i<w;i++)
315 			if(fread(image->buffer+4*(i+w*j),3,1,f)!=1) {
316 				fprintf(stderr,"Could not read 3 bytes at %d,%d\n",i,j);
317 				fclose(f);
318 				free(image->buffer);
319 				free(image);
320 				return NULL;
321 			}
322 
323 	fclose(f);
324 
325 	return image;
326 }
327 
free_image(image_t * image)328 static void free_image(image_t* image)
329 {
330 	if(image->buffer)
331 		free(image->buffer);
332 	free(image);
333 }
334 
copy_line(rfbScreenInfo * dest,char * backup,int x0,int y0,int x1,int y1,int color_offset)335 static void copy_line(rfbScreenInfo *dest, char *backup,
336 		int x0, int y0, int x1, int y1, int color_offset)
337 {
338 	uint8_t *d = (uint8_t *)dest->frameBuffer, *s = (uint8_t *)backup;
339 	int i;
340 	int steps0 = x1 > x0 ? x1 - x0 : x0 - x1;
341 	int steps1 = y1 > y0 ? y1 - y0 : y0 - y1;
342 
343 	if (steps1 > steps0)
344 		steps0 = steps1;
345 	else if (steps0 == 0)
346 		steps0 = 1;
347 
348 	for (i = 0; i <= steps0; i++) {
349 		int j, index = 4 * (x0 + i * (x1 - x0) / steps0
350 				+ dest->width * (y0 + i * (y1 - y0) / steps0));
351 		for (j = 0; j < 4; j++)
352 			d[index + j] = s[index + j] + color_offset;
353 	}
354 
355 	rfbMarkRectAsModified(dest, x0 - 5, y0 - 5, x1 + 1, y1 + 2);
356 }
357 
displaypnm(resource_t resource,const char * filename,coordinate_t x,coordinate_t y,bool_t border,timeout_t timeout_in_seconds)358 result_t displaypnm(resource_t resource, const char *filename,
359 		coordinate_t x, coordinate_t y, bool_t border,
360 		timeout_t timeout_in_seconds)
361 {
362 	private_resource_t* res = get_resource(resource);
363 	image_t *image;
364 	char* fake_frame_buffer;
365 	char* backup;
366 	int w, h, i, j, w2, h2;
367 	result_t result;
368 
369 	if (res == NULL || res->server == NULL ||
370 			(image = loadpnm(filename)) == NULL)
371 		return 0;
372 
373 	w = res->server->width;
374 	h = res->server->height;
375 	fake_frame_buffer = malloc(w * 4 * h);
376 	if(!fake_frame_buffer)
377 		return 0;
378 	memcpy(fake_frame_buffer, res->server->frameBuffer, w * 4 * h);
379 
380 	backup = res->server->frameBuffer;
381 	res->server->frameBuffer = fake_frame_buffer;
382 
383 	w2 = image->width;
384 	if (x + w2 > w)
385 		w2 = w - x;
386 	h2 = image->height;
387 	if (y + h2 > h)
388 		h2 = h - y;
389 	for (j = 0; j < h2; j++)
390 		memcpy(fake_frame_buffer + 4 * (x + (y + j) * w),
391 			image->buffer + j * 4 * image->width, 4 * w2);
392 	free(image);
393 	if (border) {
394 		copy_line(res->server, backup, x, y, x + w2, y, 0x80);
395 		copy_line(res->server, backup, x, y, x, y + h2, 0x80);
396 		copy_line(res->server, backup, x + w2, y, x + w2, y + h2, 0x80);
397 		copy_line(res->server, backup, x, y + h2, x + w2, y + h2, 0x80);
398 	}
399 	rfbMarkRectAsModified(res->server,
400 			x - 1, y - 1, x + w2 + 1, y + h2 + 1);
401 
402 	result = waitforinput(resource, timeout_in_seconds);
403 
404 	res->server->frameBuffer=backup;
405 	free(fake_frame_buffer);
406 	rfbMarkRectAsModified(res->server,
407 			x - 1, y - 1, x + w2 + 1, y + h2 + 1);
408 
409 	return result;
410 }
411 
412 /* process() and friends */
413 
414 /* this function returns only if res->result in return_mask */
private_process(resource_t resource,timeout_t timeout_in_seconds,result_t return_mask)415 static result_t private_process(resource_t resource,timeout_t timeout_in_seconds,result_t return_mask)
416 {
417 	private_resource_t* res=get_resource(resource);
418 	fd_set fds;
419 	struct timeval tv,tv_start,tv_end;
420 	unsigned long timeout=(unsigned long)(timeout_in_seconds*1000000UL);
421 	int count,max_fd;
422 
423 	if(res==0)
424 		return 0;
425 
426 	assert(res->client);
427 
428 	gettimeofday(&tv_start,NULL);
429 	res->result=0;
430 
431 	do {
432 		unsigned long timeout_done;
433 
434 		if(res->server) {
435 			rfbBool loop;
436 			do {
437 				loop=rfbProcessEvents(res->server,res->server->deferUpdateTime);
438 			} while(loop && (res->result&return_mask)==0
439 				&& rfbIsActive(res->server));
440 
441 			if(!rfbIsActive(res->server))
442 				return RESULT_SHUTDOWN;
443 
444 			if((res->result&return_mask)!=0)
445 				return res->result;
446 
447 			memcpy((char*)&fds,(const char*)&(res->server->allFds),sizeof(fd_set));
448 			max_fd=res->server->maxFd;
449 		} else {
450 			FD_ZERO(&fds);
451 			max_fd=0;
452 		}
453 		FD_SET(res->client->sock,&fds);
454 		if(res->client->sock>max_fd)
455 			max_fd=res->client->sock;
456 
457 		gettimeofday(&tv_end,NULL);
458 		timeout_done=tv_end.tv_usec-tv_start.tv_usec+
459 			1000000L*(tv_end.tv_sec-tv_start.tv_sec);
460 		if(timeout_done>=timeout)
461 			return RESULT_TIMEOUT;
462 
463 		tv.tv_usec=((timeout-timeout_done)%1000000);
464 		tv.tv_sec=(timeout-timeout_done)/1000000;
465 
466 		count=select(max_fd+1,&fds,NULL,NULL,&tv);
467 		if(count<0)
468 			return 0;
469 
470 		if(count>0) {
471 			if(FD_ISSET(res->client->sock,&fds)) {
472 				if(!HandleRFBServerMessage(res->client)) {
473 					closevnc(resource);
474 					return 0;
475 				}
476 				if((res->result&return_mask)!=0)
477 					return res->result;
478 			}
479 		} else {
480 			res->result|=RESULT_TIMEOUT;
481 			return res->result;
482 		}
483 	} while(1);
484 
485 	return RESULT_TIMEOUT;
486 }
487 
process(resource_t res,timeout_t timeout)488 result_t process(resource_t res,timeout_t timeout)
489 {
490 	return private_process(res,timeout,RESULT_TIMEOUT);
491 }
492 
waitforanything(resource_t res,timeout_t timeout)493 result_t waitforanything(resource_t res,timeout_t timeout)
494 {
495 	return private_process(res,timeout,-1);
496 }
497 
waitforinput(resource_t res,timeout_t timeout)498 result_t waitforinput(resource_t res,timeout_t timeout)
499 {
500 	return private_process(res,timeout,RESULT_KEY|RESULT_MOUSE|RESULT_TIMEOUT);
501 }
502 
waitforupdate(resource_t res,timeout_t timeout)503 result_t waitforupdate(resource_t res,timeout_t timeout)
504 {
505 	return private_process(res,timeout,RESULT_SCREEN|RESULT_TIMEOUT);
506 }
507 
visualgrep(resource_t resource,const char * filename,timeout_t timeout)508 result_t visualgrep(resource_t resource,const char* filename,timeout_t timeout)
509 {
510 	private_resource_t* res=get_resource(resource);
511 	image_t* image;
512 	result_t result;
513 
514 	if(res==0 || res->client==0)
515 		return 0;
516 
517 	/* load filename and set res->grep_image to this image */
518 	image=loadpnm(filename);
519 	if(image==0)
520 		return 0;
521 	if(res->grep_image)
522 		free_image(res->grep_image);
523 	res->grep_image=image;
524 
525 	if(do_visual_grep(res,0,0,res->client->width,res->client->height))
526 		return RESULT_FOUNDIMAGE;
527 
528 	result=private_process(resource,timeout,RESULT_FOUNDIMAGE|RESULT_TIMEOUT);
529 
530 	/* free image */
531 	if(res->grep_image) {
532 		free_image(res->grep_image);
533 		res->grep_image=NULL;
534 	}
535 
536 	return result;
537 }
538 
539 /* auxiliary function for alert */
540 
541 #include "default8x16.h"
542 
center_text(rfbScreenInfo * screen,const char * message,int * x,int * y,int * w,int * h)543 static void center_text(rfbScreenInfo* screen,const char* message,int* x,int* y,int* w,int* h)
544 {
545 	rfbFontData* font=&default8x16Font;
546 	const char* pointer;
547 	int j,x1,y1,x2,y2,line_count=0;
548 	if(message==0 || screen==0)
549 		return;
550 	rfbWholeFontBBox(font,&x1,&y1,&x2,&y2);
551 	for(line_count=1,pointer=message;*pointer;pointer++)
552 		if(*pointer=='\n')
553 			line_count++;
554 
555 	*h=(y2-y1)*line_count;
556 	assert(*h>0);
557 
558 	if(*h>screen->height)
559 		*h=screen->height;
560 
561 	*x=0; *w=screen->width; *y=(screen->height-*h)/2;
562 
563 	rfbFillRect(screen,*x,*y,*x+*w,*y+*h,0xff0000);
564 
565 	for(pointer=message,j=0;j<line_count;j++) {
566 		const char* eol;
567 		int x_cur,y_cur=*y-y1+j*(y2-y1),width;
568 
569 		for(width=0,eol=pointer;*eol && *eol!='\n';eol++)
570 			width+=rfbWidthOfChar(font,*eol);
571 		if(width>screen->width)
572 			width=screen->width;
573 
574 		x_cur=(screen->width-width)/2;
575 		for(;pointer!=eol;pointer++)
576 			x_cur+=rfbDrawCharWithClip(screen,font,
577 					x_cur,y_cur,*pointer,
578 					0,0,screen->width,screen->height,
579 					0xffffffff,0xffffffff);
580 		pointer++;
581 	}
582 	rfbMarkRectAsModified(screen,*x,*y,*x+*w,*y+*h);
583 }
584 
585 /* this is an overlay which is shown for a certain time */
586 
alert(resource_t resource,const char * message,timeout_t timeout)587 result_t alert(resource_t resource,const char* message,timeout_t timeout)
588 {
589 	private_resource_t* res=get_resource(resource);
590 	char* fake_frame_buffer;
591 	char* backup;
592 	int x,y,w,h;
593 	result_t result;
594 
595 	if(res == NULL || res->server==NULL)
596 		return -1;
597 
598 	w=res->server->width;
599 	h=res->server->height;
600 
601 	fake_frame_buffer=malloc(w*4*h);
602 	if(!fake_frame_buffer)
603 		return -1;
604 	memcpy(fake_frame_buffer,res->server->frameBuffer,w*4*h);
605 
606 	backup=res->server->frameBuffer;
607 	res->server->frameBuffer=fake_frame_buffer;
608 	center_text(res->server,message,&x,&y,&w,&h);
609 	fprintf(stderr,"%s\n",message);
610 
611 	result=waitforinput(resource,timeout);
612 
613 	res->server->frameBuffer=backup;
614 	free(fake_frame_buffer);
615 	rfbMarkRectAsModified(res->server,x,y,x+w,y+h);
616 
617 	return result;
618 }
619 /* inspect last events */
620 
getkeysym(resource_t res)621 keysym_t getkeysym(resource_t res)
622 {
623 	private_resource_t* r=get_resource(res);
624 	return r->keysym;
625 }
626 
getkeydown(resource_t res)627 bool_t getkeydown(resource_t res)
628 {
629 	private_resource_t* r=get_resource(res);
630 	return r->keydown;
631 }
632 
getx(resource_t res)633 coordinate_t getx(resource_t res)
634 {
635 	private_resource_t* r=get_resource(res);
636 	return r->x;
637 }
638 
gety(resource_t res)639 coordinate_t gety(resource_t res)
640 {
641 	private_resource_t* r=get_resource(res);
642 	return r->y;
643 }
644 
getbuttons(resource_t res)645 buttons_t getbuttons(resource_t res)
646 {
647 	private_resource_t* r=get_resource(res);
648 	return r->buttons;
649 }
650 
gettext_client(resource_t res)651 const char *gettext_client(resource_t res)
652 {
653 	private_resource_t* r=get_resource(res);
654 	return r->text_client;
655 }
656 
rubberband(resource_t resource,coordinate_t x0,coordinate_t y0)657 result_t rubberband(resource_t resource, coordinate_t x0, coordinate_t y0)
658 {
659 	private_resource_t* res=get_resource(resource);
660 	char* fake_frame_buffer;
661 	char* backup;
662 	int w, h, x, y;
663 
664 	if(res == NULL || res->server==NULL)
665 		return -1;
666 
667 	x = res->x;
668 	y = res->y;
669 	w = res->server->width;
670 	h = res->server->height;
671 	fake_frame_buffer = malloc(w * 4 * h);
672 	if(!fake_frame_buffer)
673 		return 0;
674 	memcpy(fake_frame_buffer, res->server->frameBuffer, w * 4 * h);
675 
676 	backup = res->server->frameBuffer;
677 	res->server->frameBuffer = fake_frame_buffer;
678 
679 	while (res->buttons) {
680 		result_t r = waitforinput(resource, 1000000L);
681 		if (x == res->x && y == res->y)
682 				continue;
683 		copy_line(res->server, backup, x0, y0, x, y0, 0);
684 		copy_line(res->server, backup, x0, y0, x0, y, 0);
685 		copy_line(res->server, backup, x, y0, x, y, 0);
686 		copy_line(res->server, backup, x0, y, x, y, 0);
687 		x = res->x;
688 		y = res->y;
689 		copy_line(res->server, backup, x0, y0, x, y0, 0x80);
690 		copy_line(res->server, backup, x0, y0, x0, y, 0x80);
691 		copy_line(res->server, backup, x, y0, x, y, 0x80);
692 		copy_line(res->server, backup, x0, y, x, y, 0x80);
693 	}
694 
695 	copy_line(res->server, backup, x0, y0, x, y0, 0);
696 	copy_line(res->server, backup, x0, y0, x0, y, 0);
697 	copy_line(res->server, backup, x, y0, x, y, 0);
698 	copy_line(res->server, backup, x0, y, x, y, 0);
699 
700 	res->server->frameBuffer=backup;
701 	free(fake_frame_buffer);
702 
703 	return RESULT_MOUSE;
704 }
705 
gettext_server(resource_t res)706 const char *gettext_server(resource_t res)
707 {
708 	private_resource_t* r=get_resource(res);
709 	return r->text_server;
710 }
711 
712 /* send events to the server */
713 
sendkey(resource_t res,keysym_t keysym,bool_t keydown)714 bool_t sendkey(resource_t res,keysym_t keysym,bool_t keydown)
715 {
716 	private_resource_t* r=get_resource(res);
717 	if(r==NULL)
718 		return 0;
719 	return SendKeyEvent(r->client,keysym,keydown);
720 }
721 
sendascii(resource_t res,const char * string)722 bool_t sendascii(resource_t res,const char *string)
723 {
724 	timeout_t delay = 0.1;
725 	private_resource_t* r=get_resource(res);
726 	int i;
727 	if(r==NULL)
728 		return 0;
729 	while (*string) {
730 		int keysym = *string;
731 		int need_shift = 0;
732 
733 		if (keysym >= 8 && keysym < ' ')
734 			keysym += 0xff00;
735 		else if (keysym >= 'A' && keysym <= 'Z')
736 			need_shift = 1;
737 		else if (keysym > '~') {
738 			fprintf(stderr, "String contains non-ASCII "
739 					"character 0x%02x\n", *string);
740 			return FALSE;
741 		}
742 
743 		if (need_shift) {
744 			if (!SendKeyEvent(r->client,0xffe1,1))
745 				return FALSE;
746 			waitforinput(r,delay);
747 		}
748 		for (i = 1; i >= 0; i--) {
749 			if (!SendKeyEvent(r->client,keysym,i))
750 				return FALSE;
751 			waitforinput(r,delay);
752 		}
753 		if (need_shift) {
754 			if (!SendKeyEvent(r->client,0xffe1,0))
755 				return FALSE;
756 			waitforinput(r,delay);
757 		}
758 		string++;
759 	}
760 	return TRUE;
761 }
762 
sendmouse(resource_t res,coordinate_t x,coordinate_t y,buttons_t buttons)763 bool_t sendmouse(resource_t res,coordinate_t x,coordinate_t y,buttons_t buttons)
764 {
765 	private_resource_t* r=get_resource(res);
766 	if(r==NULL)
767 		return 0;
768 	return SendPointerEvent(r->client,x,y,buttons);
769 }
770 
sendtext(resource_t res,const char * string)771 bool_t sendtext(resource_t res, const char *string)
772 {
773 	private_resource_t* r=get_resource(res);
774 	if(r==NULL)
775 		return 0;
776 	return SendClientCutText(r->client, (char *)string, (int)strlen(string));
777 }
778 
sendtext_to_server(resource_t res,const char * string)779 bool_t sendtext_to_server(resource_t res, const char *string)
780 {
781 	private_resource_t* r=get_resource(res);
782 	if(r==NULL)
783 		return 0;
784 	rfbSendServerCutText(r->server, (char *)string, (int)strlen(string));
785 	return 1;
786 }
787 
788 /* for visual grepping */
789 
getxorigin(resource_t res)790 coordinate_t getxorigin(resource_t res)
791 {
792 	private_resource_t* r=get_resource(res);
793 	return r->x_origin;
794 }
795 
getyorigin(resource_t res)796 coordinate_t getyorigin(resource_t res)
797 {
798 	private_resource_t* r=get_resource(res);
799 	return r->y_origin;
800 }
801 
802