conhost: Initialize tty output.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2020-09-04 13:49:45 +02:00 committed by Alexandre Julliard
parent 5bbd8130ad
commit 7fe03dbf21
1 changed files with 97 additions and 17 deletions

View File

@ -21,6 +21,8 @@
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>
#include <ntstatus.h>
#define WIN32_NO_STATUS
#include <windef.h>
@ -54,23 +56,27 @@ struct font_info
struct console
{
HANDLE server; /* console server handle */
unsigned int mode; /* input mode */
struct screen_buffer *active; /* active screen buffer */
INPUT_RECORD *records; /* input records */
unsigned int record_count; /* number of input records */
unsigned int record_size; /* size of input records buffer */
size_t pending_read; /* size of pending read buffer */
WCHAR *title; /* console title */
size_t title_len; /* length of console title */
struct history_line **history; /* lines history */
unsigned int history_size; /* number of entries in history array */
unsigned int history_index; /* number of used entries in history array */
unsigned int history_mode; /* mode of history (non zero means remove doubled strings */
unsigned int edition_mode; /* index to edition mode flavors */
unsigned int input_cp; /* console input codepage */
unsigned int output_cp; /* console output codepage */
unsigned int win; /* window handle if backend supports it */
HANDLE server; /* console server handle */
unsigned int mode; /* input mode */
struct screen_buffer *active; /* active screen buffer */
INPUT_RECORD *records; /* input records */
unsigned int record_count; /* number of input records */
unsigned int record_size; /* size of input records buffer */
size_t pending_read; /* size of pending read buffer */
WCHAR *title; /* console title */
size_t title_len; /* length of console title */
struct history_line **history; /* lines history */
unsigned int history_size; /* number of entries in history array */
unsigned int history_index; /* number of used entries in history array */
unsigned int history_mode; /* mode of history (non zero means remove doubled strings */
unsigned int edition_mode; /* index to edition mode flavors */
unsigned int input_cp; /* console input codepage */
unsigned int output_cp; /* console output codepage */
unsigned int win; /* window handle if backend supports it */
HANDLE tty_output; /* handle to tty output stream */
char tty_buffer[4096]; /* tty output buffer */
size_t tty_buffer_count; /* tty buffer size */
unsigned int tty_attr; /* current tty char attributes */
};
struct screen_buffer
@ -187,6 +193,75 @@ static BOOL is_active( struct screen_buffer *screen_buffer )
return screen_buffer == screen_buffer->console->active;
}
static void tty_flush( struct console *console )
{
if (!console->tty_output || !console->tty_buffer_count) return;
TRACE("%s\n", debugstr_an(console->tty_buffer, console->tty_buffer_count));
if (!WriteFile( console->tty_output, console->tty_buffer, console->tty_buffer_count,
NULL, NULL ))
WARN( "write failed: %u\n", GetLastError() );
console->tty_buffer_count = 0;
}
static void tty_write( struct console *console, const char *buffer, size_t size )
{
if (!size || !console->tty_output) return;
if (console->tty_buffer_count + size > sizeof(console->tty_buffer))
tty_flush( console );
if (console->tty_buffer_count + size <= sizeof(console->tty_buffer))
{
memcpy( console->tty_buffer + console->tty_buffer_count, buffer, size );
console->tty_buffer_count += size;
}
else
{
assert( !console->tty_buffer_count );
if (!WriteFile( console->tty_output, buffer, size, NULL, NULL ))
WARN( "write failed: %u\n", GetLastError() );
}
}
static void set_tty_attr( struct console *console, unsigned int attr )
{
char buf[8];
if ((attr & 0x0f) != (console->tty_attr & 0x0f))
{
if ((attr & 0x0f) != 7)
{
unsigned int n = 30;
if (attr & FOREGROUND_BLUE) n += 4;
if (attr & FOREGROUND_GREEN) n += 2;
if (attr & FOREGROUND_RED) n += 1;
if (attr & FOREGROUND_INTENSITY) n += 60;
sprintf(buf, "\x1b[%um", n);
tty_write( console, buf, strlen(buf) );
}
else tty_write( console, "\x1b[m", 3 );
}
if ((attr & 0xf0) != (console->tty_attr & 0xf0) && attr != 7)
{
unsigned int n = 40;
if (attr & BACKGROUND_BLUE) n += 4;
if (attr & BACKGROUND_GREEN) n += 2;
if (attr & BACKGROUND_RED) n += 1;
if (attr & BACKGROUND_INTENSITY) n += 60;
sprintf(buf, "\x1b[%um", n);
tty_write( console, buf, strlen(buf) );
}
console->tty_attr = attr;
}
static void init_tty_output( struct console *console )
{
/* initialize tty output, but don't flush */
tty_write( console, "\x1b[2J", 4 ); /* clear screen */
set_tty_attr( console, console->active->attr );
tty_write( console, "\x1b[H", 3 ); /* move cursor to (0,0) */
}
static NTSTATUS read_console_input( struct console *console, size_t out_size )
{
size_t count = min( out_size / sizeof(INPUT_RECORD), console->record_count );
@ -1199,6 +1274,11 @@ int __cdecl wmain(int argc, WCHAR *argv[])
}
if (!(console.active = create_screen_buffer( &console, 1, width, height ))) return 1;
if (headless)
{
console.tty_output = GetStdHandle( STD_OUTPUT_HANDLE );
init_tty_output( &console );
}
return main_loop( &console, signal );
}