Change-Id: If881ec130833c7e7e62caa3d31e350a531f5bc8e Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Reviewed-on: http://review.coreboot.org/12398 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
		
			
				
	
	
		
			411 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			411 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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
 |