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