Commit 632676d0 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

conhost: Import window state update from wineconsole.

parent 7d48e0c5
......@@ -294,11 +294,6 @@ static void init_tty_output( struct console *console )
console->tty_cursor_visible = TRUE;
}
static void empty_update_rect( struct screen_buffer *screen_buffer, RECT *rect )
{
SetRect( rect, screen_buffer->width, screen_buffer->height, 0, 0 );
}
static void scroll_to_cursor( struct screen_buffer *screen_buffer )
{
int w = screen_buffer->win.right - screen_buffer->win.left + 1;
......
......@@ -133,4 +133,9 @@ struct screen_buffer
BOOL init_window( struct console *console );
NTSTATUS change_screen_buffer_size( struct screen_buffer *screen_buffer, int new_width, int new_height );
static inline void empty_update_rect( struct screen_buffer *screen_buffer, RECT *rect )
{
SetRect( rect, screen_buffer->width, screen_buffer->height, 0, 0 );
}
#endif /* RC_INVOKED */
......@@ -29,11 +29,19 @@
WINE_DEFAULT_DEBUG_CHANNEL(conhost);
enum update_state
{
UPDATE_NONE,
UPDATE_PENDING,
UPDATE_BUSY
};
struct console_window
{
HDC mem_dc; /* memory DC holding the bitmap below */
HBITMAP bitmap; /* bitmap of display window content */
HFONT font; /* font used for rendering, usually fixed */
HBITMAP cursor_bitmap; /* bitmap used for the caret */
unsigned int ui_charset; /* default UI charset */
WCHAR *config_key; /* config registry key name */
LONG ext_leading; /* external leading for font */
......@@ -48,6 +56,9 @@ struct console_window
unsigned int sb_width; /* active screen buffer width */
unsigned int sb_height; /* active screen buffer height */
COORD cursor_pos; /* cursor position */
RECT update; /* screen buffer update rect */
enum update_state update_state; /* update state */
};
struct console_config
......@@ -356,6 +367,251 @@ static void save_config( const WCHAR *key_name, const struct console_config *con
RegCloseKey(key);
}
/* fill memory DC with current cells values */
static void fill_mem_dc( struct console *console, const RECT *update )
{
unsigned int i, j, k;
unsigned int attr;
char_info_t *cell;
HFONT old_font;
HBRUSH brush;
WCHAR *line;
INT *dx;
RECT r;
if (!console->window->font)
return;
if (!(line = malloc( (update->right - update->left + 1) * sizeof(WCHAR))) ) return;
dx = malloc( (update->right - update->left + 1) * sizeof(*dx) );
old_font = SelectObject( console->window->mem_dc, console->window->font );
for (j = update->top; j <= update->bottom; j++)
{
cell = &console->active->data[j * console->active->width];
for (i = update->left; i <= update->right; i++)
{
attr = cell[i].attr;
SetBkColor( console->window->mem_dc, console->active->color_map[(attr >> 4) & 0x0F] );
SetTextColor( console->window->mem_dc, console->active->color_map[attr & 0x0F] );
for (k = i; k <= update->right && cell[k].attr == attr; k++)
{
line[k - i] = cell[k].ch;
dx[k - i] = console->active->font.width;
}
ExtTextOutW( console->window->mem_dc, i * console->active->font.width,
j * console->active->font.height, 0, NULL, line, k - i, dx );
if (console->window->ext_leading &&
(brush = CreateSolidBrush( console->active->color_map[(attr >> 4) & 0x0F] )))
{
r.left = i * console->active->font.width;
r.top = (j + 1) * console->active->font.height - console->window->ext_leading;
r.right = k * console->active->font.width;
r.bottom = (j + 1) * console->active->font.height;
FillRect( console->window->mem_dc, &r, brush );
DeleteObject( brush );
}
i = k - 1;
}
}
SelectObject( console->window->mem_dc, old_font );
free( dx );
free( line );
}
/* set a new position for the cursor */
static void update_window_cursor( struct console *console )
{
if (console->win != GetFocus() || !console->active->cursor_visible) return;
SetCaretPos( (console->active->cursor_x - console->active->win.left) * console->active->font.width,
(console->active->cursor_y - console->active->win.top) * console->active->font.height );
ShowCaret( console->win );
}
/* sets a new shape for the cursor */
static void shape_cursor( struct console *console )
{
int size = console->active->cursor_size;
if (console->active->cursor_visible && console->win == GetFocus()) DestroyCaret();
if (console->window->cursor_bitmap) DeleteObject( console->window->cursor_bitmap );
console->window->cursor_bitmap = NULL;
console->window->cursor_visible = FALSE;
if (size != 100)
{
int w16b; /* number of bytes per row, aligned on word size */
int i, j, nbl;
BYTE *ptr;
w16b = ((console->active->font.width + 15) & ~15) / 8;
ptr = calloc( w16b, console->active->font.height );
if (!ptr) return;
nbl = max( (console->active->font.height * size) / 100, 1 );
for (j = console->active->font.height - nbl; j < console->active->font.height; j++)
{
for (i = 0; i < console->active->font.width; i++)
{
ptr[w16b * j + (i / 8)] |= 0x80 >> (i & 7);
}
}
console->window->cursor_bitmap = CreateBitmap( console->active->font.width,
console->active->font.height, 1, 1, ptr );
free(ptr);
}
}
static void update_window( struct console *console )
{
unsigned int win_width, win_height;
BOOL update_all = FALSE;
int dx, dy;
RECT r;
console->window->update_state = UPDATE_BUSY;
if (console->window->sb_width != console->active->width ||
console->window->sb_height != console->active->height ||
!console->window->bitmap)
{
console->window->sb_width = console->active->width;
console->window->sb_height = console->active->height;
if (console->active->width && console->active->height && console->window->font)
{
HBITMAP bitmap;
HDC dc;
RECT r;
if (!(dc = GetDC( console->win ))) return;
bitmap = CreateCompatibleBitmap( dc,
console->active->width * console->active->font.width,
console->active->height * console->active->font.height );
ReleaseDC( console->win, dc );
SelectObject( console->window->mem_dc, bitmap );
if (console->window->bitmap) DeleteObject( console->window->bitmap );
console->window->bitmap = bitmap;
SetRect( &r, 0, 0, console->active->width - 1, console->active->height - 1 );
fill_mem_dc( console, &r );
}
empty_update_rect( console->active, &console->window->update );
update_all = TRUE;
}
/* compute window size from desired client size */
win_width = console->active->win.right - console->active->win.left + 1;
win_height = console->active->win.bottom - console->active->win.top + 1;
if (update_all || win_width != console->window->win_width ||
win_height != console->window->win_height)
{
console->window->win_width = win_width;
console->window->win_height = win_height;
r.left = r.top = 0;
r.right = win_width * console->active->font.width;
r.bottom = win_height * console->active->font.height;
AdjustWindowRect( &r, GetWindowLongW( console->win, GWL_STYLE ), FALSE );
dx = dy = 0;
if (console->active->width > win_width)
{
dy = GetSystemMetrics( SM_CYHSCROLL );
SetScrollRange( console->win, SB_HORZ, 0, console->active->width - win_width, FALSE );
SetScrollPos( console->win, SB_VERT, console->active->win.top, FALSE );
ShowScrollBar( console->win, SB_HORZ, TRUE );
}
else
{
ShowScrollBar( console->win, SB_HORZ, FALSE );
}
if (console->active->height > win_height)
{
dx = GetSystemMetrics( SM_CXVSCROLL );
SetScrollRange( console->win, SB_VERT, 0, console->active->height - win_height, FALSE );
SetScrollPos( console->win, SB_VERT, console->active->win.top, FALSE );
ShowScrollBar( console->win, SB_VERT, TRUE );
}
else
ShowScrollBar( console->win, SB_VERT, FALSE );
dx += r.right - r.left;
dy += r.bottom - r.top;
SetWindowPos( console->win, 0, 0, 0, dx, dy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0 );
console->active->max_width = (r.right - r.left) / console->active->font.width;
console->active->max_height = (r.bottom - r.top - GetSystemMetrics( SM_CYCAPTION )) /
console->active->font.height;
InvalidateRect( console->win, NULL, FALSE );
UpdateWindow( console->win );
update_all = TRUE;
}
else if (console->active->win.left != console->window->win_pos.X ||
console->active->win.top != console->window->win_pos.Y)
{
ScrollWindow( console->win,
(console->window->win_pos.X - console->active->win.left) * console->active->font.width,
(console->window->win_pos.Y - console->active->win.top) * console->active->font.height,
NULL, NULL );
SetScrollPos( console->win, SB_HORZ, console->active->win.left, TRUE );
SetScrollPos( console->win, SB_VERT, console->active->win.top, TRUE );
InvalidateRect( console->win, NULL, FALSE );
}
console->window->win_pos.X = console->active->win.left;
console->window->win_pos.Y = console->active->win.top;
if (console->window->update.top <= console->window->update.bottom &&
console->window->update.left <= console->window->update.right)
{
RECT *update = &console->window->update;
r.left = (update->left - console->active->win.left) * console->active->font.width;
r.right = (update->right - console->active->win.left + 1) * console->active->font.width;
r.top = (update->top - console->active->win.top) * console->active->font.height;
r.bottom = (update->bottom - console->active->win.top + 1) * console->active->font.height;
fill_mem_dc( console, update );
empty_update_rect( console->active, &console->window->update );
InvalidateRect( console->win, &r, FALSE );
UpdateWindow( console->win );
}
if (update_all || console->active->cursor_size != console->window->cursor_size)
{
console->window->cursor_size = console->active->cursor_size;
shape_cursor( console );
}
if (console->active->cursor_visible != console->window->cursor_visible)
{
console->window->cursor_visible = console->active->cursor_visible;
if (console->win == GetFocus())
{
if (console->window->cursor_visible)
CreateCaret( console->win, console->window->cursor_bitmap,
console->active->font.width, console->active->font.height );
else
DestroyCaret();
}
}
if (update_all || console->active->cursor_x != console->window->cursor_pos.X ||
console->active->cursor_y != console->window->cursor_pos.Y)
{
console->window->cursor_pos.X = console->active->cursor_x;
console->window->cursor_pos.Y = console->active->cursor_y;
update_window_cursor( console );
}
console->window->update_state = UPDATE_NONE;
}
static void fill_logfont( LOGFONTW *lf, const WCHAR *name, unsigned int height, unsigned int weight )
{
lf->lfHeight = height;
......@@ -640,6 +896,8 @@ static void apply_config( struct console *console, const struct console_config *
{
update_console_font( console, config->face_name, config->cell_height, config->font_weight );
}
update_window( console );
}
static LRESULT window_create( HWND hwnd, const CREATESTRUCTW *create )
......@@ -651,6 +909,7 @@ static LRESULT window_create( HWND hwnd, const CREATESTRUCTW *create )
SetWindowLongPtrW( hwnd, 0, (DWORD_PTR)console );
console->win = hwnd;
console->window->mem_dc = CreateCompatibleDC( 0 );
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment