/[rdesktop]/sourceforge.net/trunk/rdesktop/vnc/vnc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/vnc/vnc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 335 - (show annotations)
Fri Feb 21 10:35:38 2003 UTC (21 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 29182 byte(s)
rfbregion.h is in rfb dir.

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

  ViewVC Help
Powered by ViewVC 1.1.26