reactos/rosapps/applications/net/tsclient/rdesktop/uiports/svgawin.c
2009-12-02 18:58:05 +00:00

1948 lines
47 KiB
C

/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
User interface services - SVGA lib
Copyright (C) Jay Sorg 2004-2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "../rdesktop.h"
#include <vga.h>
#include <vgakeyboard.h>
#include <vgamouse.h>
#include <vgagl.h>
#include <unistd.h> // gethostname
#include <pwd.h> // getpwuid
#include <stdarg.h> // va_list va_start va_end
#include <sys/ioctl.h>
#include <linux/keyboard.h>
#include <linux/kd.h>
#include <fcntl.h>
extern int g_tcp_port_rdp;
int g_use_rdp5 = 0;
char g_hostname[16] = "";
char g_username[64] = "";
int g_height = 600;
int g_width = 800;
int g_server_bpp = 8;
int g_encryption = 1;
int g_desktop_save = 1;
int g_polygon_ellipse_orders = 0;
int g_bitmap_cache = 1;
int g_bitmap_cache_persist_enable = False;
int g_bitmap_cache_precache = True;
int g_bitmap_compression = 1;
int g_rdp5_performanceflags = 0;
int g_console_session = 0;
int g_keylayout = 0x409; /* Defaults to US keyboard layout */
int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */
int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */
int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */
/* hack globals */
int g_argc = 0;
char** g_argv = 0;
int UpAndRunning = 0;
int g_sock = 0;
int deactivated = 0;
uint32 ext_disc_reason = 0;
char g_servername[128] = "";
static uint32* colmap = 0;
static uint8* desk_save = 0;
static int g_server_Bpp = 1;
/* Keyboard LEDS */
static int numlock;
static int capslock;
static int scrolllock;
// this is non null if vgalib has non accel functions available
// reading from video memory is sooo slow
static uint8* sdata = 0;
static int g_save_mem = 0; // for video memory use eg sdata == 0
// video acceleration
static int use_accel = 1;
static int has_fill_box = 0;
static int has_screen_copy = 0;
static int has_put_image = 0;
// clip
int clip_startx;
int clip_starty;
int clip_endx;
int clip_endy;
// mouse
uint8 mouse_under[32 * 32 * 4]; // save area under mouse
int mousex = 0;
int mousey = 0;
int mouseb = 0;
// mouse info
typedef struct
{
uint8 andmask[32 * 32];
uint8 xormask[32 * 32];
int x;
int y;
int w;
int h;
} tcursor;
// mouse global
static tcursor mcursor;
static int g_draw_mouse = 1;
/* Session Directory redirection */
BOOL g_redirect = False;
char g_redirect_server[64];
char g_redirect_domain[16];
char g_redirect_password[64];
char g_redirect_username[64];
char g_redirect_cookie[128];
uint32 g_redirect_flags = 0;
// bitmap
typedef struct
{
int width;
int height;
uint8* data;
uint8 Bpp;
} bitmap;
typedef struct
{
int x;
int y;
int cx;
int cy;
void* prev;
void* next;
} myrect;
myrect* head_rect = 0;
//*****************************************************************************
// Keyboard stuff - PeterS
static void setled(int mask, int state)
{
int fd;
long int leds;
if (( fd=open("/dev/console", O_NOCTTY)) != -1 )
{
if (ioctl (fd, KDGETLED, &leds) != -1)
{
leds &= 7;
if (state)
leds |= mask;
else
leds &= ~mask;
ioctl (fd, KDSETLED, leds);
}
close(fd);
}
}
//*****************************************************************************
// do a raster op
int rop(int rop, int src, int dst)
{
switch (rop)
{
case 0x0: return 0;
case 0x1: return ~(src | dst);
case 0x2: return (~src) & dst;
case 0x3: return ~src;
case 0x4: return src & (~dst);
case 0x5: return ~(dst);
case 0x6: return src ^ dst;
case 0x7: return ~(src & dst);
case 0x8: return src & dst;
case 0x9: return ~(src) ^ dst;
case 0xa: return dst;
case 0xb: return (~src) | dst;
case 0xc: return src;
case 0xd: return src | (~dst);
case 0xe: return src | dst;
case 0xf: return ~0;
}
return dst;
}
//*****************************************************************************
// get a screen pixel
int get_pixel(int x, int y)
{
if (x >= 0 && x < g_width && y >= 0 && y < g_height)
{
if (sdata != 0)
{
if (g_server_Bpp == 1)
return sdata[y * g_width + x];
else if (g_server_Bpp == 2)
return ((uint16*)sdata)[y * g_width + x];
else
return 0;
}
else
return vga_getpixel(x, y);
}
else
return 0;
}
//*****************************************************************************
// set a screen pixel
void set_pixel(int x, int y, int pixel, int op)
{
if (x >= clip_startx && x < clip_endx && y >= clip_starty && y < clip_endy)
{
if (x >= 0 && x < g_width && y >= 0 && y < g_height)
{
if (op == 0x0)
pixel = 0;
else if (op == 0xf)
pixel = -1;
else if (op != 0xc)
pixel = rop(op, pixel, get_pixel(x, y));
if (sdata != 0)
{
if (g_server_Bpp == 1)
sdata[y * g_width + x] = pixel;
else if (g_server_Bpp == 2)
((uint16*)sdata)[y * g_width + x] = pixel;
}
else
{
vga_setcolor(pixel);
vga_drawpixel(x, y);
}
}
}
}
//*****************************************************************************
// get a pixel from a bitmap
int get_pixel2(int x, int y, uint8* data, int width, int bpp)
{
if (bpp == 8)
return data[y * width + x];
else if (bpp == 16)
return ((uint16*)data)[y * width + x];
else
return 0;
}
//*****************************************************************************
// set a pixel in a bitmap
void set_pixel2(int x, int y, int pixel, uint8* data, int width, int bpp)
{
if (bpp == 8)
data[y * width + x] = pixel;
else if (bpp == 16)
((uint16*)data)[y * width + x] = pixel;
}
//*****************************************************************************
// get a pointer into a bitmap
uint8* get_ptr(int x, int y, uint8* data, int width, int bpp)
{
if (bpp == 8)
return data + (y * width + x);
else if (bpp == 16)
return data + (y * width + x) * 2;
else
return 0;
}
//*****************************************************************************
// check if a certain pixel is set in a bitmap
BOOL is_pixel_on(uint8* data, int x, int y, int width, int bpp)
{
int start;
int shift;
if (bpp == 1)
{
width = (width + 7) / 8;
start = (y * width) + x / 8;
shift = x % 8;
return (data[start] & (0x80 >> shift)) != 0;
}
else if (bpp == 8)
{
return data[y * width + x] != 0;
}
else if (bpp == 24)
{
return data[(y * 3) * width + (x * 3)] != 0 &&
data[(y * 3) * width + (x * 3) + 1] != 0 &&
data[(y * 3) * width + (x * 3) + 2] != 0;
}
else
return False;
}
//*****************************************************************************
void set_pixel_on(uint8* data, int x, int y, int width, int bpp, int pixel)
{
if (bpp == 8)
{
data[y * width + x] = pixel;
}
}
/*****************************************************************************/
int warp_coords(int* x, int* y, int* cx, int* cy, int* srcx, int* srcy)
{
int dx;
int dy;
// int lx = *x, ly = *y, lcx = *cx, lcy = *cy;
if (clip_startx > *x)
dx = clip_startx - *x;
else
dx = 0;
if (clip_starty > *y)
dy = clip_starty - *y;
else
dy = 0;
if (*x + *cx > clip_endx)
*cx = (*cx - ((*x + *cx) - clip_endx)) /*+ 1*/;
if (*y + *cy > clip_endy)
*cy = (*cy - ((*y + *cy) - clip_endy)) /*+ 1*/;
*cx = *cx - dx;
*cy = *cy - dy;
if (*cx <= 0)
return False;
if (*cy <= 0)
return False;
*x = *x + dx;
*y = *y + dy;
if (srcx != NULL)
*srcx = *srcx + dx;
if (srcy != NULL)
*srcy = *srcy + dy;
// if (*x != lx || *y != ly || *cx != lcx || *cy != lcy)
// printf("%d %d %d %d to %d %d %d %d\n", lx, ly, lcx, lcy, *x, *y, *cx, *cy);
return True;
}
//*****************************************************************************
void copy_mem(uint8* d, uint8* s, int n)
{
while (n & (~7))
{
*(d++) = *(s++);
*(d++) = *(s++);
*(d++) = *(s++);
*(d++) = *(s++);
*(d++) = *(s++);
*(d++) = *(s++);
*(d++) = *(s++);
*(d++) = *(s++);
n = n - 8;
}
while (n > 0)
{
*(d++) = *(s++);
n--;
}
}
//*****************************************************************************
void copy_memb(uint8* d, uint8* s, int n)
{
d = (d + n) - 1;
s = (s + n) - 1;
while (n & (~7))
{
*(d--) = *(s--);
*(d--) = *(s--);
*(d--) = *(s--);
*(d--) = *(s--);
*(d--) = *(s--);
*(d--) = *(s--);
*(d--) = *(s--);
*(d--) = *(s--);
n = n - 8;
}
while (n > 0)
{
*(d--) = *(s--);
n--;
}
}
//*****************************************************************************
// all in pixel except line_size is in bytes
void accel_draw_box(int x, int y, int cx, int cy, uint8* data, int line_size)
{
int i;
uint8* s;
uint8* d;
if (sdata != 0)
{
s = data;
d = get_ptr(x, y, sdata, g_width, g_server_bpp);
for (i = 0; i < cy; i++)
{
copy_mem(d, s, cx * g_server_Bpp);
s = s + line_size;
d = d + g_width * g_server_Bpp;
}
}
else if (has_put_image && line_size == cx * g_server_Bpp)
{
vga_accel(ACCEL_PUTIMAGE, x, y, cx, cy, data);
}
else
{
s = data;
for (i = 0; i < cy; i++)
{
vga_drawscansegment(s, x, y + i, cx * g_server_Bpp);
s = s + line_size;
}
}
}
//*****************************************************************************
void accel_fill_rect(int x, int y, int cx, int cy, int color)
{
int i;
uint8* temp;
uint8* d;
if (sdata != 0)
{
temp = xmalloc(cx * g_server_Bpp);
if (g_server_Bpp == 1)
for (i = 0; i < cx; i++)
temp[i] = color;
else if (g_server_Bpp == 2)
for (i = 0; i < cx; i++)
((uint16*)temp)[i] = color;
d = get_ptr(x, y, sdata, g_width, g_server_bpp);
for (i = 0; i < cy; i++)
{
copy_mem(d, temp, cx * g_server_Bpp);
d = d + g_width * g_server_Bpp;
}
xfree(temp);
}
else if (has_fill_box)
{
vga_accel(ACCEL_SETFGCOLOR, color);
vga_accel(ACCEL_FILLBOX, x, y, cx, cy);
}
else
{
temp = xmalloc(cx * g_server_Bpp);
if (g_server_Bpp == 1)
for (i = 0; i < cx; i++)
temp[i] = color;
else if (g_server_Bpp == 2)
for (i = 0; i < cx; i++)
((uint16*)temp)[i] = color;
for (i = 0; i < cy; i++)
vga_drawscansegment(temp, x, y + i, cx * g_server_Bpp);
xfree(temp);
}
}
//*****************************************************************************
void accel_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy)
{
uint8* temp;
uint8* s;
uint8* d;
int i;
if (sdata != 0)
{
if (srcy < y)
{ // bottom to top
s = get_ptr(srcx, (srcy + cy) - 1, sdata, g_width, g_server_bpp);
d = get_ptr(x, (y + cy) - 1, sdata, g_width, g_server_bpp);
for (i = 0; i < cy; i++) // copy down
{
copy_mem(d, s, cx * g_server_Bpp);
s = s - g_width * g_server_Bpp;
d = d - g_width * g_server_Bpp;
}
}
else if (srcy > y || srcx > x) // copy up or left
{ // top to bottom
s = get_ptr(srcx, srcy, sdata, g_width, g_server_bpp);
d = get_ptr(x, y, sdata, g_width, g_server_bpp);
for (i = 0; i < cy; i++)
{
copy_mem(d, s, cx * g_server_Bpp);
s = s + g_width * g_server_Bpp;
d = d + g_width * g_server_Bpp;
}
}
else // copy straight right
{
s = get_ptr(srcx, srcy, sdata, g_width, g_server_bpp);
d = get_ptr(x, y, sdata, g_width, g_server_bpp);
for (i = 0; i < cy; i++)
{
copy_memb(d, s, cx * g_server_Bpp);
s = s + g_width * g_server_Bpp;
d = d + g_width * g_server_Bpp;
}
}
}
else if (has_screen_copy)
{
vga_accel(ACCEL_SCREENCOPY, srcx, srcy, x, y, cx, cy);
}
else
{
// slow
temp = (uint8*)xmalloc(cx * cy * g_server_Bpp);
for (i = 0; i < cy; i++)
vga_getscansegment(get_ptr(0, i, temp, cx, g_server_bpp), srcx, srcy + i, cx * g_server_Bpp);
for (i = 0; i < cy; i++)
vga_drawscansegment(get_ptr(0, i, temp, cx, g_server_bpp), x, y + i, cx * g_server_Bpp);
xfree(temp);
}
}
//*****************************************************************************
// return bool
int contains_mouse(int x, int y, int cx, int cy)
{
if (mousex + 32 >= x &&
mousey + 32 >= y &&
mousex <= x + cx &&
mousey <= y + cy)
return 1;
else
return 0;
}
//*****************************************************************************
void fill_rect(int x, int y, int cx, int cy, int colour, int opcode)
{
int i;
int j;
if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
{
if (opcode == 0xc)
accel_fill_rect(x, y, cx, cy, colour);
else if (opcode == 0xf)
accel_fill_rect(x, y, cx, cy, -1);
else if (opcode == 0x0)
accel_fill_rect(x, y, cx, cy, 0);
else
{
for (i = 0; i < cy; i++)
for (j = 0; j < cx; j++)
set_pixel(x + j, y + i, colour, opcode);
}
}
}
//*****************************************************************************
void get_rect(int x, int y, int cx, int cy, uint8* p)
{
int i;
if (x < 0)
{
cx = cx + x;
x = 0;
}
if (y < 0)
{
cy = cy + y;
y = 0;
}
if (sdata != 0)
{
for (i = 0; i < cy; i++)
{
copy_mem(p, get_ptr(x, y + i, sdata, g_width, g_server_bpp), cx * g_server_Bpp);
p = p + cx * g_server_Bpp;
}
}
else
{
for (i = 0; i < cy; i++)
{
vga_getscansegment(p, x, y + i, cx * g_server_Bpp);
p = p + cx * g_server_Bpp;
}
}
}
/*****************************************************************************/
// return true if r1 is contained by r2
int is_contained_by(myrect* r1, myrect* r2)
{
if (r1->x >= r2->x &&
r1->y >= r2->y &&
r1->x + r1->cx <= r2->x + r2->cx &&
r1->y + r1->cy <= r2->y + r2->cy)
return 1;
else
return 0;
}
/*****************************************************************************/
void draw_cursor_under(int ox, int oy)
{
int i;
int j;
int k;
uint8* ptr;
int len;
if (ox < 0)
k = -ox;
else
k = 0;
j = g_width - ox;
if (j > 32)
j = 32;
if (j > 0)
{
for (i = 0; i < 32; i++)
{
ptr = get_ptr(k, i, mouse_under, 32, g_server_bpp);
len = (j - k) * g_server_Bpp;
if (ox + k >= 0 && oy + i >= 0 && ox + k < g_width && oy + i < g_height)
vga_drawscansegment(ptr, ox + k, oy + i, len);
}
}
g_draw_mouse = 1;
}
/*****************************************************************************/
void draw_cursor(void)
{
int i;
int j;
int k;
int pixel;
uint8 mouse_a[32 * 32 * 4];
uint8* ptr;
int len;
if (!g_draw_mouse)
return;
memset(mouse_under, 0, sizeof(mouse_under));
for (i = 0; i < 32; i++)
{
for (j = 0; j < 32; j++)
{
pixel = get_pixel(mousex + j, mousey + i);
set_pixel2(j, i, pixel, mouse_under, 32, g_server_bpp);
if (mcursor.andmask[i * 32 + j] == 0)
k = 0;
else
k = ~0;
pixel = rop(0x8, k, pixel);
if (mcursor.xormask[i * 32 + j] == 0)
k = 0;
else
k = ~0;
pixel = rop(0x6, k, pixel);
set_pixel2(j, i, pixel, mouse_a, 32, g_server_bpp);
}
}
if (mousex < 0)
k = -mousex;
else
k = 0;
j = g_width - mousex;
if (j > 32)
j = 32;
if (j > 0)
{
for (i = mousey; i < mousey + 32; i++)
if (i < g_height && i >= 0)
{
ptr = get_ptr(k, i - mousey, mouse_a, 32, g_server_bpp);
len = (j - k) * g_server_Bpp;
vga_drawscansegment(ptr, mousex + k, i, len);
}
}
g_draw_mouse = 0;
}
/*****************************************************************************/
// add a rect to cache
void cache_rect(int x, int y, int cx, int cy, int do_warp)
{
myrect* rect;
myrect* walk_rect;
if (sdata == 0)
{
draw_cursor();
return;
}
if (do_warp)
if (!warp_coords(&x, &y, &cx, &cy, NULL, NULL))
return;
rect = (myrect*)xmalloc(sizeof(myrect));
rect->x = x;
rect->y = y;
rect->cx = cx;
rect->cy = cy;
rect->next = 0;
rect->prev = 0;
if (head_rect == 0)
head_rect = rect;
else
{
walk_rect = 0;
do
{
if (walk_rect == 0)
walk_rect = head_rect;
else
walk_rect = walk_rect->next;
if (is_contained_by(rect, walk_rect))
{
xfree(rect);
return;
}
}
while (walk_rect->next != 0);
walk_rect->next = rect;
rect->prev = walk_rect;
}
}
//*****************************************************************************
void draw_cache_rects(void)
{
int i;
myrect* rect;
myrect* rect1;
uint8* p;
// draw all the rects
rect = head_rect;
while (rect != 0)
{
p = get_ptr(rect->x, rect->y, sdata, g_width, g_server_bpp);
for (i = 0; i < rect->cy; i++)
{
vga_drawscansegment(p, rect->x, rect->y + i, rect->cx * g_server_Bpp);
p = p + g_width * g_server_Bpp;
}
rect1 = rect;
rect = rect->next;
xfree(rect1);
}
head_rect = 0;
}
/*****************************************************************************/
void key_event(int scancode, int pressed)
{
int rdpkey;
int ext;
if (!UpAndRunning)
return;
rdpkey = scancode;
ext = 0;
// Keyboard LEDS
if ((scancode == SCANCODE_CAPSLOCK) && pressed)
{
capslock = !capslock;
setled(LED_CAP, capslock);
}
if ((scancode == SCANCODE_SCROLLLOCK) && pressed)
{
scrolllock = !scrolllock;
setled(LED_SCR, scrolllock);
}
if ((scancode == SCANCODE_NUMLOCK) && pressed)
{
numlock = !numlock;
setled(LED_NUM, numlock);
}
switch (scancode)
{
case SCANCODE_CURSORBLOCKUP: rdpkey = 0xc8; ext = KBD_FLAG_EXT; break; // up arrow
case SCANCODE_CURSORBLOCKDOWN: rdpkey = 0xd0; ext = KBD_FLAG_EXT; break; // down arrow
case SCANCODE_CURSORBLOCKRIGHT: rdpkey = 0xcd; ext = KBD_FLAG_EXT; break; // right arrow
case SCANCODE_CURSORBLOCKLEFT: rdpkey = 0xcb; ext = KBD_FLAG_EXT; break; // left arrow
case SCANCODE_PAGEDOWN: rdpkey = 0xd1; ext = KBD_FLAG_EXT; break; // page down
case SCANCODE_PAGEUP: rdpkey = 0xc9; ext = KBD_FLAG_EXT; break; // page up
case SCANCODE_HOME: rdpkey = 0xc7; ext = KBD_FLAG_EXT; break; // home
case SCANCODE_END: rdpkey = 0xcf; ext = KBD_FLAG_EXT; break; // end
case SCANCODE_INSERT: rdpkey = 0xd2; ext = KBD_FLAG_EXT; break; // insert
case SCANCODE_REMOVE: rdpkey = 0xd3; ext = KBD_FLAG_EXT; break; // delete
case SCANCODE_KEYPADDIVIDE: rdpkey = 0x35; break; // /
case SCANCODE_KEYPADENTER: rdpkey = 0x1c; break; // enter
case SCANCODE_RIGHTCONTROL: rdpkey = 0x1d; break; // right ctrl
case SCANCODE_RIGHTALT: rdpkey = 0x38; break; // right alt
case SCANCODE_LEFTWIN: rdpkey = 0x5b; ext = KBD_FLAG_EXT; break; // left win
case SCANCODE_RIGHTWIN: rdpkey = 0x5c; ext = KBD_FLAG_EXT; break; // right win
case 127: rdpkey = 0x5d; ext = KBD_FLAG_EXT; break; // menu key
case SCANCODE_PRINTSCREEN: rdpkey = 0x37; ext = KBD_FLAG_EXT; break; // print screen
case SCANCODE_BREAK: //rdpkey = 0; break; // break
{
if (pressed)
{
ext = KBD_FLAG_EXT;
rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS | ext, 0x46, 0);
rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS | ext, 0xc6, 0);
}
rdpkey = 0;
}
case SCANCODE_SCROLLLOCK: rdpkey = 0x46; break; // scroll lock
case 112: // mouse down
{
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON4,
mouse_getx(), mouse_gety());
return;
}
case 113: // mouse up
{
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON5,
mouse_getx(), mouse_gety());
return;
}
}
// printf("%d %d\n", scancode, pressed);
if (pressed)
rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS | ext, rdpkey, 0);
else
rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE | ext, rdpkey, 0);
}
/*****************************************************************************/
int ui_init(void)
{
vga_init();
memset(&mcursor, 0, sizeof(tcursor));
desk_save = (uint8*)xmalloc(0x38400 * g_server_Bpp);
return 1;
}
/*****************************************************************************/
void ui_deinit(void)
{
xfree(desk_save);
}
/*****************************************************************************/
int ui_create_window(void)
{
int vgamode;
int i;
vgamode = G800x600x256;
if (g_width == 640 && g_height == 480)
{
if (g_server_Bpp == 1)
vgamode = G640x480x256;
else if (g_server_Bpp == 2)
vgamode = G640x480x64K;
}
else if (g_width == 800 && g_height == 600)
{
if (g_server_Bpp == 1)
vgamode = G800x600x256;
else if (g_server_Bpp == 2)
vgamode = G800x600x64K;
}
else if (g_width == 1024 && g_height == 768)
{
if (g_server_Bpp == 1)
vgamode = G1024x768x256;
else if (g_server_Bpp == 2)
vgamode = G1024x768x64K;
}
else
{
error("Invalid width / height");
return 0;
}
ui_reset_clip();
if (!vga_hasmode(vgamode))
{
error("Graphics unavailable");
return 0;
}
vga_setmousesupport(1);
mouse_setposition(g_width / 2, g_height / 2);
vga_setmode(vgamode);
if (keyboard_init())
{
error("Keyboard unavailable");
return 0;
}
keyboard_seteventhandler(key_event);
if (use_accel)
{
i = vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_ACCEL);
if (i & ACCELFLAG_PUTIMAGE)
has_put_image = 1;
if (i & ACCELFLAG_SCREENCOPY)
has_screen_copy = 1;
if (i & ACCELFLAG_FILLBOX)
has_fill_box = 1;
printf("accel %d\n", i);
}
if (!has_screen_copy && !g_save_mem)
sdata = xmalloc(g_width * g_height * g_server_Bpp);
return 1;
}
/*****************************************************************************/
void ui_destroy_window(void)
{
keyboard_close(); /* Don't forget this! */
vga_setmode(TEXT);
if (sdata != 0)
xfree(sdata);
}
/*****************************************************************************/
void process_mouse(void)
{
int ox = mousex;
int oy = mousey;
int ob = mouseb;
if (!UpAndRunning)
return;
mousex = mouse_getx() - mcursor.x;
mousey = mouse_gety() - mcursor.y;
mouseb = mouse_getbutton();
if (mouseb != ob) // button
{
// right button
if (mouseb & 1)
if (!(ob & 1))
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2,
mousex + mcursor.x, mousey + mcursor.y);
if (ob & 1)
if (!(mouseb & 1))
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2,
mousex + mcursor.x, mousey + mcursor.y);
// middle button
if (mouseb & 2)
if (!(ob & 2))
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON3,
mousex + mcursor.x, mousey + mcursor.y);
if (ob & 2)
if (!(mouseb & 2))
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3,
mousex + mcursor.x, mousey + mcursor.y);
// left button
if (mouseb & 4)
if (!(ob & 4))
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1,
mousex + mcursor.x, mousey + mcursor.y);
if (ob & 4)
if (!(mouseb & 4))
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1,
mousex + mcursor.x, mousey + mcursor.y);
}
if (mousex != ox || mousey != oy) // movement
{
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
mousex + mcursor.x, mousey + mcursor.y);
draw_cursor_under(ox, oy);
draw_cursor();
}
}
/*****************************************************************************/
void process_keyboard(void)
{
if (!UpAndRunning)
return;
}
/*****************************************************************************/
BOOL ui_main_loop(void)
{
int sel;
fd_set rfds;
if (!rdp_connect(g_servername, RDP_LOGON_NORMAL, "", "", "", ""))
return False;
UpAndRunning = 1;
FD_ZERO(&rfds);
FD_SET(g_sock, &rfds);
sel = vga_waitevent(3, &rfds, NULL, NULL, NULL);
while (sel >= 0)
{
if (sel & 1) /* mouse */
{
process_mouse();
}
else if (sel & 2) /* keyboard */
{
process_keyboard();
}
else
{
if (!rdp_loop(&deactivated, &ext_disc_reason))
return True; /* ok */
}
FD_ZERO(&rfds);
FD_SET(g_sock, &rfds);
sel = vga_waitevent(3, &rfds, NULL, NULL, NULL);
}
return True;
}
/*****************************************************************************/
void ui_bell(void)
{
}
/*****************************************************************************/
int ui_select(int in)
{
g_sock = in;
return 1;
}
/*****************************************************************************/
void* ui_create_glyph(int width, int height, uint8* data)
{
int i, j;
uint8* glyph_data;
bitmap* the_glyph;
glyph_data = (uint8*)xmalloc(width * height);
the_glyph = (bitmap*)xmalloc(sizeof(bitmap));
the_glyph->width = width;
the_glyph->height = height;
the_glyph->data = glyph_data;
memset(glyph_data, 0, width * height);
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
if (is_pixel_on(data, j, i, width, 1))
set_pixel_on(glyph_data, j, i, width, 8, 255);
return the_glyph;
}
/*****************************************************************************/
void ui_destroy_glyph(void* glyph)
{
bitmap* the_glyph;
the_glyph = (bitmap*)glyph;
if (the_glyph != NULL)
{
if (the_glyph->data != NULL)
xfree(the_glyph->data);
xfree(the_glyph);
}
}
/*****************************************************************************/
void ui_destroy_bitmap(void* bmp)
{
bitmap* b;
b = (bitmap*)bmp;
xfree(b->data);
xfree(b);
}
/*****************************************************************************/
void ui_reset_clip(void)
{
clip_startx = 0;
clip_starty = 0;
clip_endx = g_width;
clip_endy = g_height;
}
/*****************************************************************************/
void ui_set_clip(int x, int y, int cx, int cy)
{
clip_startx = x;
clip_starty = y;
clip_endx = x + cx;
clip_endy = y + cy;
}
/*****************************************************************************/
void* ui_create_colourmap(COLOURMAP * colours)
{
int i = 0;
int n = colours->ncolours;
COLOURENTRY* c = colours->colours;
int* cmap = (int*)xmalloc(3 * 256 * sizeof (int));
if (n > 256)
n = 256;
bzero(cmap, 256 * 3 * sizeof (int));
for (i = 0; i < (3 * n); c++)
{
cmap[i++] = (c->red) >> 2;
cmap[i++] = (c->green) >> 2;
cmap[i++] = (c->blue) >> 2;
}
return cmap;
}
/*****************************************************************************/
void ui_destroy_colourmap(HCOLOURMAP map)
{
if (colmap == map)
colmap = 0;
xfree(map);
}
/*****************************************************************************/
void ui_set_colourmap(void* map)
{
if (colmap != 0)
xfree(colmap);
vga_setpalvec(0, 256, (int*)map);
colmap = map;
}
/*****************************************************************************/
HBITMAP ui_create_bitmap(int width, int height, uint8* data)
{
bitmap* b;
b = (bitmap*)xmalloc(sizeof(bitmap));
b->data = (uint8*)xmalloc(width * height * g_server_Bpp);
b->width = width;
b->height = height;
b->Bpp = g_server_Bpp;
copy_mem(b->data, data, width * height * g_server_Bpp);
return (void*)b;
}
//*****************************************************************************
void draw_glyph (int x, int y, HGLYPH glyph, int fgcolour)
{
bitmap* the_glyph;
int i, j;
the_glyph = (bitmap*)glyph;
if (the_glyph == NULL)
return;
for (i = 0; i < the_glyph->height; i++)
for (j = 0; j < the_glyph->width; j++)
if (is_pixel_on(the_glyph->data, j, i, the_glyph->width, 8))
set_pixel(x + j, y + i, fgcolour, 0xc);
}
#define DO_GLYPH(ttext,idx) \
{\
glyph = cache_get_font (font, ttext[idx]);\
if (!(flags & TEXT2_IMPLICIT_X))\
{\
xyoffset = ttext[++idx];\
if ((xyoffset & 0x80))\
{\
if (flags & TEXT2_VERTICAL) \
y += ttext[idx+1] | (ttext[idx+2] << 8);\
else\
x += ttext[idx+1] | (ttext[idx+2] << 8);\
idx += 2;\
}\
else\
{\
if (flags & TEXT2_VERTICAL) \
y += xyoffset;\
else\
x += xyoffset;\
}\
}\
if (glyph != NULL)\
{\
draw_glyph (x + glyph->offset, y + glyph->baseline, glyph->pixmap, fgcolour);\
if (flags & TEXT2_IMPLICIT_X)\
x += glyph->width;\
}\
}
/*****************************************************************************/
void ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode,
int x, int y,
int clipx, int clipy, int clipcx, int clipcy,
int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
int bgcolour, int fgcolour, uint8* text, uint8 length)
{
int i;
int j;
int xyoffset;
DATABLOB* entry;
FONTGLYPH* glyph;
if (boxcx > 1)
{
if (contains_mouse(boxx, boxy, boxcx, boxcy))
draw_cursor_under(mousex, mousey);
fill_rect(boxx, boxy, boxcx, boxcy, bgcolour, 0xc);
}
else
{
if (contains_mouse(clipx, clipy, clipcx, clipcy))
draw_cursor_under(mousex, mousey);
if (mixmode == MIX_OPAQUE)
fill_rect(clipx, clipy, clipcx, clipcy, bgcolour, 0xc);
}
/* Paint text, character by character */
for (i = 0; i < length;)
{
switch (text[i])
{
case 0xff:
if (i + 2 < length)
cache_put_text(text[i + 1], text, text[i + 2]);
else
{
error("this shouldn't be happening\n");
exit(1);
}
/* this will move pointer from start to first character after FF command */
length -= i + 3;
text = &(text[i + 3]);
i = 0;
break;
case 0xfe:
entry = cache_get_text(text[i + 1]);
if (entry != NULL)
{
if ((((uint8 *) (entry->data))[1] == 0) && (!(flags & TEXT2_IMPLICIT_X)))
{
if (flags & TEXT2_VERTICAL)
y += text[i + 2];
else
x += text[i + 2];
}
for (j = 0; j < entry->size; j++)
DO_GLYPH(((uint8 *) (entry->data)), j);
}
if (i + 2 < length)
i += 3;
else
i += 2;
length -= i;
/* this will move pointer from start to first character after FE command */
text = &(text[i]);
i = 0;
break;
default:
DO_GLYPH(text, i);
i++;
break;
}
}
if (boxcx > 1)
cache_rect(boxx, boxy, boxcx, boxcy, True);
else
cache_rect(clipx, clipy, clipcx, clipcy, True);
}
//*****************************************************************************
// Bresenham's line drawing algorithm
void ui_line(uint8 opcode, int startx, int starty, int endx,
int endy, PEN* pen)
{
int dx;
int dy;
int incx;
int incy;
int dpr;
int dpru;
int p;
int left;
int top;
int right;
int bottom;
if (startx > endx)
{
dx = startx - endx;
incx = -1;
left = endx;
right = startx;
}
else
{
dx = endx - startx;
incx = 1;
left = startx;
right = endx;
}
if (starty > endy)
{
dy = starty - endy;
incy = -1;
top = endy;
bottom = starty;
}
else
{
dy = endy - starty;
incy = 1;
top = starty;
bottom = endy;
}
if (contains_mouse(left, top, (right - left) + 1, (bottom - top) + 1))
draw_cursor_under(mousex, mousey);
if (dx >= dy)
{
dpr = dy << 1;
dpru = dpr - (dx << 1);
p = dpr - dx;
for (; dx >= 0; dx--)
{
set_pixel(startx, starty, pen->colour, opcode);
if (p > 0)
{
startx += incx;
starty += incy;
p += dpru;
}
else
{
startx += incx;
p += dpr;
}
}
}
else
{
dpr = dx << 1;
dpru = dpr - (dy << 1);
p = dpr - dy;
for (; dy >= 0; dy--)
{
set_pixel(startx, starty, pen->colour, opcode);
if (p > 0)
{
startx += incx;
starty += incy;
p += dpru;
}
else
{
starty += incy;
p += dpr;
}
}
}
cache_rect(left, top, (right - left) + 1, (bottom - top) + 1, True);
}
/*****************************************************************************/
void ui_triblt(uint8 opcode, int x, int y, int cx, int cy,
HBITMAP src, int srcx, int srcy,
BRUSH* brush, int bgcolour, int fgcolour)
{
// non used
}
/*****************************************************************************/
void ui_memblt(uint8 opcode, int x, int y, int cx, int cy,
HBITMAP src, int srcx, int srcy)
{
bitmap* b;
int i;
int j;
int pixel;
if (warp_coords(&x, &y, &cx, &cy, &srcx, &srcy))
{
if (contains_mouse(x, y, cx, cy))
draw_cursor_under(mousex, mousey);
b = (bitmap*)src;
if (opcode == 0xc)
accel_draw_box(x, y, cx, cy, get_ptr(srcx, srcy, b->data, b->width, g_server_bpp),
b->width * g_server_Bpp);
else
{
for (i = 0; i < cy; i++)
{
for (j = 0; j < cx; j++)
{
pixel = get_pixel2(srcx + j, srcy + i, b->data, b->width, g_server_bpp);
set_pixel(x + j, y + i, pixel, opcode);
}
}
}
cache_rect(x, y, cx, cy, False);
}
}
/*****************************************************************************/
void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
{
uint8* p;
if (offset > 0x38400)
offset = 0;
if (offset + cx * cy > 0x38400)
return;
p = desk_save + offset * g_server_Bpp;
ui_paint_bitmap(x, y, cx, cy, cx, cy, p);
}
/*****************************************************************************/
void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
{
uint8* p;
if (offset > 0x38400)
offset = 0;
if (offset + cx * cy > 0x38400)
return;
if (contains_mouse(x, y, cx, cy))
draw_cursor_under(mousex, mousey);
p = desk_save + offset * g_server_Bpp;
get_rect(x, y, cx, cy, p);
}
/*****************************************************************************/
void ui_rect(int x, int y, int cx, int cy, int colour)
{
if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
{
if (contains_mouse(x, y, cx, cy))
draw_cursor_under(mousex, mousey);
accel_fill_rect(x, y, cx, cy, colour);
cache_rect(x, y, cx, cy, False);
}
}
/*****************************************************************************/
void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,
int srcx, int srcy)
{
int i;
int j;
uint8* temp;
if (x == srcx && y == srcy)
return;
if (warp_coords(&x, &y, &cx, &cy, &srcx, &srcy))
{
if (contains_mouse(x, y, cx, cy) || contains_mouse(srcx, srcy, cx, cy))
draw_cursor_under(mousex, mousey);
if (opcode == 0xc) /* copy */
accel_screen_copy(x, y, cx, cy, srcx, srcy);
else
{
temp = (uint8*)xmalloc(cx * cy * g_server_Bpp);
for (i = 0; i < cy; i++)
for (j = 0; j < cx; j++)
set_pixel2(j, i, get_pixel(srcx + j, srcy + i), temp, cx, g_server_bpp);
for (i = 0; i < cy; i++)
for (j = 0; j < cx; j++)
set_pixel(x + j, y + i, get_pixel2(j, i, temp, cx, g_server_bpp), opcode);
xfree(temp);
}
cache_rect(x, y, cx, cy, False);
draw_cache_rects(); // draw them all so screen is not jumpy
}
}
/*****************************************************************************/
void ui_patblt(uint8 opcode, int x, int y, int cx, int cy,
BRUSH * brush, int bgcolour, int fgcolour)
{
int i;
int j;
uint8 ipattern[8];
if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
{
if (contains_mouse(x, y, cx, cy))
draw_cursor_under(mousex, mousey);
switch (brush->style)
{
case 0:
fill_rect(x, y, cx, cy, fgcolour, opcode);
break;
case 3:
for (i = 0; i < 8; i++)
ipattern[i] = ~brush->pattern[7 - i];
for (i = 0; i < cy; i++)
for (j = 0; j < cx; j++)
if (is_pixel_on(ipattern, (x + j + brush->xorigin) % 8,
(y + i + brush->yorigin) % 8, 8, 1))
set_pixel(x + j, y + i, fgcolour, opcode);
else
set_pixel(x + j, y + i, bgcolour, opcode);
break;
}
cache_rect(x, y, cx, cy, False);
}
}
/*****************************************************************************/
void ui_destblt(uint8 opcode, int x, int y, int cx, int cy)
{
if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
{
if (contains_mouse(x, y, cx, cy))
draw_cursor_under(mousex, mousey);
fill_rect(x, y, cx, cy, -1, opcode);
cache_rect(x, y, cx, cy, False);
}
}
/*****************************************************************************/
void ui_move_pointer(int x, int y)
{
}
/*****************************************************************************/
void ui_set_null_cursor(void)
{
draw_cursor_under(mousex, mousey);
mousex = mousex - mcursor.x;
mousey = mousey - mcursor.y;
memset(&mcursor, 0, sizeof(mcursor));
memset(mcursor.andmask, 255, sizeof(mcursor.andmask));
memset(mcursor.xormask, 0, sizeof(mcursor.xormask));
draw_cursor();
}
/*****************************************************************************/
void ui_paint_bitmap(int x, int y, int cx, int cy,
int width, int height, uint8* data)
{
if (warp_coords(&x, &y, &cx, &cy, NULL, NULL))
{
if (contains_mouse(x, y, cx, cy))
draw_cursor_under(mousex, mousey);
accel_draw_box(x, y, cx, cy, data, width * g_server_Bpp);
cache_rect(x, y, cx, cy, False);
}
}
/*****************************************************************************/
void* ui_create_cursor(unsigned int x, unsigned int y,
int width, int height,
uint8* andmask, uint8* xormask)
{
tcursor* c;
int i;
int j;
c = (tcursor*)xmalloc(sizeof(tcursor));
memset(c, 0, sizeof(tcursor));
c->w = width;
c->h = height;
c->x = x;
c->y = y;
for (i = 0; i < 32; i++)
{
for (j = 0; j < 32; j++)
{
if (is_pixel_on(andmask, j, i, 32, 1))
set_pixel_on(c->andmask, j, 31 - i, 32, 8, 255);
if (is_pixel_on(xormask, j, i, 32, 24))
set_pixel_on(c->xormask, j, 31 - i, 32, 8, 255);
}
}
return (void*)c;
}
/*****************************************************************************/
void ui_destroy_cursor(void* cursor)
{
if (cursor != NULL)
xfree(cursor);
}
/*****************************************************************************/
void ui_set_cursor(void* cursor)
{
int x;
int y;
int ox;
int oy;
ox = mousex;
oy = mousey;
x = mousex + mcursor.x;
y = mousey + mcursor.y;
memcpy(&mcursor, cursor, sizeof(tcursor));
mousex = x - mcursor.x;
mousey = y - mcursor.y;
draw_cursor_under(ox, oy);
draw_cursor();
}
/*****************************************************************************/
uint16 ui_get_numlock_state(unsigned int state)
{
return 0;
}
/*****************************************************************************/
unsigned int read_keyboard_state(void)
{
return 0;
}
/*****************************************************************************/
void ui_resize_window(void)
{
}
/*****************************************************************************/
void ui_begin_update(void)
{
}
/*****************************************************************************/
void ui_end_update(void)
{
draw_cache_rects();
draw_cursor();
}
/*****************************************************************************/
void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints,
BRUSH * brush, int bgcolour, int fgcolour)
{
}
/*****************************************************************************/
void ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen)
{
}
/*****************************************************************************/
void ui_ellipse(uint8 opcode, uint8 fillmode,
int x, int y, int cx, int cy,
BRUSH * brush, int bgcolour, int fgcolour)
{
}
/*****************************************************************************/
void generate_random(uint8* random)
{
memcpy(random, "12345678901234567890123456789012", 32);
}
/*****************************************************************************/
void save_licence(uint8* data, int length)
{
}
/*****************************************************************************/
int load_licence(uint8** data)
{
return 0;
}
/*****************************************************************************/
void* xrealloc(void* in_val, int size)
{
return realloc(in_val, size);
}
/*****************************************************************************/
void* xmalloc(int size)
{
return malloc(size);
}
/*****************************************************************************/
void xfree(void* in_val)
{
free(in_val);
}
/*****************************************************************************/
char * xstrdup(const char * s)
{
char * mem = strdup(s);
if (mem == NULL)
{
perror("strdup");
exit(1);
}
return mem;
}
/*****************************************************************************/
void warning(char* format, ...)
{
va_list ap;
fprintf(stderr, "WARNING: ");
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
}
/*****************************************************************************/
void unimpl(char* format, ...)
{
va_list ap;
fprintf(stderr, "NOT IMPLEMENTED: ");
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
}
/*****************************************************************************/
void error(char* format, ...)
{
va_list ap;
fprintf(stderr, "ERROR: ");
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
}
BOOL rd_pstcache_mkdir(void)
{
return 0;
}
/*****************************************************************************/
int rd_open_file(char *filename)
{
return 0;
}
/*****************************************************************************/
void rd_close_file(int fd)
{
return;
}
/*****************************************************************************/
int rd_read_file(int fd, void *ptr, int len)
{
return 0;
}
/*****************************************************************************/
int rd_write_file(int fd, void* ptr, int len)
{
return 0;
}
/*****************************************************************************/
int rd_lseek_file(int fd, int offset)
{
return 0;
}
/*****************************************************************************/
BOOL rd_lock_file(int fd, int start, int len)
{
return False;
}
/*****************************************************************************/
void get_username_and_hostname(void)
{
char fullhostname[64];
char* p;
struct passwd* pw;
STRNCPY(g_username, "unknown", sizeof(g_username));
STRNCPY(g_hostname, "unknown", sizeof(g_hostname));
pw = getpwuid(getuid());
if (pw != NULL && pw->pw_name != NULL)
{
STRNCPY(g_username, pw->pw_name, sizeof(g_username));
}
if (gethostname(fullhostname, sizeof(fullhostname)) != -1)
{
p = strchr(fullhostname, '.');
if (p != NULL)
*p = 0;
STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
}
}
/*****************************************************************************/
void out_params(void)
{
fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
fprintf(stderr, "Usage: svgardesktop [options] server\n");
fprintf(stderr, " -g: desktop geometry (WxH)\n");
fprintf(stderr, " -4: use RDP version 4\n");
fprintf(stderr, " -5: use RDP version 5 (default)\n");
fprintf(stderr, " -t: tcp port\n");
fprintf(stderr, " -u: user name\n");
fprintf(stderr, " -n: client hostname\n");
fprintf(stderr, " -d: disable accel funcs\n");
fprintf(stderr, " -a: connection colour depth\n");
fprintf(stderr, " -l: low memory\n");
fprintf(stderr, "\n");
}
/* produce a hex dump */
void hexdump(uint8* p, uint32 len)
{
uint8* line;
int i;
int thisline;
int offset;
line = p;
offset = 0;
while (offset < len)
{
printf("%04x ", offset);
thisline = len - offset;
if (thisline > 16)
thisline = 16;
for (i = 0; i < thisline; i++)
printf("%02x ", line[i]);
for (; i < 16; i++)
printf(" ");
for (i = 0; i < thisline; i++)
printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
printf("\n");
offset += thisline;
line += thisline;
}
}
/*****************************************************************************/
int parse_parameters(int in_argc, char** in_argv)
{
int i;
char* p;
if (in_argc <= 1)
{
out_params();
return 0;
}
g_argc = in_argc;
g_argv = in_argv;
for (i = 1; i < in_argc; i++)
{
strcpy(g_servername, in_argv[i]);
if (strcmp(in_argv[i], "-g") == 0)
{
g_width = strtol(in_argv[i + 1], &p, 10);
if (g_width <= 0)
{
error("invalid geometry\n");
return 0;
}
if (*p == 'x')
g_height = strtol(p + 1, NULL, 10);
if (g_height <= 0)
{
error("invalid geometry\n");
return 0;
}
g_width = (g_width + 3) & ~3;
}
else if (strcmp(in_argv[i], "-4") == 0)
g_use_rdp5 = 0;
else if (strcmp(in_argv[i], "-5") == 0)
g_use_rdp5 = 1;
else if (strcmp(in_argv[i], "-t") == 0)
g_tcp_port_rdp = strtol(in_argv[i + 1], &p, 10);
else if (strcmp(in_argv[i], "-h") == 0)
{
out_params();
return 0;
}
else if (strcmp(in_argv[i], "-n") == 0)
{
STRNCPY(g_hostname, in_argv[i + 1], sizeof(g_hostname));
}
else if (strcmp(in_argv[i], "-u") == 0)
{
STRNCPY(g_username, in_argv[i + 1], sizeof(g_username));
}
else if (strcmp(in_argv[i], "-d") == 0)
{
use_accel = 0;
}
else if (strcmp(in_argv[i], "-a") == 0)
{
g_server_bpp = strtol(in_argv[i + 1], NULL, 10);
if (g_server_bpp != 8 && g_server_bpp != 16)
{
error("invalid server bpp\n");
return 0;
}
g_server_Bpp = (g_server_bpp + 7) / 8;
}
else if (strcmp(in_argv[i], "-l") == 0)
g_save_mem = 1;
}
return 1;
}
/*****************************************************************************/
int main(int in_argc, char** in_argv)
{
get_username_and_hostname();
if (!parse_parameters(in_argc, in_argv))
return 0;
if (!ui_init())
return 1;
if (!ui_create_window())
return 1;
ui_main_loop();
ui_destroy_window();
ui_deinit();
return 0;
}