modified dll/win32/kernel32/kernel32.rbuild
[reactos.git] / reactos / base / applications / tsclient / rdesktop / uiports / svgawin.c
1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - SVGA lib
4 Copyright (C) Jay Sorg 2004-2005
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "../rdesktop.h"
22
23 #include <vga.h>
24 #include <vgakeyboard.h>
25 #include <vgamouse.h>
26 #include <vgagl.h>
27
28 #include <unistd.h> // gethostname
29 #include <pwd.h> // getpwuid
30 #include <stdarg.h> // va_list va_start va_end
31
32 #include <sys/ioctl.h>
33 #include <linux/keyboard.h>
34 #include <linux/kd.h>
35 #include <fcntl.h>
36
37 extern int g_tcp_port_rdp;
38 int g_use_rdp5 = 0;
39 char g_hostname[16] = "";
40 char g_username[64] = "";
41 int g_height = 600;
42 int g_width = 800;
43 int g_server_bpp = 8;
44 int g_encryption = 1;
45 int g_desktop_save = 1;
46 int g_polygon_ellipse_orders = 0;
47 int g_bitmap_cache = 1;
48 int g_bitmap_cache_persist_enable = False;
49 int g_bitmap_cache_precache = True;
50 int g_bitmap_compression = 1;
51 int g_rdp5_performanceflags = 0;
52 int g_console_session = 0;
53 int g_keylayout = 0x409; /* Defaults to US keyboard layout */
54 int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */
55 int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */
56 int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */
57
58 /* hack globals */
59 int g_argc = 0;
60 char** g_argv = 0;
61 int UpAndRunning = 0;
62 int g_sock = 0;
63 int deactivated = 0;
64 uint32 ext_disc_reason = 0;
65 char g_servername[128] = "";
66 static uint32* colmap = 0;
67 static uint8* desk_save = 0;
68 static int g_server_Bpp = 1;
69
70 /* Keyboard LEDS */
71 static int numlock;
72 static int capslock;
73 static int scrolllock;
74
75 // this is non null if vgalib has non accel functions available
76 // reading from video memory is sooo slow
77 static uint8* sdata = 0;
78 static int g_save_mem = 0; // for video memory use eg sdata == 0
79
80 // video acceleration
81 static int use_accel = 1;
82 static int has_fill_box = 0;
83 static int has_screen_copy = 0;
84 static int has_put_image = 0;
85
86 // clip
87 int clip_startx;
88 int clip_starty;
89 int clip_endx;
90 int clip_endy;
91
92 // mouse
93 uint8 mouse_under[32 * 32 * 4]; // save area under mouse
94 int mousex = 0;
95 int mousey = 0;
96 int mouseb = 0;
97
98 // mouse info
99 typedef struct
100 {
101 uint8 andmask[32 * 32];
102 uint8 xormask[32 * 32];
103 int x;
104 int y;
105 int w;
106 int h;
107 } tcursor;
108
109 // mouse global
110 static tcursor mcursor;
111
112 static int g_draw_mouse = 1;
113
114 /* Session Directory redirection */
115 BOOL g_redirect = False;
116 char g_redirect_server[64];
117 char g_redirect_domain[16];
118 char g_redirect_password[64];
119 char g_redirect_username[64];
120 char g_redirect_cookie[128];
121 uint32 g_redirect_flags = 0;
122
123 // bitmap
124 typedef struct
125 {
126 int width;
127 int height;
128 uint8* data;
129 uint8 Bpp;
130 } bitmap;
131
132 typedef struct
133 {
134 int x;
135 int y;
136 int cx;
137 int cy;
138 void* prev;
139 void* next;
140 } myrect;
141
142 myrect* head_rect = 0;
143
144 //*****************************************************************************
145 // Keyboard stuff - PeterS
146 static void setled(int mask, int state)
147 {
148 int fd;
149 long int leds;
150
151 if (( fd=open("/dev/console", O_NOCTTY)) != -1 )
152 {
153 if (ioctl (fd, KDGETLED, &leds) != -1)
154 {
155 leds &= 7;
156 if (state)
157 leds |= mask;
158 else
159 leds &= ~mask;
160 ioctl (fd, KDSETLED, leds);
161 }
162 close(fd);
163 }
164 }
165
166
167 //*****************************************************************************
168 // do a raster op
169 int rop(int rop, int src, int dst)
170 {
171 switch (rop)
172 {
173 case 0x0: return 0;
174 case 0x1: return ~(src | dst);
175 case 0x2: return (~src) & dst;
176 case 0x3: return ~src;
177 case 0x4: return src & (~dst);
178 case 0x5: return ~(dst);
179 case 0x6: return src ^ dst;
180 case 0x7: return ~(src & dst);
181 case 0x8: return src & dst;
182 case 0x9: return ~(src) ^ dst;
183 case 0xa: return dst;
184 case 0xb: return (~src) | dst;
185 case 0xc: return src;
186 case 0xd: return src | (~dst);
187 case 0xe: return src | dst;
188 case 0xf: return ~0;
189 }
190 return dst;
191 }
192
193 //*****************************************************************************
194 // get a screen pixel
195 int get_pixel(int x, int y)
196 {
197 if (x >= 0 && x < g_width && y >= 0 && y < g_height)
198 {
199 if (sdata != 0)
200 {
201 if (g_server_Bpp == 1)
202 return sdata[y * g_width + x];
203 else if (g_server_Bpp == 2)
204 return ((uint16*)sdata)[y * g_width + x];
205 else
206 return 0;
207 }
208 else
209 return vga_getpixel(x, y);
210 }
211 else
212 return 0;
213 }
214
215 //*****************************************************************************
216 // set a screen pixel
217 void set_pixel(int x, int y, int pixel, int op)
218 {
219 if (x >= clip_startx && x < clip_endx && y >= clip_starty && y < clip_endy)
220 {
221 if (x >= 0 && x < g_width && y >= 0 && y < g_height)
222 {
223 if (op == 0x0)
224 pixel = 0;
225 else if (op == 0xf)
226 pixel = -1;
227 else if (op != 0xc)
228 pixel = rop(op, pixel, get_pixel(x, y));
229 if (sdata != 0)
230 {
231 if (g_server_Bpp == 1)
232 sdata[y * g_width + x] = pixel;
233 else if (g_server_Bpp == 2)
234 ((uint16*)sdata)[y * g_width + x] = pixel;
235 }
236 else
237 {
238 vga_setcolor(pixel);
239 vga_drawpixel(x, y);
240 }
241 }
242 }
243 }
244
245 //*****************************************************************************
246 // get a pixel from a bitmap
247 int get_pixel2(int x, int y, uint8* data, int width, int bpp)
248 {
249 if (bpp == 8)
250 return data[y * width + x];
251 else if (bpp == 16)
252 return ((uint16*)data)[y * width + x];
253 else
254 return 0;
255 }
256
257 //*****************************************************************************
258 // set a pixel in a bitmap
259 void set_pixel2(int x, int y, int pixel, uint8* data, int width, int bpp)
260 {
261 if (bpp == 8)
262 data[y * width + x] = pixel;
263 else if (bpp == 16)
264 ((uint16*)data)[y * width + x] = pixel;
265 }
266
267 //*****************************************************************************
268 // get a pointer into a bitmap
269 uint8* get_ptr(int x, int y, uint8* data, int width, int bpp)
270 {
271 if (bpp == 8)
272 return data + (y * width + x);
273 else if (bpp == 16)
274 return data + (y * width + x) * 2;
275 else
276 return 0;
277 }
278
279 //*****************************************************************************
280 // check if a certain pixel is set in a bitmap
281 BOOL is_pixel_on(uint8* data, int x, int y, int width, int bpp)
282 {
283 int start;
284 int shift;
285
286 if (bpp == 1)
287 {
288 width = (width + 7) / 8;
289 start = (y * width) + x / 8;
290 shift = x % 8;
291 return (data[start] & (0x80 >> shift)) != 0;
292 }
293 else if (bpp == 8)
294 {
295 return data[y * width + x] != 0;
296 }
297 else if (bpp == 24)
298 {
299 return data[(y * 3) * width + (x * 3)] != 0 &&
300 data[(y * 3) * width + (x * 3) + 1] != 0 &&
301 data[(y * 3) * width + (x * 3) + 2] != 0;
302 }
303 else
304 return False;
305 }
306
307 //*****************************************************************************
308 void set_pixel_on(uint8* data, int x, int y, int width, int bpp, int pixel)
309 {
310 if (bpp == 8)
311 {
312 data[y * width + x] = pixel;
313 }
314 }
315
316 /*****************************************************************************/
317 int warp_coords(int* x, int* y, int* cx, int* cy, int* srcx, int* srcy)
318 {
319 int dx;
320 int dy;
321 // int lx = *x, ly = *y, lcx = *cx, lcy = *cy;
322
323 if (clip_startx > *x)
324 dx = clip_startx - *x;
325 else
326 dx = 0;
327 if (clip_starty > *y)
328 dy = clip_starty - *y;
329 else
330 dy = 0;
331 if (*x + *cx > clip_endx)
332 *cx = (*cx - ((*x + *cx) - clip_endx)) /*+ 1*/;
333 if (*y + *cy > clip_endy)
334 *cy = (*cy - ((*y + *cy) - clip_endy)) /*+ 1*/;
335 *cx = *cx - dx;
336 *cy = *cy - dy;
337 if (*cx <= 0)
338 return False;
339 if (*cy <= 0)
340 return False;
341 *x = *x + dx;
342 *y = *y + dy;
343 if (srcx != NULL)
344 *srcx = *srcx + dx;
345 if (srcy != NULL)
346 *srcy = *srcy + dy;
347
348 // if (*x != lx || *y != ly || *cx != lcx || *cy != lcy)
349 // printf("%d %d %d %d to %d %d %d %d\n", lx, ly, lcx, lcy, *x, *y, *cx, *cy);
350
351 return True;
352 }
353
354 //*****************************************************************************
355 void copy_mem(uint8* d, uint8* s, int n)
356 {
357 while (n & (~7))
358 {
359 *(d++) = *(s++);
360 *(d++) = *(s++);
361 *(d++) = *(s++);
362 *(d++) = *(s++);
363 *(d++) = *(s++);
364 *(d++) = *(s++);
365 *(d++) = *(s++);
366 *(d++) = *(s++);
367 n = n - 8;
368 }
369 while (n > 0)
370 {
371 *(d++) = *(s++);
372 n--;
373 }
374 }
375
376 //*****************************************************************************
377 void copy_memb(uint8* d, uint8* s, int n)
378 {
379 d = (d + n) - 1;
380 s = (s + n) - 1;
381 while (n & (~7))
382 {
383 *(d--) = *(s--);
384 *(d--) = *(s--);
385 *(d--) = *(s--);
386 *(d--) = *(s--);
387 *(d--) = *(s--);
388 *(d--) = *(s--);
389 *(d--) = *(s--);
390 *(d--) = *(s--);
391 n = n - 8;
392 }
393 while (n > 0)
394 {
395 *(d--) = *(s--);
396 n--;
397 }
398 }
399
400 //*****************************************************************************
401 // all in pixel except line_size is in bytes
402 void accel_draw_box(int x, int y, int cx, int cy, uint8* data, int line_size)
403 {
404 int i;
405 uint8* s;
406 uint8* d;
407
408 if (sdata != 0)
409 {
410 s = data;
411 d = get_ptr(x, y, sdata, g_width, g_server_bpp);
412 for (i = 0; i < cy; i++)
413 {
414 copy_mem(d, s, cx * g_server_Bpp);
415 s = s + line_size;
416 d = d + g_width * g_server_Bpp;
417 }
418 }
419 else if (has_put_image && line_size == cx * g_server_Bpp)
420 {
421 vga_accel(ACCEL_PUTIMAGE, x, y, cx, cy, data);
422 }
423 else
424 {
425 s = data;
426 for (i = 0; i < cy; i++)
427 {
428 vga_drawscansegment(s, x, y + i, cx * g_server_Bpp);
429 s = s + line_size;
430 }
431 }
432 }
433
434 //*****************************************************************************
435 void accel_fill_rect(int x, int y, int cx, int cy, int color)
436 {
437 int i;
438 uint8* temp;
439 uint8* d;
440
441 if (sdata != 0)
442 {
443 temp = xmalloc(cx * g_server_Bpp);
444 if (g_server_Bpp == 1)
445 for (i = 0; i < cx; i++)
446 temp[i] = color;
447 else if (g_server_Bpp == 2)
448 for (i = 0; i < cx; i++)
449 ((uint16*)temp)[i] = color;
450 d = get_ptr(x, y, sdata, g_width, g_server_bpp);
451 for (i = 0; i < cy; i++)
452 {
453 copy_mem(d, temp, cx * g_server_Bpp);
454 d = d + g_width * g_server_Bpp;
455 }
456 xfree(temp);
457 }
458 else if (has_fill_box)
459 {
460 vga_accel(ACCEL_SETFGCOLOR, color);
461 vga_accel(ACCEL_FILLBOX, x, y, cx, cy);
462 }
463 else
464 {
465 temp = xmalloc(cx * g_server_Bpp);
466 if (g_server_Bpp == 1)
467 for (i = 0; i < cx; i++)
468 temp[i] = color;
469 else if (g_server_Bpp == 2)
470 for (i = 0; i < cx; i++)
471 ((uint16*)temp)[i] = color;
472 for (i = 0; i < cy; i++)
473 vga_drawscansegment(temp, x, y + i, cx * g_server_Bpp);
474 xfree(temp);
475 }
476 }
477
478 //*****************************************************************************
479 void accel_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy)
480 {
481 uint8* temp;
482 uint8* s;
483 uint8* d;
484 int i;
485
486 if (sdata != 0)
487 {
488 if (srcy < y)
489 { // bottom to top
490 s = get_ptr(srcx, (srcy + cy) - 1, sdata, g_width, g_server_bpp);
491 d = get_ptr(x, (y + cy) - 1, sdata, g_width, g_server_bpp);
492 for (i = 0; i < cy; i++) // copy down
493 {
494 copy_mem(d, s, cx * g_server_Bpp);
495 s = s - g_width * g_server_Bpp;
496 d = d - g_width * g_server_Bpp;
497 }
498 }
499 else if (srcy > y || srcx > x) // copy up or left
500 { // top to bottom
501 s = get_ptr(srcx, srcy, sdata, g_width, g_server_bpp);
502 d = get_ptr(x, y, sdata, g_width, g_server_bpp);
503 for (i = 0; i < cy; i++)
504 {
505 copy_mem(d, s, cx * g_server_Bpp);
506 s = s + g_width * g_server_Bpp;
507 d = d + g_width * g_server_Bpp;
508 }
509 }
510 else // copy straight right
511 {
512 s = get_ptr(srcx, srcy, sdata, g_width, g_server_bpp);
513 d = get_ptr(x, y, sdata, g_width, g_server_bpp);
514 for (i = 0; i < cy; i++)
515 {
516 copy_memb(d, s, cx * g_server_Bpp);
517 s = s + g_width * g_server_Bpp;
518 d = d + g_width * g_server_Bpp;
519 }
520 }
521 }
522 else if (has_screen_copy)
523 {
524 vga_accel(ACCEL_SCREENCOPY, srcx, srcy, x, y, cx, cy);
525 }
526 else
527 {
528 // slow
529 temp = (uint8*)xmalloc(cx * cy * g_server_Bpp);
530 for (i = 0; i < cy; i++)
531 vga_getscansegment(get_ptr(0, i, temp, cx, g_server_bpp), srcx, srcy + i, cx * g_server_Bpp);
532 for (i = 0; i < cy; i++)
533 vga_drawscansegment(get_ptr(0, i, temp, cx, g_server_bpp), x, y + i, cx * g_server_Bpp);
534 xfree(temp);
535 }
536 }
537
538 //*****************************************************************************
539 // return bool
540 int contains_mouse(int x, int y, int cx, int cy)
541 {
542 if (mousex + 32 >= x &&
543 mousey + 32 >= y &&
544 mousex <= x + cx &&
545 mousey <= y + cy)
546 return 1;
547 else
548 return 0;
549 }
550
551 //*****************************************************************************
552 void fill_rect(int x, int y, int cx, int cy, int colour, int opcode)
553 {
554 int i;
555 int j;
556
557 if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
558 {
559 if (opcode == 0xc)
560 accel_fill_rect(x, y, cx, cy, colour);
561 else if (opcode == 0xf)
562 accel_fill_rect(x, y, cx, cy, -1);
563 else if (opcode == 0x0)
564 accel_fill_rect(x, y, cx, cy, 0);
565 else
566 {
567 for (i = 0; i < cy; i++)
568 for (j = 0; j < cx; j++)
569 set_pixel(x + j, y + i, colour, opcode);
570 }
571 }
572 }
573
574 //*****************************************************************************
575 void get_rect(int x, int y, int cx, int cy, uint8* p)
576 {
577 int i;
578
579 if (x < 0)
580 {
581 cx = cx + x;
582 x = 0;
583 }
584 if (y < 0)
585 {
586 cy = cy + y;
587 y = 0;
588 }
589 if (sdata != 0)
590 {
591 for (i = 0; i < cy; i++)
592 {
593 copy_mem(p, get_ptr(x, y + i, sdata, g_width, g_server_bpp), cx * g_server_Bpp);
594 p = p + cx * g_server_Bpp;
595 }
596 }
597 else
598 {
599 for (i = 0; i < cy; i++)
600 {
601 vga_getscansegment(p, x, y + i, cx * g_server_Bpp);
602 p = p + cx * g_server_Bpp;
603 }
604 }
605 }
606
607 /*****************************************************************************/
608 // return true if r1 is contained by r2
609 int is_contained_by(myrect* r1, myrect* r2)
610 {
611 if (r1->x >= r2->x &&
612 r1->y >= r2->y &&
613 r1->x + r1->cx <= r2->x + r2->cx &&
614 r1->y + r1->cy <= r2->y + r2->cy)
615 return 1;
616 else
617 return 0;
618 }
619
620 /*****************************************************************************/
621 void draw_cursor_under(int ox, int oy)
622 {
623 int i;
624 int j;
625 int k;
626 uint8* ptr;
627 int len;
628
629 if (ox < 0)
630 k = -ox;
631 else
632 k = 0;
633 j = g_width - ox;
634 if (j > 32)
635 j = 32;
636 if (j > 0)
637 {
638 for (i = 0; i < 32; i++)
639 {
640 ptr = get_ptr(k, i, mouse_under, 32, g_server_bpp);
641 len = (j - k) * g_server_Bpp;
642 if (ox + k >= 0 && oy + i >= 0 && ox + k < g_width && oy + i < g_height)
643 vga_drawscansegment(ptr, ox + k, oy + i, len);
644 }
645 }
646 g_draw_mouse = 1;
647 }
648
649 /*****************************************************************************/
650 void draw_cursor(void)
651 {
652 int i;
653 int j;
654 int k;
655 int pixel;
656 uint8 mouse_a[32 * 32 * 4];
657 uint8* ptr;
658 int len;
659
660 if (!g_draw_mouse)
661 return;
662 memset(mouse_under, 0, sizeof(mouse_under));
663 for (i = 0; i < 32; i++)
664 {
665 for (j = 0; j < 32; j++)
666 {
667 pixel = get_pixel(mousex + j, mousey + i);
668 set_pixel2(j, i, pixel, mouse_under, 32, g_server_bpp);
669 if (mcursor.andmask[i * 32 + j] == 0)
670 k = 0;
671 else
672 k = ~0;
673 pixel = rop(0x8, k, pixel);
674 if (mcursor.xormask[i * 32 + j] == 0)
675 k = 0;
676 else
677 k = ~0;
678 pixel = rop(0x6, k, pixel);
679 set_pixel2(j, i, pixel, mouse_a, 32, g_server_bpp);
680 }
681 }
682 if (mousex < 0)
683 k = -mousex;
684 else
685 k = 0;
686 j = g_width - mousex;
687 if (j > 32)
688 j = 32;
689 if (j > 0)
690 {
691 for (i = mousey; i < mousey + 32; i++)
692 if (i < g_height && i >= 0)
693 {
694 ptr = get_ptr(k, i - mousey, mouse_a, 32, g_server_bpp);
695 len = (j - k) * g_server_Bpp;
696 vga_drawscansegment(ptr, mousex + k, i, len);
697 }
698 }
699 g_draw_mouse = 0;
700 }
701
702 /*****************************************************************************/
703 // add a rect to cache
704 void cache_rect(int x, int y, int cx, int cy, int do_warp)
705 {
706 myrect* rect;
707 myrect* walk_rect;
708
709 if (sdata == 0)
710 {
711 draw_cursor();
712 return;
713 }
714 if (do_warp)
715 if (!warp_coords(&x, &y, &cx, &cy, NULL, NULL))
716 return;
717 rect = (myrect*)xmalloc(sizeof(myrect));
718 rect->x = x;
719 rect->y = y;
720 rect->cx = cx;
721 rect->cy = cy;
722 rect->next = 0;
723 rect->prev = 0;
724 if (head_rect == 0)
725 head_rect = rect;
726 else
727 {
728 walk_rect = 0;
729 do
730 {
731 if (walk_rect == 0)
732 walk_rect = head_rect;
733 else
734 walk_rect = walk_rect->next;
735 if (is_contained_by(rect, walk_rect))
736 {
737 xfree(rect);
738 return;
739 }
740 }
741 while (walk_rect->next != 0);
742 walk_rect->next = rect;
743 rect->prev = walk_rect;
744 }
745 }
746
747 //*****************************************************************************
748 void draw_cache_rects(void)
749 {
750 int i;
751 myrect* rect;
752 myrect* rect1;
753 uint8* p;
754
755 // draw all the rects
756 rect = head_rect;
757 while (rect != 0)
758 {
759 p = get_ptr(rect->x, rect->y, sdata, g_width, g_server_bpp);
760 for (i = 0; i < rect->cy; i++)
761 {
762 vga_drawscansegment(p, rect->x, rect->y + i, rect->cx * g_server_Bpp);
763 p = p + g_width * g_server_Bpp;
764 }
765 rect1 = rect;
766 rect = rect->next;
767 xfree(rect1);
768 }
769 head_rect = 0;
770 }
771
772 /*****************************************************************************/
773 void key_event(int scancode, int pressed)
774 {
775 int rdpkey;
776 int ext;
777
778 if (!UpAndRunning)
779 return;
780 rdpkey = scancode;
781 ext = 0;
782
783 // Keyboard LEDS
784 if ((scancode == SCANCODE_CAPSLOCK) && pressed)
785 {
786 capslock = !capslock;
787 setled(LED_CAP, capslock);
788 }
789 if ((scancode == SCANCODE_SCROLLLOCK) && pressed)
790 {
791 scrolllock = !scrolllock;
792 setled(LED_SCR, scrolllock);
793 }
794
795 if ((scancode == SCANCODE_NUMLOCK) && pressed)
796 {
797 numlock = !numlock;
798 setled(LED_NUM, numlock);
799 }
800
801 switch (scancode)
802 {
803 case SCANCODE_CURSORBLOCKUP: rdpkey = 0xc8; ext = KBD_FLAG_EXT; break; // up arrow
804 case SCANCODE_CURSORBLOCKDOWN: rdpkey = 0xd0; ext = KBD_FLAG_EXT; break; // down arrow
805 case SCANCODE_CURSORBLOCKRIGHT: rdpkey = 0xcd; ext = KBD_FLAG_EXT; break; // right arrow
806 case SCANCODE_CURSORBLOCKLEFT: rdpkey = 0xcb; ext = KBD_FLAG_EXT; break; // left arrow
807 case SCANCODE_PAGEDOWN: rdpkey = 0xd1; ext = KBD_FLAG_EXT; break; // page down
808 case SCANCODE_PAGEUP: rdpkey = 0xc9; ext = KBD_FLAG_EXT; break; // page up
809 case SCANCODE_HOME: rdpkey = 0xc7; ext = KBD_FLAG_EXT; break; // home
810 case SCANCODE_END: rdpkey = 0xcf; ext = KBD_FLAG_EXT; break; // end
811 case SCANCODE_INSERT: rdpkey = 0xd2; ext = KBD_FLAG_EXT; break; // insert
812 case SCANCODE_REMOVE: rdpkey = 0xd3; ext = KBD_FLAG_EXT; break; // delete
813 case SCANCODE_KEYPADDIVIDE: rdpkey = 0x35; break; // /
814 case SCANCODE_KEYPADENTER: rdpkey = 0x1c; break; // enter
815 case SCANCODE_RIGHTCONTROL: rdpkey = 0x1d; break; // right ctrl
816 case SCANCODE_RIGHTALT: rdpkey = 0x38; break; // right alt
817 case SCANCODE_LEFTWIN: rdpkey = 0x5b; ext = KBD_FLAG_EXT; break; // left win
818 case SCANCODE_RIGHTWIN: rdpkey = 0x5c; ext = KBD_FLAG_EXT; break; // right win
819 case 127: rdpkey = 0x5d; ext = KBD_FLAG_EXT; break; // menu key
820 case SCANCODE_PRINTSCREEN: rdpkey = 0x37; ext = KBD_FLAG_EXT; break; // print screen
821 case SCANCODE_BREAK: //rdpkey = 0; break; // break
822 {
823 if (pressed)
824 {
825 ext = KBD_FLAG_EXT;
826 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS | ext, 0x46, 0);
827 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS | ext, 0xc6, 0);
828 }
829 rdpkey = 0;
830 }
831 case SCANCODE_SCROLLLOCK: rdpkey = 0x46; break; // scroll lock
832 case 112: // mouse down
833 {
834 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON4,
835 mouse_getx(), mouse_gety());
836 return;
837 }
838 case 113: // mouse up
839 {
840 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON5,
841 mouse_getx(), mouse_gety());
842 return;
843 }
844 }
845 // printf("%d %d\n", scancode, pressed);
846 if (pressed)
847 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS | ext, rdpkey, 0);
848 else
849 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE | ext, rdpkey, 0);
850
851
852 }
853
854 /*****************************************************************************/
855 int ui_init(void)
856 {
857 vga_init();
858 memset(&mcursor, 0, sizeof(tcursor));
859 desk_save = (uint8*)xmalloc(0x38400 * g_server_Bpp);
860 return 1;
861 }
862
863 /*****************************************************************************/
864 void ui_deinit(void)
865 {
866 xfree(desk_save);
867 }
868
869 /*****************************************************************************/
870 int ui_create_window(void)
871 {
872 int vgamode;
873 int i;
874
875 vgamode = G800x600x256;
876 if (g_width == 640 && g_height == 480)
877 {
878 if (g_server_Bpp == 1)
879 vgamode = G640x480x256;
880 else if (g_server_Bpp == 2)
881 vgamode = G640x480x64K;
882 }
883 else if (g_width == 800 && g_height == 600)
884 {
885 if (g_server_Bpp == 1)
886 vgamode = G800x600x256;
887 else if (g_server_Bpp == 2)
888 vgamode = G800x600x64K;
889 }
890 else if (g_width == 1024 && g_height == 768)
891 {
892 if (g_server_Bpp == 1)
893 vgamode = G1024x768x256;
894 else if (g_server_Bpp == 2)
895 vgamode = G1024x768x64K;
896 }
897 else
898 {
899 error("Invalid width / height");
900 return 0;
901 }
902 ui_reset_clip();
903 if (!vga_hasmode(vgamode))
904 {
905 error("Graphics unavailable");
906 return 0;
907 }
908 vga_setmousesupport(1);
909 mouse_setposition(g_width / 2, g_height / 2);
910 vga_setmode(vgamode);
911 if (keyboard_init())
912 {
913 error("Keyboard unavailable");
914 return 0;
915 }
916 keyboard_seteventhandler(key_event);
917 if (use_accel)
918 {
919 i = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL);
920 if (i & ACCELFLAG_PUTIMAGE)
921 has_put_image = 1;
922 if (i & ACCELFLAG_SCREENCOPY)
923 has_screen_copy = 1;
924 if (i & ACCELFLAG_FILLBOX)
925 has_fill_box = 1;
926 printf("accel %d\n", i);
927 }
928 if (!has_screen_copy && !g_save_mem)
929 sdata = xmalloc(g_width * g_height * g_server_Bpp);
930 return 1;
931 }
932
933 /*****************************************************************************/
934 void ui_destroy_window(void)
935 {
936 keyboard_close(); /* Don't forget this! */
937 vga_setmode(TEXT);
938 if (sdata != 0)
939 xfree(sdata);
940 }
941
942 /*****************************************************************************/
943 void process_mouse(void)
944 {
945 int ox = mousex;
946 int oy = mousey;
947 int ob = mouseb;
948
949 if (!UpAndRunning)
950 return;
951 mousex = mouse_getx() - mcursor.x;
952 mousey = mouse_gety() - mcursor.y;
953 mouseb = mouse_getbutton();
954
955 if (mouseb != ob) // button
956 {
957 // right button
958 if (mouseb & 1)
959 if (!(ob & 1))
960 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2,
961 mousex + mcursor.x, mousey + mcursor.y);
962 if (ob & 1)
963 if (!(mouseb & 1))
964 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2,
965 mousex + mcursor.x, mousey + mcursor.y);
966 // middle button
967 if (mouseb & 2)
968 if (!(ob & 2))
969 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON3,
970 mousex + mcursor.x, mousey + mcursor.y);
971 if (ob & 2)
972 if (!(mouseb & 2))
973 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3,
974 mousex + mcursor.x, mousey + mcursor.y);
975 // left button
976 if (mouseb & 4)
977 if (!(ob & 4))
978 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1,
979 mousex + mcursor.x, mousey + mcursor.y);
980 if (ob & 4)
981 if (!(mouseb & 4))
982 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1,
983 mousex + mcursor.x, mousey + mcursor.y);
984 }
985 if (mousex != ox || mousey != oy) // movement
986 {
987 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
988 mousex + mcursor.x, mousey + mcursor.y);
989 draw_cursor_under(ox, oy);
990 draw_cursor();
991 }
992 }
993
994 /*****************************************************************************/
995 void process_keyboard(void)
996 {
997 if (!UpAndRunning)
998 return;
999 }
1000
1001 /*****************************************************************************/
1002 BOOL ui_main_loop(void)
1003 {
1004 int sel;
1005 fd_set rfds;
1006
1007 if (!rdp_connect(g_servername, RDP_LOGON_NORMAL, "", "", "", ""))
1008 return False;
1009 UpAndRunning = 1;
1010 FD_ZERO(&rfds);
1011 FD_SET(g_sock, &rfds);
1012 sel = vga_waitevent(3, &rfds, NULL, NULL, NULL);
1013 while (sel >= 0)
1014 {
1015 if (sel & 1) /* mouse */
1016 {
1017 process_mouse();
1018 }
1019 else if (sel & 2) /* keyboard */
1020 {
1021 process_keyboard();
1022 }
1023 else
1024 {
1025 if (!rdp_loop(&deactivated, &ext_disc_reason))
1026 return True; /* ok */
1027 }
1028 FD_ZERO(&rfds);
1029 FD_SET(g_sock, &rfds);
1030 sel = vga_waitevent(3, &rfds, NULL, NULL, NULL);
1031 }
1032 return True;
1033 }
1034
1035 /*****************************************************************************/
1036 void ui_bell(void)
1037 {
1038 }
1039
1040 /*****************************************************************************/
1041 int ui_select(int in)
1042 {
1043 g_sock = in;
1044 return 1;
1045 }
1046
1047 /*****************************************************************************/
1048 void* ui_create_glyph(int width, int height, uint8* data)
1049 {
1050 int i, j;
1051 uint8* glyph_data;
1052 bitmap* the_glyph;
1053
1054 glyph_data = (uint8*)xmalloc(width * height);
1055 the_glyph = (bitmap*)xmalloc(sizeof(bitmap));
1056 the_glyph->width = width;
1057 the_glyph->height = height;
1058 the_glyph->data = glyph_data;
1059 memset(glyph_data, 0, width * height);
1060 for (i = 0; i < height; i++)
1061 for (j = 0; j < width; j++)
1062 if (is_pixel_on(data, j, i, width, 1))
1063 set_pixel_on(glyph_data, j, i, width, 8, 255);
1064 return the_glyph;
1065 }
1066
1067 /*****************************************************************************/
1068 void ui_destroy_glyph(void* glyph)
1069 {
1070 bitmap* the_glyph;
1071
1072 the_glyph = (bitmap*)glyph;
1073 if (the_glyph != NULL)
1074 {
1075 if (the_glyph->data != NULL)
1076 xfree(the_glyph->data);
1077 xfree(the_glyph);
1078 }
1079 }
1080
1081 /*****************************************************************************/
1082 void ui_destroy_bitmap(void* bmp)
1083 {
1084 bitmap* b;
1085
1086 b = (bitmap*)bmp;
1087 xfree(b->data);
1088 xfree(b);
1089 }
1090
1091 /*****************************************************************************/
1092 void ui_reset_clip(void)
1093 {
1094 clip_startx = 0;
1095 clip_starty = 0;
1096 clip_endx = g_width;
1097 clip_endy = g_height;
1098 }
1099
1100 /*****************************************************************************/
1101 void ui_set_clip(int x, int y, int cx, int cy)
1102 {
1103 clip_startx = x;
1104 clip_starty = y;
1105 clip_endx = x + cx;
1106 clip_endy = y + cy;
1107 }
1108
1109 /*****************************************************************************/
1110 void* ui_create_colourmap(COLOURMAP * colours)
1111 {
1112 int i = 0;
1113 int n = colours->ncolours;
1114 COLOURENTRY* c = colours->colours;
1115 int* cmap = (int*)xmalloc(3 * 256 * sizeof (int));
1116 if (n > 256)
1117 n = 256;
1118 bzero(cmap, 256 * 3 * sizeof (int));
1119 for (i = 0; i < (3 * n); c++)
1120 {
1121 cmap[i++] = (c->red) >> 2;
1122 cmap[i++] = (c->green) >> 2;
1123 cmap[i++] = (c->blue) >> 2;
1124 }
1125 return cmap;
1126 }
1127
1128 /*****************************************************************************/
1129 void ui_destroy_colourmap(HCOLOURMAP map)
1130 {
1131 if (colmap == map)
1132 colmap = 0;
1133 xfree(map);
1134 }
1135
1136 /*****************************************************************************/
1137 void ui_set_colourmap(void* map)
1138 {
1139 if (colmap != 0)
1140 xfree(colmap);
1141 vga_setpalvec(0, 256, (int*)map);
1142 colmap = map;
1143 }
1144
1145 /*****************************************************************************/
1146 HBITMAP ui_create_bitmap(int width, int height, uint8* data)
1147 {
1148 bitmap* b;
1149
1150 b = (bitmap*)xmalloc(sizeof(bitmap));
1151 b->data = (uint8*)xmalloc(width * height * g_server_Bpp);
1152 b->width = width;
1153 b->height = height;
1154 b->Bpp = g_server_Bpp;
1155 copy_mem(b->data, data, width * height * g_server_Bpp);
1156 return (void*)b;
1157 }
1158
1159 //*****************************************************************************
1160 void draw_glyph (int x, int y, HGLYPH glyph, int fgcolour)
1161 {
1162 bitmap* the_glyph;
1163 int i, j;
1164
1165 the_glyph = (bitmap*)glyph;
1166 if (the_glyph == NULL)
1167 return;
1168 for (i = 0; i < the_glyph->height; i++)
1169 for (j = 0; j < the_glyph->width; j++)
1170 if (is_pixel_on(the_glyph->data, j, i, the_glyph->width, 8))
1171 set_pixel(x + j, y + i, fgcolour, 0xc);
1172 }
1173
1174 #define DO_GLYPH(ttext,idx) \
1175 {\
1176 glyph = cache_get_font (font, ttext[idx]);\
1177 if (!(flags & TEXT2_IMPLICIT_X))\
1178 {\
1179 xyoffset = ttext[++idx];\
1180 if ((xyoffset & 0x80))\
1181 {\
1182 if (flags & TEXT2_VERTICAL) \
1183 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1184 else\
1185 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1186 idx += 2;\
1187 }\
1188 else\
1189 {\
1190 if (flags & TEXT2_VERTICAL) \
1191 y += xyoffset;\
1192 else\
1193 x += xyoffset;\
1194 }\
1195 }\
1196 if (glyph != NULL)\
1197 {\
1198 draw_glyph (x + glyph->offset, y + glyph->baseline, glyph->pixmap, fgcolour);\
1199 if (flags & TEXT2_IMPLICIT_X)\
1200 x += glyph->width;\
1201 }\
1202 }
1203
1204 /*****************************************************************************/
1205 void ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode,
1206 int x, int y,
1207 int clipx, int clipy, int clipcx, int clipcy,
1208 int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
1209 int bgcolour, int fgcolour, uint8* text, uint8 length)
1210 {
1211 int i;
1212 int j;
1213 int xyoffset;
1214 DATABLOB* entry;
1215 FONTGLYPH* glyph;
1216
1217 if (boxcx > 1)
1218 {
1219 if (contains_mouse(boxx, boxy, boxcx, boxcy))
1220 draw_cursor_under(mousex, mousey);
1221 fill_rect(boxx, boxy, boxcx, boxcy, bgcolour, 0xc);
1222 }
1223 else
1224 {
1225 if (contains_mouse(clipx, clipy, clipcx, clipcy))
1226 draw_cursor_under(mousex, mousey);
1227 if (mixmode == MIX_OPAQUE)
1228 fill_rect(clipx, clipy, clipcx, clipcy, bgcolour, 0xc);
1229 }
1230
1231 /* Paint text, character by character */
1232 for (i = 0; i < length;)
1233 {
1234 switch (text[i])
1235 {
1236 case 0xff:
1237 if (i + 2 < length)
1238 cache_put_text(text[i + 1], text, text[i + 2]);
1239 else
1240 {
1241 error("this shouldn't be happening\n");
1242 exit(1);
1243 }
1244 /* this will move pointer from start to first character after FF command */
1245 length -= i + 3;
1246 text = &(text[i + 3]);
1247 i = 0;
1248 break;
1249
1250 case 0xfe:
1251 entry = cache_get_text(text[i + 1]);
1252 if (entry != NULL)
1253 {
1254 if ((((uint8 *) (entry->data))[1] == 0) && (!(flags & TEXT2_IMPLICIT_X)))
1255 {
1256 if (flags & TEXT2_VERTICAL)
1257 y += text[i + 2];
1258 else
1259 x += text[i + 2];
1260 }
1261 for (j = 0; j < entry->size; j++)
1262 DO_GLYPH(((uint8 *) (entry->data)), j);
1263 }
1264 if (i + 2 < length)
1265 i += 3;
1266 else
1267 i += 2;
1268 length -= i;
1269 /* this will move pointer from start to first character after FE command */
1270 text = &(text[i]);
1271 i = 0;
1272 break;
1273
1274 default:
1275 DO_GLYPH(text, i);
1276 i++;
1277 break;
1278 }
1279 }
1280 if (boxcx > 1)
1281 cache_rect(boxx, boxy, boxcx, boxcy, True);
1282 else
1283 cache_rect(clipx, clipy, clipcx, clipcy, True);
1284 }
1285
1286 //*****************************************************************************
1287 // Bresenham's line drawing algorithm
1288 void ui_line(uint8 opcode, int startx, int starty, int endx,
1289 int endy, PEN* pen)
1290 {
1291 int dx;
1292 int dy;
1293 int incx;
1294 int incy;
1295 int dpr;
1296 int dpru;
1297 int p;
1298 int left;
1299 int top;
1300 int right;
1301 int bottom;
1302
1303 if (startx > endx)
1304 {
1305 dx = startx - endx;
1306 incx = -1;
1307 left = endx;
1308 right = startx;
1309 }
1310 else
1311 {
1312 dx = endx - startx;
1313 incx = 1;
1314 left = startx;
1315 right = endx;
1316 }
1317 if (starty > endy)
1318 {
1319 dy = starty - endy;
1320 incy = -1;
1321 top = endy;
1322 bottom = starty;
1323 }
1324 else
1325 {
1326 dy = endy - starty;
1327 incy = 1;
1328 top = starty;
1329 bottom = endy;
1330 }
1331 if (contains_mouse(left, top, (right - left) + 1, (bottom - top) + 1))
1332 draw_cursor_under(mousex, mousey);
1333 if (dx >= dy)
1334 {
1335 dpr = dy << 1;
1336 dpru = dpr - (dx << 1);
1337 p = dpr - dx;
1338 for (; dx >= 0; dx--)
1339 {
1340 set_pixel(startx, starty, pen->colour, opcode);
1341 if (p > 0)
1342 {
1343 startx += incx;
1344 starty += incy;
1345 p += dpru;
1346 }
1347 else
1348 {
1349 startx += incx;
1350 p += dpr;
1351 }
1352 }
1353 }
1354 else
1355 {
1356 dpr = dx << 1;
1357 dpru = dpr - (dy << 1);
1358 p = dpr - dy;
1359 for (; dy >= 0; dy--)
1360 {
1361 set_pixel(startx, starty, pen->colour, opcode);
1362 if (p > 0)
1363 {
1364 startx += incx;
1365 starty += incy;
1366 p += dpru;
1367 }
1368 else
1369 {
1370 starty += incy;
1371 p += dpr;
1372 }
1373 }
1374 }
1375 cache_rect(left, top, (right - left) + 1, (bottom - top) + 1, True);
1376 }
1377
1378 /*****************************************************************************/
1379 void ui_triblt(uint8 opcode, int x, int y, int cx, int cy,
1380 HBITMAP src, int srcx, int srcy,
1381 BRUSH* brush, int bgcolour, int fgcolour)
1382 {
1383 // non used
1384 }
1385
1386 /*****************************************************************************/
1387 void ui_memblt(uint8 opcode, int x, int y, int cx, int cy,
1388 HBITMAP src, int srcx, int srcy)
1389 {
1390 bitmap* b;
1391 int i;
1392 int j;
1393 int pixel;
1394
1395 if (warp_coords(&x, &y, &cx, &cy, &srcx, &srcy))
1396 {
1397 if (contains_mouse(x, y, cx, cy))
1398 draw_cursor_under(mousex, mousey);
1399 b = (bitmap*)src;
1400 if (opcode == 0xc)
1401 accel_draw_box(x, y, cx, cy, get_ptr(srcx, srcy, b->data, b->width, g_server_bpp),
1402 b->width * g_server_Bpp);
1403 else
1404 {
1405 for (i = 0; i < cy; i++)
1406 {
1407 for (j = 0; j < cx; j++)
1408 {
1409 pixel = get_pixel2(srcx + j, srcy + i, b->data, b->width, g_server_bpp);
1410 set_pixel(x + j, y + i, pixel, opcode);
1411 }
1412 }
1413 }
1414 cache_rect(x, y, cx, cy, False);
1415 }
1416 }
1417
1418 /*****************************************************************************/
1419 void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1420 {
1421 uint8* p;
1422
1423 if (offset > 0x38400)
1424 offset = 0;
1425 if (offset + cx * cy > 0x38400)
1426 return;
1427 p = desk_save + offset * g_server_Bpp;
1428 ui_paint_bitmap(x, y, cx, cy, cx, cy, p);
1429 }
1430
1431 /*****************************************************************************/
1432 void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1433 {
1434 uint8* p;
1435
1436 if (offset > 0x38400)
1437 offset = 0;
1438 if (offset + cx * cy > 0x38400)
1439 return;
1440 if (contains_mouse(x, y, cx, cy))
1441 draw_cursor_under(mousex, mousey);
1442 p = desk_save + offset * g_server_Bpp;
1443 get_rect(x, y, cx, cy, p);
1444 }
1445
1446 /*****************************************************************************/
1447 void ui_rect(int x, int y, int cx, int cy, int colour)
1448 {
1449 if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
1450 {
1451 if (contains_mouse(x, y, cx, cy))
1452 draw_cursor_under(mousex, mousey);
1453 accel_fill_rect(x, y, cx, cy, colour);
1454 cache_rect(x, y, cx, cy, False);
1455 }
1456 }
1457
1458 /*****************************************************************************/
1459 void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,
1460 int srcx, int srcy)
1461 {
1462 int i;
1463 int j;
1464 uint8* temp;
1465
1466 if (x == srcx && y == srcy)
1467 return;
1468 if (warp_coords(&x, &y, &cx, &cy, &srcx, &srcy))
1469 {
1470 if (contains_mouse(x, y, cx, cy) || contains_mouse(srcx, srcy, cx, cy))
1471 draw_cursor_under(mousex, mousey);
1472 if (opcode == 0xc) /* copy */
1473 accel_screen_copy(x, y, cx, cy, srcx, srcy);
1474 else
1475 {
1476 temp = (uint8*)xmalloc(cx * cy * g_server_Bpp);
1477 for (i = 0; i < cy; i++)
1478 for (j = 0; j < cx; j++)
1479 set_pixel2(j, i, get_pixel(srcx + j, srcy + i), temp, cx, g_server_bpp);
1480 for (i = 0; i < cy; i++)
1481 for (j = 0; j < cx; j++)
1482 set_pixel(x + j, y + i, get_pixel2(j, i, temp, cx, g_server_bpp), opcode);
1483 xfree(temp);
1484 }
1485 cache_rect(x, y, cx, cy, False);
1486 draw_cache_rects(); // draw them all so screen is not jumpy
1487 }
1488 }
1489
1490 /*****************************************************************************/
1491 void ui_patblt(uint8 opcode, int x, int y, int cx, int cy,
1492 BRUSH * brush, int bgcolour, int fgcolour)
1493 {
1494 int i;
1495 int j;
1496 uint8 ipattern[8];
1497
1498 if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
1499 {
1500 if (contains_mouse(x, y, cx, cy))
1501 draw_cursor_under(mousex, mousey);
1502 switch (brush->style)
1503 {
1504 case 0:
1505 fill_rect(x, y, cx, cy, fgcolour, opcode);
1506 break;
1507 case 3:
1508 for (i = 0; i < 8; i++)
1509 ipattern[i] = ~brush->pattern[7 - i];
1510 for (i = 0; i < cy; i++)
1511 for (j = 0; j < cx; j++)
1512 if (is_pixel_on(ipattern, (x + j + brush->xorigin) % 8,
1513 (y + i + brush->yorigin) % 8, 8, 1))
1514 set_pixel(x + j, y + i, fgcolour, opcode);
1515 else
1516 set_pixel(x + j, y + i, bgcolour, opcode);
1517 break;
1518 }
1519 cache_rect(x, y, cx, cy, False);
1520 }
1521 }
1522
1523 /*****************************************************************************/
1524 void ui_destblt(uint8 opcode, int x, int y, int cx, int cy)
1525 {
1526 if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
1527 {
1528 if (contains_mouse(x, y, cx, cy))
1529 draw_cursor_under(mousex, mousey);
1530 fill_rect(x, y, cx, cy, -1, opcode);
1531 cache_rect(x, y, cx, cy, False);
1532 }
1533 }
1534
1535 /*****************************************************************************/
1536 void ui_move_pointer(int x, int y)
1537 {
1538 }
1539
1540 /*****************************************************************************/
1541 void ui_set_null_cursor(void)
1542 {
1543 draw_cursor_under(mousex, mousey);
1544 mousex = mousex - mcursor.x;
1545 mousey = mousey - mcursor.y;
1546 memset(&mcursor, 0, sizeof(mcursor));
1547 memset(mcursor.andmask, 255, sizeof(mcursor.andmask));
1548 memset(mcursor.xormask, 0, sizeof(mcursor.xormask));
1549 draw_cursor();
1550 }
1551
1552 /*****************************************************************************/
1553 void ui_paint_bitmap(int x, int y, int cx, int cy,
1554 int width, int height, uint8* data)
1555 {
1556 if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
1557 {
1558 if (contains_mouse(x, y, cx, cy))
1559 draw_cursor_under(mousex, mousey);
1560 accel_draw_box(x, y, cx, cy, data, width * g_server_Bpp);
1561 cache_rect(x, y, cx, cy, False);
1562 }
1563 }
1564
1565 /*****************************************************************************/
1566 void* ui_create_cursor(unsigned int x, unsigned int y,
1567 int width, int height,
1568 uint8* andmask, uint8* xormask)
1569 {
1570 tcursor* c;
1571 int i;
1572 int j;
1573
1574 c = (tcursor*)xmalloc(sizeof(tcursor));
1575 memset(c, 0, sizeof(tcursor));
1576 c->w = width;
1577 c->h = height;
1578 c->x = x;
1579 c->y = y;
1580 for (i = 0; i < 32; i++)
1581 {
1582 for (j = 0; j < 32; j++)
1583 {
1584 if (is_pixel_on(andmask, j, i, 32, 1))
1585 set_pixel_on(c->andmask, j, 31 - i, 32, 8, 255);
1586 if (is_pixel_on(xormask, j, i, 32, 24))
1587 set_pixel_on(c->xormask, j, 31 - i, 32, 8, 255);
1588 }
1589 }
1590 return (void*)c;
1591 }
1592
1593 /*****************************************************************************/
1594 void ui_destroy_cursor(void* cursor)
1595 {
1596 if (cursor != NULL)
1597 xfree(cursor);
1598 }
1599
1600 /*****************************************************************************/
1601 void ui_set_cursor(void* cursor)
1602 {
1603 int x;
1604 int y;
1605 int ox;
1606 int oy;
1607
1608 ox = mousex;
1609 oy = mousey;
1610 x = mousex + mcursor.x;
1611 y = mousey + mcursor.y;
1612 memcpy(&mcursor, cursor, sizeof(tcursor));
1613 mousex = x - mcursor.x;
1614 mousey = y - mcursor.y;
1615 draw_cursor_under(ox, oy);
1616 draw_cursor();
1617 }
1618
1619 /*****************************************************************************/
1620 uint16 ui_get_numlock_state(unsigned int state)
1621 {
1622 return 0;
1623 }
1624
1625 /*****************************************************************************/
1626 unsigned int read_keyboard_state(void)
1627 {
1628 return 0;
1629 }
1630
1631 /*****************************************************************************/
1632 void ui_resize_window(void)
1633 {
1634 }
1635
1636 /*****************************************************************************/
1637 void ui_begin_update(void)
1638 {
1639 }
1640
1641 /*****************************************************************************/
1642 void ui_end_update(void)
1643 {
1644 draw_cache_rects();
1645 draw_cursor();
1646 }
1647
1648 /*****************************************************************************/
1649 void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints,
1650 BRUSH * brush, int bgcolour, int fgcolour)
1651 {
1652 }
1653
1654 /*****************************************************************************/
1655 void ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen)
1656 {
1657 }
1658
1659 /*****************************************************************************/
1660 void ui_ellipse(uint8 opcode, uint8 fillmode,
1661 int x, int y, int cx, int cy,
1662 BRUSH * brush, int bgcolour, int fgcolour)
1663 {
1664 }
1665
1666 /*****************************************************************************/
1667 void generate_random(uint8* random)
1668 {
1669 memcpy(random, "12345678901234567890123456789012", 32);
1670 }
1671
1672 /*****************************************************************************/
1673 void save_licence(uint8* data, int length)
1674 {
1675 }
1676
1677 /*****************************************************************************/
1678 int load_licence(uint8** data)
1679 {
1680 return 0;
1681 }
1682
1683 /*****************************************************************************/
1684 void* xrealloc(void* in_val, int size)
1685 {
1686 return realloc(in_val, size);
1687 }
1688
1689 /*****************************************************************************/
1690 void* xmalloc(int size)
1691 {
1692 return malloc(size);
1693 }
1694
1695 /*****************************************************************************/
1696 void xfree(void* in_val)
1697 {
1698 free(in_val);
1699 }
1700
1701 /*****************************************************************************/
1702 char * xstrdup(const char * s)
1703 {
1704 char * mem = strdup(s);
1705 if (mem == NULL)
1706 {
1707 perror("strdup");
1708 exit(1);
1709 }
1710 return mem;
1711 }
1712
1713 /*****************************************************************************/
1714 void warning(char* format, ...)
1715 {
1716 va_list ap;
1717
1718 fprintf(stderr, "WARNING: ");
1719 va_start(ap, format);
1720 vfprintf(stderr, format, ap);
1721 va_end(ap);
1722 }
1723
1724 /*****************************************************************************/
1725 void unimpl(char* format, ...)
1726 {
1727 va_list ap;
1728
1729 fprintf(stderr, "NOT IMPLEMENTED: ");
1730 va_start(ap, format);
1731 vfprintf(stderr, format, ap);
1732 va_end(ap);
1733 }
1734
1735 /*****************************************************************************/
1736 void error(char* format, ...)
1737 {
1738 va_list ap;
1739
1740 fprintf(stderr, "ERROR: ");
1741 va_start(ap, format);
1742 vfprintf(stderr, format, ap);
1743 va_end(ap);
1744 }
1745
1746 BOOL rd_pstcache_mkdir(void)
1747 {
1748 return 0;
1749 }
1750
1751 /*****************************************************************************/
1752 int rd_open_file(char *filename)
1753 {
1754 return 0;
1755 }
1756
1757 /*****************************************************************************/
1758 void rd_close_file(int fd)
1759 {
1760 return;
1761 }
1762
1763 /*****************************************************************************/
1764 int rd_read_file(int fd, void *ptr, int len)
1765 {
1766 return 0;
1767 }
1768
1769 /*****************************************************************************/
1770 int rd_write_file(int fd, void* ptr, int len)
1771 {
1772 return 0;
1773 }
1774
1775 /*****************************************************************************/
1776 int rd_lseek_file(int fd, int offset)
1777 {
1778 return 0;
1779 }
1780
1781 /*****************************************************************************/
1782 BOOL rd_lock_file(int fd, int start, int len)
1783 {
1784 return False;
1785 }
1786
1787 /*****************************************************************************/
1788 void get_username_and_hostname(void)
1789 {
1790 char fullhostname[64];
1791 char* p;
1792 struct passwd* pw;
1793
1794 STRNCPY(g_username, "unknown", sizeof(g_username));
1795 STRNCPY(g_hostname, "unknown", sizeof(g_hostname));
1796 pw = getpwuid(getuid());
1797 if (pw != NULL && pw->pw_name != NULL)
1798 {
1799 STRNCPY(g_username, pw->pw_name, sizeof(g_username));
1800 }
1801 if (gethostname(fullhostname, sizeof(fullhostname)) != -1)
1802 {
1803 p = strchr(fullhostname, '.');
1804 if (p != NULL)
1805 *p = 0;
1806 STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
1807 }
1808 }
1809
1810 /*****************************************************************************/
1811 void out_params(void)
1812 {
1813 fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
1814 fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
1815 fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
1816 fprintf(stderr, "Usage: svgardesktop [options] server\n");
1817 fprintf(stderr, " -g: desktop geometry (WxH)\n");
1818 fprintf(stderr, " -4: use RDP version 4\n");
1819 fprintf(stderr, " -5: use RDP version 5 (default)\n");
1820 fprintf(stderr, " -t: tcp port\n");
1821 fprintf(stderr, " -u: user name\n");
1822 fprintf(stderr, " -n: client hostname\n");
1823 fprintf(stderr, " -d: disable accel funcs\n");
1824 fprintf(stderr, " -a: connection colour depth\n");
1825 fprintf(stderr, " -l: low memory\n");
1826 fprintf(stderr, "\n");
1827 }
1828
1829 /* produce a hex dump */
1830 void hexdump(uint8* p, uint32 len)
1831 {
1832 uint8* line;
1833 int i;
1834 int thisline;
1835 int offset;
1836
1837 line = p;
1838 offset = 0;
1839 while (offset < len)
1840 {
1841 printf("%04x ", offset);
1842 thisline = len - offset;
1843 if (thisline > 16)
1844 thisline = 16;
1845
1846 for (i = 0; i < thisline; i++)
1847 printf("%02x ", line[i]);
1848
1849 for (; i < 16; i++)
1850 printf(" ");
1851
1852 for (i = 0; i < thisline; i++)
1853 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
1854
1855 printf("\n");
1856 offset += thisline;
1857 line += thisline;
1858 }
1859 }
1860
1861 /*****************************************************************************/
1862 int parse_parameters(int in_argc, char** in_argv)
1863 {
1864 int i;
1865 char* p;
1866
1867 if (in_argc <= 1)
1868 {
1869 out_params();
1870 return 0;
1871 }
1872 g_argc = in_argc;
1873 g_argv = in_argv;
1874 for (i = 1; i < in_argc; i++)
1875 {
1876 strcpy(g_servername, in_argv[i]);
1877 if (strcmp(in_argv[i], "-g") == 0)
1878 {
1879 g_width = strtol(in_argv[i + 1], &p, 10);
1880 if (g_width <= 0)
1881 {
1882 error("invalid geometry\n");
1883 return 0;
1884 }
1885 if (*p == 'x')
1886 g_height = strtol(p + 1, NULL, 10);
1887 if (g_height <= 0)
1888 {
1889 error("invalid geometry\n");
1890 return 0;
1891 }
1892 g_width = (g_width + 3) & ~3;
1893 }
1894 else if (strcmp(in_argv[i], "-4") == 0)
1895 g_use_rdp5 = 0;
1896 else if (strcmp(in_argv[i], "-5") == 0)
1897 g_use_rdp5 = 1;
1898 else if (strcmp(in_argv[i], "-t") == 0)
1899 g_tcp_port_rdp = strtol(in_argv[i + 1], &p, 10);
1900 else if (strcmp(in_argv[i], "-h") == 0)
1901 {
1902 out_params();
1903 return 0;
1904 }
1905 else if (strcmp(in_argv[i], "-n") == 0)
1906 {
1907 STRNCPY(g_hostname, in_argv[i + 1], sizeof(g_hostname));
1908 }
1909 else if (strcmp(in_argv[i], "-u") == 0)
1910 {
1911 STRNCPY(g_username, in_argv[i + 1], sizeof(g_username));
1912 }
1913 else if (strcmp(in_argv[i], "-d") == 0)
1914 {
1915 use_accel = 0;
1916 }
1917 else if (strcmp(in_argv[i], "-a") == 0)
1918 {
1919 g_server_bpp = strtol(in_argv[i + 1], NULL, 10);
1920 if (g_server_bpp != 8 && g_server_bpp != 16)
1921 {
1922 error("invalid server bpp\n");
1923 return 0;
1924 }
1925 g_server_Bpp = (g_server_bpp + 7) / 8;
1926 }
1927 else if (strcmp(in_argv[i], "-l") == 0)
1928 g_save_mem = 1;
1929 }
1930 return 1;
1931 }
1932
1933 /*****************************************************************************/
1934 int main(int in_argc, char** in_argv)
1935 {
1936 get_username_and_hostname();
1937 if (!parse_parameters(in_argc, in_argv))
1938 return 0;
1939 if (!ui_init())
1940 return 1;
1941 if (!ui_create_window())
1942 return 1;
1943 ui_main_loop();
1944 ui_destroy_window();
1945 ui_deinit();
1946 return 0;
1947 }