pdcurses/getch.c

changeset 97
2d43f05b284c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pdcurses/getch.c	Thu Jul 23 18:07:39 2015 +0300
@@ -0,0 +1,410 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: getch.c,v 1.72 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         getch
+
+  Synopsis:
+        int getch(void);
+        int wgetch(WINDOW *win);
+        int mvgetch(int y, int x);
+        int mvwgetch(WINDOW *win, int y, int x);
+        int ungetch(int ch);
+        int flushinp(void);
+
+        int get_wch(wint_t *wch);
+        int wget_wch(WINDOW *win, wint_t *wch);
+        int mvget_wch(int y, int x, wint_t *wch);
+        int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch);
+        int unget_wch(const wchar_t wch);
+
+        unsigned long PDC_get_key_modifiers(void);
+        int PDC_save_key_modifiers(bool flag);
+        int PDC_return_key_modifiers(bool flag);
+
+  Description:
+        With the getch(), wgetch(), mvgetch(), and mvwgetch() functions, 
+        a character is read from the terminal associated with the window. 
+        In nodelay mode, if there is no input waiting, the value ERR is 
+        returned. In delay mode, the program will hang until the system 
+        passes text through to the program. Depending on the setting of 
+        cbreak(), this will be after one character or after the first 
+        newline.  Unless noecho() has been set, the character will also 
+        be echoed into the designated window.
+
+        If keypad() is TRUE, and a function key is pressed, the token for
+        that function key will be returned instead of the raw characters.
+        Possible function keys are defined in <curses.h> with integers
+        beginning with 0401, whose names begin with KEY_.
+
+        If nodelay(win, TRUE) has been called on the window and no input
+        is waiting, the value ERR is returned.
+
+        ungetch() places ch back onto the input queue to be returned by 
+        the next call to wgetch().
+
+        flushinp() throws away any type-ahead that has been typed by the 
+        user and has not yet been read by the program.
+
+        PDC_get_key_modifiers() returns the keyboard modifiers (shift, 
+        control, alt, numlock) effective at the time of the last getch() 
+        call, if PDC_save_key_modifiers(TRUE) has been called before the 
+        getch(). Use the macros PDC_KEY_MODIFIER_* to determine which 
+        modifier(s) were set. PDC_return_key_modifiers() tells getch() 
+        to return modifier keys pressed alone as keystrokes (KEY_ALT_L, 
+        etc.). These may not work on all platforms.
+
+        NOTE: getch() and ungetch() are implemented as macros, to avoid 
+        conflict with many DOS compiler's runtime libraries.
+
+  Return Value:
+        These functions return ERR or the value of the character, meta 
+        character or function key token.
+
+  Portability                                X/Open    BSD    SYS V
+        getch                                   Y       Y       Y
+        wgetch                                  Y       Y       Y
+        mvgetch                                 Y       Y       Y
+        mvwgetch                                Y       Y       Y
+        ungetch                                 Y       Y       Y
+        flushinp                                Y       Y       Y
+        get_wch                                 Y
+        wget_wch                                Y
+        mvget_wch                               Y
+        mvwget_wch                              Y
+        unget_wch                               Y
+        PDC_get_key_modifiers                   -       -       -
+
+**man-end****************************************************************/
+
+#define _INBUFSIZ   512 /* size of terminal input buffer */
+#define NUNGETCH    256 /* max # chars to ungetch() */
+
+static int c_pindex = 0;    /* putter index */
+static int c_gindex = 1;    /* getter index */
+static int c_ungind = 0;    /* ungetch() push index */
+static int c_ungch[NUNGETCH];   /* array of ungotten chars */
+
+static int _mouse_key(WINDOW *win)
+{
+    int i, key = KEY_MOUSE;
+    unsigned long mbe = SP->_trap_mbe;
+
+    /* Filter unwanted mouse events */
+
+    for (i = 0; i < 3; i++)
+    {
+        if (pdc_mouse_status.changes & (1 << i))
+        {
+            int shf = i * 5;
+            short button = pdc_mouse_status.button[i] & BUTTON_ACTION_MASK;
+
+            if (   (!(mbe & (BUTTON1_PRESSED << shf)) &&
+                    (button == BUTTON_PRESSED))
+
+                || (!(mbe & (BUTTON1_CLICKED << shf)) &&
+                    (button == BUTTON_CLICKED))
+
+                || (!(mbe & (BUTTON1_DOUBLE_CLICKED << shf)) &&
+                    (button == BUTTON_DOUBLE_CLICKED))
+
+                || (!(mbe & (BUTTON1_MOVED << shf)) &&
+                    (button == BUTTON_MOVED))
+
+                || (!(mbe & (BUTTON1_RELEASED << shf)) &&
+                    (button == BUTTON_RELEASED))
+            )
+                pdc_mouse_status.changes ^= (1 << i);
+        }
+    }
+
+    if (pdc_mouse_status.changes & PDC_MOUSE_MOVED)
+    {
+        if (!(mbe & (BUTTON1_MOVED|BUTTON2_MOVED|BUTTON3_MOVED)))
+            pdc_mouse_status.changes ^= PDC_MOUSE_MOVED;
+    }
+
+    if (pdc_mouse_status.changes &
+        (PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN))
+    {
+        if (!(mbe & MOUSE_WHEEL_SCROLL))
+            pdc_mouse_status.changes &=
+                ~(PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN);
+    }
+
+    if (!pdc_mouse_status.changes)
+        return -1;
+
+    /* Check for click in slk area */
+
+    i = PDC_mouse_in_slk(pdc_mouse_status.y, pdc_mouse_status.x);
+
+    if (i)
+    {
+        if (pdc_mouse_status.button[0] & (BUTTON_PRESSED|BUTTON_CLICKED))
+            key = KEY_F(i);
+        else
+            key = -1;
+    }
+
+    return key;
+}
+
+int wgetch(WINDOW *win)
+{
+    static int buffer[_INBUFSIZ];   /* character buffer */
+    int key, waitcount;
+
+    PDC_LOG(("wgetch() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    waitcount = 0;
+
+     /* set the number of 1/20th second napms() calls */
+
+    if (SP->delaytenths)
+        waitcount = 2 * SP->delaytenths;
+    else
+        if (win->_delayms)
+        {
+            /* Can't really do millisecond intervals, so delay in 
+               1/20ths of a second (50ms) */
+
+            waitcount = win->_delayms / 50;
+            if (!waitcount)
+                waitcount = 1;
+        }
+
+    /* refresh window when wgetch is called if there have been changes 
+       to it and it is not a pad */
+
+    if (!(win->_flags & _PAD) && ((!win->_leaveit &&
+         (win->_begx + win->_curx != SP->curscol ||
+          win->_begy + win->_cury != SP->cursrow)) || is_wintouched(win)))
+        wrefresh(win);
+
+    /* if ungotten char exists, remove and return it */
+
+    if (c_ungind)
+        return c_ungch[--c_ungind];
+
+    /* if normal and data in buffer */
+
+    if ((!SP->raw_inp && !SP->cbreak) && (c_gindex < c_pindex))
+        return buffer[c_gindex++];
+
+    /* prepare to buffer data */
+
+    c_pindex = 0;
+    c_gindex = 0;
+
+    /* to get here, no keys are buffered. go and get one. */
+
+    for (;;)            /* loop for any buffering */
+    {
+        /* is there a keystroke ready? */
+
+        if (!PDC_check_key())
+        {
+            /* if not, handle timeout() and halfdelay() */
+
+            if (SP->delaytenths || win->_delayms)
+            {
+                if (!waitcount)
+                    return ERR;
+
+                waitcount--;
+            }
+            else
+                if (win->_nodelay)
+                    return ERR;
+
+            napms(50);  /* sleep for 1/20th second */
+            continue;   /* then check again */
+        }
+
+        /* if there is, fetch it */
+
+        key = PDC_get_key();
+
+        if (SP->key_code)
+        {
+            /* filter special keys if not in keypad mode */
+
+            if (!win->_use_keypad)
+                key = -1;
+
+            /* filter mouse events; translate mouse clicks in the slk 
+               area to function keys */
+
+            else if (key == KEY_MOUSE)
+                key = _mouse_key(win);
+        }
+
+        /* unwanted key? loop back */
+
+        if (key == -1)
+            continue;
+
+        /* translate CR */
+
+        if (key == '\r' && SP->autocr && !SP->raw_inp)
+            key = '\n';
+
+        /* if echo is enabled */
+
+        if (SP->echo && !SP->key_code)
+        {
+            waddch(win, key);
+            wrefresh(win);
+        }
+
+        /* if no buffering */
+
+        if (SP->raw_inp || SP->cbreak)
+            return key;
+
+        /* if no overflow, put data in buffer */
+
+        if (key == '\b')
+        {
+            if (c_pindex > c_gindex)
+                c_pindex--;
+        }
+        else
+            if (c_pindex < _INBUFSIZ - 2)
+                buffer[c_pindex++] = key;
+
+        /* if we got a line */
+
+        if (key == '\n' || key == '\r')
+            return buffer[c_gindex++];
+    }
+}
+
+int mvgetch(int y, int x)
+{
+    PDC_LOG(("mvgetch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wgetch(stdscr);
+}
+
+int mvwgetch(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("mvwgetch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wgetch(win);
+}
+
+int PDC_ungetch(int ch)
+{
+    PDC_LOG(("ungetch() - called\n"));
+
+    if (c_ungind >= NUNGETCH)   /* pushback stack full */
+        return ERR;
+
+    c_ungch[c_ungind++] = ch;
+
+    return OK;
+}
+
+int flushinp(void)
+{
+    PDC_LOG(("flushinp() - called\n"));
+
+    PDC_flushinp();
+
+    c_gindex = 1;           /* set indices to kill buffer */
+    c_pindex = 0;
+    c_ungind = 0;           /* clear c_ungch array */
+
+    return OK;
+}
+
+unsigned long PDC_get_key_modifiers(void)
+{
+    PDC_LOG(("PDC_get_key_modifiers() - called\n"));
+
+    return pdc_key_modifiers;
+}
+
+int PDC_save_key_modifiers(bool flag)
+{
+    PDC_LOG(("PDC_save_key_modifiers() - called\n"));
+
+    SP->save_key_modifiers = flag;
+    return OK;
+}
+
+int PDC_return_key_modifiers(bool flag)
+{
+    PDC_LOG(("PDC_return_key_modifiers() - called\n"));
+
+    SP->return_key_modifiers = flag;
+    return PDC_modifiers_set();
+}
+
+#ifdef PDC_WIDE
+int wget_wch(WINDOW *win, wint_t *wch)
+{
+    int key;
+
+    PDC_LOG(("wget_wch() - called\n"));
+
+    if (!wch)
+        return ERR;
+
+    key = wgetch(win);
+
+    if (key == ERR)
+        return ERR;
+
+    *wch = key;
+
+    return SP->key_code ? KEY_CODE_YES : OK;
+}
+
+int get_wch(wint_t *wch)
+{
+    PDC_LOG(("get_wch() - called\n"));
+
+    return wget_wch(stdscr, wch);
+}
+
+int mvget_wch(int y, int x, wint_t *wch)
+{
+    PDC_LOG(("mvget_wch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wget_wch(stdscr, wch);
+}
+
+int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch)
+{
+    PDC_LOG(("mvwget_wch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wget_wch(win, wch);
+}
+
+int unget_wch(const wchar_t wch)
+{
+    return PDC_ungetch(wch);
+}
+#endif

mercurial