rdesktop/uiports/svgawin.c
Jay Sorg ab4e3fdb48 added makefile and keyboard work from peter
git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@810 423420c4-83ab-492f-b58f-81f9feb106b5
2005-02-07 00:54:10 +00:00

1906 lines
46 KiB
C

/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
User interface services - SVGA lib
Copyright (C) Jay Sorg 2004
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., 675 Mass Ave, Cambridge, MA 02139, 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_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 */
/* 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;
// 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, int mixmode,
int x, int y,
int clipx, int clipy, int clipcx, int clipcy,
int boxx, int boxy, int boxcx, int boxcy,
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 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);
}
/*****************************************************************************/
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;
}