]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/win32con/win_driver.c
ncurses 5.9 - patch 20120310
[ncurses.git] / ncurses / win32con / win_driver.c
index 78cd8f5089d3c640a5f639f0fbdf64b86137bcbb..9122513ab5b06a26e965daa4bd552e3c541111f5 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2010,2012 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
 
 /****************************************************************************
  *  Author: Juergen Pfeifer                                                 *
- *                                                                          *
  ****************************************************************************/
 
+/*
+ * TODO - GetMousePos(POINT * result) from ntconio.c
+ * TODO - implement nodelay
+ */
+
 #include <curses.priv.h>
+#define CUR my_term.type.
 
-MODULE_ID("$Id: win_driver.c,v 1.5 2010/01/16 22:42:30 tom Exp $")
+MODULE_ID("$Id: win_driver.c,v 1.11 2012/02/18 20:28:25 tom Exp $")
 
 #define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
 
 #define AssertTCB() assert(TCB!=0 && TCB->magic==WINMAGIC)
-#define SetSP() assert(TCB->csp!=0); sp = TCB->csp
+#define SetSP() assert(TCB->csp!=0); sp = TCB->csp; (void) sp
 
 #define GenMap(vKey,key) MAKELONG(key, vKey)
 
@@ -105,7 +110,7 @@ MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, chtype ch)
 
        AssertTCB();
        SetSP();
-       p = PAIR_NUMBER(ch);
+       p = PairNumber(ch);
        if (p > 0 && p < NUMPAIRS && TCB != 0 && sp != 0) {
            WORD a;
            a = PropOf(TCB)->pairs[p];
@@ -257,14 +262,41 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
 {
     bool code = FALSE;
 
-    T((T_CALLED("drv_CanHandle(%p)"), TCB));
+    T((T_CALLED("win32con::drv_CanHandle(%p)"), TCB));
 
     assert(TCB != 0);
     assert(tname != 0);
 
     TCB->magic = WINMAGIC;
-    if (*tname == 0 || *tname == 0 || strcmp(tname, "unknown") == 0) {
+    if (*tname == 0 || *tname == 0) {
        code = TRUE;
+    } else {
+       TERMINAL my_term;
+       int status;
+
+       code = FALSE;
+#if (USE_DATABASE || USE_TERMCAP)
+       status = _nc_setup_tinfo(tname, &my_term.type);
+#else
+       status = TGETENT_NO;
+#endif
+       if (status != TGETENT_YES) {
+           const TERMTYPE *fallback = _nc_fallback(tname);
+
+           if (fallback) {
+               my_term.type = *fallback;
+               status = TGETENT_YES;
+           } else if (!strcmp(tname, "unknown")) {
+               code = TRUE;
+           }
+       }
+       if (status == TGETENT_YES) {
+           if (generic_type || hard_copy)
+               code = TRUE;
+       }
+    }
+
+    if (code) {
        if ((TCB->term.type.Booleans) == 0) {
            _nc_init_entry(&(TCB->term.type));
        }
@@ -275,7 +307,7 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
 
 static int
 drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
-               bool beepFlag GCC_UNUSED)
+               int beepFlag GCC_UNUSED)
 {
     SCREEN *sp;
     int res = ERR;
@@ -315,7 +347,7 @@ drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
 
 static void
 drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
-            bool fore,
+            int fore,
             int color,
             int (*outc) (SCREEN *, int) GCC_UNUSED)
 {
@@ -379,7 +411,7 @@ drv_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
 }
 
 static int
-drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool setFlag, TTY * buf)
+drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
 {
     DWORD dwFlag = 0;
     tcflag_t iflag;
@@ -411,8 +443,7 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool setFlag, TTY * buf)
        else
            dwFlag &= ~ENABLE_PROCESSED_INPUT;
 
-       /* we disable that for now to focus on keyboard. */
-       dwFlag &= ~ENABLE_MOUSE_INPUT;
+       dwFlag |= ENABLE_MOUSE_INPUT;
 
        buf->c_iflag = iflag;
        buf->c_lflag = lflag;
@@ -447,7 +478,7 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool setFlag, TTY * buf)
 }
 
 static int
-drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag)
+drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
 {
     SCREEN *sp;
     TERMINAL *_term = (TERMINAL *) TCB;
@@ -552,7 +583,7 @@ MapKey(TERMINAL_CONTROL_BLOCK * TCB, WORD vKey)
 static void
 drv_release(TERMINAL_CONTROL_BLOCK * TCB)
 {
-    T((T_CALLED("drv_release(%p)"), TCB));
+    T((T_CALLED("win32con::drv_release(%p)"), TCB));
 
     AssertTCB();
     if (TCB->prop)
@@ -564,7 +595,9 @@ drv_release(TERMINAL_CONTROL_BLOCK * TCB)
 static void
 drv_init(TERMINAL_CONTROL_BLOCK * TCB)
 {
-    T((T_CALLED("drv_init(%p)"), TCB));
+    DWORD num_buttons;
+
+    T((T_CALLED("win32con::drv_init(%p)"), TCB));
 
     AssertTCB();
 
@@ -606,6 +639,13 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
        TCB->info.nocolorvideo = 1;
        TCB->info.tabsize = 8;
 
+       if (GetNumberOfConsoleMouseButtons(&num_buttons)) {
+           T(("mouse has %ld buttons", num_buttons));
+           TCB->info.numbuttons = num_buttons;
+       } else {
+           TCB->info.numbuttons = 1;
+       }
+
        TCB->info.defaultPalette = _nc_cga_palette;
 
        for (i = 0; i < (N_INI + FKEYS); i++) {
@@ -633,9 +673,9 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
 
 static void
 drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,
-            short pair,
-            short f,
-            short b)
+            int pair,
+            int f,
+            int b)
 {
     SCREEN *sp;
 
@@ -650,10 +690,10 @@ drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,
 
 static void
 drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
-             short color GCC_UNUSED,
-             short r GCC_UNUSED,
-             short g GCC_UNUSED,
-             short b GCC_UNUSED)
+             int color GCC_UNUSED,
+             int r GCC_UNUSED,
+             int g GCC_UNUSED,
+             int b GCC_UNUSED)
 {
     SCREEN *sp;
 
@@ -663,9 +703,9 @@ drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
 
 static void
 drv_do_color(TERMINAL_CONTROL_BLOCK * TCB,
-            short old_pair GCC_UNUSED,
-            short pair GCC_UNUSED,
-            bool reverse GCC_UNUSED,
+            int old_pair GCC_UNUSED,
+            int pair GCC_UNUSED,
+            int reverse GCC_UNUSED,
             int (*outc) (SCREEN *, int) GCC_UNUSED
 )
 {
@@ -682,6 +722,30 @@ drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
 
     AssertTCB();
     SetSP();
+
+    sp->_mouse_type = M_TERM_DRIVER;
+}
+
+static int
+drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
+{
+    int rc = 0;
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+
+    if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
+       rc = TW_MOUSE;
+    } else {
+       rc = TCBOf(sp)->drv->twait(TCBOf(sp),
+                                  TWAIT_MASK,
+                                  delay,
+                                  (int *) 0
+                                  EVENTLIST_2nd(evl));
+    }
+
+    return rc;
 }
 
 static int
@@ -713,7 +777,7 @@ drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
 
 static void
 drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
-                bool OnFlag GCC_UNUSED)
+                int OnFlag GCC_UNUSED)
 {
     SCREEN *sp;
 
@@ -812,6 +876,50 @@ Adjust(int milliseconds, int diff)
     return milliseconds;
 }
 
