Jacek Caban : conhost: Initialize tty output.

Alexandre Julliard julliard at winehq.org
Fri Sep 4 15:47:32 CDT 2020


Module: wine
Branch: master
Commit: 7fe03dbf21196d40ad533f6acf2e216fb48540d6
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=7fe03dbf21196d40ad533f6acf2e216fb48540d6

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Sep  4 13:49:45 2020 +0200

conhost: Initialize tty output.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/conhost/conhost.c | 114 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 97 insertions(+), 17 deletions(-)

diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c
index aef9b8e199..30dedcf83f 100644
--- a/programs/conhost/conhost.c
+++ b/programs/conhost/conhost.c
@@ -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 );
 }




More information about the wine-cvs mailing list