/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 astrand 333 /*
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 astrand 335 #include <rfb/rfbregion.h>
58 astrand 333
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