1 /* -*- c-basic-offset: 8 -*- 2 rdesktop: A Remote Desktop Protocol client. 3 User interface services - NanoX(microwindows) 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 problems with nanox lib 22 opcodes don't work, can only rely on copy 23 stipple orgins don't work 24 clip seems to affect source too, it should only affect dest 25 in copyarea functions 26 */ 27 28 #include "../rdesktop.h" 29 30 #include <stdarg.h> /* va_list va_start va_end */ 31 #include <unistd.h> /* gethostname */ 32 #include <pwd.h> /* getpwuid */ 33 34 #include <nano-X.h> 35 36 extern int g_tcp_port_rdp; 37 int g_use_rdp5 = 1; 38 char g_hostname[16]; 39 char g_username[64]; 40 int g_width = 800; 41 int g_height = 600; 42 int g_server_bpp = 16; 43 int g_encryption = 1; 44 int g_desktop_save = 0; /* todo */ 45 int g_polygon_ellipse_orders = 0; 46 int g_bitmap_cache = 1; 47 int g_bitmap_cache_persist_enable = 0; 48 int g_bitmap_cache_precache = 1; 49 int g_bitmap_compression = 1; 50 uint32 g_rdp5_performanceflags = 51 RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS; 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 static int g_sck = 0; 59 static char g_servername[256] = ""; 60 static char g_password[64] = ""; 61 static char g_domain[64] = ""; 62 static char g_shell[64] = ""; 63 static char g_directory[64] = ""; 64 static GR_WINDOW_ID g_wnd = 0; 65 static GR_GC_ID g_gc = 0; 66 static GR_GC_ID g_gc_clean = 0; 67 static int g_deactivated = 0; 68 static int g_ext_disc_reason = 0; 69 static GR_SCREEN_INFO g_screen_info; 70 static int g_bpp = 0; 71 static int g_Bpp = 0; 72 static GR_RECT g_clip; /* set in main */ 73 static GR_CURSOR_ID g_null_cursor; /* set in main */ 74 static int g_flags = RDP_LOGON_NORMAL; 75 76 struct key 77 { 78 int ch1; 79 int ch2; 80 int ch3; 81 int chs; /* shift char */ 82 }; 83 84 static struct key g_keys[256]; 85 86 /* Session Directory redirection */ 87 BOOL g_redirect = False; 88 char g_redirect_server[64]; 89 char g_redirect_domain[16]; 90 char g_redirect_password[64]; 91 char g_redirect_username[64]; 92 char g_redirect_cookie[128]; 93 uint32 g_redirect_flags = 0; 94 95 #define COLOR16TO32(color) \ 96 ( \ 97 ((((color >> 8) & 0xf8) | ((color >> 13) & 0x7)) << 0) | \ 98 ((((color >> 3) & 0xfc) | ((color >> 9) & 0x3)) << 8) | \ 99 ((((color << 3) & 0xf8) | ((color >> 2) & 0x7)) << 16) \ 100 ) 101 102 static uint32 g_ops[16] = 103 { 104 GR_MODE_CLEAR, /* 0 */ 105 GR_MODE_NOR, /* ~(src | dst) */ 106 GR_MODE_ANDINVERTED, /* (~src) & dst */ 107 GR_MODE_COPYINVERTED, /* ~src */ 108 GR_MODE_ANDREVERSE, /* src & (~dst) */ 109 GR_MODE_INVERT, /* ~(dst) */ 110 GR_MODE_XOR, /* src ^ dst */ 111 GR_MODE_NAND, /* ~(src & dst) */ 112 GR_MODE_AND, /* src & dst */ 113 GR_MODE_EQUIV, /* ~(src) ^ dst or is it ~(src ^ dst) */ 114 GR_MODE_NOOP, /* dst */ 115 GR_MODE_ORINVERTED, /* (~src) | dst */ 116 GR_MODE_COPY, /* src */ 117 GR_MODE_ORREVERSE, /* src | (~dst) */ 118 GR_MODE_OR, /* src | dst */ 119 GR_MODE_SETTO1 /* ~0 */ 120 }; 121 122 /*****************************************************************************/ 123 /* do a raster op */ 124 static int rop(int rop, int src, int dst) 125 { 126 switch (rop) 127 { 128 case 0x0: return 0; 129 case 0x1: return ~(src | dst); 130 case 0x2: return (~src) & dst; 131 case 0x3: return ~src; 132 case 0x4: return src & (~dst); 133 case 0x5: return ~(dst); 134 case 0x6: return src ^ dst; 135 case 0x7: return ~(src & dst); 136 case 0x8: return src & dst; 137 case 0x9: return ~(src) ^ dst; 138 case 0xa: return dst; 139 case 0xb: return (~src) | dst; 140 case 0xc: return src; 141 case 0xd: return src | (~dst); 142 case 0xe: return src | dst; 143 case 0xf: return ~0; 144 } 145 return dst; 146 } 147 148 /*****************************************************************************/ 149 static int get_pixel32(uint8 * data, int x, int y, 150 int width, int height) 151 { 152 if (x >= 0 && y >= 0 && x < width && y < height) 153 { 154 return *(((int*)data) + (y * width + x)); 155 } 156 else 157 { 158 return 0; 159 } 160 } 161 162 /*****************************************************************************/ 163 static void set_pixel32(uint8 * data, int x, int y, 164 int width, int height, int pixel) 165 { 166 if (x >= 0 && y >= 0 && x < width && y < height) 167 { 168 *(((int*)data) + (y * width + x)) = pixel; 169 } 170 } 171 172 /*****************************************************************************/ 173 static int warp_coords(int * x, int * y, int * cx, int * cy, 174 int * srcx, int * srcy) 175 { 176 int dx; 177 int dy; 178 179 if (g_clip.x > *x) 180 { 181 dx = g_clip.x - *x; 182 } 183 else 184 { 185 dx = 0; 186 } 187 if (g_clip.y > *y) 188 { 189 dy = g_clip.y - *y; 190 } 191 else 192 { 193 dy = 0; 194 } 195 if (*x + *cx > g_clip.x + g_clip.width) 196 { 197 *cx = (*cx - ((*x + *cx) - (g_clip.x + g_clip.width))); 198 } 199 if (*y + *cy > g_clip.y + g_clip.height) 200 { 201 *cy = (*cy - ((*y + *cy) - (g_clip.y + g_clip.height))); 202 } 203 *cx = *cx - dx; 204 *cy = *cy - dy; 205 if (*cx <= 0) 206 { 207 return 0; 208 } 209 if (*cy <= 0) 210 { 211 return 0; 212 } 213 *x = *x + dx; 214 *y = *y + dy; 215 if (srcx != 0) 216 { 217 *srcx = *srcx + dx; 218 } 219 if (srcy != 0) 220 { 221 *srcy = *srcy + dy; 222 } 223 return 1; 224 } 225 226 /******************************************************************************/ 227 /* check if a certain pixel is set in a bitmap */ 228 static int is_pixel_on(uint8 * data, int x, int y, int width, int bpp) 229 { 230 int start; 231 int shift; 232 233 if (bpp == 1) 234 { 235 width = (width + 7) / 8; 236 start = (y * width) + x / 8; 237 shift = x % 8; 238 return (data[start] & (0x80 >> shift)) != 0; 239 } 240 else 241 return 0; 242 } 243 244 /*****************************************************************************/ 245 int ui_select(int in) 246 { 247 if (g_sck == 0) 248 { 249 g_sck = in; 250 } 251 return 1; 252 } 253 254 /*****************************************************************************/ 255 void ui_set_clip(int x, int y, int cx, int cy) 256 { 257 GR_REGION_ID region; 258 259 g_clip.x = x; 260 g_clip.y = y; 261 g_clip.width = cx; 262 g_clip.height = cy; 263 region = GrNewRegion(); 264 GrUnionRectWithRegion(region, &g_clip); 265 GrSetGCRegion(g_gc, region); /* can't destroy region here, i guess gc */ 266 /* takes owership, if you destroy it */ 267 /* clip is reset, hum */ 268 } 269 270 /*****************************************************************************/ 271 void ui_reset_clip(void) 272 { 273 GrSetGCRegion(g_gc, 0); 274 g_clip.x = 0; 275 g_clip.y = 0; 276 g_clip.width = g_width; 277 g_clip.height = g_height; 278 } 279 280 /*****************************************************************************/ 281 void ui_bell(void) 282 { 283 GrBell(); 284 } 285 286 /*****************************************************************************/ 287 /* gota convert the rdp glyph to nanox glyph */ 288 void * ui_create_glyph(int width, int height, uint8 * data) 289 { 290 char * p, * q, * r; 291 int datasize, i, j; 292 293 datasize = GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP); 294 p = xmalloc(datasize); 295 q = p; 296 r = data; 297 memset(p, 0, datasize); 298 for (i = 0; i < height; i++) 299 { 300 j = 0; 301 while (j + 8 < width) 302 { 303 *q = *(r + 1); 304 q++; 305 r++; 306 *q = *(r - 1); 307 q++; 308 r++; 309 j += 16; 310 } 311 if ((width % 16) <= 8 && (width % 16) > 0) 312 { 313 q++; 314 *q = *r; 315 q++; 316 r++; 317 j += 8; 318 } 319 } 320 return p; 321 } 322 323 /*****************************************************************************/ 324 void ui_destroy_glyph(void * glyph) 325 { 326 xfree(glyph); 327 } 328 329 /*****************************************************************************/ 330 void * ui_create_colourmap(COLOURMAP * colors) 331 { 332 return 0; 333 } 334 335 /*****************************************************************************/ 336 void ui_set_colourmap(void * map) 337 { 338 } 339 340 /*****************************************************************************/ 341 void * ui_create_bitmap(int width, int height, uint8 * data) 342 { 343 GR_WINDOW_ID pixmap; 344 uint8 * p; 345 uint32 i, j, pixel; 346 347 p = data; 348 pixmap = GrNewPixmap(width, height, 0); 349 if (g_server_bpp == 16 && g_bpp == 32) 350 { 351 p = xmalloc(width * height * g_Bpp); 352 for (i = 0; i < height; i++) 353 { 354 for (j = 0; j < width; j++) 355 { 356 pixel = *(((uint16 *) data) + (i * width + j)); 357 pixel = COLOR16TO32(pixel); 358 *(((uint32 *) p) + (i * width + j)) = pixel; 359 } 360 } 361 } 362 GrArea(pixmap, g_gc_clean, 0, 0, width, height, p, MWPF_RGB); 363 if (p != data) 364 { 365 xfree(p); 366 } 367 return (void *) pixmap; 368 } 369 370 /*****************************************************************************/ 371 void ui_destroy_bitmap(void * bmp) 372 { 373 GrDestroyWindow((GR_WINDOW_ID)bmp); 374 } 375 376 /*****************************************************************************/ 377 #define DO_GLYPH(ttext,idx) \ 378 { \ 379 glyph = cache_get_font (font, ttext[idx]); \ 380 if (!(flags & TEXT2_IMPLICIT_X)) \ 381 { \ 382 xyoffset = ttext[++idx]; \ 383 if ((xyoffset & 0x80)) \ 384 { \ 385 if (flags & TEXT2_VERTICAL) \ 386 { \ 387 y += ttext[idx+1] | (ttext[idx+2] << 8); \ 388 } \ 389 else \ 390 { \ 391 x += ttext[idx+1] | (ttext[idx+2] << 8); \ 392 } \ 393 idx += 2; \ 394 } \ 395 else \ 396 { \ 397 if (flags & TEXT2_VERTICAL) \ 398 { \ 399 y += xyoffset; \ 400 } \ 401 else \ 402 { \ 403 x += xyoffset; \ 404 } \ 405 } \ 406 } \ 407 if (glyph != NULL) \ 408 { \ 409 x1 = x + glyph->offset; \ 410 y1 = y + glyph->baseline; \ 411 GrBitmap(g_wnd, g_gc, x1, y1, glyph->width, glyph->height, glyph->pixmap); \ 412 if (flags & TEXT2_IMPLICIT_X) \ 413 { \ 414 x += glyph->width; \ 415 } \ 416 } \ 417 } 418 419 /*****************************************************************************/ 420 void ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, 421 int x, int y, 422 int clipx, int clipy, int clipcx, int clipcy, 423 int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush, 424 int bgcolor, int fgcolor, uint8 * text, uint8 length) 425 { 426 FONTGLYPH * glyph; 427 int i, j, xyoffset, x1, y1; 428 DATABLOB * entry; 429 430 GrSetGCMode(g_gc, GR_MODE_COPY); 431 GrSetGCUseBackground(g_gc, 0); /* this can be set when gc is created */ 432 if (g_server_bpp == 16 && g_bpp == 32) 433 { 434 fgcolor = COLOR16TO32(fgcolor); 435 bgcolor = COLOR16TO32(bgcolor); 436 } 437 GrSetGCForeground(g_gc, bgcolor); 438 if (boxx + boxcx > g_width) 439 { 440 boxcx = g_width - boxx; 441 } 442 if (boxcx > 1) 443 { 444 GrFillRect(g_wnd, g_gc, boxx, boxy, boxcx, boxcy); 445 } 446 else if (mixmode == MIX_OPAQUE) 447 { 448 GrFillRect(g_wnd, g_gc, clipx, clipy, clipcx, clipcy); 449 } 450 GrSetGCForeground(g_gc, fgcolor); 451 /* Paint text, character by character */ 452 for (i = 0; i < length;) 453 { 454 switch (text[i]) 455 { 456 case 0xff: 457 if (i + 2 < length) 458 { 459 cache_put_text(text[i + 1], text, text[i + 2]); 460 } 461 else 462 { 463 error("this shouldn't be happening\n"); 464 exit(1); 465 } 466 /* this will move pointer from start to first character after */ 467 /* FF command */ 468 length -= i + 3; 469 text = &(text[i + 3]); 470 i = 0; 471 break; 472 case 0xfe: 473 entry = cache_get_text(text[i + 1]); 474 if (entry != NULL) 475 { 476 if ((((uint8 *) (entry->data))[1] == 0) && 477 (!(flags & TEXT2_IMPLICIT_X))) 478 { 479 if (flags & TEXT2_VERTICAL) 480 { 481 y += text[i + 2]; 482 } 483 else 484 { 485 x += text[i + 2]; 486 } 487 } 488 for (j = 0; j < entry->size; j++) 489 { 490 DO_GLYPH(((uint8 *) (entry->data)), j); 491 } 492 } 493 if (i + 2 < length) 494 { 495 i += 3; 496 } 497 else 498 { 499 i += 2; 500 } 501 length -= i; 502 /* this will move pointer from start to first character after */ 503 /* FE command */ 504 text = &(text[i]); 505 i = 0; 506 break; 507 default: 508 DO_GLYPH(text, i); 509 i++; 510 break; 511 } 512 } 513 } 514 515 /*****************************************************************************/ 516 void ui_line(uint8 opcode, int startx, int starty, int endx, int endy, 517 PEN * pen) 518 { 519 uint32 op; 520 uint32 color; 521 522 color = pen->colour; 523 if (opcode == 5) /* GR_MODE_INVERT, not supported so convert it */ 524 { /* i think x ^ -1 = ~x */ 525 color = 0xffffffff; 526 opcode = 6; /* GR_MODE_XOR */ 527 } 528 if (opcode == 12 || opcode == 6) /* nanox only supports these 2 opcode */ 529 { 530 op = g_ops[opcode]; 531 GrSetGCMode(g_gc, op); 532 if (g_server_bpp == 16 && g_bpp == 32) 533 { 534 color = COLOR16TO32(color); 535 } 536 GrSetGCForeground(g_gc, color); 537 GrLine(g_wnd, g_gc, startx, starty, endx, endy); 538 GrSetGCMode(g_gc, GR_MODE_COPY); 539 } 540 else 541 { 542 unimpl("opcode %d in ui_line\n", opcode); 543 } 544 } 545 546 /*****************************************************************************/ 547 void ui_triblt(uint8 opcode, int x, int y, int cx, int cy, 548 void * src, int srcx, int srcy, 549 BRUSH * brush, int bgcolor, int fgcolor) 550 { 551 /* not used, turned off */ 552 } 553 554 /*****************************************************************************/ 555 void ui_memblt(uint8 opcode, int x, int y, int cx, int cy, 556 void * src, int srcx, int srcy) 557 { 558 uint8 * dest; 559 uint8 * source; 560 uint8 * final; 561 GR_WINDOW_INFO wi; 562 int i, j, s, d; 563 GR_WINDOW_ID pixmap; 564 565 if (opcode == 12) 566 { 567 GrCopyArea(g_wnd, g_gc, x, y, cx, cy, (GR_DRAW_ID)src, srcx, srcy, 568 GR_MODE_COPY); 569 } 570 else /* do opcodes ourself */ 571 { /* slow but its correct, ok to be slow here, these are rare */ 572 GrGetWindowInfo((GR_DRAW_ID)src, &wi); 573 dest = xmalloc(cx * cy * g_Bpp); 574 source = xmalloc(wi.width * wi.height * g_Bpp); 575 final = xmalloc(cx * cy * g_Bpp); 576 memset(final, 0, cx * cy * g_Bpp); 577 /* dest */ 578 GrReadArea(g_wnd, x, y, cx, cy, (GR_PIXELVAL*)dest); 579 /* source */ 580 GrReadArea((GR_DRAW_ID)src, 0, 0, 581 wi.width, wi.height, (GR_PIXELVAL*)source); 582 for (i = 0; i < cy; i++) 583 { 584 for (j = 0; j < cx; j++) 585 { 586 s = get_pixel32(source, j + srcx, i + srcy, wi.width, wi.height); 587 d = get_pixel32(dest, j, i, cx ,cy); 588 set_pixel32(final, j, i, cx, cy, rop(opcode, s, d)); 589 } 590 } 591 pixmap = GrNewPixmap(cx, cy, 0); 592 GrArea(pixmap, g_gc_clean, 0, 0, cx, cy, final, MWPF_TRUECOLOR0888); 593 GrCopyArea(g_wnd, g_gc, x, y, cx, cy, pixmap, 0, 0, GR_MODE_COPY); 594 GrDestroyWindow(pixmap); 595 xfree(dest); 596 xfree(source); 597 xfree(final); 598 } 599 } 600 601 /*****************************************************************************/ 602 void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy) 603 { 604 /* not used, turned off */ 605 } 606 607 /*****************************************************************************/ 608 void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy) 609 { 610 /* not used, turned off */ 611 } 612 613 /*****************************************************************************/ 614 void ui_rect(int x, int y, int cx, int cy, int color) 615 { 616 if (g_server_bpp == 16 && g_bpp == 32) 617 { 618 color = COLOR16TO32(color); 619 } 620 GrSetGCForeground(g_gc, color); 621 GrFillRect(g_wnd, g_gc, x, y, cx, cy); 622 } 623 624 /*****************************************************************************/ 625 /* using warp_coords cause clip seems to affect source in GrCopyArea */ 626 void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy, 627 int srcx, int srcy) 628 { 629 if (opcode == 12) 630 { 631 if (warp_coords(&x, &y, &cx, &cy, &srcx, &srcy)) 632 { 633 GrCopyArea(g_wnd, g_gc_clean, x, y, cx, cy, g_wnd, srcx, srcy, 634 GR_MODE_COPY); 635 } 636 } 637 else 638 { 639 unimpl("opcode %d in ui_screenblt\n", opcode); 640 } 641 } 642 643 /******************************************************************************/ 644 /* can't use stipple cause tsorigin don't work, GrPoint too slow, 645 GrPoints too slow but better, using a copy from the screen, 646 do the pattern and copy it back */ 647 void ui_patblt(uint8 opcode, int x, int y, int cx, int cy, 648 BRUSH * brush, int bgcolor, int fgcolor) 649 { 650 uint8 ipattern[8], * dest, * final; 651 uint32 op; 652 int i, j, s, d; 653 GR_WINDOW_ID pixmap; 654 655 if (g_server_bpp == 16 && g_bpp == 32) 656 { 657 fgcolor = COLOR16TO32(fgcolor); 658 bgcolor = COLOR16TO32(bgcolor); 659 } 660 switch (brush->style) 661 { 662 case 0: /* Solid */ 663 if (opcode == 12 || opcode == 6) 664 { 665 op = g_ops[opcode]; 666 GrSetGCMode(g_gc, op); 667 GrSetGCForeground(g_gc, fgcolor); 668 GrFillRect(g_wnd, g_gc, x, y, cx, cy); 669 GrSetGCMode(g_gc, GR_MODE_COPY); 670 } 671 else 672 { 673 unimpl("opcode %d in ui_patblt solid brush\n", opcode); 674 } 675 break; 676 case 3: /* Pattern - all opcodes ok */ 677 for (i = 0; i != 8; i++) 678 { 679 ipattern[7 - i] = brush->pattern[i]; 680 } 681 dest = xmalloc(cx * cy * g_Bpp); 682 final = xmalloc(cx * cy * g_Bpp); 683 memset(final, 0, cx * cy * g_Bpp); 684 /* dest */ 685 if (opcode != 12) 686 { 687 GrReadArea(g_wnd, x, y, cx, cy, (GR_PIXELVAL*)dest); 688 } 689 for (i = 0; i < cy; i++) 690 { 691 for (j = 0; j < cx; j++) 692 { 693 if (is_pixel_on(ipattern, (x + j + brush->xorigin) % 8, 694 (y + i + brush->yorigin) % 8, 8, 1)) 695 { 696 s = fgcolor; 697 } 698 else 699 { 700 s = bgcolor; 701 } 702 d = get_pixel32(dest, j, i, cx ,cy); 703 set_pixel32(final, j, i, cx, cy, rop(opcode, s, d)); 704 } 705 } 706 pixmap = GrNewPixmap(cx, cy, 0); 707 GrArea(pixmap, g_gc_clean, 0, 0, cx, cy, final, MWPF_TRUECOLOR0888); 708 GrCopyArea(g_wnd, g_gc, x, y, cx, cy, pixmap, 0, 0, GR_MODE_COPY); 709 GrDestroyWindow(pixmap); 710 xfree(dest); 711 xfree(final); 712 break; 713 } 714 } 715 716 /*****************************************************************************/ 717 void ui_destblt(uint8 opcode, int x, int y, int cx, int cy) 718 { 719 uint32 op; 720 721 if (opcode == 0) /* black */ 722 { 723 GrSetGCForeground(g_gc, 0); 724 opcode = 12; 725 } 726 else if (opcode == 5) /* invert */ 727 { 728 GrSetGCForeground(g_gc, 0xffffffff); 729 opcode = 6; 730 } 731 else if (opcode == 15) /* white */ 732 { 733 GrSetGCForeground(g_gc, 0xffffffff); 734 opcode = 12; 735 } 736 if (opcode == 12 || opcode == 6) 737 { 738 op = g_ops[opcode]; 739 GrSetGCMode(g_gc, op); 740 GrFillRect(g_wnd, g_gc, x, y, cx, cy); 741 GrSetGCMode(g_gc, GR_MODE_COPY); 742 } 743 else 744 { 745 unimpl("opcode %d in ui_destblt\n", opcode); 746 } 747 } 748 749 /*****************************************************************************/ 750 void ui_paint_bitmap(int x, int y, int cx, int cy, 751 int width, int height, uint8 * data) 752 { 753 void * b; 754 755 b = ui_create_bitmap(width, height, data); 756 ui_memblt(12, x, y, cx, cy, b, 0, 0); 757 ui_destroy_bitmap(b); 758 } 759 760 /*****************************************************************************/ 761 void ui_move_pointer(int x, int y) 762 { 763 GrMoveCursor(x, y); 764 } 765 766 /*****************************************************************************/ 767 void ui_set_null_cursor(void) 768 { 769 GrSetWindowCursor(g_wnd, g_null_cursor); 770 } 771 772 /*****************************************************************************/ 773 void ui_set_cursor(void * cursor) 774 { 775 GrSetWindowCursor(g_wnd, (GR_CURSOR_ID)cursor); 776 } 777 778 //****************************************************************************** 779 static int is24on(uint8 * data, int x, int y) 780 { 781 uint8 r, g, b; 782 int start; 783 784 if (data == 0) 785 { 786 return 0; 787 } 788 start = y * 32 * 3 + x * 3; 789 r = data[start]; 790 g = data[start + 1]; 791 b = data[start + 2]; 792 return !((r == 0) && (g == 0) && (b == 0)); 793 } 794 795 //****************************************************************************** 796 static int is1on(uint8 * data, int x, int y) 797 { 798 int start; 799 int shift; 800 801 if (data == 0) 802 { 803 return 0; 804 } 805 start = (y * 32) / 8 + x / 8; 806 shift = x % 8; 807 return (data[start] & (0x80 >> shift)) == 0; 808 } 809 810 //****************************************************************************** 811 static void set1(uint8 * data, int x, int y) 812 { 813 int start; 814 int shift; 815 816 if (data == 0) 817 { 818 return; 819 } 820 start = (y * 32) / 8 + x / 8; 821 shift = x % 8; 822 data[start] = data[start] | (0x80 >> shift); 823 } 824 825 //****************************************************************************** 826 static void flipover(uint8 * data) 827 { 828 uint8 adata[128]; 829 int index; 830 831 if (data == 0) 832 { 833 return; 834 } 835 memcpy(adata, data, 128); 836 for (index = 0; index <= 31; index++) 837 { 838 data[127 - (index * 4 + 3)] = adata[index * 4]; 839 data[127 - (index * 4 + 2)] = adata[index * 4 + 1]; 840 data[127 - (index * 4 + 1)] = adata[index * 4 + 2]; 841 data[127 - index * 4] = adata[index * 4 + 3]; 842 } 843 } 844 845 /*****************************************************************************/ 846 void * ui_create_cursor(uint32 x, uint32 y, 847 int width, int height, 848 uint8 * andmask, uint8 * xormask) 849 { 850 uint8 adata[128]; 851 uint8 amask[128]; 852 GR_BITMAP * databitmap; 853 GR_BITMAP * maskbitmap; 854 GR_CURSOR_ID cursor; 855 int i1, i2, bon, mon; 856 857 if (width != 32 || height != 32) 858 { 859 return 0; 860 } 861 memset(adata, 0, 128); 862 memset(amask, 0, 128); 863 for (i1 = 0; i1 <= 31; i1++) 864 { 865 for (i2 = 0; i2 <= 31; i2++) 866 { 867 mon = is24on(xormask, i1, i2); 868 bon = is1on(andmask, i1, i2); 869 if (bon ^ mon) // xor 870 { 871 set1(adata, i1, i2); 872 if (!mon) 873 { 874 set1(amask, i1, i2); 875 } 876 } 877 if (mon) 878 { 879 set1(amask, i1, i2); 880 } 881 } 882 } 883 flipover(adata); 884 flipover(amask); 885 databitmap = ui_create_glyph(32, 32, adata); 886 maskbitmap = ui_create_glyph(32, 32, amask); 887 cursor = GrNewCursor(32, 32, x, y, 0xffffff, 0, databitmap, maskbitmap); 888 ui_destroy_glyph(databitmap); 889 ui_destroy_glyph(maskbitmap); 890 return (void*)cursor; 891 } 892 893 /*****************************************************************************/ 894 void ui_destroy_cursor(void * cursor) 895 { 896 GrDestroyCursor((GR_CURSOR_ID)cursor); 897 } 898 899 /*****************************************************************************/ 900 uint16 ui_get_numlock_state(uint32 state) 901 { 902 return 0; 903 } 904 905 /*****************************************************************************/ 906 uint32 read_keyboard_state(void) 907 { 908 return 0; 909 } 910 911 /*****************************************************************************/ 912 void ui_resize_window(void) 913 { 914 } 915 916 /*****************************************************************************/ 917 void ui_begin_update(void) 918 { 919 } 920 921 /*****************************************************************************/ 922 void ui_end_update(void) 923 { 924 } 925 926 /*****************************************************************************/ 927 void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints, 928 BRUSH * brush, int bgcolor, int fgcolor) 929 { 930 /* not used, turned off */ 931 } 932 933 /*****************************************************************************/ 934 void ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen) 935 { 936 int i, x, y, dx, dy; 937 938 if (npoints > 0) 939 { 940 x = points[0].x; 941 y = points[0].y; 942 for (i = 1; i < npoints; i++) 943 { 944 dx = points[i].x; 945 dy = points[i].y; 946 ui_line(opcode, x, y, x + dx, y + dy, pen); 947 x = x + dx; 948 y = y + dy; 949 } 950 } 951 } 952 953 /*****************************************************************************/ 954 void ui_ellipse(uint8 opcode, uint8 fillmode, 955 int x, int y, int cx, int cy, 956 BRUSH * brush, int bgcolor, int fgcolor) 957 { 958 /* not used, turned off */ 959 } 960 961 /*****************************************************************************/ 962 void generate_random(uint8 * random) 963 { 964 memcpy(random, "12345678901234567890123456789012", 32); 965 } 966 967 /*****************************************************************************/ 968 void save_licence(uint8 * data, int length) 969 { 970 } 971 972 /*****************************************************************************/ 973 int load_licence(uint8 ** data) 974 { 975 return 0; 976 } 977 978 /*****************************************************************************/ 979 void * xrealloc(void * in, int size) 980 { 981 if (size < 1) 982 { 983 size = 1; 984 } 985 return realloc(in, size); 986 } 987 988 /*****************************************************************************/ 989 void * xmalloc(int size) 990 { 991 return malloc(size); 992 } 993 994 /*****************************************************************************/ 995 void xfree(void * in) 996 { 997 if (in != 0) 998 { 999 free(in); 1000 } 1001 } 1002 1003 /*****************************************************************************/ 1004 char * xstrdup(const char * s) 1005 { 1006 char * mem = strdup(s); 1007 if (mem == NULL) 1008 { 1009 perror("strdup"); 1010 exit(1); 1011 } 1012 return mem; 1013 } 1014 1015 /*****************************************************************************/ 1016 void warning(char * format, ...) 1017 { 1018 va_list ap; 1019 1020 fprintf(stderr, "WARNING: "); 1021 va_start(ap, format); 1022 vfprintf(stderr, format, ap); 1023 va_end(ap); 1024 } 1025 1026 /*****************************************************************************/ 1027 void unimpl(char * format, ...) 1028 { 1029 va_list ap; 1030 1031 fprintf(stderr, "NOT IMPLEMENTED: "); 1032 va_start(ap, format); 1033 vfprintf(stderr, format, ap); 1034 va_end(ap); 1035 } 1036 1037 /*****************************************************************************/ 1038 void error(char * format, ...) 1039 { 1040 va_list ap; 1041 1042 fprintf(stderr, "ERROR: "); 1043 va_start(ap, format); 1044 vfprintf(stderr, format, ap); 1045 va_end(ap); 1046 } 1047 1048 /*****************************************************************************/ 1049 int rd_pstcache_mkdir(void) 1050 { 1051 return 0; 1052 } 1053 1054 /*****************************************************************************/ 1055 int rd_open_file(char * filename) 1056 { 1057 return 0; 1058 } 1059 1060 /*****************************************************************************/ 1061 void rd_close_file(int fd) 1062 { 1063 return; 1064 } 1065 1066 /*****************************************************************************/ 1067 int rd_read_file(int fd, void * ptr, int len) 1068 { 1069 return 0; 1070 } 1071 1072 /*****************************************************************************/ 1073 int rd_write_file(int fd, void * ptr, int len) 1074 { 1075 return 0; 1076 } 1077 1078 /*****************************************************************************/ 1079 int rd_lseek_file(int fd, int offset) 1080 { 1081 return 0; 1082 } 1083 1084 /*****************************************************************************/ 1085 int rd_lock_file(int fd, int start, int len) 1086 { 1087 return False; 1088 } 1089 1090 /*****************************************************************************/ 1091 /*static int key(int ch, int flags) 1092 { 1093 return (ch & 0xffff) | ((flags & 0xffff) << 16); 1094 }*/ 1095 1096 /*****************************************************************************/ 1097 static void init_keys(void) 1098 { 1099 memset(&g_keys, 0, sizeof(g_keys)); 1100 g_keys[0x01].ch1 = 27; /* esc */ 1101 g_keys[0x02].ch1 = '1'; 1102 g_keys[0x02].chs = '!'; 1103 g_keys[0x03].ch1 = '2'; 1104 g_keys[0x03].chs = '@'; 1105 g_keys[0x04].ch1 = '3'; 1106 g_keys[0x04].chs = '#'; 1107 g_keys[0x05].ch1 = '4'; 1108 g_keys[0x05].chs = '$'; 1109 g_keys[0x06].ch1 = '5'; 1110 g_keys[0x06].chs = '%'; 1111 g_keys[0x07].ch1 = '6'; 1112 g_keys[0x07].chs = '^'; 1113 g_keys[0x08].ch1 = '7'; 1114 g_keys[0x08].chs = '&'; 1115 g_keys[0x09].ch1 = '8'; 1116 g_keys[0x09].chs = '*'; 1117 g_keys[0x0a].ch1 = '9'; 1118 g_keys[0x0a].chs = '('; 1119 g_keys[0x0b].ch1 = '0'; 1120 g_keys[0x0b].chs = ')'; 1121 g_keys[0x0c].ch1 = '-'; 1122 g_keys[0x0c].chs = '_'; 1123 g_keys[0x0d].ch1 = '='; 1124 g_keys[0x0d].chs = '+'; 1125 g_keys[0x0e].ch1 = 8; /* backspace */ 1126 g_keys[0x0f].ch1 = 9; /* tab */ 1127 g_keys[0x10].ch1 = 'q'; 1128 g_keys[0x10].chs = 'Q'; 1129 g_keys[0x11].ch1 = 'w'; 1130 g_keys[0x11].chs = 'W'; 1131 g_keys[0x12].ch1 = 'e'; 1132 g_keys[0x12].chs = 'E'; 1133 g_keys[0x13].ch1 = 'r'; 1134 g_keys[0x13].chs = 'R'; 1135 g_keys[0x14].ch1 = 't'; 1136 g_keys[0x14].chs = 'T'; 1137 g_keys[0x15].ch1 = 'y'; 1138 g_keys[0x15].chs = 'Y'; 1139 g_keys[0x16].ch1 = 'u'; 1140 g_keys[0x16].chs = 'U'; 1141 g_keys[0x17].ch1 = 'i'; 1142 g_keys[0x17].chs = 'I'; 1143 g_keys[0x18].ch1 = 'o'; 1144 g_keys[0x18].chs = 'O'; 1145 g_keys[0x19].ch1 = 'p'; 1146 g_keys[0x19].chs = 'P'; 1147 g_keys[0x1a].ch1 = '['; 1148 g_keys[0x1a].chs = '{'; 1149 g_keys[0x1b].ch1 = ']'; 1150 g_keys[0x1b].chs = '}'; 1151 g_keys[0x1c].ch2 = 13; /* enter */ 1152 g_keys[0x1d].ch1 = 63533; /* left control */ 1153 g_keys[0x1d].ch2 = 63534; /* right control */ 1154 g_keys[0x1e].ch1 = 'a'; 1155 g_keys[0x1e].chs = 'A'; 1156 g_keys[0x1f].ch1 = 's'; 1157 g_keys[0x1f].chs = 'S'; 1158 g_keys[0x20].ch1 = 'd'; 1159 g_keys[0x20].chs = 'D'; 1160 g_keys[0x21].ch1 = 'f'; 1161 g_keys[0x21].chs = 'F'; 1162 g_keys[0x22].ch1 = 'g'; 1163 g_keys[0x22].chs = 'G'; 1164 g_keys[0x23].ch1 = 'h'; 1165 g_keys[0x23].chs = 'H'; 1166 g_keys[0x24].ch1 = 'j'; 1167 g_keys[0x24].chs = 'J'; 1168 g_keys[0x25].ch1 = 'k'; 1169 g_keys[0x25].chs = 'K'; 1170 g_keys[0x26].ch1 = 'l'; 1171 g_keys[0x26].chs = 'L'; 1172 g_keys[0x27].ch1 = ';'; 1173 g_keys[0x27].chs = ':'; 1174 g_keys[0x28].ch1 = '\''; 1175 g_keys[0x28].chs = '"'; 1176 g_keys[0x29].ch1 = '`'; 1177 g_keys[0x29].chs = '~'; 1178 g_keys[0x2a].ch1 = 63531; /* left shift */ 1179 g_keys[0x2b].ch1 = '\\'; 1180 g_keys[0x2c].ch1 = 'z'; 1181 g_keys[0x2c].chs = 'Z'; 1182 g_keys[0x2d].ch1 = 'x'; 1183 g_keys[0x2d].chs = 'X'; 1184 g_keys[0x2e].ch1 = 'c'; 1185 g_keys[0x2e].chs = 'C'; 1186 g_keys[0x2f].ch1 = 'v'; 1187 g_keys[0x2f].chs = 'V'; 1188 g_keys[0x30].ch1 = 'b'; 1189 g_keys[0x30].chs = 'B'; 1190 g_keys[0x31].ch1 = 'n'; 1191 g_keys[0x31].chs = 'N'; 1192 g_keys[0x32].ch1 = 'm'; 1193 g_keys[0x32].chs = 'M'; 1194 g_keys[0x33].ch1 = ','; 1195 g_keys[0x33].chs = '<'; 1196 g_keys[0x34].ch1 = '.'; 1197 g_keys[0x34].chs = '>'; 1198 g_keys[0x35].ch1 = '/'; 1199 g_keys[0x35].ch2 = 63509; 1200 g_keys[0x35].chs = '?'; 1201 g_keys[0x36].ch1 = 63532; /* right shift */ 1202 g_keys[0x37].ch1 = '*'; /* star on keypad */ 1203 g_keys[0x37].ch2 = 63510; /* star on keypad */ 1204 g_keys[0x38].ch1 = 63535; /* alt */ 1205 g_keys[0x38].ch2 = 63536; /* alt */ 1206 g_keys[0x39].ch1 = ' '; 1207 g_keys[0x3a].ch1 = 0; /* caps lock */ 1208 g_keys[0x3b].ch1 = 63515; /* f1 */ 1209 g_keys[0x3c].ch1 = 63516; /* f2 */ 1210 g_keys[0x3d].ch1 = 63517; /* f3 */ 1211 g_keys[0x3e].ch1 = 63518; /* f4 */ 1212 g_keys[0x3f].ch1 = 63519; /* f5 */ 1213 g_keys[0x40].ch1 = 63520; /* f6 */ 1214 g_keys[0x41].ch1 = 63521; /* f7 */ 1215 g_keys[0x42].ch1 = 63522; /* f8 */ 1216 g_keys[0x43].ch1 = 63523; /* f9 */ 1217 g_keys[0x44].ch1 = 63524; /* f10 */ 1218 g_keys[0x45].ch1 = 0; /* num lock */ 1219 g_keys[0x46].ch1 = 0; /* scroll lock */ 1220 g_keys[0x47].ch1 = 63505; /* home */ 1221 g_keys[0x47].ch2 = 63494; /* home */ 1222 g_keys[0x48].ch1 = 63490; /* arrow up */ 1223 g_keys[0x48].ch2 = 63506; /* arrow up */ 1224 g_keys[0x49].ch1 = 63507; /* page up */ 1225 g_keys[0x49].ch2 = 63496; /* page up */ 1226 g_keys[0x4a].ch1 = '-'; /* -(minus) on keypad */ 1227 g_keys[0x4a].ch2 = 63511; /* -(minus) on keypad */ 1228 g_keys[0x4b].ch1 = 63502; /* arrow left */ 1229 g_keys[0x4b].ch2 = 63488; /* arrow left */ 1230 g_keys[0x4c].ch1 = 63503; /* middle(5 key) on keypad */ 1231 g_keys[0x4d].ch1 = 63504; /* arrow right */ 1232 g_keys[0x4d].ch2 = 63489; /* arrow right */ 1233 g_keys[0x4e].ch1 = '+'; /* +(plus) on keypad */ 1234 g_keys[0x4e].ch2 = 63512; /* +(plus) on keypad */ 1235 g_keys[0x4f].ch1 = 63499; /* end */ 1236 g_keys[0x4f].ch2 = 63495; /* end */ 1237 g_keys[0x50].ch1 = 63500; /* arrow down */ 1238 g_keys[0x50].ch2 = 63491; /* arrow down */ 1239 g_keys[0x51].ch1 = 63501; /* page down */ 1240 g_keys[0x51].ch2 = 63497; /* page down */ 1241 g_keys[0x52].ch1 = 63498; /* insert */ 1242 g_keys[0x52].ch2 = 63492; /* insert */ 1243 g_keys[0x53].ch1 = 63508; /* delete */ 1244 g_keys[0x53].ch2 = 63493; /* delete */ 1245 g_keys[0x54].ch1 = 63525; /* f11 */ 1246 g_keys[0x54].ch1 = 63527; /* f12 */ 1247 } 1248 1249 /*****************************************************************************/ 1250 /* returns 0 if found key */ 1251 static int get_sc(GR_EVENT_KEYSTROKE * event_keystroke, int * sc, int * ec) 1252 { 1253 int i; 1254 1255 //printf("%d %d\n", event_keystroke->ch, event_keystroke->modifiers); 1256 *sc = 0; 1257 *ec = 0; 1258 for (i = 0; i < 256; i++) 1259 { 1260 if (event_keystroke->modifiers & 1) /* shift is down */ 1261 { 1262 if (event_keystroke->ch == g_keys[i].chs) 1263 { 1264 *sc = i; 1265 break; 1266 } 1267 } 1268 if (event_keystroke->ch == g_keys[i].ch1 || 1269 event_keystroke->ch == g_keys[i].ch2 || 1270 event_keystroke->ch == g_keys[i].ch3) 1271 { 1272 *sc = i; 1273 break; 1274 } 1275 } 1276 if (*sc == 0) 1277 { 1278 return 1; 1279 } 1280 else 1281 { 1282 return 0; 1283 } 1284 } 1285 1286 /*****************************************************************************/ 1287 void static process_keystroke(GR_EVENT_KEYSTROKE * event_keystroke, int down) 1288 { 1289 int sc, ec; 1290 1291 if (get_sc(event_keystroke, &sc, &ec) == 0) 1292 { 1293 if (down) 1294 { 1295 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, sc, ec); 1296 } 1297 else 1298 { 1299 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, sc, ec); 1300 } 1301 } 1302 } 1303 1304 /*****************************************************************************/ 1305 void nanox_event(GR_EVENT * ev) 1306 { 1307 GR_EVENT_MOUSE * event_mouse; 1308 GR_EVENT_BUTTON * event_button; 1309 GR_EVENT_FDINPUT * event_fdinput; 1310 GR_EVENT_KEYSTROKE * event_keystroke; 1311 1312 do 1313 { 1314 if (ev->type == GR_EVENT_TYPE_FDINPUT) /* 12 */ 1315 { 1316 event_fdinput = (GR_EVENT_FDINPUT *) ev; 1317 if (event_fdinput->fd == g_sck) 1318 { 1319 if (!rdp_loop(&g_deactivated, &g_ext_disc_reason)) 1320 { 1321 fprintf(stderr, "rdp_loop in nanox_event exit codes %d %d\n", 1322 g_deactivated, g_ext_disc_reason); 1323 exit(1); 1324 } 1325 } 1326 } 1327 else if (ev->type == GR_EVENT_TYPE_BUTTON_DOWN) /* 2 */ 1328 { 1329 event_button = (GR_EVENT_BUTTON *) ev; 1330 if (event_button->changebuttons & 4) /* left */ 1331 { 1332 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1, 1333 event_button->x, event_button->y); 1334 } 1335 else if (event_button->changebuttons & 1) /* right */ 1336 { 1337 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2, 1338 event_button->x, event_button->y); 1339 } 1340 } 1341 else if (ev->type == GR_EVENT_TYPE_BUTTON_UP) /* 3 */ 1342 { 1343 event_button = (GR_EVENT_BUTTON *) ev; 1344 if (event_button->changebuttons & 4) /* left */ 1345 { 1346 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, 1347 event_button->x, event_button->y); 1348 } 1349 else if (event_button->changebuttons & 1) /* right */ 1350 { 1351 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, 1352 event_button->x, event_button->y); 1353 } 1354 } 1355 else if (ev->type == GR_EVENT_TYPE_MOUSE_MOTION) /* 6 */ 1356 { 1357 event_mouse = (GR_EVENT_MOUSE *) ev; 1358 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, 1359 event_mouse->x, event_mouse->y); 1360 } 1361 else if (ev->type == GR_EVENT_TYPE_MOUSE_POSITION) /* 7 */ 1362 { 1363 /* use GR_EVENT_TYPE_MOUSE_MOTION */ 1364 } 1365 else if (ev->type == GR_EVENT_TYPE_KEY_DOWN) /* 8 */ 1366 { 1367 event_keystroke = (GR_EVENT_KEYSTROKE *) ev; 1368 process_keystroke(event_keystroke, 1); 1369 } 1370 else if (ev->type == GR_EVENT_TYPE_KEY_UP) /* 9 */ 1371 { 1372 event_keystroke = (GR_EVENT_KEYSTROKE *) ev; 1373 process_keystroke(event_keystroke, 0); 1374 } 1375 else if (ev->type == GR_EVENT_TYPE_FOCUS_IN) /* 10 */ 1376 { 1377 } 1378 else if (ev->type == GR_EVENT_TYPE_FOCUS_OUT) /* 11 */ 1379 { 1380 } 1381 else if (ev->type == GR_EVENT_TYPE_UPDATE) /* 13 */ 1382 { 1383 } 1384 GrCheckNextEvent(ev); 1385 } while (ev->type != GR_EVENT_TYPE_NONE); 1386 } 1387 1388 /*****************************************************************************/ 1389 static void get_username_and_hostname(void) 1390 { 1391 char fullhostname[64]; 1392 char * p; 1393 struct passwd * pw; 1394 1395 STRNCPY(g_username, "unknown", sizeof(g_username)); 1396 STRNCPY(g_hostname, "unknown", sizeof(g_hostname)); 1397 pw = getpwuid(getuid()); 1398 if (pw != NULL && pw->pw_name != NULL) 1399 { 1400 STRNCPY(g_username, pw->pw_name, sizeof(g_username)); 1401 } 1402 if (gethostname(fullhostname, sizeof(fullhostname)) != -1) 1403 { 1404 p = strchr(fullhostname, '.'); 1405 if (p != NULL) 1406 { 1407 *p = 0; 1408 } 1409 STRNCPY(g_hostname, fullhostname, sizeof(g_hostname)); 1410 } 1411 } 1412 /*****************************************************************************/ 1413 static void out_params(void) 1414 { 1415 fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n"); 1416 fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n"); 1417 fprintf(stderr, "nanox uiport by Jay Sorg\n"); 1418 fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n"); 1419 fprintf(stderr, "Usage: nanoxrdesktop [options] server\n"); 1420 fprintf(stderr, " -u: user name\n"); 1421 fprintf(stderr, " -n: client hostname\n"); 1422 fprintf(stderr, " -p: password\n"); 1423 fprintf(stderr, " -d: domain\n"); 1424 fprintf(stderr, " -s: shell\n"); 1425 fprintf(stderr, " -c: working directory\n"); 1426 fprintf(stderr, "\n"); 1427 } 1428 1429 /*****************************************************************************/ 1430 static int parse_parameters(int in_argc, char ** in_argv) 1431 { 1432 int i; 1433 1434 if (in_argc <= 1) 1435 { 1436 out_params(); 1437 return 0; 1438 } 1439 for (i = 1; i < in_argc; i++) 1440 { 1441 strcpy(g_servername, in_argv[i]); 1442 if (strcmp(in_argv[i], "-h") == 0) 1443 { 1444 out_params(); 1445 return 0; 1446 } 1447 else if (strcmp(in_argv[i], "-n") == 0) 1448 { 1449 STRNCPY(g_hostname, in_argv[i + 1], sizeof(g_hostname)); 1450 } 1451 else if (strcmp(in_argv[i], "-u") == 0) 1452 { 1453 STRNCPY(g_username, in_argv[i + 1], sizeof(g_username)); 1454 } 1455 else if (strcmp(in_argv[i], "-p") == 0) 1456 { 1457 STRNCPY(g_password, in_argv[i + 1], sizeof(g_password)); 1458 g_flags |= RDP_LOGON_AUTO; 1459 i++; 1460 } 1461 else if (strcmp(in_argv[i], "-d") == 0) 1462 { 1463 STRNCPY(g_domain, in_argv[i + 1], sizeof(g_domain)); 1464 i++; 1465 } 1466 else if (strcmp(in_argv[i], "-s") == 0) 1467 { 1468 STRNCPY(g_shell, in_argv[i + 1], sizeof(g_shell)); 1469 i++; 1470 } 1471 else if (strcmp(in_argv[i], "-c") == 0) 1472 { 1473 STRNCPY(g_directory, in_argv[i + 1], sizeof(g_directory)); 1474 i++; 1475 } 1476 } 1477 return 1; 1478 } 1479 1480 /*****************************************************************************/ 1481 int main(int in_argc, char ** in_argv) 1482 { 1483 get_username_and_hostname(); 1484 /* read command line options */ 1485 if (!parse_parameters(in_argc, in_argv)) 1486 { 1487 exit(0); 1488 } 1489 /* connect to server */ 1490 if (GrOpen() < 0) 1491 { 1492 fprintf(stderr, "Couldn't connect to Nano-X server\n"); 1493 exit(1); 1494 } 1495 GrGetScreenInfo(&g_screen_info); 1496 g_bpp = g_screen_info.bpp; 1497 g_Bpp = (g_screen_info.bpp + 7) / 8; 1498 g_width = g_screen_info.vs_width; 1499 g_height = g_screen_info.vs_height; 1500 g_clip.x = 0; 1501 g_clip.y = 0; 1502 g_clip.width = g_width; 1503 g_clip.height = g_height; 1504 if (!((g_bpp == 32 && g_server_bpp == 16) || 1505 (g_bpp == 16 && g_server_bpp == 16))) 1506 { 1507 fprintf(stderr, "unsupported bpp, server = %d, client = %d\n", 1508 g_server_bpp, g_bpp); 1509 GrClose(); 1510 exit(0); 1511 } 1512 init_keys(); 1513 /* connect to server */ 1514 if (!rdp_connect(g_servername, g_flags, g_domain, g_password, g_shell, 1515 g_directory)) 1516 { 1517 fprintf(stderr, "Error connecting\n"); 1518 GrClose(); 1519 exit(1); 1520 } 1521 /* create window */ 1522 g_wnd = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, g_width, g_height, 0, 0, 0); 1523 /* show window */ 1524 GrMapWindow(g_wnd); 1525 /* create graphic context */ 1526 g_gc = GrNewGC(); 1527 g_gc_clean = GrNewGC(); 1528 /* clear screen */ 1529 GrSetGCForeground(g_gc, 0); 1530 GrFillRect(g_wnd, g_gc, 0, 0, g_width, g_height); 1531 /* create null cursor */ 1532 g_null_cursor = (GR_CURSOR_ID)ui_create_cursor(0, 0, 32, 32, 0, 0); 1533 /* register callbacks, set mask, and run main loop */ 1534 GrSelectEvents(g_wnd, -1); /* all events */ 1535 GrRegisterInput(g_sck); 1536 GrMainLoop(nanox_event); 1537 /* free null cursor */ 1538 ui_destroy_cursor((void*)g_null_cursor); 1539 /* free graphic context */ 1540 GrDestroyGC(g_gc); 1541 GrDestroyGC(g_gc_clean); 1542 /* free window */ 1543 GrDestroyWindow(g_wnd); 1544 /* close connection */ 1545 GrClose(); 1546 return 0; 1547 } 1548