[PATCH 1/5] [WineHelp]: added basic infrastructure for a new wineconsole mode: line

Eric Pouech eric.pouech at orange.fr
Mon Dec 3 15:12:03 CST 2012


(using simple read/write ops to unix fd:s)

A+
---

 programs/wineconsole/Makefile.in       |    1 
 programs/wineconsole/curses.c          |   14 +
 programs/wineconsole/line.c            |  334 ++++++++++++++++++++++++++++++++
 programs/wineconsole/winecon_private.h |   16 ++
 programs/wineconsole/wineconsole.c     |    5 
 5 files changed, 363 insertions(+), 7 deletions(-)
 create mode 100644 programs/wineconsole/line.c


diff --git a/programs/wineconsole/Makefile.in b/programs/wineconsole/Makefile.in
index 1471ad5..5ef2b51 100644
--- a/programs/wineconsole/Makefile.in
+++ b/programs/wineconsole/Makefile.in
@@ -6,6 +6,7 @@ DELAYIMPORTS = comctl32 user32 gdi32
 C_SRCS = \
 	curses.c \
 	dialog.c \
+	line.c \
 	registry.c \
 	user.c \
 	wineconsole.c
diff --git a/programs/wineconsole/curses.c b/programs/wineconsole/curses.c
index 735ec97..aa45054 100644
--- a/programs/wineconsole/curses.c
+++ b/programs/wineconsole/curses.c
@@ -515,7 +515,7 @@ static void WCCURSES_ScrollV(struct inner_data* data, int delta)
 }
 
 /* Ascii -> VK, generated by calling VkKeyScanA(i) */
-static const int vkkeyscan_table[256] =
+const int vkkeyscan_table[256] =
 {
      0,0,0,0,0,0,0,0,8,9,0,0,0,13,0,0,0,0,0,19,145,556,0,0,0,0,0,27,0,0,0,
      0,32,305,478,307,308,309,311,222,313,304,312,443,188,189,190,191,48,
@@ -529,7 +529,7 @@ static const int vkkeyscan_table[256] =
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0
 };
 
-static const int mapvkey_0[256] =
+const int mapvkey_0[256] =
 {
      0,0,0,0,0,0,0,0,14,15,0,0,0,28,0,0,42,29,56,69,58,0,0,0,0,0,0,1,0,0,
      0,0,57,73,81,79,71,75,72,77,80,0,0,0,55,82,83,0,11,2,3,4,5,6,7,8,9,
@@ -629,11 +629,11 @@ static unsigned WCCURSES_FillSimpleChar(INPUT_RECORD* ir, unsigned real_inchar)
     numEvent += 2;
 
     if (vk & 0x0400)
-        WCCURSES_InitComplexChar(&ir[numEvent++], 0, 0x38, 0x12, LEFT_ALT_PRESSED);
+        init_complex_char(&ir[numEvent++], 0, 0x38, 0x12, LEFT_ALT_PRESSED);
     if ((vk & 0x0200) || (unsigned char)real_inchar <= 26)
-        WCCURSES_InitComplexChar(&ir[numEvent++], 0, 0x1d, 0x11, 0);
+        init_complex_char(&ir[numEvent++], 0, 0x1d, 0x11, 0);
     if (vk & 0x0100)
-        WCCURSES_InitComplexChar(&ir[numEvent++], 0, 0x2a, 0x10, 0);
+        init_complex_char(&ir[numEvent++], 0, 0x2a, 0x10, 0);
 
     return numEvent;
 }
@@ -645,8 +645,8 @@ static unsigned WCCURSES_FillSimpleChar(INPUT_RECORD* ir, unsigned real_inchar)
  */
 static unsigned WCCURSES_FillComplexChar(INPUT_RECORD* ir, WORD vk, WORD kc, DWORD cks)
 {
-    WCCURSES_InitComplexChar(&ir[0], 1, vk, kc, ENHANCED_KEY | cks);
-    WCCURSES_InitComplexChar(&ir[1], 0, vk, kc, ENHANCED_KEY | cks);
+    init_complex_char(&ir[0], 1, vk, kc, ENHANCED_KEY | cks);
+    init_complex_char(&ir[1], 0, vk, kc, ENHANCED_KEY | cks);
 
     return 2;
 }