+#define BUTTON_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | \
+                    FROM_LEFT_2ND_BUTTON_PRESSED | \
+                    FROM_LEFT_3RD_BUTTON_PRESSED | \
+                    FROM_LEFT_4TH_BUTTON_PRESSED | \
+                    RIGHTMOST_BUTTON_PRESSED)
+
+static int
+decode_mouse(TERMINAL_CONTROL_BLOCK * TCB, int mask)
+{
+    SCREEN *sp;
+    int result = 0;
+
+    AssertTCB();
+    SetSP();
+
+    if (mask & FROM_LEFT_1ST_BUTTON_PRESSED)
+       result |= BUTTON1_PRESSED;
+    if (mask & FROM_LEFT_2ND_BUTTON_PRESSED)
+       result |= BUTTON2_PRESSED;
+    if (mask & FROM_LEFT_3RD_BUTTON_PRESSED)
+       result |= BUTTON3_PRESSED;
+    if (mask & FROM_LEFT_4TH_BUTTON_PRESSED)
+       result |= BUTTON4_PRESSED;
+
+    if (mask & RIGHTMOST_BUTTON_PRESSED) {
+       switch (TCB->info.numbuttons) {
+       case 1:
+           result |= BUTTON1_PRESSED;
+           break;
+       case 2:
+           result |= BUTTON2_PRESSED;
+           break;
+       case 3:
+           result |= BUTTON3_PRESSED;
+           break;
+       case 4:
+           result |= BUTTON4_PRESSED;
+           break;
+       }
+    }
+
+    return result;
+}
+
 static int
 drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
          int mode,
