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
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 #include "../rdesktop.h"
24 #include <vgakeyboard.h>
28 #include <unistd.h> // gethostname
29 #include <pwd.h> // getpwuid
30 #include <stdarg.h> // va_list va_start va_end
32 #include <sys/ioctl.h>
33 #include <linux/keyboard.h>
37 extern int g_tcp_port_rdp
;
39 char g_hostname
[16] = "";
40 char g_username
[64] = "";
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 */
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;
73 static int scrolllock
;
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
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;
93 uint8 mouse_under
[32 * 32 * 4]; // save area under mouse
101 uint8 andmask
[32 * 32];
102 uint8 xormask
[32 * 32];
110 static tcursor mcursor
;
112 static int g_draw_mouse
= 1;
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;
142 myrect
* head_rect
= 0;
144 //*****************************************************************************
145 // Keyboard stuff - PeterS
146 static void setled(int mask
, int state
)
151 if (( fd
=open("/dev/console", O_NOCTTY
)) != -1 )
153 if (ioctl (fd
, KDGETLED
, &leds
) != -1)
160 ioctl (fd
, KDSETLED
, leds
);
167 //*****************************************************************************
169 int rop(int rop
, int src
, int dst
)
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
;
193 //*****************************************************************************
194 // get a screen pixel
195 int get_pixel(int x
, int y
)
197 if (x
>= 0 && x
< g_width
&& y
>= 0 && y
< g_height
)
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
];
209 return vga_getpixel(x
, y
);
215 //*****************************************************************************
216 // set a screen pixel
217 void set_pixel(int x
, int y
, int pixel
, int op
)
219 if (x
>= clip_startx
&& x
< clip_endx
&& y
>= clip_starty
&& y
< clip_endy
)
221 if (x
>= 0 && x
< g_width
&& y
>= 0 && y
< g_height
)
228 pixel
= rop(op
, pixel
, get_pixel(x
, y
));
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
;
245 //*****************************************************************************
246 // get a pixel from a bitmap
247 int get_pixel2(int x
, int y
, uint8
* data
, int width
, int bpp
)
250 return data
[y
* width
+ x
];
252 return ((uint16
*)data
)[y
* width
+ x
];
257 //*****************************************************************************
258 // set a pixel in a bitmap
259 void set_pixel2(int x
, int y
, int pixel
, uint8
* data
, int width
, int bpp
)
262 data
[y
* width
+ x
] = pixel
;
264 ((uint16
*)data
)[y
* width
+ x
] = pixel
;
267 //*****************************************************************************
268 // get a pointer into a bitmap
269 uint8
* get_ptr(int x
, int y
, uint8
* data
, int width
, int bpp
)
272 return data
+ (y
* width
+ x
);
274 return data
+ (y
* width
+ x
) * 2;
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
)
288 width
= (width
+ 7) / 8;
289 start
= (y
* width
) + x
/ 8;
291 return (data
[start
] & (0x80 >> shift
)) != 0;
295 return data
[y
* width
+ x
] != 0;
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;
307 //*****************************************************************************
308 void set_pixel_on(uint8
* data
, int x
, int y
, int width
, int bpp
, int pixel
)
312 data
[y
* width
+ x
] = pixel
;
316 /*****************************************************************************/
317 int warp_coords(int* x
, int* y
, int* cx
, int* cy
, int* srcx
, int* srcy
)
321 // int lx = *x, ly = *y, lcx = *cx, lcy = *cy;
323 if (clip_startx
> *x
)
324 dx
= clip_startx
- *x
;
327 if (clip_starty
> *y
)
328 dy
= clip_starty
- *y
;
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*/;
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);
354 //*****************************************************************************
355 void copy_mem(uint8
* d
, uint8
* s
, int n
)
376 //*****************************************************************************
377 void copy_memb(uint8
* d
, uint8
* s
, int n
)
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
)
411 d
= get_ptr(x
, y
, sdata
, g_width
, g_server_bpp
);
412 for (i
= 0; i
< cy
; i
++)
414 copy_mem(d
, s
, cx
* g_server_Bpp
);
416 d
= d
+ g_width
* g_server_Bpp
;
419 else if (has_put_image
&& line_size
== cx
* g_server_Bpp
)
421 vga_accel(ACCEL_PUTIMAGE
, x
, y
, cx
, cy
, data
);
426 for (i
= 0; i
< cy
; i
++)
428 vga_drawscansegment(s
, x
, y
+ i
, cx
* g_server_Bpp
);
434 //*****************************************************************************
435 void accel_fill_rect(int x
, int y
, int cx
, int cy
, int color
)
443 temp
= xmalloc(cx
* g_server_Bpp
);
444 if (g_server_Bpp
== 1)
445 for (i
= 0; i
< cx
; i
++)
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
++)
453 copy_mem(d
, temp
, cx
* g_server_Bpp
);
454 d
= d
+ g_width
* g_server_Bpp
;
458 else if (has_fill_box
)
460 vga_accel(ACCEL_SETFGCOLOR
, color
);
461 vga_accel(ACCEL_FILLBOX
, x
, y
, cx
, cy
);
465 temp
= xmalloc(cx
* g_server_Bpp
);
466 if (g_server_Bpp
== 1)
467 for (i
= 0; i
< cx
; i
++)
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
);
478 //*****************************************************************************
479 void accel_screen_copy(int x
, int y
, int cx
, int cy
, int srcx
, int srcy
)
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
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
;
499 else if (srcy
> y
|| srcx
> x
) // copy up or left
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
++)
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
;
510 else // copy straight right
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
++)
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
;
522 else if (has_screen_copy
)
524 vga_accel(ACCEL_SCREENCOPY
, srcx
, srcy
, x
, y
, cx
, cy
);
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
);
538 //*****************************************************************************
540 int contains_mouse(int x
, int y
, int cx
, int cy
)
542 if (mousex
+ 32 >= x
&&
551 //*****************************************************************************
552 void fill_rect(int x
, int y
, int cx
, int cy
, int colour
, int opcode
)
557 if (warp_coords(&x
, &y
, &cx
, &cy
, NULL
, NULL
))
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);
567 for (i
= 0; i
< cy
; i
++)
568 for (j
= 0; j
< cx
; j
++)
569 set_pixel(x
+ j
, y
+ i
, colour
, opcode
);
574 //*****************************************************************************
575 void get_rect(int x
, int y
, int cx
, int cy
, uint8
* p
)
591 for (i
= 0; i
< cy
; i
++)
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
;
599 for (i
= 0; i
< cy
; i
++)
601 vga_getscansegment(p
, x
, y
+ i
, cx
* g_server_Bpp
);
602 p
= p
+ cx
* g_server_Bpp
;
607 /*****************************************************************************/
608 // return true if r1 is contained by r2
609 int is_contained_by(myrect
* r1
, myrect
* r2
)
611 if (r1
->x
>= r2
->x
&&
613 r1
->x
+ r1
->cx
<= r2
->x
+ r2
->cx
&&
614 r1
->y
+ r1
->cy
<= r2
->y
+ r2
->cy
)
620 /*****************************************************************************/
621 void draw_cursor_under(int ox
, int oy
)
638 for (i
= 0; i
< 32; i
++)
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
);
649 /*****************************************************************************/
650 void draw_cursor(void)
656 uint8 mouse_a
[32 * 32 * 4];
662 memset(mouse_under
, 0, sizeof(mouse_under
));
663 for (i
= 0; i
< 32; i
++)
665 for (j
= 0; j
< 32; j
++)
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)
673 pixel
= rop(0x8, k
, pixel
);
674 if (mcursor
.xormask
[i
* 32 + j
] == 0)
678 pixel
= rop(0x6, k
, pixel
);
679 set_pixel2(j
, i
, pixel
, mouse_a
, 32, g_server_bpp
);
686 j
= g_width
- mousex
;
691 for (i
= mousey
; i
< mousey
+ 32; i
++)
692 if (i
< g_height
&& i
>= 0)
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
);
702 /*****************************************************************************/
703 // add a rect to cache
704 void cache_rect(int x
, int y
, int cx
, int cy
, int do_warp
)
715 if (!warp_coords(&x
, &y
, &cx
, &cy
, NULL
, NULL
))
717 rect
= (myrect
*)xmalloc(sizeof(myrect
));
732 walk_rect
= head_rect
;
734 walk_rect
= walk_rect
->next
;
735 if (is_contained_by(rect
, walk_rect
))
741 while (walk_rect
->next
!= 0);
742 walk_rect
->next
= rect
;
743 rect
->prev
= walk_rect
;
747 //*****************************************************************************
748 void draw_cache_rects(void)
755 // draw all the rects
759 p
= get_ptr(rect
->x
, rect
->y
, sdata
, g_width
, g_server_bpp
);
760 for (i
= 0; i
< rect
->cy
; i
++)
762 vga_drawscansegment(p
, rect
->x
, rect
->y
+ i
, rect
->cx
* g_server_Bpp
);
763 p
= p
+ g_width
* g_server_Bpp
;
772 /*****************************************************************************/
773 void key_event(int scancode
, int pressed
)
784 if ((scancode
== SCANCODE_CAPSLOCK
) && pressed
)
786 capslock
= !capslock
;
787 setled(LED_CAP
, capslock
);
789 if ((scancode
== SCANCODE_SCROLLLOCK
) && pressed
)
791 scrolllock
= !scrolllock
;
792 setled(LED_SCR
, scrolllock
);
795 if ((scancode
== SCANCODE_NUMLOCK
) && pressed
)
798 setled(LED_NUM
, numlock
);
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
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);
831 case SCANCODE_SCROLLLOCK
: rdpkey
= 0x46; break; // scroll lock
832 case 112: // mouse down
834 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON4
,
835 mouse_getx(), mouse_gety());
838 case 113: // mouse up
840 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON5
,
841 mouse_getx(), mouse_gety());
845 // printf("%d %d\n", scancode, pressed);
847 rdp_send_input(0, RDP_INPUT_SCANCODE
, RDP_KEYPRESS
| ext
, rdpkey
, 0);
849 rdp_send_input(0, RDP_INPUT_SCANCODE
, RDP_KEYRELEASE
| ext
, rdpkey
, 0);
854 /*****************************************************************************/
858 memset(&mcursor
, 0, sizeof(tcursor
));
859 desk_save
= (uint8
*)xmalloc(0x38400 * g_server_Bpp
);
863 /*****************************************************************************/
869 /*****************************************************************************/
870 int ui_create_window(void)
875 vgamode
= G800x600x256
;
876 if (g_width
== 640 && g_height
== 480)
878 if (g_server_Bpp
== 1)
879 vgamode
= G640x480x256
;
880 else if (g_server_Bpp
== 2)
881 vgamode
= G640x480x64K
;
883 else if (g_width
== 800 && g_height
== 600)
885 if (g_server_Bpp
== 1)
886 vgamode
= G800x600x256
;
887 else if (g_server_Bpp
== 2)
888 vgamode
= G800x600x64K
;
890 else if (g_width
== 1024 && g_height
== 768)
892 if (g_server_Bpp
== 1)
893 vgamode
= G1024x768x256
;
894 else if (g_server_Bpp
== 2)
895 vgamode
= G1024x768x64K
;
899 error("Invalid width / height");
903 if (!vga_hasmode(vgamode
))
905 error("Graphics unavailable");
908 vga_setmousesupport(1);
909 mouse_setposition(g_width
/ 2, g_height
/ 2);
910 vga_setmode(vgamode
);
913 error("Keyboard unavailable");
916 keyboard_seteventhandler(key_event
);
919 i
= vga_ext_set(VGA_EXT_AVAILABLE
, VGA_AVAIL_ACCEL
);
920 if (i
& ACCELFLAG_PUTIMAGE
)
922 if (i
& ACCELFLAG_SCREENCOPY
)
924 if (i
& ACCELFLAG_FILLBOX
)
926 printf("accel %d\n", i
);
928 if (!has_screen_copy
&& !g_save_mem
)
929 sdata
= xmalloc(g_width
* g_height
* g_server_Bpp
);
933 /*****************************************************************************/
934 void ui_destroy_window(void)
936 keyboard_close(); /* Don't forget this! */
942 /*****************************************************************************/
943 void process_mouse(void)
951 mousex
= mouse_getx() - mcursor
.x
;
952 mousey
= mouse_gety() - mcursor
.y
;
953 mouseb
= mouse_getbutton();
955 if (mouseb
!= ob
) // button
960 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON2
,
961 mousex
+ mcursor
.x
, mousey
+ mcursor
.y
);
964 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON2
,
965 mousex
+ mcursor
.x
, mousey
+ mcursor
.y
);
969 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON3
,
970 mousex
+ mcursor
.x
, mousey
+ mcursor
.y
);
973 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON3
,
974 mousex
+ mcursor
.x
, mousey
+ mcursor
.y
);
978 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON1
,
979 mousex
+ mcursor
.x
, mousey
+ mcursor
.y
);
982 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON1
,
983 mousex
+ mcursor
.x
, mousey
+ mcursor
.y
);
985 if (mousex
!= ox
|| mousey
!= oy
) // movement
987 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_MOVE
,
988 mousex
+ mcursor
.x
, mousey
+ mcursor
.y
);
989 draw_cursor_under(ox
, oy
);
994 /*****************************************************************************/
995 void process_keyboard(void)
1001 /*****************************************************************************/
1002 BOOL
ui_main_loop(void)
1007 if (!rdp_connect(g_servername
, RDP_LOGON_NORMAL
, "", "", "", ""))
1011 FD_SET(g_sock
, &rfds
);
1012 sel
= vga_waitevent(3, &rfds
, NULL
, NULL
, NULL
);
1015 if (sel
& 1) /* mouse */
1019 else if (sel
& 2) /* keyboard */
1025 if (!rdp_loop(&deactivated
, &ext_disc_reason
))
1026 return True
; /* ok */
1029 FD_SET(g_sock
, &rfds
);
1030 sel
= vga_waitevent(3, &rfds
, NULL
, NULL
, NULL
);
1035 /*****************************************************************************/
1040 /*****************************************************************************/
1041 int ui_select(int in
)
1047 /*****************************************************************************/
1048 void* ui_create_glyph(int width
, int height
, uint8
* data
)
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);
1067 /*****************************************************************************/
1068 void ui_destroy_glyph(void* glyph
)
1072 the_glyph
= (bitmap
*)glyph
;
1073 if (the_glyph
!= NULL
)
1075 if (the_glyph
->data
!= NULL
)
1076 xfree(the_glyph
->data
);
1081 /*****************************************************************************/
1082 void ui_destroy_bitmap(void* bmp
)
1091 /*****************************************************************************/
1092 void ui_reset_clip(void)
1096 clip_endx
= g_width
;
1097 clip_endy
= g_height
;
1100 /*****************************************************************************/
1101 void ui_set_clip(int x
, int y
, int cx
, int cy
)
1109 /*****************************************************************************/
1110 void* ui_create_colourmap(COLOURMAP
* colours
)
1113 int n
= colours
->ncolours
;
1114 COLOURENTRY
* c
= colours
->colours
;
1115 int* cmap
= (int*)xmalloc(3 * 256 * sizeof (int));
1118 bzero(cmap
, 256 * 3 * sizeof (int));
1119 for (i
= 0; i
< (3 * n
); c
++)
1121 cmap
[i
++] = (c
->red
) >> 2;
1122 cmap
[i
++] = (c
->green
) >> 2;
1123 cmap
[i
++] = (c
->blue
) >> 2;
1128 /*****************************************************************************/
1129 void ui_destroy_colourmap(HCOLOURMAP map
)
1136 /*****************************************************************************/
1137 void ui_set_colourmap(void* map
)
1141 vga_setpalvec(0, 256, (int*)map
);
1145 /*****************************************************************************/
1146 HBITMAP
ui_create_bitmap(int width
, int height
, uint8
* data
)
1150 b
= (bitmap
*)xmalloc(sizeof(bitmap
));
1151 b
->data
= (uint8
*)xmalloc(width
* height
* g_server_Bpp
);
1154 b
->Bpp
= g_server_Bpp
;
1155 copy_mem(b
->data
, data
, width
* height
* g_server_Bpp
);
1159 //*****************************************************************************
1160 void draw_glyph (int x
, int y
, HGLYPH glyph
, int fgcolour
)
1165 the_glyph
= (bitmap
*)glyph
;
1166 if (the_glyph
== NULL
)
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);
1174 #define DO_GLYPH(ttext,idx) \
1176 glyph = cache_get_font (font, ttext[idx]);\
1177 if (!(flags & TEXT2_IMPLICIT_X))\
1179 xyoffset = ttext[++idx];\
1180 if ((xyoffset & 0x80))\
1182 if (flags & TEXT2_VERTICAL) \
1183 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1185 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1190 if (flags & TEXT2_VERTICAL) \
1198 draw_glyph (x + glyph->offset, y + glyph->baseline, glyph->pixmap, fgcolour);\
1199 if (flags & TEXT2_IMPLICIT_X)\
1204 /*****************************************************************************/
1205 void ui_draw_text(uint8 font
, uint8 flags
, uint8 opcode
, int mixmode
,
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
)
1219 if (contains_mouse(boxx
, boxy
, boxcx
, boxcy
))
1220 draw_cursor_under(mousex
, mousey
);
1221 fill_rect(boxx
, boxy
, boxcx
, boxcy
, bgcolour
, 0xc);
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);
1231 /* Paint text, character by character */
1232 for (i
= 0; i
< length
;)
1238 cache_put_text(text
[i
+ 1], text
, text
[i
+ 2]);
1241 error("this shouldn't be happening\n");
1244 /* this will move pointer from start to first character after FF command */
1246 text
= &(text
[i
+ 3]);
1251 entry
= cache_get_text(text
[i
+ 1]);
1254 if ((((uint8
*) (entry
->data
))[1] == 0) && (!(flags
& TEXT2_IMPLICIT_X
)))
1256 if (flags
& TEXT2_VERTICAL
)
1261 for (j
= 0; j
< entry
->size
; j
++)
1262 DO_GLYPH(((uint8
*) (entry
->data
)), j
);
1269 /* this will move pointer from start to first character after FE command */
1281 cache_rect(boxx
, boxy
, boxcx
, boxcy
, True
);
1283 cache_rect(clipx
, clipy
, clipcx
, clipcy
, True
);
1286 //*****************************************************************************
1287 // Bresenham's line drawing algorithm
1288 void ui_line(uint8 opcode
, int startx
, int starty
, int endx
,
1331 if (contains_mouse(left
, top
, (right
- left
) + 1, (bottom
- top
) + 1))
1332 draw_cursor_under(mousex
, mousey
);
1336 dpru
= dpr
- (dx
<< 1);
1338 for (; dx
>= 0; dx
--)
1340 set_pixel(startx
, starty
, pen
->colour
, opcode
);
1357 dpru
= dpr
- (dy
<< 1);
1359 for (; dy
>= 0; dy
--)
1361 set_pixel(startx
, starty
, pen
->colour
, opcode
);
1375 cache_rect(left
, top
, (right
- left
) + 1, (bottom
- top
) + 1, True
);
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
)
1386 /*****************************************************************************/
1387 void ui_memblt(uint8 opcode
, int x
, int y
, int cx
, int cy
,
1388 HBITMAP src
, int srcx
, int srcy
)
1395 if (warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
1397 if (contains_mouse(x
, y
, cx
, cy
))
1398 draw_cursor_under(mousex
, mousey
);
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
);
1405 for (i
= 0; i
< cy
; i
++)
1407 for (j
= 0; j
< cx
; j
++)
1409 pixel
= get_pixel2(srcx
+ j
, srcy
+ i
, b
->data
, b
->width
, g_server_bpp
);
1410 set_pixel(x
+ j
, y
+ i
, pixel
, opcode
);
1414 cache_rect(x
, y
, cx
, cy
, False
);
1418 /*****************************************************************************/
1419 void ui_desktop_restore(uint32 offset
, int x
, int y
, int cx
, int cy
)
1423 if (offset
> 0x38400)
1425 if (offset
+ cx
* cy
> 0x38400)
1427 p
= desk_save
+ offset
* g_server_Bpp
;
1428 ui_paint_bitmap(x
, y
, cx
, cy
, cx
, cy
, p
);
1431 /*****************************************************************************/
1432 void ui_desktop_save(uint32 offset
, int x
, int y
, int cx
, int cy
)
1436 if (offset
> 0x38400)
1438 if (offset
+ cx
* cy
> 0x38400)
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
);
1446 /*****************************************************************************/
1447 void ui_rect(int x
, int y
, int cx
, int cy
, int colour
)
1449 if (warp_coords(&x
, &y
, &cx
, &cy
, NULL
, NULL
))
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
);
1458 /*****************************************************************************/
1459 void ui_screenblt(uint8 opcode
, int x
, int y
, int cx
, int cy
,
1466 if (x
== srcx
&& y
== srcy
)
1468 if (warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
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
);
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
);
1485 cache_rect(x
, y
, cx
, cy
, False
);
1486 draw_cache_rects(); // draw them all so screen is not jumpy
1490 /*****************************************************************************/
1491 void ui_patblt(uint8 opcode
, int x
, int y
, int cx
, int cy
,
1492 BRUSH
* brush
, int bgcolour
, int fgcolour
)
1498 if (warp_coords(&x
, &y
, &cx
, &cy
, NULL
, NULL
))
1500 if (contains_mouse(x
, y
, cx
, cy
))
1501 draw_cursor_under(mousex
, mousey
);
1502 switch (brush
->style
)
1505 fill_rect(x
, y
, cx
, cy
, fgcolour
, opcode
);
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
);
1516 set_pixel(x
+ j
, y
+ i
, bgcolour
, opcode
);
1519 cache_rect(x
, y
, cx
, cy
, False
);
1523 /*****************************************************************************/
1524 void ui_destblt(uint8 opcode
, int x
, int y
, int cx
, int cy
)
1526 if (warp_coords(&x
, &y
, &cx
, &cy
, NULL
, NULL
))
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
);
1535 /*****************************************************************************/
1536 void ui_move_pointer(int x
, int y
)
1540 /*****************************************************************************/
1541 void ui_set_null_cursor(void)
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
));
1552 /*****************************************************************************/
1553 void ui_paint_bitmap(int x
, int y
, int cx
, int cy
,
1554 int width
, int height
, uint8
* data
)
1556 if (warp_coords(&x
, &y
, &cx
, &cy
, NULL
, NULL
))
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
);
1565 /*****************************************************************************/
1566 void* ui_create_cursor(unsigned int x
, unsigned int y
,
1567 int width
, int height
,
1568 uint8
* andmask
, uint8
* xormask
)
1574 c
= (tcursor
*)xmalloc(sizeof(tcursor
));
1575 memset(c
, 0, sizeof(tcursor
));
1580 for (i
= 0; i
< 32; i
++)
1582 for (j
= 0; j
< 32; j
++)
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);
1593 /*****************************************************************************/
1594 void ui_destroy_cursor(void* cursor
)
1600 /*****************************************************************************/
1601 void ui_set_cursor(void* cursor
)
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
);
1619 /*****************************************************************************/
1620 uint16
ui_get_numlock_state(unsigned int state
)
1625 /*****************************************************************************/
1626 unsigned int read_keyboard_state(void)
1631 /*****************************************************************************/
1632 void ui_resize_window(void)
1636 /*****************************************************************************/
1637 void ui_begin_update(void)
1641 /*****************************************************************************/
1642 void ui_end_update(void)
1648 /*****************************************************************************/
1649 void ui_polygon(uint8 opcode
, uint8 fillmode
, POINT
* point
, int npoints
,
1650 BRUSH
* brush
, int bgcolour
, int fgcolour
)
1654 /*****************************************************************************/
1655 void ui_polyline(uint8 opcode
, POINT
* points
, int npoints
, PEN
* pen
)
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
)
1666 /*****************************************************************************/
1667 void generate_random(uint8
* random
)
1669 memcpy(random
, "12345678901234567890123456789012", 32);
1672 /*****************************************************************************/
1673 void save_licence(uint8
* data
, int length
)
1677 /*****************************************************************************/
1678 int load_licence(uint8
** data
)
1683 /*****************************************************************************/
1684 void* xrealloc(void* in_val
, int size
)
1686 return realloc(in_val
, size
);
1689 /*****************************************************************************/
1690 void* xmalloc(int size
)
1692 return malloc(size
);
1695 /*****************************************************************************/
1696 void xfree(void* in_val
)
1701 /*****************************************************************************/
1702 char * xstrdup(const char * s
)
1704 char * mem
= strdup(s
);
1713 /*****************************************************************************/
1714 void warning(char* format
, ...)
1718 fprintf(stderr
, "WARNING: ");
1719 va_start(ap
, format
);
1720 vfprintf(stderr
, format
, ap
);
1724 /*****************************************************************************/
1725 void unimpl(char* format
, ...)
1729 fprintf(stderr
, "NOT IMPLEMENTED: ");
1730 va_start(ap
, format
);
1731 vfprintf(stderr
, format
, ap
);
1735 /*****************************************************************************/
1736 void error(char* format
, ...)
1740 fprintf(stderr
, "ERROR: ");
1741 va_start(ap
, format
);
1742 vfprintf(stderr
, format
, ap
);
1746 BOOL
rd_pstcache_mkdir(void)
1751 /*****************************************************************************/
1752 int rd_open_file(char *filename
)
1757 /*****************************************************************************/
1758 void rd_close_file(int fd
)
1763 /*****************************************************************************/
1764 int rd_read_file(int fd
, void *ptr
, int len
)
1769 /*****************************************************************************/
1770 int rd_write_file(int fd
, void* ptr
, int len
)
1775 /*****************************************************************************/
1776 int rd_lseek_file(int fd
, int offset
)
1781 /*****************************************************************************/
1782 BOOL
rd_lock_file(int fd
, int start
, int len
)
1787 /*****************************************************************************/
1788 void get_username_and_hostname(void)
1790 char fullhostname
[64];
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
)
1799 STRNCPY(g_username
, pw
->pw_name
, sizeof(g_username
));
1801 if (gethostname(fullhostname
, sizeof(fullhostname
)) != -1)
1803 p
= strchr(fullhostname
, '.');
1806 STRNCPY(g_hostname
, fullhostname
, sizeof(g_hostname
));
1810 /*****************************************************************************/
1811 void out_params(void)
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");
1829 /* produce a hex dump */
1830 void hexdump(uint8
* p
, uint32 len
)
1839 while (offset
< len
)
1841 printf("%04x ", offset
);
1842 thisline
= len
- offset
;
1846 for (i
= 0; i
< thisline
; i
++)
1847 printf("%02x ", line
[i
]);
1852 for (i
= 0; i
< thisline
; i
++)
1853 printf("%c", (line
[i
] >= 0x20 && line
[i
] < 0x7f) ? line
[i
] : '.');
1861 /*****************************************************************************/
1862 int parse_parameters(int in_argc
, char** in_argv
)
1874 for (i
= 1; i
< in_argc
; i
++)
1876 strcpy(g_servername
, in_argv
[i
]);
1877 if (strcmp(in_argv
[i
], "-g") == 0)
1879 g_width
= strtol(in_argv
[i
+ 1], &p
, 10);
1882 error("invalid geometry\n");
1886 g_height
= strtol(p
+ 1, NULL
, 10);
1889 error("invalid geometry\n");
1892 g_width
= (g_width
+ 3) & ~3;
1894 else if (strcmp(in_argv
[i
], "-4") == 0)
1896 else if (strcmp(in_argv
[i
], "-5") == 0)
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)
1905 else if (strcmp(in_argv
[i
], "-n") == 0)
1907 STRNCPY(g_hostname
, in_argv
[i
+ 1], sizeof(g_hostname
));
1909 else if (strcmp(in_argv
[i
], "-u") == 0)
1911 STRNCPY(g_username
, in_argv
[i
+ 1], sizeof(g_username
));
1913 else if (strcmp(in_argv
[i
], "-d") == 0)
1917 else if (strcmp(in_argv
[i
], "-a") == 0)
1919 g_server_bpp
= strtol(in_argv
[i
+ 1], NULL
, 10);
1920 if (g_server_bpp
!= 8 && g_server_bpp
!= 16)
1922 error("invalid server bpp\n");
1925 g_server_Bpp
= (g_server_bpp
+ 7) / 8;
1927 else if (strcmp(in_argv
[i
], "-l") == 0)
1933 /*****************************************************************************/
1934 int main(int in_argc
, char** in_argv
)
1936 get_username_and_hostname();
1937 if (!parse_parameters(in_argc
, in_argv
))
1941 if (!ui_create_window())
1944 ui_destroy_window();