[PATCH 3/5] [WineConsole]: in line mode, now support extended characters

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




A+
---

 programs/wineconsole/curses.c          |   47 ++--
 programs/wineconsole/line.c            |  367 +++++++++++++++++++++++++++++++-
 programs/wineconsole/registry.c        |    8 -
 programs/wineconsole/user.c            |   24 +-
 programs/wineconsole/winecon_private.h |    5 
 programs/wineconsole/wineconsole.c     |   10 -
 6 files changed, 412 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 2bc29ea..49f953b 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,310 @@ 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(putp)
+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(putp)
+    LOAD_FUNCPTR(setupterm)
+    LOAD_FUNCPTR(tigetstr)
+    LOAD_FUNCPTR(tigetnum)
+    LOAD_FUNCPTR(tparm)
+
+#undef LOAD_FUNCPTR
+
+    return TRUE;
+}
+
+#define putp      p_putp
+#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()) return FALSE;
+    if (setupterm(NULL, 1 /* really ?? */, NULL) == -1) return FALSE;
+    TERM_init_done = TRUE;
+    TERM_BuildKeyDB();
+    /* set application key mode */
+    putp(tigetstr((char *)"smkx"));
+    return TRUE;
+}
+
+static BOOL TERM_Exit(void)
+{
+    if (TERM_init_done)
+    {
+        /* put back the cursor key mode */
+        putp(tigetstr((char *)"rmkx"));
+    }
+    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
  *
@@ -214,6 +531,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"));
 }
 
 /******************************************************************
@@ -222,11 +541,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;
@@ -236,21 +556,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]);
@@ -291,6 +640,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;
@@ -323,6 +673,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..456e2f3 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;
 }
+
+BOOL    bind_libcurses(void);
+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