diff --git a/programs/wineconsole/line.c b/programs/wineconsole/line.c
new file mode 100644
index 0000000..4b7fd29
--- /dev/null
+++ b/programs/wineconsole/line.c
@@ -0,0 +1,334 @@
+/*
+ * a GUI application for displaying a console
+ *	Line back end
+ *
+ * Copyright 2002 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <windef.h>
+#include <winbase.h>
+#include <winnls.h>
+#include "winecon_private.h"
+
+#include "wine/library.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(line);
+
+#define PRIVATE(data)   ((struct inner_data_line*)((data)->private))
+
+struct inner_data_line
+{
+    int                 sync_pipe[2];
+    HANDLE              input_thread;
+    CRITICAL_SECTION    lock;
+};
+
+/******************************************************************
+ *		WCLINE_FillSimpleChar
+ *
+ *
+ */
+static unsigned WCLINE_FillSimpleChar(INPUT_RECORD* ir, unsigned real_inchar)
+{
+    unsigned vk;
+    unsigned inchar;
+    char ch;
+    unsigned numEvent = 0;
+
+    switch (real_inchar)
+    {
+    case   9: inchar = real_inchar;
+              real_inchar = 27; /* so that we don't think key is ctrl- something */
+	      break;
+    case  13:
+    case  10: inchar = '\r';
+              real_inchar = 27; /* Fixme: so that we don't think key is ctrl- something */
+	      break;
+    case 127: inchar = '\b';
+	      break;
+    default:  inchar = real_inchar;
+              break;
+    }
+    if ((inchar & ~0xFF) != 0) WINE_FIXME("What a char (%u)\n", inchar);
+    vk = vkkeyscan_table[inchar];
+    if (vk & 0x0100)
+        init_complex_char(&ir[numEvent++], 1, 0x2a, 0x10, SHIFT_PRESSED);
+    if ((vk & 0x0200) || (unsigned char)real_inchar <= 26)
+        init_complex_char(&ir[numEvent++], 1, 0x1d, 0x11, LEFT_CTRL_PRESSED);
+    if (vk & 0x0400)
+        init_complex_char(&ir[numEvent++], 1, 0x38, 0x12, LEFT_ALT_PRESSED);
+
+    ir[numEvent].EventType                        = KEY_EVENT;
+    ir[numEvent].Event.KeyEvent.bKeyDown          = 1;
+    ir[numEvent].Event.KeyEvent.wRepeatCount      = 1;
+    ir[numEvent].Event.KeyEvent.dwControlKeyState = 0;
+    if (vk & 0x0100)
+        ir[numEvent].Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
+    if ((vk & 0x0200) || (unsigned char)real_inchar <= 26)
+        ir[numEvent].Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED;
+    if (vk & 0x0400)
+        ir[numEvent].Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED;
+    ir[numEvent].Event.KeyEvent.wVirtualKeyCode = vk;
+    ir[numEvent].Event.KeyEvent.wVirtualScanCode = mapvkey_0[vk & 0x00ff]; /* VirtualKeyCodes to ScanCode */
+
+    ch = inchar;
+    MultiByteToWideChar(CP_UNIXCP, 0,&ch,1,&ir[numEvent].Event.KeyEvent.uChar.UnicodeChar, 1);
+    ir[numEvent + 1] = ir[numEvent];
+    ir[numEvent + 1].Event.KeyEvent.bKeyDown      = 0;
+
+    numEvent += 2;
+
+    if (vk & 0x0400)
+        init_complex_char(&ir[numEvent++], 0, 0x38, 0x12, LEFT_ALT_PRESSED);
+    if ((vk & 0x0200) || (unsigned char)real_inchar <= 26)
+        init_complex_char(&ir[numEvent++], 0, 0x1d, 0x11, 0);
+    if (vk & 0x0100)
+        init_complex_char(&ir[numEvent++], 0, 0x2a, 0x10, 0);
+
+    return numEvent;
+}
+
+/******************************************************************
+ *		WCLINE_ResizeScreenBuffer
+ *
+ *
+ */
+static void WCLINE_ResizeScreenBuffer(struct inner_data* data)
+{
+}
+
+/******************************************************************
+ *		WCLINE_PosCursor
+ *
+ * Set a new position for the cursor (and refresh any modified part of our pad)
+ */
+static void	WCLINE_PosCursor(const struct inner_data* data)
+{
+}
+
+/******************************************************************
+ *		WCLINE_ShapeCursor
+ *
+ * Sets a new shape for the cursor
+ */
+static void	WCLINE_ShapeCursor(struct inner_data* data, int size, int vis, BOOL force)
+{
+}
+
+/******************************************************************
+ *		WCLINE_ComputePositions
+ *
+ * Recomputes all the components (mainly scroll bars) positions
+ */
+static void	WCLINE_ComputePositions(struct inner_data* data)
+{
+}
+
+/******************************************************************
+ *		WCLINE_SetTitle
+ *
+ * Sets the title to the wine console
+ */
+static void	WCLINE_SetTitle(const struct inner_data* data)
+{
+    WCHAR   wbuf[256];
+
+    if (WINECON_GetConsoleTitle(data->hConIn, wbuf, sizeof(wbuf)/sizeof(WCHAR)))
+    {
+        char        buffer[256];
+
+        WideCharToMultiByte(CP_UNIXCP, 0, wbuf, -1, buffer, sizeof(buffer),
+                            NULL, NULL);
+        fputs("\033]2;", stdout);
+        fputs(buffer, stdout);
+        fputc('\a', stdout);
+        fflush(stdout);
+    }
+}
+
+/******************************************************************
+ *		WCLINE_Refresh
+ *
+ *
+ */
+static void WCLINE_Refresh(const struct inner_data* data, int tp, int bm)
+{
+    WCLINE_PosCursor(data);
+}
+
+/******************************************************************
+ *		WCLINE_Scroll
+ *
+ *
+ */
+static void WCLINE_Scroll(struct inner_data* data, int pos, BOOL horz)
+{
+    WCLINE_PosCursor(data);
+}
+
+/******************************************************************
+ *		WCLINE_SetFont
+ *
+ *
+ */
+static void WCLINE_SetFont(struct inner_data* data, const WCHAR* font,
+                            unsigned height, unsigned weight)
+{
+    /* FIXME: really not much to do ? */
+}
+
+/******************************************************************
+ *		WCLINE_Resize
+ *
+ */
+static void WCLINE_Resize(struct inner_data* data)
+{
+}
+
+/******************************************************************
+ *		input_thread
+ */
+static DWORD CALLBACK input_thread(void *arg)
+{
+    struct inner_data* data = arg;
+    int		        inchar;
+    INPUT_RECORD        ir[8];
+    unsigned		numEvent;
+    DWORD               n;
+    struct pollfd       pfd[2];
+
+    pfd[0].fd = 0;
+    pfd[0].events = POLLIN;
+    pfd[1].fd = PRIVATE(data)->sync_pipe[0];
+    pfd[1].events = POLLHUP;
+
+    for (;;)
+    {
+        pfd[0].revents = pfd[1].revents = 0;
+        if (poll(pfd, 2, -1) == -1) break;
+        if (pfd[0].revents & (POLLHUP|POLLERR)) break;
+        if (pfd[1].revents & (POLLHUP|POLLERR)) break;
+        if (!(pfd[0].revents & POLLIN)) continue;
+
+        /* we're called from input thread (not main thread), so force unique access */
+        EnterCriticalSection(&PRIVATE(data)->lock);
+        if ((inchar = fgetc(stdin)) != -1)
+        {
+            WINE_TRACE("Got o%o (0x%x)\n", inchar, inchar);
+
+            numEvent = WCLINE_FillSimpleChar(ir, inchar);
+
+            if (numEvent) WriteConsoleInputW(data->hConIn, ir, numEvent, &n);
+        }
+        LeaveCriticalSection(&PRIVATE(data)->lock);
+    }
+    close(PRIVATE(data)->sync_pipe[0]);
+    return 0;
+}
+
+/******************************************************************
+ *		WCLINE_DeleteBackend
+ *
+ *
+ */
+static void WCLINE_DeleteBackend(struct inner_data* data)
+{
+    if (!PRIVATE(data)) return;
+
+    if (PRIVATE(data)->input_thread)
+    {
+        close(PRIVATE(data)->sync_pipe[1]);
+        WaitForSingleObject(PRIVATE(data)->input_thread, INFINITE);
+        CloseHandle(PRIVATE(data)->input_thread);
+    }
+    PRIVATE(data)->lock.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection(&PRIVATE(data)->lock);
+
+    HeapFree(GetProcessHeap(), 0, PRIVATE(data));
+    data->private = NULL;
+}
+
+/******************************************************************
+ *		WCLINE_MainLoop
+ *
+ *
+ */
+static int WCLINE_MainLoop(struct inner_data* data)
+{
+    DWORD       id;
+
+    WCLINE_Resize(data);
+
+    if (pipe(PRIVATE(data)->sync_pipe) == -1) return 0;
+    PRIVATE(data)->input_thread = CreateThread(NULL, 0, input_thread, data, 0, &id);
+
+    while (!data->dying && WaitForSingleObject(data->hSynchro, INFINITE) == WAIT_OBJECT_0)
+    {
+        EnterCriticalSection(&PRIVATE(data)->lock);
+        WINECON_GrabChanges(data);
+        LeaveCriticalSection(&PRIVATE(data)->lock);
+    }
+
+    close(PRIVATE(data)->sync_pipe[1]);
+    WaitForSingleObject(PRIVATE(data)->input_thread, INFINITE);
+    CloseHandle(PRIVATE(data)->input_thread);
+    PRIVATE(data)->input_thread = 0;
+    return 0;
+}
+
+/******************************************************************
+ *		WCLINE_InitBackend
+ *
+ * Initialisation part II: creation of window.
+ *
+ */
+enum init_return WCLINE_InitBackend(struct inner_data* data)
+{
+    data->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct inner_data_line));
+    if (!data->private) return init_failed;
+
+    data->fnMainLoop           = WCLINE_MainLoop;
+    data->fnPosCursor          = WCLINE_PosCursor;
+    data->fnShapeCursor        = WCLINE_ShapeCursor;
+    data->fnComputePositions   = WCLINE_ComputePositions;
+    data->fnRefresh            = WCLINE_Refresh;
+    data->fnResizeScreenBuffer = WCLINE_ResizeScreenBuffer;
+    data->fnSetTitle           = WCLINE_SetTitle;
+    data->fnScroll             = WCLINE_Scroll;
+    data->fnSetFont            = WCLINE_SetFont;
+    data->fnDeleteBackend      = WCLINE_DeleteBackend;
+    data->hWnd                 = NULL;
+
+    InitializeCriticalSection(&PRIVATE(data)->lock);
+    PRIVATE(data)->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": line");
+
+    return init_success;
+}
+
diff --git a/programs/wineconsole/winecon_private.h b/programs/wineconsole/winecon_private.h
index 1daf581..7c492d6 100644
--- a/programs/wineconsole/winecon_private.h
+++ b/programs/wineconsole/winecon_private.h
@@ -98,3 +98,19 @@ enum init_return {
 };
 extern enum init_return WCUSER_InitBackend(struct inner_data* data);
 extern enum init_return WCCURSES_InitBackend(struct inner_data* data);
