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 along 17 with this program; if not, write to the Free Software Foundation, Inc., 18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 } 1948