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