@@ -820,7 +928,7 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
          EVENTLIST_2nd(_nc_eventlist * evl))
 {
     SCREEN *sp;
-    INPUT_RECORD inp;
+    INPUT_RECORD inp_rec;
     BOOL b;
     DWORD nRead = 0, rc = -1;
     int code = 0;
@@ -829,15 +937,18 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
     int diff;
     bool isImmed = (milliseconds == 0);
 
-#define CONSUME() ReadConsoleInput(TCB->inp,&inp,1,&nRead)
+#define CONSUME() ReadConsoleInput(TCB->inp,&inp_rec,1,&nRead)
 
     AssertTCB();
     SetSP();
 
+    TR(TRACE_IEVENT, ("start twait: %d milliseconds, mode: %d",
+                     milliseconds, mode));
+
     if (milliseconds < 0)
        milliseconds = INFINITY;
 
-    memset(&inp, 0, sizeof(inp));
+    memset(&inp_rec, 0, sizeof(inp_rec));
 
     while (true) {
        GetSystemTimeAsFileTime(&fstart);
@@ -853,15 +964,15 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
            if (mode) {
                b = GetNumberOfConsoleInputEvents(TCB->inp, &nRead);
                if (b && nRead > 0) {
-                   b = PeekConsoleInput(TCB->inp, &inp, 1, &nRead);
+                   b = PeekConsoleInput(TCB->inp, &inp_rec, 1, &nRead);
                    if (b && nRead > 0) {
-                       switch (inp.EventType) {
+                       switch (inp_rec.EventType) {
                        case KEY_EVENT:
                            if (mode & TW_INPUT) {
-                               WORD vk = inp.Event.KeyEvent.wVirtualKeyCode;
-                               char ch = inp.Event.KeyEvent.uChar.AsciiChar;
+                               WORD vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
+                               char ch = inp_rec.Event.KeyEvent.uChar.AsciiChar;
 
-                               if (inp.Event.KeyEvent.bKeyDown) {
+                               if (inp_rec.Event.KeyEvent.bKeyDown) {
                                    if (0 == ch) {
                                        int nKey = MapKey(TCB, vk);
                                        if ((nKey < 0) || FALSE == sp->_keypad_on) {
@@ -877,11 +988,15 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
                            }
                            continue;
                        case MOUSE_EVENT:
-                           if (0 && mode & TW_MOUSE) {
+                           if (decode_mouse(TCB,
+                                            (inp_rec.Event.MouseEvent.dwButtonState
+                                             & BUTTON_MASK)) == 0) {
+                               CONSUME();
+                           } else if (mode & TW_MOUSE) {
                                code = TW_MOUSE;
                                goto end;
-                           } else
-                               continue;
+                           }
+                           continue;
                        default:
                            SetConsoleActiveScreenBuffer(!PropOf(TCB)->progMode ?
                                                         TCB->hdl : TCB->out);
@@ -902,37 +1017,83 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
        }
     }
   end:
+
+    TR(TRACE_IEVENT, ("end twait: returned %d (%d), remaining time %d msec",
+                     code, errno, milliseconds));
+
     if (timeleft)
        *timeleft = milliseconds;
 
     return code;
 }
 
+static bool
+handle_mouse(TERMINAL_CONTROL_BLOCK * TCB, MOUSE_EVENT_RECORD mer)
+{
+    SCREEN *sp;
+    MEVENT work;
+    bool result = FALSE;
+
+    AssertTCB();
+    SetSP();
+
+    sp->_drv_mouse_old_buttons = sp->_drv_mouse_new_buttons;
+    sp->_drv_mouse_new_buttons = mer.dwButtonState & BUTTON_MASK;
+
+    /*
+     * We're only interested if the button is pressed or released.
+     * FIXME: implement continuous event-tracking.
+     */
+    if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) {
+
+       memset(&work, 0, sizeof(work));
+
+       if (sp->_drv_mouse_new_buttons) {
+
+           work.bstate |= decode_mouse(TCB, sp->_drv_mouse_new_buttons);
+
+       } else {
+
+           /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
+           work.bstate |= (decode_mouse(TCB, sp->_drv_mouse_old_buttons) >> 1);
+
+           result = TRUE;
+       }
+
+       work.x = mer.dwMousePosition.X;
+       work.y = mer.dwMousePosition.Y;
+
+       sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work;
+       sp->_drv_mouse_tail += 1;
+    }
+
+    return result;
+}
+
 static int
 drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
 {
     SCREEN *sp;
     int n = 1;
-    INPUT_RECORD inp;
+    INPUT_RECORD inp_rec;
     BOOL b;
     DWORD nRead;
     WORD vk;
-    WORD sc;
 
     AssertTCB();
     assert(buf);
     SetSP();
 
-    memset(&inp, 0, sizeof(inp));
+    memset(&inp_rec, 0, sizeof(inp_rec));
 
-    while ((b = ReadConsoleInput(TCB->inp, &inp, 1, &nRead))) {
+    T((T_CALLED("win32con::drv_read(%p)"), TCB));
+    while ((b = ReadConsoleInput(TCB->inp, &inp_rec, 1, &nRead))) {
        if (b && nRead > 0) {
-           if (inp.EventType == KEY_EVENT) {
-               if (!inp.Event.KeyEvent.bKeyDown)
+           if (inp_rec.EventType == KEY_EVENT) {
+               if (!inp_rec.Event.KeyEvent.bKeyDown)
                    continue;
-               *buf = (int) inp.Event.KeyEvent.uChar.AsciiChar;
-               vk = inp.Event.KeyEvent.wVirtualKeyCode;
-               sc = inp.Event.KeyEvent.wVirtualScanCode;
+               *buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
+               vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
                if (*buf == 0) {
                    if (sp->_keypad_on) {
                        *buf = MapKey(TCB, vk);
@@ -945,14 +1106,16 @@ drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
                } else {        /* *buf != 0 */
                    break;
                }
-           } else if (0 && inp.EventType == MOUSE_EVENT) {
-               *buf = KEY_MOUSE;
-               break;
+           } else if (inp_rec.EventType == MOUSE_EVENT) {
+               if (handle_mouse(TCB, inp_rec.Event.MouseEvent)) {
+                   *buf = KEY_MOUSE;
+                   break;
+               }
            }
            continue;
        }
     }
-    return n;
+    returnCode(n);
 }
 
 static int
@@ -991,7 +1154,7 @@ drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
 }
 
 static int
-drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, bool flag GCC_UNUSED)
+drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
 {
     SCREEN *sp;
     int code = ERR;
@@ -1006,7 +1169,7 @@ drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, bool flag GCC_UNUSED)
 }
 
 static int
-drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, bool flag)
+drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag)
 {
     int code = ERR;
     SCREEN *sp;
@@ -1054,6 +1217,7 @@ NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {
        drv_initcolor,          /* initcolor */
        drv_do_color,           /* docolor */
        drv_initmouse,          /* initmouse */
+       drv_testmouse,          /* testmouse */
        drv_setfilter,          /* setfilter */
        drv_hwlabel,            /* hwlabel */
        drv_hwlabelOnOff,       /* hwlabelOnOff */