[PATCH 3/7] [WineConsole]: in line mode, now support extended characters
Eric Pouech
eric.pouech at orange.fr
Sat Dec 29 09:21:29 CST 2012
A+
---
programs/wineconsole/curses.c | 47 ++--
programs/wineconsole/line.c | 369 +++++++++++++++++++++++++++++++-
programs/wineconsole/registry.c | 8 -
programs/wineconsole/user.c | 24 +-
programs/wineconsole/winecon_private.h | 5
programs/wineconsole/wineconsole.c | 10 -
6 files changed, 414 insertions(+), 49 deletions(-)
diff --git a/programs/wineconsole/curses.c b/programs/wineconsole/curses.c
index aa45054..6cb99b9 100644
--- a/programs/wineconsole/curses.c
+++ b/programs/wineconsole/curses.c
@@ -131,7 +131,7 @@ MAKE_FUNCPTR(acs_map)
/**********************************************************************/
-static BOOL WCCURSES_bind_libcurses(void)
+BOOL bind_libcurses(void)
{
#ifdef SONAME_LIBNCURSES
static const char ncname[] = SONAME_LIBNCURSES;
@@ -140,19 +140,37 @@ static BOOL WCCURSES_bind_libcurses(void)
#endif
nc_handle = wine_dlopen(ncname, RTLD_NOW, NULL, 0);
- if(!nc_handle)
+ if (!nc_handle)
{
WINE_MESSAGE("Wine cannot find the " CURSES_NAME " library (%s).\n",
ncname);
return FALSE;
}
+ return TRUE;
+}
-#define LOAD_FUNCPTR(f) \
- if((p_##f = wine_dlsym(nc_handle, #f, NULL, 0)) == NULL) \
- { \
- WINE_WARN("Can't find symbol %s\n", #f); \
- goto sym_not_found; \
+void* load_curses_func(const char* fn)
+{
+ void* pfn = wine_dlsym(nc_handle, fn, NULL, 0);
+ if (pfn == NULL)
+ {
+ WINE_WARN("Can't find symbol %s\n", fn);
+ WINE_MESSAGE(
+ "Wine cannot find certain functions that it needs inside the "
+ CURSES_NAME "\nlibrary. To enable Wine to use " CURSES_NAME
+ " please upgrade your " CURSES_NAME "\nlibraries\n");
+ wine_dlclose(nc_handle, NULL, 0);
+ nc_handle = NULL;
}
+ return pfn;
+}
+
+static BOOL WCCURSES_bind_libcurses(void)
+{
+ if (!bind_libcurses()) return FALSE;
+
+#define LOAD_FUNCPTR(f) \
+ if ((p_##f = load_curses_func(#f)) == NULL) return FALSE;
LOAD_FUNCPTR(curs_set)
LOAD_FUNCPTR(delwin)
@@ -194,15 +212,6 @@ static BOOL WCCURSES_bind_libcurses(void)
#undef LOAD_FUNCPTR
return TRUE;
-
-sym_not_found:
- WINE_MESSAGE(
- "Wine cannot find certain functions that it needs inside the "
- CURSES_NAME "\nlibrary. To enable Wine to use " CURSES_NAME
- " please upgrade your " CURSES_NAME "\nlibraries\n");
- wine_dlclose(nc_handle, NULL, 0);
- nc_handle = NULL;
- return FALSE;
}
#define curs_set p_curs_set
@@ -270,7 +279,7 @@ static void WCCURSES_PosCursor(const struct inner_data* data)
int scr_width;
int scr_height;
- if (data->curcfg.cursor_visible &&
+ if (data->curcfg.cursor_is_visible &&
data->cursor.Y >= data->curcfg.win_pos.Y &&
data->cursor.Y < data->curcfg.win_pos.Y + data->curcfg.win_height &&
data->cursor.X >= data->curcfg.win_pos.X &&
@@ -300,7 +309,7 @@ static void WCCURSES_ShapeCursor(struct inner_data* data, int size, int vis, BOO
{
/* we can't do much about the size... */
data->curcfg.cursor_size = size;
- data->curcfg.cursor_visible = vis != 0;
+ data->curcfg.cursor_is_visible = vis != 0;
WCCURSES_PosCursor(data);
}
@@ -1040,7 +1049,7 @@ static int WCCURSES_MainLoop(struct inner_data* data)
*/
enum init_return WCCURSES_InitBackend(struct inner_data* data)
{
- if( !WCCURSES_bind_libcurses() )
+ if (!WCCURSES_bind_libcurses())
return init_not_supported;
data->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct inner_data_curse));
diff --git a/programs/wineconsole/line.c b/programs/wineconsole/line.c
index f755b7b..a6816f6 100644
--- a/programs/wineconsole/line.c
+++ b/programs/wineconsole/line.c
@@ -34,6 +34,19 @@
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#endif
+#ifdef HAVE_NCURSES_H
+# include <ncurses.h>
+#elif defined(HAVE_CURSES_H)
+# include <curses.h>
+#endif
+/* avoid redefinition warnings */
+#undef KEY_EVENT
+#undef MOUSE_MOVED
+#undef cursor_visible
+#if defined(HAVE_CURSES_H) || defined(HAVE_NCURSES_H)
+#include <term.h>
+#endif
+
#include <windef.h>
#include <winbase.h>
#include <winnls.h>
@@ -119,6 +132,312 @@ static unsigned WCLINE_FillSimpleChar(INPUT_RECORD* ir, unsigned real_inchar)
return numEvent;
}
+#if defined(SONAME_LIBCURSES) || defined(SONAME_LIBNCURSES)
+
+#ifdef HAVE_NCURSES_H
+# define CURSES_NAME "ncurses"
+#else
+# define CURSES_NAME "curses"
+#endif
+
+#define MAKE_FUNCPTR(f) static typeof(f) * p_##f;
+
+MAKE_FUNCPTR(tputs)
+MAKE_FUNCPTR(setupterm)
+MAKE_FUNCPTR(tigetstr)
+MAKE_FUNCPTR(tigetnum)
+MAKE_FUNCPTR(tparm)
+
+#undef MAKE_FUNCPTR
+
+/**********************************************************************/
+
+static BOOL TERM_bind_libcurses(void)
+{
+ if (!bind_libcurses()) return FALSE;
+
+#define LOAD_FUNCPTR(f) \
+ if ((p_##f = load_curses_func(#f)) == NULL) return FALSE;
+
+ LOAD_FUNCPTR(tputs)
+ LOAD_FUNCPTR(setupterm)
+ LOAD_FUNCPTR(tigetstr)
+ LOAD_FUNCPTR(tigetnum)
+ LOAD_FUNCPTR(tparm)
+
+#undef LOAD_FUNCPTR
+
+ return TRUE;
+}
+
+#define tputs p_tputs
+#define setupterm p_setupterm
+#define tigetstr p_tigetstr
+#define tigetnum p_tigetnum
+#define tparm p_tparm
+
+struct dbkey_descr
+{
+ enum dbkey_kind {dbk_simple, dbk_complex} kind;
+ DWORD_PTR p1;
+ DWORD_PTR p2;
+ DWORD_PTR p3;
+};
+
+struct dbkey_init
+{
+ const char* string_normal;
+ const char* string_xterm;
+ struct dbkey_descr descr;
+};
+
+static struct dbkey_init TERM_dbkey_init[] = {
+ {"kcud1", "kDN", {dbk_complex, 0x50, 0x28, 0}},
+ {"kcuu1", "kUP", {dbk_complex, 0x48, 0x26, 0}},
+ {"kcub1", "kLFT", {dbk_complex, 0x4b, 0x25, 0}},
+ {"kcuf1", "kRIT", {dbk_complex, 0x4d, 0x27, 0}},
+ {"khome", "kHOM", {dbk_complex, 0x47, 0x24, 0}},
+ {"kbs", NULL, {dbk_simple, 0x7f, 0x00, 0}},
+ {"kf1", NULL, {dbk_complex, 0x3b, 0x70, 0}},
+ {"kf2", NULL, {dbk_complex, 0x3c, 0x71, 0}},
+ {"kf3", NULL, {dbk_complex, 0x3d, 0x72, 0}},
+ {"kf4", NULL, {dbk_complex, 0x3e, 0x73, 0}},
+ {"kf5", NULL, {dbk_complex, 0x3f, 0x74, 0}},
+ {"kf6", NULL, {dbk_complex, 0x40, 0x75, 0}},
+ {"kf7", NULL, {dbk_complex, 0x41, 0x76, 0}},
+ {"kf8", NULL, {dbk_complex, 0x42, 0x77, 0}},
+ {"kf9", NULL, {dbk_complex, 0x43, 0x78, 0}},
+ {"kf10", NULL, {dbk_complex, 0x44, 0x79, 0}},
+ {"kf11", NULL, {dbk_complex, 0xd9, 0x7a, 0}},
+ {"kf12", NULL, {dbk_complex, 0xda, 0x7b, 0}},
+ {"kf13", NULL, {dbk_complex, 0x3b, 0x70, SHIFT_PRESSED}},
+ {"kf14", NULL, {dbk_complex, 0x3c, 0x71, SHIFT_PRESSED}},
+ {"kf15", NULL, {dbk_complex, 0x3d, 0x72, SHIFT_PRESSED}},
+ {"kf16", NULL, {dbk_complex, 0x3e, 0x73, SHIFT_PRESSED}},
+ {"kf17", NULL, {dbk_complex, 0x3f, 0x74, SHIFT_PRESSED}},
+ {"kf18", NULL, {dbk_complex, 0x40, 0x75, SHIFT_PRESSED}},
+ {"kf19", NULL, {dbk_complex, 0x41, 0x76, SHIFT_PRESSED}},
+ {"kf20", NULL, {dbk_complex, 0x42, 0x77, SHIFT_PRESSED}},
+ {"kf21", NULL, {dbk_complex, 0x43, 0x78, SHIFT_PRESSED}},
+ {"kf22", NULL, {dbk_complex, 0x44, 0x79, SHIFT_PRESSED}},
+ {"kf23", NULL, {dbk_complex, 0xd9, 0x7a, SHIFT_PRESSED}},
+ {"kf24", NULL, {dbk_complex, 0xda, 0x7b, SHIFT_PRESSED}},
+ {"kf25", NULL, {dbk_complex, 0x3b, 0x70, LEFT_CTRL_PRESSED}},
+ {"kf26", NULL, {dbk_complex, 0x3c, 0x71, LEFT_CTRL_PRESSED}},
+ {"kf27", NULL, {dbk_complex, 0x3d, 0x72, LEFT_CTRL_PRESSED}},
+ {"kf28", NULL, {dbk_complex, 0x3e, 0x73, LEFT_CTRL_PRESSED}},
+ {"kf29", NULL, {dbk_complex, 0x3f, 0x74, LEFT_CTRL_PRESSED}},
+ {"kf30", NULL, {dbk_complex, 0x40, 0x75, LEFT_CTRL_PRESSED}},
+ {"kf31", NULL, {dbk_complex, 0x41, 0x76, LEFT_CTRL_PRESSED}},
+ {"kf32", NULL, {dbk_complex, 0x42, 0x77, LEFT_CTRL_PRESSED}},
+ {"kf33", NULL, {dbk_complex, 0x43, 0x78, LEFT_CTRL_PRESSED}},
+ {"kf34", NULL, {dbk_complex, 0x44, 0x79, LEFT_CTRL_PRESSED}},
+ {"kf35", NULL, {dbk_complex, 0xd9, 0x7a, LEFT_CTRL_PRESSED}},
+ {"kf36", NULL, {dbk_complex, 0xda, 0x7b, LEFT_CTRL_PRESSED}},
+ {"kf37", NULL, {dbk_complex, 0x3b, 0x70, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf38", NULL, {dbk_complex, 0x3c, 0x71, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf39", NULL, {dbk_complex, 0x3d, 0x72, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf40", NULL, {dbk_complex, 0x3e, 0x73, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf41", NULL, {dbk_complex, 0x3f, 0x74, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf42", NULL, {dbk_complex, 0x40, 0x75, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf43", NULL, {dbk_complex, 0x41, 0x76, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf44", NULL, {dbk_complex, 0x42, 0x77, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf45", NULL, {dbk_complex, 0x43, 0x78, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf46", NULL, {dbk_complex, 0x44, 0x79, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf47", NULL, {dbk_complex, 0xd9, 0x7a, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf48", NULL, {dbk_complex, 0xda, 0x7b, LEFT_CTRL_PRESSED|SHIFT_PRESSED}},
+ {"kf49", NULL, {dbk_complex, 0x3b, 0x70, LEFT_ALT_PRESSED}},
+ {"kf50", NULL, {dbk_complex, 0x3c, 0x71, LEFT_ALT_PRESSED}},
+ {"kf51", NULL, {dbk_complex, 0x3d, 0x72, LEFT_ALT_PRESSED}},
+ {"kf52", NULL, {dbk_complex, 0x3e, 0x73, LEFT_ALT_PRESSED}},
+ {"kf53", NULL, {dbk_complex, 0x3f, 0x74, LEFT_ALT_PRESSED}},
+ {"kf54", NULL, {dbk_complex, 0x40, 0x75, LEFT_ALT_PRESSED}},
+ {"kf55", NULL, {dbk_complex, 0x41, 0x76, LEFT_ALT_PRESSED}},
+ {"kf56", NULL, {dbk_complex, 0x42, 0x77, LEFT_ALT_PRESSED}},
+ {"kf57", NULL, {dbk_complex, 0x43, 0x78, LEFT_ALT_PRESSED}},
+ {"kf58", NULL, {dbk_complex, 0x44, 0x79, LEFT_ALT_PRESSED}},
+ {"kf59", NULL, {dbk_complex, 0xd9, 0x7a, LEFT_ALT_PRESSED}},
+ {"kf60", NULL, {dbk_complex, 0xda, 0x7b, LEFT_ALT_PRESSED}},
+ {"kf61", NULL, {dbk_complex, 0x3b, 0x70, LEFT_ALT_PRESSED|SHIFT_PRESSED}},
+ {"kf62", NULL, {dbk_complex, 0x3c, 0x71, LEFT_ALT_PRESSED|SHIFT_PRESSED}},
+ {"kf63", NULL, {dbk_complex, 0x3d, 0x72, LEFT_ALT_PRESSED|SHIFT_PRESSED}},
+
+ {"kdch1", "kDC", {dbk_complex, 0x53, 0x2e, 0}},
+ {"kich1", "kIC", {dbk_complex, 0x52, 0x2d, 0}},
+ {"knp", "kNXT", {dbk_complex, 0x51, 0x22, 0}},
+ {"kpp", "kPRV", {dbk_complex, 0x49, 0x21, 0}},
+ {"kcbt", NULL, {dbk_simple, 0x09, 0x00, SHIFT_PRESSED}},
+ {"kend", "kEND", {dbk_complex, 0x4f, 0x23, 0}},
+
+ /* {"kmous", NULL, }, */
+ /* Still some keys to manage:
+ KEY_DL KEY_IL KEY_EIC KEY_CLEAR KEY_EOS
+ KEY_EOL KEY_SF KEY_SR KEY_STAB KEY_CTAB
+ KEY_CATAB KEY_ENTER KEY_SRESET KEY_RESET KEY_PRINT
+ KEY_LL KEY_A1 KEY_A3 KEY_B2 KEY_C1
+ KEY_C3 KEY_BEG KEY_CANCEL KEY_CLOSE KEY_COMMAND
+ KEY_COPY KEY_CREATE KEY_EXIT KEY_FIND KEY_HELP
+ KEY_MARK KEY_MESSAGE KEY_MOVE KEY_NEXT KEY_OPEN
+ KEY_OPTIONS KEY_PREVIOUS KEY_REDO KEY_REFERENCE KEY_REFRESH
+ KEY_REPLACE KEY_RESTART KEY_RESUME KEY_SAVE KEY_SBEG
+ KEY_SCANCEL KEY_SCOMMAND KEY_SCOPY KEY_SCREATE KEY_RESIZE
+ KEY_SDL KEY_SELECT KEY_SEOL KEY_SEXIT KEY_SFIND
+ KEY_SHELP KEY_SMESSAGE KEY_SMOVE KEY_SNEXT KEY_SOPTIONS
+ KEY_SPREVIOUS KEY_SPRINT KEY_SREDO KEY_SREPLACE KEY_SRSUME
+ KEY_SSAVE KEY_SSUSPEND KEY_SUNDO KEY_SUSPEND KEY_UNDO
+ */
+};
+
+struct dbkey_pair
+{
+ const char* string;
+ unsigned string_len;
+ struct dbkey_descr descr;
+};
+
+static struct dbkey_pair* TERM_dbkey;
+static unsigned TERM_dbkey_size;
+static unsigned TERM_dbkey_index;
+
+static int TERM_dbkey_cmp(const void* p1, const void* p2)
+{
+ const struct dbkey_pair* kp1 = p1;
+ const struct dbkey_pair* kp2 = p2;
+ return strcmp(kp1->string, kp2->string);
+}
+
+static BOOL TERM_AddKeyDescr(const char* string, struct dbkey_descr* descr)
+{
+ if (!string || string == (const char*)-1) return TRUE;
+ if (!TERM_dbkey)
+ {
+ TERM_dbkey_size = 32;
+ TERM_dbkey = HeapAlloc(GetProcessHeap(), 0, TERM_dbkey_size * sizeof(struct dbkey_pair));
+ if (!TERM_dbkey) return FALSE;
+ }
+ if (TERM_dbkey_index == TERM_dbkey_size)
+ {
+ struct dbkey_pair* new;
+
+ new = HeapReAlloc(GetProcessHeap(), 0, TERM_dbkey, (2 * TERM_dbkey_size) * sizeof(struct dbkey_pair));
+ if (!new) return FALSE;
+ TERM_dbkey = new;
+ TERM_dbkey_size *= 2;
+ }
+ TERM_dbkey[TERM_dbkey_index].string = string;
+ TERM_dbkey[TERM_dbkey_index].string_len = strlen(string);
+ TERM_dbkey[TERM_dbkey_index].descr = *descr;
+ TERM_dbkey_index++;
+ return TRUE;
+}
+
+static BOOL TERM_BuildKeyDB(void)
+{
+ unsigned i, j, len;
+ struct dbkey_descr descr;
+ char tmp[64];
+
+ for (i = 0; i < sizeof(TERM_dbkey_init) / sizeof(TERM_dbkey_init[0]); i++)
+ {
+ if (!TERM_AddKeyDescr(tigetstr((char *)TERM_dbkey_init[i].string_normal), &TERM_dbkey_init[i].descr))
+ return FALSE;
+ if (TERM_dbkey_init[i].string_xterm)
+ {
+ descr = TERM_dbkey_init[i].descr;
+ strcpy(tmp, TERM_dbkey_init[i].string_xterm);
+ len = strlen(tmp);
+ tmp[len + 1] = '\0';
+#define X(v, f) do { tmp[len] = v; descr.p3 = (f); if (!TERM_AddKeyDescr(tigetstr(tmp), &descr)) return FALSE; } while (0)
+ X('\0', SHIFT_PRESSED);
+ X('3', LEFT_ALT_PRESSED);
+ X('4', SHIFT_PRESSED | LEFT_ALT_PRESSED);
+ X('5', LEFT_CTRL_PRESSED);
+ X('6', LEFT_CTRL_PRESSED|SHIFT_PRESSED);
+ X('7', LEFT_CTRL_PRESSED|LEFT_ALT_PRESSED);
+ X('8', LEFT_CTRL_PRESSED|LEFT_ALT_PRESSED|SHIFT_PRESSED);
+#undef X
+ }
+ }
+ for (i = 0; i < TERM_dbkey_index; i++)
+ {
+ for (j = 0; j < TERM_dbkey_index; j++)
+ {
+ if (i != j &&
+ TERM_dbkey[i].string_len >= TERM_dbkey[j].string_len &&
+ !memcmp(TERM_dbkey[i].string, TERM_dbkey[j].string, TERM_dbkey[j].string_len))
+ FIXME("substring %d/%s %d/%s\n", i, TERM_dbkey[i].string, j, TERM_dbkey[j].string);
+ }
+ }
+ qsort(TERM_dbkey, TERM_dbkey_index, sizeof(TERM_dbkey[0]), TERM_dbkey_cmp);
+ WINE_TRACE("loaded %d keys\n", TERM_dbkey_index);
+ return TRUE;
+}
+
+static BOOL TERM_init_done /* = FALSE */;
+
+static BOOL TERM_Init(void)
+{
+ /* if we're not attached to a tty, don't fire the curses support */
+ if (!isatty(0) && !isatty(1) && !isatty(2)) return FALSE;
+ if (!getenv("TERM")) return FALSE;
+ if (TERM_bind_libcurses())
+ {
+ if (setupterm(NULL, 1 /* really ?? */, NULL) == -1) return FALSE;
+ TERM_init_done = TRUE;
+ TERM_BuildKeyDB();
+ /* set application key mode */
+ tputs(tigetstr((char *)"smkx"), 1, putchar);
+ }
+ return TRUE;
+}
+
+static BOOL TERM_Exit(void)
+{
+ if (TERM_init_done)
+ {
+ /* put back the cursor key mode */
+ tputs(tigetstr((char *)"rmkx"), 1, putchar);
+ }
+ return TRUE;
+}
+
+/* -1 not found, 0 cannot decide, > 0 found */
+static int TERM_FillInputRecord(const char* in, size_t len, INPUT_RECORD* ir)
+{
+ int low = 0, high = TERM_dbkey_index - 1, mid, res;
+ struct dbkey_descr* found;
+
+ while (low <= high)
+ {
+ mid = low + (high - low) / 2;
+ res = memcmp(in, TERM_dbkey[mid].string, len);
+ if (!res)
+ {
+ if (len < TERM_dbkey[mid].string_len) return 0;
+ found = &TERM_dbkey[mid].descr;
+ switch (found->kind)
+ {
+ case dbk_simple:
+ return WCLINE_FillSimpleChar(ir, found->p1);
+ case dbk_complex:
+ init_complex_char(&ir[0], 1, found->p1, found->p2, ENHANCED_KEY | found->p3);
+ init_complex_char(&ir[1], 0, found->p1, found->p2, ENHANCED_KEY | found->p3);
+ return 2;
+ }
+ return -1;
+ }
+ else if (res < 0) high = mid - 1;
+ else low = mid + 1;
+ }
+ return -1;
+}
+
+#else
+static BOOL TERM_Init(void) {return FALSE;}
+static BOOL TERM_Exit(void) {return FALSE;}
+static int TERM_FillInputRecord(const char* in, size_t len, INPUT_RECORD* ir) {return -1;}
+#endif
+
/******************************************************************
* WCLINE_ResizeScreenBuffer
*
@@ -201,6 +520,8 @@ static void WCLINE_SetFont(struct inner_data* data, const WCHAR* font,
*/
static void WCLINE_Resize(struct inner_data* data)
{
+ WINECON_ResizeWithContainer(data,
+ tigetnum((char*)"cols"), tigetnum((char*)"lines"));
}
/******************************************************************
@@ -209,11 +530,12 @@ static void WCLINE_Resize(struct inner_data* data)
static DWORD CALLBACK input_thread(void *arg)
{
struct inner_data* data = arg;
- int inchar;
+ char input[8];
INPUT_RECORD ir[8];
unsigned numEvent;
- DWORD n;
+ DWORD n, timeout = -1;
struct pollfd pfd[2];
+ size_t i, idx = 0;
pfd[0].fd = 0;
pfd[0].events = POLLIN;
@@ -223,21 +545,50 @@ static DWORD CALLBACK input_thread(void *arg)
for (;;)
{
pfd[0].revents = pfd[1].revents = 0;
- if (poll(pfd, 2, -1) == -1) break;
+ if (poll(pfd, 2, timeout) == -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)
+ if ((input[idx] = fgetc(stdin)) == -1)
{
- WINE_TRACE("Got o%o (0x%x)\n", inchar, inchar);
+ LeaveCriticalSection(&PRIVATE(data)->lock);
+ break;
+ }
- numEvent = WCLINE_FillSimpleChar(ir, inchar);
+ do
+ {
+ idx++;
+ numEvent = TERM_FillInputRecord(input, idx, ir);
+ } while (numEvent == 0 && (input[idx] = fgetc(stdin)) != -1);
+ /* FIXME stdin/0 should be made non blocking */
- if (numEvent) WriteConsoleInputW(data->hConIn, ir, numEvent, &n);
+ switch (numEvent)
+ {
+ case 0:
+ if (timeout != 500)
+ {
+ /* we need more char(s) to tell if it matches a key-db entry. wait 1/2s for next char */
+ timeout = 500;
+ LeaveCriticalSection(&PRIVATE(data)->lock);
+ continue;
+ }
+ /* fall through... don't wait too long and push keys */
+ case -1:
+ /* we haven't found the string into key-db, push full input string into server */
+ for (i = 0; i < idx; i++)
+ {
+ numEvent = WCLINE_FillSimpleChar(ir, input[i]);
+ WriteConsoleInputW(data->hConIn, ir, numEvent, &n);
+ }
+ break;
+ default:
+ /* we got a transformation from key-db... push this into server */
+ WriteConsoleInputW(data->hConIn, ir, numEvent, &n);
}
+ idx = 0;
+ timeout = -1;
LeaveCriticalSection(&PRIVATE(data)->lock);
}
close(PRIVATE(data)->sync_pipe[0]);
@@ -278,6 +629,7 @@ static int WCLINE_MainLoop(struct inner_data* data)
DWORD id;
struct termios term;
+ if (!TERM_Init()) return 0;
WCLINE_Resize(data);
if (pipe(PRIVATE(data)->sync_pipe) == -1) return 0;
@@ -305,6 +657,7 @@ static int WCLINE_MainLoop(struct inner_data* data)
WaitForSingleObject(PRIVATE(data)->input_thread, INFINITE);
CloseHandle(PRIVATE(data)->input_thread);
PRIVATE(data)->input_thread = 0;
+ TERM_Exit();
return 0;
}
diff --git a/programs/wineconsole/registry.c b/programs/wineconsole/registry.c
index 2805f2a..6bfb721 100644
--- a/programs/wineconsole/registry.c
+++ b/programs/wineconsole/registry.c
@@ -49,7 +49,7 @@ static const WCHAR wszWindowSize[] = {'W','i','n','d','o','w','S','i','z'
void WINECON_DumpConfig(const char* pfx, const struct config_data* cfg)
{
WINE_TRACE("%s cell=(%u,%u) cursor=(%d,%d) attr=%02x font=%s/%u hist=%u/%d flags=%c%c msk=%08x sb=(%u,%u) win=(%u,%u)x(%u,%u) edit=%u registry=%s\n",
- pfx, cfg->cell_width, cfg->cell_height, cfg->cursor_size, cfg->cursor_visible, cfg->def_attr,
+ pfx, cfg->cell_width, cfg->cell_height, cfg->cursor_size, cfg->cursor_is_visible, cfg->def_attr,
wine_dbgstr_w(cfg->face_name), cfg->font_weight, cfg->history_size, cfg->history_nodup ? 1 : 2,
cfg->quick_edit ? 'Q' : 'q', cfg->exit_on_die ? 'X' : 'x',
cfg->menu_mask, cfg->sb_width, cfg->sb_height, cfg->win_pos.X, cfg->win_pos.Y, cfg->win_width, cfg->win_height,
@@ -93,7 +93,7 @@ static void WINECON_RegLoadHelper(HKEY hConKey, struct config_data* cfg)
count = sizeof(val);
if (!RegQueryValueExW(hConKey, wszCursorVisible, 0, &type, (LPBYTE)&val, &count))
- cfg->cursor_visible = val;
+ cfg->cursor_is_visible = val;
count = sizeof(val);
if (!RegQueryValueExW(hConKey, wszEditionMode, 0, &type, (LPBYTE)&val, &count))
@@ -167,7 +167,7 @@ void WINECON_RegLoad(const WCHAR* appname, struct config_data* cfg)
/* first set default values */
cfg->cursor_size = 25;
- cfg->cursor_visible = 1;
+ cfg->cursor_is_visible = 1;
cfg->exit_on_die = 1;
memset(cfg->face_name, 0, sizeof(cfg->face_name));
cfg->cell_height = 12;
@@ -222,7 +222,7 @@ static void WINECON_RegSaveHelper(HKEY hConKey, const struct config_data* cfg)
val = cfg->cursor_size;
RegSetValueExW(hConKey, wszCursorSize, 0, REG_DWORD, (LPBYTE)&val, sizeof(val));
- val = cfg->cursor_visible;
+ val = cfg->cursor_is_visible;
RegSetValueExW(hConKey, wszCursorVisible, 0, REG_DWORD, (LPBYTE)&val, sizeof(val));
val = cfg->edition_mode;
diff --git a/programs/wineconsole/user.c b/programs/wineconsole/user.c
index 9b8ad15..92e02c0 100644
--- a/programs/wineconsole/user.c
+++ b/programs/wineconsole/user.c
@@ -147,7 +147,7 @@ static void WCUSER_ResizeScreenBuffer(struct inner_data* data)
*/
static void WCUSER_PosCursor(const struct inner_data* data)
{
- if (data->hWnd != GetFocus() || !data->curcfg.cursor_visible) return;
+ if (data->hWnd != GetFocus() || !data->curcfg.cursor_is_visible) return;
SetCaretPos((data->cursor.X - data->curcfg.win_pos.X) * data->curcfg.cell_width,
(data->cursor.Y - data->curcfg.win_pos.Y) * data->curcfg.cell_height);
@@ -163,7 +163,7 @@ static void WCUSER_ShapeCursor(struct inner_data* data, int size, int vis, BOOL
{
if (force || size != data->curcfg.cursor_size)
{
- if (data->curcfg.cursor_visible && data->hWnd == GetFocus()) DestroyCaret();
+ if (data->curcfg.cursor_is_visible && data->hWnd == GetFocus()) DestroyCaret();
if (PRIVATE(data)->cursor_bitmap) DeleteObject(PRIVATE(data)->cursor_bitmap);
PRIVATE(data)->cursor_bitmap = NULL;
if (size != 100)
@@ -188,13 +188,13 @@ static void WCUSER_ShapeCursor(struct inner_data* data, int size, int vis, BOOL
HeapFree(GetProcessHeap(), 0, ptr);
}
data->curcfg.cursor_size = size;
- data->curcfg.cursor_visible = -1;
+ data->curcfg.cursor_is_visible = -1;
}
vis = vis != 0;
- if (force || vis != data->curcfg.cursor_visible)
+ if (force || vis != data->curcfg.cursor_is_visible)
{
- data->curcfg.cursor_visible = vis;
+ data->curcfg.cursor_is_visible = vis;
if (data->hWnd == GetFocus())
{
if (vis)
@@ -260,7 +260,7 @@ static void WCUSER_ComputePositions(struct inner_data* data)
SetWindowPos(data->hWnd, 0, 0, 0, r.right - r.left + dx, r.bottom - r.top + dy,
SWP_NOMOVE|SWP_NOZORDER);
- WCUSER_ShapeCursor(data, data->curcfg.cursor_size, data->curcfg.cursor_visible, TRUE);
+ WCUSER_ShapeCursor(data, data->curcfg.cursor_size, data->curcfg.cursor_is_visible, TRUE);
WCUSER_PosCursor(data);
}
@@ -615,12 +615,12 @@ static void WCUSER_SetSelection(const struct inner_data* data, HDC hRefDC)
hDC = hRefDC ? hRefDC : GetDC(data->hWnd);
if (hDC)
{
- if (data->hWnd == GetFocus() && data->curcfg.cursor_visible)
+ if (data->hWnd == GetFocus() && data->curcfg.cursor_is_visible)
HideCaret(data->hWnd);
InvertRect(hDC, &r);
if (hDC != hRefDC)
ReleaseDC(data->hWnd, hDC);
- if (data->hWnd == GetFocus() && data->curcfg.cursor_visible)
+ if (data->hWnd == GetFocus() && data->curcfg.cursor_is_visible)
ShowCaret(data->hWnd);
}
}
@@ -645,7 +645,7 @@ static void WCUSER_MoveSelection(struct inner_data* data, COORD c1, COORD c2)
hDC = GetDC(data->hWnd);
if (hDC)
{
- if (data->hWnd == GetFocus() && data->curcfg.cursor_visible)
+ if (data->hWnd == GetFocus() && data->curcfg.cursor_is_visible)
HideCaret(data->hWnd);
InvertRect(hDC, &r);
}
@@ -656,7 +656,7 @@ static void WCUSER_MoveSelection(struct inner_data* data, COORD c1, COORD c2)
WCUSER_GetSelectionRect(data, &r);
InvertRect(hDC, &r);
ReleaseDC(data->hWnd, hDC);
- if (data->hWnd == GetFocus() && data->curcfg.cursor_visible)
+ if (data->hWnd == GetFocus() && data->curcfg.cursor_is_visible)
ShowCaret(data->hWnd);
}
}
@@ -1203,7 +1203,7 @@ static LRESULT CALLBACK WCUSER_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
WCUSER_GenerateMouseInputRecord(data, WCUSER_GetCell(data, lParam), wParam, DOUBLE_CLICK);
break;
case WM_SETFOCUS:
- if (data->curcfg.cursor_visible)
+ if (data->curcfg.cursor_is_visible)
{
CreateCaret(data->hWnd, PRIVATE(data)->cursor_bitmap,
data->curcfg.cell_width, data->curcfg.cell_height);
@@ -1211,7 +1211,7 @@ static LRESULT CALLBACK WCUSER_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
}
break;
case WM_KILLFOCUS:
- if (data->curcfg.cursor_visible)
+ if (data->curcfg.cursor_is_visible)
DestroyCaret();
break;
case WM_HSCROLL:
diff --git a/programs/wineconsole/winecon_private.h b/programs/wineconsole/winecon_private.h
index 7c492d6..ff3fbd9 100644
--- a/programs/wineconsole/winecon_private.h
+++ b/programs/wineconsole/winecon_private.h
@@ -30,7 +30,7 @@ struct config_data {
unsigned cell_width; /* width in pixels of a character */
unsigned cell_height; /* height in pixels of a character */
int cursor_size; /* in % of cell height */
- int cursor_visible;
+ int cursor_is_visible;
DWORD def_attr;
WCHAR face_name[32]; /* name of font (size is LF_FACESIZE) */
DWORD font_weight;
@@ -114,3 +114,6 @@ static inline void init_complex_char(INPUT_RECORD* ir, BOOL down, WORD vk, WORD
ir->Event.KeyEvent.dwControlKeyState = cks;
ir->Event.KeyEvent.uChar.UnicodeChar = 0;
}
+
+extern BOOL bind_libcurses(void);
+extern void* load_curses_func(const char* fn);
diff --git a/programs/wineconsole/wineconsole.c b/programs/wineconsole/wineconsole.c
index e6e599a..ffd32c9 100644
--- a/programs/wineconsole/wineconsole.c
+++ b/programs/wineconsole/wineconsole.c
@@ -320,7 +320,7 @@ void WINECON_GrabChanges(struct inner_data* data)
break;
case CONSOLE_RENDERER_CURSOR_GEOM_EVENT:
if (evts[i].u.cursor_geom.size != data->curcfg.cursor_size ||
- evts[i].u.cursor_geom.visible != data->curcfg.cursor_visible)
+ evts[i].u.cursor_geom.visible != data->curcfg.cursor_is_visible)
{
WINE_TRACE("%u/%u: curs-geom(%d,%d)\n", i+1, num,
evts[i].u.cursor_geom.size, evts[i].u.cursor_geom.visible);
@@ -373,17 +373,17 @@ void WINECON_SetConfig(struct inner_data* data, const struct config_data* cf
if (data->in_set_config) return;
data->in_set_config = TRUE;
if (data->curcfg.cursor_size != cfg->cursor_size ||
- data->curcfg.cursor_visible != cfg->cursor_visible)
+ data->curcfg.cursor_is_visible != cfg->cursor_is_visible)
{
CONSOLE_CURSOR_INFO cinfo;
cinfo.dwSize = cfg->cursor_size;
/* <FIXME>: this hack is needed to pass through the invariant test operation on the server side
* (no notification is sent when invariant operation is requested)
*/
- cinfo.bVisible = !cfg->cursor_visible;
+ cinfo.bVisible = !cfg->cursor_is_visible;
SetConsoleCursorInfo(data->hConOut, &cinfo);
/* </FIXME> */
- cinfo.bVisible = cfg->cursor_visible;
+ cinfo.bVisible = cfg->cursor_is_visible;
/* this shall update (through notif) curcfg */
SetConsoleCursorInfo(data->hConOut, &cinfo);
}
@@ -549,7 +549,7 @@ static BOOL WINECON_GetServerConfig(struct inner_data* data)
req->handle = wine_server_obj_handle( data->hConOut );
ret = !wine_server_call_err( req );
data->curcfg.cursor_size = reply->cursor_size;
- data->curcfg.cursor_visible = reply->cursor_visible;
+ data->curcfg.cursor_is_visible = reply->cursor_visible;
data->curcfg.def_attr = reply->attr;
data->curcfg.sb_width = reply->width;
data->curcfg.sb_height = reply->height;
More information about the wine-patches
mailing list