Jacek Caban : conhost: Add support for ENABLE_ECHO_INPUT.
Alexandre Julliard
julliard at winehq.org
Mon Sep 14 14:58:24 CDT 2020
Module: wine
Branch: master
Commit: 73f55e234101739a456774a334e1d732b57afd0b
URL: https://source.winehq.org/git/wine.git/?a=commit;h=73f55e234101739a456774a334e1d732b57afd0b
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon Sep 14 18:46:18 2020 +0200
conhost: Add support for ENABLE_ECHO_INPUT.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
programs/conhost/conhost.c | 98 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 93 insertions(+), 5 deletions(-)
diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c
index 32b2462786..d93bcbfa60 100644
--- a/programs/conhost/conhost.c
+++ b/programs/conhost/conhost.c
@@ -413,8 +413,8 @@ static void new_line( struct screen_buffer *screen_buffer, RECT *update_rect )
{
unsigned int i;
- assert( screen_buffer->cursor_y == screen_buffer->height );
- screen_buffer->cursor_y--;
+ assert( screen_buffer->cursor_y >= screen_buffer->height );
+ screen_buffer->cursor_y = screen_buffer->height - 1;
if (screen_buffer->console->tty_output)
update_output( screen_buffer, update_rect );
@@ -434,7 +434,7 @@ static void new_line( struct screen_buffer *screen_buffer, RECT *update_rect )
}
}
-static void write_char( struct screen_buffer *screen_buffer, WCHAR ch, RECT *update_rect )
+static void write_char( struct screen_buffer *screen_buffer, WCHAR ch, RECT *update_rect, unsigned int *home_y )
{
if (screen_buffer->cursor_x == screen_buffer->width)
{
@@ -443,6 +443,11 @@ static void write_char( struct screen_buffer *screen_buffer, WCHAR ch, RECT *upd
}
if (screen_buffer->cursor_y == screen_buffer->height)
{
+ if (home_y)
+ {
+ if (!*home_y) return;
+ (*home_y)--;
+ }
new_line( screen_buffer, update_rect );
}
@@ -561,6 +566,88 @@ static void edit_line_insert( struct console *console, const WCHAR *str, unsigne
ctx->cursor += len;
}
+static unsigned int edit_line_string_width( const WCHAR *str, unsigned int len)
+{
+ unsigned int i, offset = 0;
+ for (i = 0; i < len; i++) offset += str[i] < ' ' ? 2 : 1;
+ return offset;
+}
+
+static void update_read_output( struct console *console )
+{
+ struct screen_buffer *screen_buffer = console->active;
+ struct edit_line *ctx = &console->edit_line;
+ int offset = 0, j, end_offset;
+ RECT update_rect;
+
+ empty_update_rect( screen_buffer, &update_rect );
+
+ if (ctx->update_end >= ctx->update_begin)
+ {
+ TRACE( "update %d-%d %s\n", ctx->update_begin, ctx->update_end,
+ debugstr_wn( ctx->buf + ctx->update_begin, ctx->update_end - ctx->update_begin + 1 ));
+
+ hide_tty_cursor( screen_buffer->console );
+
+ offset = edit_line_string_width( ctx->buf, ctx->update_begin );
+ screen_buffer->cursor_x = (ctx->home_x + offset) % screen_buffer->width;
+ screen_buffer->cursor_y = ctx->home_y + (ctx->home_x + offset) / screen_buffer->width;
+ for (j = ctx->update_begin; j <= ctx->update_end; j++)
+ {
+ if (screen_buffer->cursor_y >= screen_buffer->height && !ctx->home_y) break;
+ if (j >= ctx->len) break;
+ if (ctx->buf[j] < ' ')
+ {
+ write_char( screen_buffer, '^', &update_rect, &ctx->home_y );
+ write_char( screen_buffer, '@' + ctx->buf[j], &update_rect, &ctx->home_y );
+ offset += 2;
+ }
+ else
+ {
+ write_char( screen_buffer, ctx->buf[j], &update_rect, &ctx->home_y );
+ offset++;
+ }
+ }
+ end_offset = ctx->end_offset;
+ ctx->end_offset = offset;
+ if (j >= ctx->len)
+ {
+ /* clear trailing characters if buffer was shortened */
+ while (offset < end_offset && screen_buffer->cursor_y < screen_buffer->height)
+ {
+ write_char( screen_buffer, ' ', &update_rect, &ctx->home_y );
+ offset++;
+ }
+ }
+ }
+
+ if (!ctx->status)
+ {
+ offset = edit_line_string_width( ctx->buf, ctx->len );
+ screen_buffer->cursor_x = 0;
+ screen_buffer->cursor_y = ctx->home_y + (ctx->home_x + offset) / screen_buffer->width;
+ if (++screen_buffer->cursor_y >= screen_buffer->height)
+ new_line( screen_buffer, &update_rect );
+ }
+ else
+ {
+ offset = edit_line_string_width( ctx->buf, ctx->cursor );
+ screen_buffer->cursor_y = ctx->home_y + (ctx->home_x + offset) / screen_buffer->width;
+ if (screen_buffer->cursor_y < screen_buffer->height)
+ {
+ screen_buffer->cursor_x = (ctx->home_x + offset) % screen_buffer->width;
+ }
+ else
+ {
+ screen_buffer->cursor_x = screen_buffer->width - 1;
+ screen_buffer->cursor_y = screen_buffer->height - 1;
+ }
+ }
+
+ update_output( screen_buffer, &update_rect );
+ tty_sync( screen_buffer->console );
+}
+
static NTSTATUS process_console_input( struct console *console )
{
struct edit_line *ctx = &console->edit_line;
@@ -605,6 +692,7 @@ static NTSTATUS process_console_input( struct console *console )
if (ctx->status == STATUS_PENDING && !(console->mode & ENABLE_LINE_INPUT) && ctx->len)
ctx->status = STATUS_SUCCESS;
+ if (console->mode & ENABLE_ECHO_INPUT) update_read_output( console );
if (ctx->status == STATUS_PENDING) return STATUS_SUCCESS;
console->read_buffer = ctx->buf;
@@ -1169,7 +1257,7 @@ static NTSTATUS write_console( struct screen_buffer *screen_buffer, const WCHAR
continue;
case '\t':
j = min( screen_buffer->width - screen_buffer->cursor_x, 8 - (screen_buffer->cursor_x % 8) );
- while (j--) write_char( screen_buffer, ' ', &update_rect );
+ while (j--) write_char( screen_buffer, ' ', &update_rect, NULL );
continue;
case '\n':
screen_buffer->cursor_x = 0;
@@ -1188,7 +1276,7 @@ static NTSTATUS write_console( struct screen_buffer *screen_buffer, const WCHAR
}
if (screen_buffer->cursor_x == screen_buffer->width && !(screen_buffer->mode & ENABLE_WRAP_AT_EOL_OUTPUT))
screen_buffer->cursor_x = update_rect.left;
- write_char( screen_buffer, buffer[i], &update_rect );
+ write_char( screen_buffer, buffer[i], &update_rect, NULL );
}
if (screen_buffer->cursor_x == screen_buffer->width)
More information about the wine-cvs
mailing list