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
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.
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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
28 #include "../rdesktop.h"
30 #include <stdarg.h> /* va_list va_start va_end */
31 #include <unistd.h> /* gethostname */
32 #include <pwd.h> /* getpwuid */
36 extern int g_tcp_port_rdp
;
42 int g_server_bpp
= 16;
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 */
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
;
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
;
81 int chs
; /* shift char */
84 static struct key g_keys
[256];
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;
95 #define COLOR16TO32(color) \
97 ((((color >> 8) & 0xf8) | ((color >> 13) & 0x7)) << 0) | \
98 ((((color >> 3) & 0xfc) | ((color >> 9) & 0x3)) << 8) | \
99 ((((color << 3) & 0xf8) | ((color >> 2) & 0x7)) << 16) \
102 static uint32 g_ops
[16] =
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 */
122 /*****************************************************************************/
124 static int rop(int rop
, int src
, int dst
)
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
;
148 /*****************************************************************************/
149 static int get_pixel32(uint8
* data
, int x
, int y
,
150 int width
, int height
)
152 if (x
>= 0 && y
>= 0 && x
< width
&& y
< height
)
154 return *(((int*)data
) + (y
* width
+ x
));
162 /*****************************************************************************/
163 static void set_pixel32(uint8
* data
, int x
, int y
,
164 int width
, int height
, int pixel
)
166 if (x
>= 0 && y
>= 0 && x
< width
&& y
< height
)
168 *(((int*)data
) + (y
* width
+ x
)) = pixel
;
172 /*****************************************************************************/
173 static int warp_coords(int * x
, int * y
, int * cx
, int * cy
,
174 int * srcx
, int * srcy
)
195 if (*x
+ *cx
> g_clip
.x
+ g_clip
.width
)
197 *cx
= (*cx
- ((*x
+ *cx
) - (g_clip
.x
+ g_clip
.width
)));
199 if (*y
+ *cy
> g_clip
.y
+ g_clip
.height
)
201 *cy
= (*cy
- ((*y
+ *cy
) - (g_clip
.y
+ g_clip
.height
)));
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
)
235 width
= (width
+ 7) / 8;
236 start
= (y
* width
) + x
/ 8;
238 return (data
[start
] & (0x80 >> shift
)) != 0;
244 /*****************************************************************************/
245 int ui_select(int in
)
254 /*****************************************************************************/
255 void ui_set_clip(int x
, int y
, int cx
, int 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 */
270 /*****************************************************************************/
271 void ui_reset_clip(void)
273 GrSetGCRegion(g_gc
, 0);
276 g_clip
.width
= g_width
;
277 g_clip
.height
= g_height
;
280 /*****************************************************************************/
286 /*****************************************************************************/
287 /* gota convert the rdp glyph to nanox glyph */
288 void * ui_create_glyph(int width
, int height
, uint8
* data
)
293 datasize
= GR_BITMAP_SIZE(width
, height
) * sizeof(GR_BITMAP
);
294 p
= xmalloc(datasize
);
297 memset(p
, 0, datasize
);
298 for (i
= 0; i
< height
; i
++)
301 while (j
+ 8 < width
)
311 if ((width
% 16) <= 8 && (width
% 16) > 0)
323 /*****************************************************************************/
324 void ui_destroy_glyph(void * glyph
)
329 /*****************************************************************************/
330 void * ui_create_colourmap(COLOURMAP
* colors
)
335 /*****************************************************************************/
336 void ui_set_colourmap(void * map
)
340 /*****************************************************************************/
341 void * ui_create_bitmap(int width
, int height
, uint8
* data
)
348 pixmap
= GrNewPixmap(width
, height
, 0);
349 if (g_server_bpp
== 16 && g_bpp
== 32)
351 p
= xmalloc(width
* height
* g_Bpp
);
352 for (i
= 0; i
< height
; i
++)
354 for (j
= 0; j
< width
; j
++)
356 pixel
= *(((uint16
*) data
) + (i
* width
+ j
));
357 pixel
= COLOR16TO32(pixel
);
358 *(((uint32
*) p
) + (i
* width
+ j
)) = pixel
;
362 GrArea(pixmap
, g_gc_clean
, 0, 0, width
, height
, p
, MWPF_RGB
);
367 return (void *) pixmap
;
370 /*****************************************************************************/
371 void ui_destroy_bitmap(void * bmp
)
373 GrDestroyWindow((GR_WINDOW_ID
)bmp
);
376 /*****************************************************************************/
377 #define DO_GLYPH(ttext,idx) \
379 glyph = cache_get_font (font, ttext[idx]); \
380 if (!(flags & TEXT2_IMPLICIT_X)) \
382 xyoffset = ttext[++idx]; \
383 if ((xyoffset & 0x80)) \
385 if (flags & TEXT2_VERTICAL) \
387 y += ttext[idx+1] | (ttext[idx+2] << 8); \
391 x += ttext[idx+1] | (ttext[idx+2] << 8); \
397 if (flags & TEXT2_VERTICAL) \
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) \
419 /*****************************************************************************/
420 void ui_draw_text(uint8 font
, uint8 flags
, uint8 opcode
, int mixmode
,
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
)
427 int i
, j
, xyoffset
, x1
, y1
;
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)
434 fgcolor
= COLOR16TO32(fgcolor
);
435 bgcolor
= COLOR16TO32(bgcolor
);
437 GrSetGCForeground(g_gc
, bgcolor
);
438 if (boxx
+ boxcx
> g_width
)
440 boxcx
= g_width
- boxx
;
444 GrFillRect(g_wnd
, g_gc
, boxx
, boxy
, boxcx
, boxcy
);
446 else if (mixmode
== MIX_OPAQUE
)
448 GrFillRect(g_wnd
, g_gc
, clipx
, clipy
, clipcx
, clipcy
);
450 GrSetGCForeground(g_gc
, fgcolor
);
451 /* Paint text, character by character */
452 for (i
= 0; i
< length
;)
459 cache_put_text(text
[i
+ 1], text
, text
[i
+ 2]);
463 error("this shouldn't be happening\n");
466 /* this will move pointer from start to first character after */
469 text
= &(text
[i
+ 3]);
473 entry
= cache_get_text(text
[i
+ 1]);
476 if ((((uint8
*) (entry
->data
))[1] == 0) &&
477 (!(flags
& TEXT2_IMPLICIT_X
)))
479 if (flags
& TEXT2_VERTICAL
)
488 for (j
= 0; j
< entry
->size
; j
++)
490 DO_GLYPH(((uint8
*) (entry
->data
)), j
);
502 /* this will move pointer from start to first character after */
515 /*****************************************************************************/
516 void ui_line(uint8 opcode
, int startx
, int starty
, int endx
, int endy
,
523 if (opcode
== 5) /* GR_MODE_INVERT, not supported so convert it */
524 { /* i think x ^ -1 = ~x */
526 opcode
= 6; /* GR_MODE_XOR */
528 if (opcode
== 12 || opcode
== 6) /* nanox only supports these 2 opcode */
531 GrSetGCMode(g_gc
, op
);
532 if (g_server_bpp
== 16 && g_bpp
== 32)
534 color
= COLOR16TO32(color
);
536 GrSetGCForeground(g_gc
, color
);
537 GrLine(g_wnd
, g_gc
, startx
, starty
, endx
, endy
);
538 GrSetGCMode(g_gc
, GR_MODE_COPY
);
542 unimpl("opcode %d in ui_line\n", opcode
);
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
)
551 /* not used, turned off */
554 /*****************************************************************************/
555 void ui_memblt(uint8 opcode
, int x
, int y
, int cx
, int cy
,
556 void * src
, int srcx
, int srcy
)
567 GrCopyArea(g_wnd
, g_gc
, x
, y
, cx
, cy
, (GR_DRAW_ID
)src
, srcx
, srcy
,
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
);
578 GrReadArea(g_wnd
, x
, y
, cx
, cy
, (GR_PIXELVAL
*)dest
);
580 GrReadArea((GR_DRAW_ID
)src
, 0, 0,
581 wi
.width
, wi
.height
, (GR_PIXELVAL
*)source
);
582 for (i
= 0; i
< cy
; i
++)
584 for (j
= 0; j
< cx
; j
++)
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
));
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
);
601 /*****************************************************************************/
602 void ui_desktop_restore(uint32 offset
, int x
, int y
, int cx
, int cy
)
604 /* not used, turned off */
607 /*****************************************************************************/
608 void ui_desktop_save(uint32 offset
, int x
, int y
, int cx
, int cy
)
610 /* not used, turned off */
613 /*****************************************************************************/
614 void ui_rect(int x
, int y
, int cx
, int cy
, int color
)
616 if (g_server_bpp
== 16 && g_bpp
== 32)
618 color
= COLOR16TO32(color
);
620 GrSetGCForeground(g_gc
, color
);
621 GrFillRect(g_wnd
, g_gc
, x
, y
, cx
, cy
);
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
,
631 if (warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
633 GrCopyArea(g_wnd
, g_gc_clean
, x
, y
, cx
, cy
, g_wnd
, srcx
, srcy
,
639 unimpl("opcode %d in ui_screenblt\n", opcode
);
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
)
650 uint8 ipattern
[8], * dest
, * final
;
655 if (g_server_bpp
== 16 && g_bpp
== 32)
657 fgcolor
= COLOR16TO32(fgcolor
);
658 bgcolor
= COLOR16TO32(bgcolor
);
660 switch (brush
->style
)
663 if (opcode
== 12 || opcode
== 6)
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
);
673 unimpl("opcode %d in ui_patblt solid brush\n", opcode
);
676 case 3: /* Pattern - all opcodes ok */
677 for (i
= 0; i
!= 8; i
++)
679 ipattern
[7 - i
] = brush
->pattern
[i
];
681 dest
= xmalloc(cx
* cy
* g_Bpp
);
682 final
= xmalloc(cx
* cy
* g_Bpp
);
683 memset(final
, 0, cx
* cy
* g_Bpp
);
687 GrReadArea(g_wnd
, x
, y
, cx
, cy
, (GR_PIXELVAL
*)dest
);
689 for (i
= 0; i
< cy
; i
++)
691 for (j
= 0; j
< cx
; j
++)
693 if (is_pixel_on(ipattern
, (x
+ j
+ brush
->xorigin
) % 8,
694 (y
+ i
+ brush
->yorigin
) % 8, 8, 1))
702 d
= get_pixel32(dest
, j
, i
, cx
,cy
);
703 set_pixel32(final
, j
, i
, cx
, cy
, rop(opcode
, s
, d
));
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
);
716 /*****************************************************************************/
717 void ui_destblt(uint8 opcode
, int x
, int y
, int cx
, int cy
)
721 if (opcode
== 0) /* black */
723 GrSetGCForeground(g_gc
, 0);
726 else if (opcode
== 5) /* invert */
728 GrSetGCForeground(g_gc
, 0xffffffff);
731 else if (opcode
== 15) /* white */
733 GrSetGCForeground(g_gc
, 0xffffffff);
736 if (opcode
== 12 || opcode
== 6)
739 GrSetGCMode(g_gc
, op
);
740 GrFillRect(g_wnd
, g_gc
, x
, y
, cx
, cy
);
741 GrSetGCMode(g_gc
, GR_MODE_COPY
);
745 unimpl("opcode %d in ui_destblt\n", opcode
);
749 /*****************************************************************************/
750 void ui_paint_bitmap(int x
, int y
, int cx
, int cy
,
751 int width
, int height
, uint8
* data
)
755 b
= ui_create_bitmap(width
, height
, data
);
756 ui_memblt(12, x
, y
, cx
, cy
, b
, 0, 0);
757 ui_destroy_bitmap(b
);
760 /*****************************************************************************/
761 void ui_move_pointer(int x
, int y
)
766 /*****************************************************************************/
767 void ui_set_null_cursor(void)
769 GrSetWindowCursor(g_wnd
, g_null_cursor
);
772 /*****************************************************************************/
773 void ui_set_cursor(void * cursor
)
775 GrSetWindowCursor(g_wnd
, (GR_CURSOR_ID
)cursor
);
778 //******************************************************************************
779 static int is24on(uint8
* data
, int x
, int y
)
788 start
= y
* 32 * 3 + x
* 3;
792 return !((r
== 0) && (g
== 0) && (b
== 0));
795 //******************************************************************************
796 static int is1on(uint8
* data
, int x
, int y
)
805 start
= (y
* 32) / 8 + x
/ 8;
807 return (data
[start
] & (0x80 >> shift
)) == 0;
810 //******************************************************************************
811 static void set1(uint8
* data
, int x
, int y
)
820 start
= (y
* 32) / 8 + x
/ 8;
822 data
[start
] = data
[start
] | (0x80 >> shift
);
825 //******************************************************************************
826 static void flipover(uint8
* data
)
835 memcpy(adata
, data
, 128);
836 for (index
= 0; index
<= 31; index
++)
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];
845 /*****************************************************************************/
846 void * ui_create_cursor(uint32 x
, uint32 y
,
847 int width
, int height
,
848 uint8
* andmask
, uint8
* xormask
)
852 GR_BITMAP
* databitmap
;
853 GR_BITMAP
* maskbitmap
;
855 int i1
, i2
, bon
, mon
;
857 if (width
!= 32 || height
!= 32)
861 memset(adata
, 0, 128);
862 memset(amask
, 0, 128);
863 for (i1
= 0; i1
<= 31; i1
++)
865 for (i2
= 0; i2
<= 31; i2
++)
867 mon
= is24on(xormask
, i1
, i2
);
868 bon
= is1on(andmask
, i1
, i2
);
869 if (bon
^ mon
) // xor
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
;
893 /*****************************************************************************/
894 void ui_destroy_cursor(void * cursor
)
896 GrDestroyCursor((GR_CURSOR_ID
)cursor
);
899 /*****************************************************************************/
900 uint16
ui_get_numlock_state(uint32 state
)
905 /*****************************************************************************/
906 uint32
read_keyboard_state(void)
911 /*****************************************************************************/
912 void ui_resize_window(void)
916 /*****************************************************************************/
917 void ui_begin_update(void)
921 /*****************************************************************************/
922 void ui_end_update(void)
926 /*****************************************************************************/
927 void ui_polygon(uint8 opcode
, uint8 fillmode
, POINT
* point
, int npoints
,
928 BRUSH
* brush
, int bgcolor
, int fgcolor
)
930 /* not used, turned off */
933 /*****************************************************************************/
934 void ui_polyline(uint8 opcode
, POINT
* points
, int npoints
, PEN
* pen
)
942 for (i
= 1; i
< npoints
; i
++)
946 ui_line(opcode
, x
, y
, x
+ dx
, y
+ dy
, pen
);
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
)
958 /* not used, turned off */
961 /*****************************************************************************/
962 void generate_random(uint8
* random
)
964 memcpy(random
, "12345678901234567890123456789012", 32);
967 /*****************************************************************************/
968 void save_licence(uint8
* data
, int length
)
972 /*****************************************************************************/
973 int load_licence(uint8
** data
)
978 /*****************************************************************************/
979 void * xrealloc(void * in
, int size
)
985 return realloc(in
, size
);
988 /*****************************************************************************/
989 void * xmalloc(int size
)
994 /*****************************************************************************/
995 void xfree(void * in
)
1003 /*****************************************************************************/
1004 char * xstrdup(const char * s
)
1006 char * mem
= strdup(s
);
1015 /*****************************************************************************/
1016 void warning(char * format
, ...)
1020 fprintf(stderr
, "WARNING: ");
1021 va_start(ap
, format
);
1022 vfprintf(stderr
, format
, ap
);
1026 /*****************************************************************************/
1027 void unimpl(char * format
, ...)
1031 fprintf(stderr
, "NOT IMPLEMENTED: ");
1032 va_start(ap
, format
);
1033 vfprintf(stderr
, format
, ap
);
1037 /*****************************************************************************/
1038 void error(char * format
, ...)
1042 fprintf(stderr
, "ERROR: ");
1043 va_start(ap
, format
);
1044 vfprintf(stderr
, format
, ap
);
1048 /*****************************************************************************/
1049 int rd_pstcache_mkdir(void)
1054 /*****************************************************************************/
1055 int rd_open_file(char * filename
)
1060 /*****************************************************************************/
1061 void rd_close_file(int fd
)
1066 /*****************************************************************************/
1067 int rd_read_file(int fd
, void * ptr
, int len
)
1072 /*****************************************************************************/
1073 int rd_write_file(int fd
, void * ptr
, int len
)
1078 /*****************************************************************************/
1079 int rd_lseek_file(int fd
, int offset
)
1084 /*****************************************************************************/
1085 int rd_lock_file(int fd
, int start
, int len
)
1090 /*****************************************************************************/
1091 /*static int key(int ch, int flags)
1093 return (ch & 0xffff) | ((flags & 0xffff) << 16);
1096 /*****************************************************************************/
1097 static void init_keys(void)
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 */
1249 /*****************************************************************************/
1250 /* returns 0 if found key */
1251 static int get_sc(GR_EVENT_KEYSTROKE
* event_keystroke
, int * sc
, int * ec
)
1255 //printf("%d %d\n", event_keystroke->ch, event_keystroke->modifiers);
1258 for (i
= 0; i
< 256; i
++)
1260 if (event_keystroke
->modifiers
& 1) /* shift is down */
1262 if (event_keystroke
->ch
== g_keys
[i
].chs
)
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
)
1286 /*****************************************************************************/
1287 void static process_keystroke(GR_EVENT_KEYSTROKE
* event_keystroke
, int down
)
1291 if (get_sc(event_keystroke
, &sc
, &ec
) == 0)
1295 rdp_send_input(0, RDP_INPUT_SCANCODE
, RDP_KEYPRESS
, sc
, ec
);
1299 rdp_send_input(0, RDP_INPUT_SCANCODE
, RDP_KEYRELEASE
, sc
, ec
);
1304 /*****************************************************************************/
1305 void nanox_event(GR_EVENT
* ev
)
1307 GR_EVENT_MOUSE
* event_mouse
;
1308 GR_EVENT_BUTTON
* event_button
;
1309 GR_EVENT_FDINPUT
* event_fdinput
;
1310 GR_EVENT_KEYSTROKE
* event_keystroke
;
1314 if (ev
->type
== GR_EVENT_TYPE_FDINPUT
) /* 12 */
1316 event_fdinput
= (GR_EVENT_FDINPUT
*) ev
;
1317 if (event_fdinput
->fd
== g_sck
)
1319 if (!rdp_loop(&g_deactivated
, &g_ext_disc_reason
))
1321 fprintf(stderr
, "rdp_loop in nanox_event exit codes %d %d\n",
1322 g_deactivated
, g_ext_disc_reason
);
1327 else if (ev
->type
== GR_EVENT_TYPE_BUTTON_DOWN
) /* 2 */
1329 event_button
= (GR_EVENT_BUTTON
*) ev
;
1330 if (event_button
->changebuttons
& 4) /* left */
1332 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON1
,
1333 event_button
->x
, event_button
->y
);
1335 else if (event_button
->changebuttons
& 1) /* right */
1337 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON2
,
1338 event_button
->x
, event_button
->y
);
1341 else if (ev
->type
== GR_EVENT_TYPE_BUTTON_UP
) /* 3 */
1343 event_button
= (GR_EVENT_BUTTON
*) ev
;
1344 if (event_button
->changebuttons
& 4) /* left */
1346 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON1
,
1347 event_button
->x
, event_button
->y
);
1349 else if (event_button
->changebuttons
& 1) /* right */
1351 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON2
,
1352 event_button
->x
, event_button
->y
);
1355 else if (ev
->type
== GR_EVENT_TYPE_MOUSE_MOTION
) /* 6 */
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
);
1361 else if (ev
->type
== GR_EVENT_TYPE_MOUSE_POSITION
) /* 7 */
1363 /* use GR_EVENT_TYPE_MOUSE_MOTION */
1365 else if (ev
->type
== GR_EVENT_TYPE_KEY_DOWN
) /* 8 */
1367 event_keystroke
= (GR_EVENT_KEYSTROKE
*) ev
;
1368 process_keystroke(event_keystroke
, 1);
1370 else if (ev
->type
== GR_EVENT_TYPE_KEY_UP
) /* 9 */
1372 event_keystroke
= (GR_EVENT_KEYSTROKE
*) ev
;
1373 process_keystroke(event_keystroke
, 0);
1375 else if (ev
->type
== GR_EVENT_TYPE_FOCUS_IN
) /* 10 */
1378 else if (ev
->type
== GR_EVENT_TYPE_FOCUS_OUT
) /* 11 */
1381 else if (ev
->type
== GR_EVENT_TYPE_UPDATE
) /* 13 */
1384 GrCheckNextEvent(ev
);
1385 } while (ev
->type
!= GR_EVENT_TYPE_NONE
);
1388 /*****************************************************************************/
1389 static void get_username_and_hostname(void)
1391 char fullhostname
[64];
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
)
1400 STRNCPY(g_username
, pw
->pw_name
, sizeof(g_username
));
1402 if (gethostname(fullhostname
, sizeof(fullhostname
)) != -1)
1404 p
= strchr(fullhostname
, '.');
1409 STRNCPY(g_hostname
, fullhostname
, sizeof(g_hostname
));
1412 /*****************************************************************************/
1413 static void out_params(void)
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");
1429 /*****************************************************************************/
1430 static int parse_parameters(int in_argc
, char ** in_argv
)
1439 for (i
= 1; i
< in_argc
; i
++)
1441 strcpy(g_servername
, in_argv
[i
]);
1442 if (strcmp(in_argv
[i
], "-h") == 0)
1447 else if (strcmp(in_argv
[i
], "-n") == 0)
1449 STRNCPY(g_hostname
, in_argv
[i
+ 1], sizeof(g_hostname
));
1451 else if (strcmp(in_argv
[i
], "-u") == 0)
1453 STRNCPY(g_username
, in_argv
[i
+ 1], sizeof(g_username
));
1455 else if (strcmp(in_argv
[i
], "-p") == 0)
1457 STRNCPY(g_password
, in_argv
[i
+ 1], sizeof(g_password
));
1458 g_flags
|= RDP_LOGON_AUTO
;
1461 else if (strcmp(in_argv
[i
], "-d") == 0)
1463 STRNCPY(g_domain
, in_argv
[i
+ 1], sizeof(g_domain
));
1466 else if (strcmp(in_argv
[i
], "-s") == 0)
1468 STRNCPY(g_shell
, in_argv
[i
+ 1], sizeof(g_shell
));
1471 else if (strcmp(in_argv
[i
], "-c") == 0)
1473 STRNCPY(g_directory
, in_argv
[i
+ 1], sizeof(g_directory
));
1480 /*****************************************************************************/
1481 int main(int in_argc
, char ** in_argv
)
1483 get_username_and_hostname();
1484 /* read command line options */
1485 if (!parse_parameters(in_argc
, in_argv
))
1489 /* connect to server */
1492 fprintf(stderr
, "Couldn't connect to Nano-X server\n");
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
;
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)))
1507 fprintf(stderr
, "unsupported bpp, server = %d, client = %d\n",
1508 g_server_bpp
, g_bpp
);
1513 /* connect to server */
1514 if (!rdp_connect(g_servername
, g_flags
, g_domain
, g_password
, g_shell
,
1517 fprintf(stderr
, "Error connecting\n");
1522 g_wnd
= GrNewWindow(GR_ROOT_WINDOW_ID
, 0, 0, g_width
, g_height
, 0, 0, 0);
1525 /* create graphic context */
1527 g_gc_clean
= GrNewGC();
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 */
1541 GrDestroyGC(g_gc_clean
);
1543 GrDestroyWindow(g_wnd
);
1544 /* close connection */