[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