+extern enum init_return WCLINE_InitBackend(struct inner_data* data);
+
+/* generics */
+extern const int vkkeyscan_table[256];
+extern const int mapvkey_0[256];
+
+static inline void init_complex_char(INPUT_RECORD* ir, BOOL down, WORD vk, WORD kc, DWORD cks)
+{
+    ir->EventType			 = KEY_EVENT;
+    ir->Event.KeyEvent.bKeyDown	         = down;
+    ir->Event.KeyEvent.wRepeatCount	 = 1;
+    ir->Event.KeyEvent.wVirtualScanCode  = vk;
+    ir->Event.KeyEvent.wVirtualKeyCode   = kc;
+    ir->Event.KeyEvent.dwControlKeyState = cks;
+    ir->Event.KeyEvent.uChar.UnicodeChar = 0;
+}
diff --git a/programs/wineconsole/wineconsole.c b/programs/wineconsole/wineconsole.c
index bda69a4..e6e599a 100644
--- a/programs/wineconsole/wineconsole.c
+++ b/programs/wineconsole/wineconsole.c
@@ -777,6 +777,11 @@ static UINT WINECON_ParseOptions(const char* lpCmdLine, struct wc_init* wci)
                 wci->backend = WCCURSES_InitBackend;
                 wci->ptr += 16;
             }
+            else if (strncmp(wci->ptr + 10, "line", 4) == 0)
+            {
+                wci->backend = WCLINE_InitBackend;
+                wci->ptr += 14;
+            }
             else
                 return IDS_CMD_INVALID_BACKEND;
         }




More information about the wine-patches mailing list