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
 |