2006-06-26 04:33:04 +04:00
|
|
|
/* -*- c-basic-offset: 8 -*-
|
|
|
|
rdesktop: A Remote Desktop Protocol client.
|
|
|
|
Main ui file
|
|
|
|
Copyright (C) Jay Sorg 2006
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2006-07-07 08:38:33 +04:00
|
|
|
#include <stdarg.h>
|
2006-06-26 04:33:04 +04:00
|
|
|
#include "rdesktop.h"
|
|
|
|
#include "bsops.h"
|
|
|
|
#include "uimain.h"
|
|
|
|
|
|
|
|
char g_username[256] = "";
|
|
|
|
char g_hostname[256] = "";
|
|
|
|
char g_servername[256] = "";
|
|
|
|
char g_password[256] = "";
|
|
|
|
char g_shell[256] = "";
|
|
|
|
char g_directory[256] = "";
|
|
|
|
char g_domain[256] = "";
|
|
|
|
char * g_bs = 0; /* created in hardware file, used in bsops.c */
|
|
|
|
int g_bs_Bpp = 4;
|
|
|
|
int g_bs_bpp = 32;
|
|
|
|
BOOL g_desktop_save = False; /* desktop save order */
|
|
|
|
BOOL g_polygon_ellipse_orders = False; /* polygon / ellipse orders */
|
|
|
|
BOOL g_bitmap_compression = True;
|
|
|
|
uint32 g_rdp5_performanceflags =
|
|
|
|
RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
|
|
|
|
BOOL g_bitmap_cache_persist_enable = False;
|
|
|
|
BOOL g_bitmap_cache_precache = True;
|
|
|
|
BOOL g_bitmap_cache = True;
|
|
|
|
BOOL g_encryption = True;
|
|
|
|
int g_server_depth = 8;
|
2006-07-15 19:52:53 +04:00
|
|
|
BOOL g_use_rdp5 = True;
|
2006-06-26 04:33:04 +04:00
|
|
|
int g_width = 800;
|
|
|
|
int g_height = 600;
|
|
|
|
uint32 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 */
|
|
|
|
BOOL g_console_session = False;
|
|
|
|
|
|
|
|
/* can't be static, hardware file or bsops need these */
|
|
|
|
int g_tcp_sck = 0;
|
|
|
|
int pal_entries[256];
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
extern int g_tcp_port_rdp;
|
|
|
|
|
|
|
|
static int g_deactivated = 0;
|
|
|
|
static uint32 g_ext_disc_reason = 0;
|
|
|
|
|
|
|
|
struct bitmap
|
|
|
|
{
|
|
|
|
uint8 * data;
|
|
|
|
uint32 width;
|
|
|
|
uint32 height;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* in ui specific file eg win32.c, qt.c, dfb.c, ... */
|
|
|
|
int
|
|
|
|
mi_create_window(void);
|
|
|
|
void
|
|
|
|
mi_invalidate(int x, int y, int cx, int cy);
|
|
|
|
int
|
|
|
|
mi_create_bs(void);
|
|
|
|
int
|
|
|
|
mi_main_loop(void);
|
|
|
|
void
|
|
|
|
mi_error(char * msg);
|
|
|
|
void
|
|
|
|
mi_warning(char * msg);
|
|
|
|
void
|
|
|
|
ui_invalidate(int x, int y, int cx, int cy);
|
|
|
|
void
|
|
|
|
mi_paint_rect(char * data, int width, int height, int x, int y, int cx, int cy);
|
|
|
|
void
|
|
|
|
mi_begin_update(void);
|
|
|
|
void
|
|
|
|
mi_end_update(void);
|
|
|
|
void
|
|
|
|
mi_fill_rect(int x, int y, int cx, int cy, int colour);
|
|
|
|
void
|
|
|
|
mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy);
|
|
|
|
void
|
|
|
|
mi_set_clip(int x, int y, int cx, int cy);
|
|
|
|
void
|
|
|
|
mi_reset_clip(void);
|
|
|
|
void
|
|
|
|
mi_line(int x1, int y1, int x2, int y2, int colour);
|
2006-07-07 08:38:33 +04:00
|
|
|
void *
|
2006-06-26 04:33:04 +04:00
|
|
|
mi_create_cursor(unsigned int x, unsigned int y,
|
|
|
|
int width, int height,
|
|
|
|
unsigned char * andmask, unsigned char * xormask);
|
|
|
|
void
|
|
|
|
mi_destroy_cursor(void * cursor);
|
|
|
|
void
|
|
|
|
mi_set_cursor(void * cursor);
|
|
|
|
void
|
|
|
|
mi_set_null_cursor(void);
|
|
|
|
int
|
|
|
|
mi_read_keyboard_state(void);
|
2006-10-24 08:04:03 +04:00
|
|
|
void
|
|
|
|
mi_logon(void);
|
2006-06-26 04:33:04 +04:00
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* put part of the screen from the backing store to the display */
|
|
|
|
void
|
|
|
|
ui_invalidate(int x, int y, int cx, int cy)
|
|
|
|
{
|
|
|
|
if (cx < 1 || cy < 1 || g_bs == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (bs_warp_coords(&x, &y, &cx, &cy, 0, 0))
|
|
|
|
{
|
|
|
|
mi_invalidate(x, y, cx, cy);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
if (bs_warp_coords(&x, &y, &cx, &cy, 0, 0))
|
|
|
|
{
|
|
|
|
cx = (cx + 3) & ~3;
|
|
|
|
data = (char *) xmalloc(cx * cy * 4);
|
|
|
|
bs_copy_box(data, x, y, cx, cy, cx * ((g_server_depth + 7) / 8));
|
|
|
|
mi_paint_rect(data, cx, cy, x, y, cx, cy);
|
|
|
|
xfree(data);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
static int
|
|
|
|
convert_colour(int in_colour)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
int g;
|
|
|
|
int b;
|
|
|
|
|
2006-08-05 05:58:01 +04:00
|
|
|
r = 0;
|
|
|
|
g = 0;
|
|
|
|
b = 0;
|
2006-06-26 04:33:04 +04:00
|
|
|
if (g_server_depth == 8)
|
|
|
|
{
|
|
|
|
r = (pal_entries[in_colour & 0xff] & 0xff0000) >> 16;
|
|
|
|
g = (pal_entries[in_colour & 0xff] & 0xff00) >> 8;
|
|
|
|
b = pal_entries[in_colour & 0xff] & 0xff;
|
|
|
|
}
|
|
|
|
else if (g_server_depth == 15)
|
|
|
|
{
|
|
|
|
SPLIT_COLOUR15(in_colour, r, g, b);
|
2006-07-15 19:52:53 +04:00
|
|
|
}
|
2006-06-26 04:33:04 +04:00
|
|
|
else if (g_server_depth == 16)
|
|
|
|
{
|
|
|
|
SPLIT_COLOUR16(in_colour, r, g, b);
|
|
|
|
}
|
|
|
|
else if (g_server_depth == 24)
|
|
|
|
{
|
|
|
|
SPLIT_COLOUR32(in_colour, r, g, b);
|
|
|
|
}
|
|
|
|
if (g_bs_bpp == 32)
|
|
|
|
{
|
|
|
|
MAKE_COLOUR32(in_colour, r, g, b);
|
|
|
|
}
|
2006-07-15 19:52:53 +04:00
|
|
|
return in_colour;
|
2006-06-26 04:33:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_bell(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
|
|
ui_select(int in)
|
|
|
|
{
|
|
|
|
if (g_tcp_sck == 0)
|
|
|
|
{
|
|
|
|
g_tcp_sck = in;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void *
|
|
|
|
ui_create_cursor(uint32 x, uint32 y,
|
|
|
|
int width, int height,
|
|
|
|
uint8 * andmask, uint8 * xormask)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
char am[32 * 4];
|
|
|
|
char xm[32 * 4];
|
|
|
|
|
|
|
|
if (width != 32 || height != 32)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
memset(am, 0, 32 * 4);
|
|
|
|
memset(xm, 0, 32 * 4);
|
|
|
|
for (i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < 32; j++)
|
|
|
|
{
|
|
|
|
if (bs_is_pixel_on(andmask, j, i, 32, 1))
|
|
|
|
{
|
|
|
|
bs_set_pixel_on(am, j, 31 - i, 32, 1, 1);
|
|
|
|
}
|
|
|
|
if (bs_is_pixel_on(xormask, j, i, 32, 24))
|
|
|
|
{
|
|
|
|
bs_set_pixel_on(xm, j, 31 - i, 32, 1, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (void *) mi_create_cursor(x, y, width, height, am, xm);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_destroy_cursor(void * cursor)
|
|
|
|
{
|
|
|
|
mi_destroy_cursor(cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_set_cursor(void * cursor)
|
|
|
|
{
|
|
|
|
mi_set_cursor(cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_set_null_cursor(void)
|
|
|
|
{
|
|
|
|
mi_set_null_cursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void *
|
|
|
|
ui_create_glyph(int width, int height, uint8 * data)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
char * glyph_data;
|
|
|
|
struct bitmap * the_glyph;
|
|
|
|
|
|
|
|
glyph_data = (char *) xmalloc(width * height);
|
|
|
|
memset(glyph_data, 0, width * height);
|
|
|
|
the_glyph = (struct bitmap *) xmalloc(sizeof(struct bitmap));
|
|
|
|
memset(the_glyph, 0, sizeof(struct bitmap));
|
|
|
|
the_glyph->width = width;
|
|
|
|
the_glyph->height = height;
|
|
|
|
the_glyph->data = glyph_data;
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
if (bs_is_pixel_on(data, j, i, width, 1))
|
|
|
|
{
|
|
|
|
bs_set_pixel_on(glyph_data, j, i, width, 8, 255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return the_glyph;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_destroy_glyph(void * glyph)
|
|
|
|
{
|
|
|
|
struct bitmap * the_glyph;
|
|
|
|
|
|
|
|
the_glyph = glyph;
|
|
|
|
if (the_glyph != 0)
|
|
|
|
{
|
|
|
|
xfree(the_glyph->data);
|
|
|
|
}
|
|
|
|
xfree(the_glyph);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void *
|
|
|
|
ui_create_bitmap(int width, int height, uint8 * data)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
struct bitmap * b;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
size = width * height * ((g_server_depth + 7) / 8);
|
|
|
|
b = (struct bitmap *) xmalloc(sizeof(struct bitmap));
|
|
|
|
b->data = (uint8 *) xmalloc(size);
|
|
|
|
memcpy(b->data, data, size);
|
|
|
|
b->width = width;
|
|
|
|
b->height = height;
|
|
|
|
return b;
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void *
|
|
|
|
ui_create_bitmap_ex(int width, int height, uint8 * data, int data_size,
|
|
|
|
int compressed)
|
|
|
|
{
|
|
|
|
struct bitmap * b;
|
|
|
|
int size;
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int pixel;
|
|
|
|
int red;
|
|
|
|
int green;
|
|
|
|
int blue;
|
|
|
|
unsigned short * s16;
|
|
|
|
unsigned char * s8;
|
|
|
|
unsigned int * d32;
|
|
|
|
|
|
|
|
size = width * height * 4;
|
|
|
|
b = (struct bitmap *) xmalloc(sizeof(struct bitmap));
|
|
|
|
b->data = (uint8 *) xmalloc(size);
|
|
|
|
if (compressed)
|
|
|
|
{
|
|
|
|
bitmap_decompress_ex(b->data, width, height, data, data_size,
|
|
|
|
g_server_depth, 32);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (g_server_depth == 16 && g_bs_bpp == 32)
|
|
|
|
{
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
s16 = ((unsigned short *) data) + (i * width);
|
|
|
|
d32 = ((unsigned int *) b->data) + (height - i - 1) * width;
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
pixel = *s16;
|
|
|
|
s16++;
|
|
|
|
SPLIT_COLOUR16(pixel, red, green, blue);
|
|
|
|
MAKE_COLOUR32(pixel, red, green, blue);
|
|
|
|
*d32 = pixel;
|
|
|
|
d32++;
|
|
|
|
}
|
|
|
|
}
|
2006-07-15 19:52:53 +04:00
|
|
|
}
|
2006-06-26 04:33:04 +04:00
|
|
|
else if (g_server_depth == 24 && g_bs_bpp == 32)
|
|
|
|
{
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
s8 = ((unsigned char *) data) + (i * width * 3);
|
|
|
|
d32 = ((unsigned int *) b->data) + (height - i - 1) * width;
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
blue = *s8;
|
|
|
|
s8++;
|
|
|
|
green = *s8;
|
|
|
|
s8++;
|
|
|
|
red = *s8;
|
|
|
|
s8++;
|
|
|
|
MAKE_COLOUR32(pixel, red, green, blue);
|
|
|
|
*d32 = pixel;
|
|
|
|
d32++;
|
|
|
|
}
|
|
|
|
}
|
2006-07-15 19:52:53 +04:00
|
|
|
}
|
2006-06-26 04:33:04 +04:00
|
|
|
}
|
|
|
|
b->width = width;
|
|
|
|
b->height = height;
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_destroy_bitmap(void * bmp)
|
|
|
|
{
|
|
|
|
struct bitmap * b;
|
|
|
|
|
|
|
|
b = (struct bitmap *) bmp;
|
|
|
|
if (b != 0)
|
|
|
|
{
|
|
|
|
xfree(b->data);
|
|
|
|
}
|
|
|
|
xfree(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_paint_bitmap(int x, int y, int cx, int cy,
|
|
|
|
int width, int height, uint8 * data)
|
|
|
|
{
|
|
|
|
/* struct bitmap b;
|
|
|
|
|
|
|
|
b.width = width;
|
|
|
|
b.height = height;
|
|
|
|
b.data = data;
|
|
|
|
ui_memblt(12, x, y, cx, cy, &b, 0, 0); */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_paint_bitmap_ex(int x, int y, int cx, int cy,
|
|
|
|
int width, int height, uint8 * data, int data_size,
|
|
|
|
int compressed)
|
|
|
|
{
|
|
|
|
struct bitmap * b;
|
|
|
|
|
|
|
|
b = ui_create_bitmap_ex(width, height, data, data_size, compressed);
|
|
|
|
ui_memblt(12, x, y, cx, cy, b, 0, 0);
|
|
|
|
ui_destroy_bitmap(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_set_clip(int x, int y, int cx, int cy)
|
|
|
|
{
|
|
|
|
bs_set_clip(x, y, cx, cy);
|
|
|
|
mi_set_clip(x, y, cx, cy);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_reset_clip(void)
|
|
|
|
{
|
|
|
|
bs_reset_clip();
|
|
|
|
mi_reset_clip();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void *
|
|
|
|
ui_create_colourmap(COLOURMAP * colours)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = MIN(256, colours->ncolours);
|
|
|
|
memset(pal_entries, 0, sizeof(pal_entries));
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
pal_entries[i] = (colours->colours[i].red << 16) |
|
|
|
|
(colours->colours[i].green << 8) |
|
|
|
|
colours->colours[i].blue;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_set_colourmap(void * map)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* don't convert colour here */
|
|
|
|
static void
|
|
|
|
draw_glyph(int x, int y, void * glyph, int fgcolor)
|
|
|
|
{
|
|
|
|
struct bitmap * b;
|
|
|
|
|
|
|
|
b = glyph;
|
|
|
|
bs_draw_glyph(x, y, b->data, b->width, b->height, fgcolor);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
#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;
|
|
|
|
|
|
|
|
fgcolour = convert_colour(fgcolour);
|
|
|
|
bgcolour = convert_colour(bgcolour);
|
|
|
|
if (boxx + boxcx > g_width)
|
|
|
|
{
|
|
|
|
boxcx = g_width - boxx;
|
|
|
|
}
|
|
|
|
if (boxcx > 1)
|
|
|
|
{
|
|
|
|
bs_rect(boxx, boxy, boxcx, boxcy, bgcolour, 0xc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (mixmode == MIX_OPAQUE)
|
|
|
|
{
|
|
|
|
bs_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)
|
|
|
|
{
|
|
|
|
ui_invalidate(boxx, boxy, boxcx, boxcy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ui_invalidate(clipx, clipy, clipcx, clipcy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_line(uint8 opcode, int startx, int starty, int endx, int endy,
|
|
|
|
PEN * pen)
|
|
|
|
{
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int cx;
|
|
|
|
int cy;
|
|
|
|
int colour;
|
|
|
|
|
|
|
|
colour = convert_colour(pen->colour);
|
|
|
|
|
|
|
|
bs_line(opcode, startx, starty, endx, endy, pen->width, pen->style,
|
|
|
|
colour);
|
|
|
|
if (pen->style == 0 && pen->width < 2 && opcode == 12)
|
|
|
|
{
|
|
|
|
mi_line(startx, starty, endx, endy, colour);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = MIN(startx, endx);
|
|
|
|
y = MIN(starty, endy);
|
|
|
|
cx = (MAX(startx, endx) + 1) - x;
|
|
|
|
cy = (MAX(starty, endy) + 1) - y;
|
|
|
|
ui_invalidate(x, y, cx, cy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_triblt(uint8 opcode, int x, int y, int cx, int cy,
|
|
|
|
void * src, int srcx, int srcy,
|
|
|
|
BRUSH* brush, int bgcolour, int fgcolour)
|
|
|
|
{
|
|
|
|
/* not used */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_memblt(uint8 opcode, int x, int y, int cx, int cy,
|
|
|
|
void * src, int srcx, int srcy)
|
|
|
|
{
|
|
|
|
struct bitmap* b;
|
|
|
|
|
|
|
|
b = (struct bitmap *) src;
|
2006-08-05 05:58:01 +04:00
|
|
|
if (bs_memblt(opcode, x, y, cx, cy, b->data, b->width, b->height,
|
|
|
|
srcx, srcy))
|
|
|
|
{
|
|
|
|
ui_invalidate(x, y, cx, cy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//printf("skipped %d %d\r\n", cx, cy);
|
|
|
|
}
|
2006-06-26 04:33:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_rect(int x, int y, int cx, int cy, int colour)
|
|
|
|
{
|
|
|
|
colour = convert_colour(colour);
|
|
|
|
bs_rect(x, y, cx, cy, colour, 12);
|
|
|
|
mi_fill_rect(x, y, cx, cy, colour);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,
|
|
|
|
int srcx, int srcy)
|
|
|
|
{
|
|
|
|
bs_screenblt(opcode, x, y, cx, cy, srcx, srcy);
|
|
|
|
if (opcode == 12)
|
|
|
|
{
|
|
|
|
mi_screen_copy(x, y, cx, cy, srcx, srcy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ui_invalidate(x, y, cx, cy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_patblt(uint8 opcode, int x, int y, int cx, int cy,
|
|
|
|
BRUSH * brush, int bgcolour, int fgcolour)
|
|
|
|
{
|
|
|
|
bgcolour = convert_colour(bgcolour);
|
|
|
|
fgcolour = convert_colour(fgcolour);
|
|
|
|
bs_patblt(opcode, x, y, cx, cy, brush->style, brush->pattern,
|
|
|
|
brush->xorigin, brush->yorigin, bgcolour, fgcolour);
|
|
|
|
ui_invalidate(x, y, cx, cy);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_destblt(uint8 opcode, int x, int y, int cx, int cy)
|
|
|
|
{
|
|
|
|
bs_rect(x, y, cx, cy, 0, opcode);
|
|
|
|
ui_invalidate(x, y, cx, cy);
|
|
|
|
/* todo */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_move_pointer(int x, int y)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint16
|
|
|
|
ui_get_numlock_state(uint32 state)
|
|
|
|
{
|
|
|
|
return (uint16) state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* get the num, caps, and scroll lock state */
|
|
|
|
/* scroll lock is 1, num lock is 2 and caps lock is 4 */
|
|
|
|
/* just returning 0, the hardware specific file is responsable for this */
|
|
|
|
uint32
|
|
|
|
read_keyboard_state(void)
|
|
|
|
{
|
|
|
|
return (uint32) mi_read_keyboard_state();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_set_modifier_state(int code)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//error("%8.8x", code);
|
|
|
|
|
|
|
|
rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, (uint16) code, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_resize_window(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_begin_update(void)
|
|
|
|
{
|
|
|
|
mi_begin_update();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_end_update(void)
|
|
|
|
{
|
|
|
|
mi_end_update();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
2006-07-07 08:38:33 +04:00
|
|
|
ui_polygon(uint8 opcode, uint8 fillmode, RD_POINT * point, int npoints,
|
2006-06-26 04:33:04 +04:00
|
|
|
BRUSH * brush, int bgcolour, int fgcolour)
|
|
|
|
{
|
|
|
|
/* not used */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
2006-07-07 08:38:33 +04:00
|
|
|
ui_polyline(uint8 opcode, RD_POINT * points, int npoints, PEN * pen)
|
2006-06-26 04:33:04 +04:00
|
|
|
{
|
|
|
|
int i, x, y, dx, dy;
|
|
|
|
if (npoints > 0)
|
|
|
|
{
|
|
|
|
x = points[0].x;
|
|
|
|
y = points[0].y;
|
|
|
|
for (i = 1; i < npoints; i++)
|
|
|
|
{
|
|
|
|
dx = points[i].x;
|
|
|
|
dy = points[i].y;
|
|
|
|
ui_line(opcode, x, y, x + dx, y + dy, pen);
|
|
|
|
x = x + dx;
|
|
|
|
y = y + dy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_ellipse(uint8 opcode, uint8 fillmode,
|
|
|
|
int x, int y, int cx, int cy,
|
|
|
|
BRUSH * brush, int bgcolour, int fgcolour)
|
|
|
|
{
|
|
|
|
/* not used */
|
|
|
|
}
|
|
|
|
|
2006-10-24 08:04:03 +04:00
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_logon(void)
|
|
|
|
{
|
|
|
|
mi_logon();
|
|
|
|
}
|
|
|
|
|
2006-06-26 04:33:04 +04:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* get a 32 byte random */
|
|
|
|
void
|
|
|
|
generate_random(uint8 * random)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
rand();
|
|
|
|
rand();
|
|
|
|
for (i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
random[i] = rand() >> 16; /* higher bits are more random */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
save_licence(uint8 * data, int length)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
|
|
load_licence(uint8 ** data)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void *
|
|
|
|
xrealloc(void * in, int size)
|
|
|
|
{
|
|
|
|
if (size < 1)
|
|
|
|
{
|
|
|
|
size = 1;
|
|
|
|
}
|
|
|
|
return realloc(in, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void *
|
|
|
|
xmalloc(int size)
|
|
|
|
{
|
|
|
|
if (size < 1)
|
|
|
|
{
|
|
|
|
size = 1;
|
|
|
|
}
|
|
|
|
return malloc(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
xfree(void * in)
|
|
|
|
{
|
|
|
|
if (in != 0)
|
|
|
|
{
|
|
|
|
free(in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
char *
|
|
|
|
xstrdup(const char * s)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char * p;
|
|
|
|
|
|
|
|
if (s == 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
len = strlen(s);
|
|
|
|
p = (char *) xmalloc(len + 1);
|
|
|
|
strcpy(p, s);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
warning(char * format, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char text[512];
|
|
|
|
char text1[512];
|
|
|
|
|
|
|
|
sprintf(text1, "WARNING: ");
|
|
|
|
va_start(ap, format);
|
|
|
|
vsprintf(text, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
strcat(text1, text);
|
|
|
|
mi_warning(text1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
unimpl(char * format, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char text[512];
|
|
|
|
char text1[512];
|
|
|
|
|
|
|
|
sprintf(text1, "UNIMPL: ");
|
|
|
|
va_start(ap, format);
|
|
|
|
vsprintf(text, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
strcat(text1, text);
|
|
|
|
mi_warning(text1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
error(char * format, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char text[512];
|
|
|
|
char text1[512];
|
|
|
|
|
|
|
|
sprintf(text1, "ERROR: ");
|
|
|
|
va_start(ap, format);
|
|
|
|
vsprintf(text, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
strcat(text1, text);
|
|
|
|
mi_error(text1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
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
|
|
|
|
ui_mouse_move(int x, int y)
|
|
|
|
{
|
|
|
|
rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, (uint16) x, (uint16) y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_mouse_button(int button, int x, int y, int down)
|
|
|
|
{
|
|
|
|
uint16 flags;
|
|
|
|
|
|
|
|
flags = 0;
|
|
|
|
if (down)
|
|
|
|
{
|
|
|
|
flags |= MOUSE_FLAG_DOWN;
|
|
|
|
}
|
|
|
|
switch (button)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
flags |= MOUSE_FLAG_BUTTON1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
flags |= MOUSE_FLAG_BUTTON2;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
flags |= MOUSE_FLAG_BUTTON3;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
flags |= MOUSE_FLAG_BUTTON4;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
flags |= MOUSE_FLAG_BUTTON5;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rdp_send_input(0, RDP_INPUT_MOUSE, flags, (uint16) x, (uint16) y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_key_down(int key, int ext)
|
|
|
|
|
|
|
|
{
|
|
|
|
rdp_send_input(0, RDP_INPUT_SCANCODE, (uint16) (RDP_KEYPRESS | ext),
|
|
|
|
(uint16) key, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
ui_key_up(int key, int ext)
|
|
|
|
{
|
|
|
|
rdp_send_input(0, RDP_INPUT_SCANCODE, (uint16) (RDP_KEYRELEASE | ext),
|
|
|
|
(uint16) key, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* returns boolean, non zero is good */
|
|
|
|
int
|
|
|
|
ui_read_wire(void)
|
|
|
|
{
|
|
|
|
return rdp_loop(&g_deactivated, &g_ext_disc_reason);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* called after the command line parameters are processed */
|
|
|
|
/* returns boolean, non zero is ok */
|
|
|
|
int
|
|
|
|
ui_main(void)
|
|
|
|
{
|
|
|
|
uint32 flags;
|
|
|
|
|
|
|
|
/* try to connect */
|
|
|
|
flags = RDP_LOGON_NORMAL;
|
|
|
|
if (g_password[0] != 0)
|
|
|
|
{
|
|
|
|
flags |= RDP_LOGON_AUTO;
|
|
|
|
}
|
|
|
|
if (!rdp_connect(g_servername, flags, g_domain, g_password,
|
|
|
|
g_shell, g_directory))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* create the window */
|
|
|
|
if (!mi_create_window())
|
|
|
|
{
|
|
|
|
error("mi_create_window failed\r\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* create backingstore stuff for use in bsops.c */
|
|
|
|
if (!mi_create_bs())
|
|
|
|
{
|
|
|
|
error("mi_create_bs failed\r\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* init backingstore */
|
|
|
|
bs_init();
|
|
|
|
/* if all ok, enter main loop */
|
|
|
|
return mi_main_loop();
|
|
|
|
}
|
|
|
|
|
2006-07-15 19:52:53 +04:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* called after the command line parameters are processed */
|
|
|
|
/* returns boolean, non zero is ok */
|
|
|
|
int
|
|
|
|
ui_lib_main(void)
|
|
|
|
{
|
|
|
|
uint32 flags;
|
|
|
|
|
|
|
|
/* try to connect */
|
|
|
|
flags = RDP_LOGON_NORMAL;
|
|
|
|
if (g_password[0] != 0)
|
|
|
|
{
|
|
|
|
flags |= RDP_LOGON_AUTO;
|
|
|
|
}
|
|
|
|
if (!rdp_connect(g_servername, flags, g_domain, g_password,
|
|
|
|
g_shell, g_directory))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* create the window */
|
|
|
|
if (!mi_create_window())
|
|
|
|
{
|
|
|
|
error("mi_create_window failed\r\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* create backingstore stuff for use in bsops.c */
|
|
|
|
if (!mi_create_bs())
|
|
|
|
{
|
|
|
|
error("mi_create_bs failed\r\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* init backingstore */
|
|
|
|
bs_init();
|
|
|
|
/* if all ok, enter main loop */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2006-06-26 04:33:04 +04:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* produce a hex dump */
|
|
|
|
void
|
|
|
|
hexdump(uint8 * p, uint32 len)
|
|
|
|
{
|
|
|
|
uint8 * line = p;
|
|
|
|
int i, thisline, offset = 0;
|
|
|
|
|
|
|
|
while (offset < (int)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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|