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>
		
			
				
	
	
		
			512 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			512 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Public Domain Curses */
 | |
| 
 | |
| /* MS C doesn't return flags from int86() */
 | |
| #ifdef MSC
 | |
| # define USE_KBHIT
 | |
| #endif
 | |
| 
 | |
| #ifdef USE_KBHIT
 | |
| # include <conio.h>
 | |
| #endif
 | |
| 
 | |
| #include "pdcdos.h"
 | |
| 
 | |
| RCSID("$Id: pdckbd.c,v 1.87 2008/07/13 16:08:17 wmcbrine Exp $")
 | |
| 
 | |
| /*man-start**************************************************************
 | |
| 
 | |
|   Name:                                                         pdckbd
 | |
| 
 | |
|   Synopsis:
 | |
|         unsigned long PDC_get_input_fd(void);
 | |
| 
 | |
|   Description:
 | |
|         PDC_get_input_fd() returns the file descriptor that PDCurses
 | |
|         reads its input from. It can be used for select().
 | |
| 
 | |
|   Portability                                X/Open    BSD    SYS V
 | |
|         PDC_get_input_fd                        -       -       -
 | |
| 
 | |
| **man-end****************************************************************/
 | |
| 
 | |
| #ifdef __DJGPP__
 | |
| # include <fcntl.h>
 | |
| # include <io.h>
 | |
| # include <signal.h>
 | |
| #endif
 | |
| 
 | |
| /************************************************************************
 | |
|  *    Table for key code translation of function keys in keypad mode    *
 | |
|  *    These values are for strict IBM keyboard compatibles only         *
 | |
|  ************************************************************************/
 | |
| 
 | |
| static short key_table[] =
 | |
| {
 | |
|     -1,             ALT_ESC,        -1,             0,
 | |
|     -1,             -1,             -1,             -1,
 | |
|     -1,             -1,             -1,             -1,
 | |
|     -1,             -1,             ALT_BKSP,       KEY_BTAB,
 | |
|     ALT_Q,          ALT_W,          ALT_E,          ALT_R,
 | |
|     ALT_T,          ALT_Y,          ALT_U,          ALT_I,
 | |
|     ALT_O,          ALT_P,          ALT_LBRACKET,   ALT_RBRACKET,
 | |
|     ALT_ENTER,      -1,             ALT_A,          ALT_S,
 | |
|     ALT_D,          ALT_F,          ALT_G,          ALT_H,
 | |
|     ALT_J,          ALT_K,          ALT_L,          ALT_SEMICOLON,
 | |
|     ALT_FQUOTE,     ALT_BQUOTE,     -1,             ALT_BSLASH,
 | |
|     ALT_Z,          ALT_X,          ALT_C,          ALT_V,
 | |
|     ALT_B,          ALT_N,          ALT_M,          ALT_COMMA,
 | |
|     ALT_STOP,       ALT_FSLASH,     -1,             ALT_PADSTAR,
 | |
|     -1,             -1,             -1,             KEY_F(1),
 | |
|     KEY_F(2),       KEY_F(3),       KEY_F(4),       KEY_F(5),
 | |
|     KEY_F(6),       KEY_F(7),       KEY_F(8),       KEY_F(9),
 | |
|     KEY_F(10),      -1,             -1,             KEY_HOME,
 | |
|     KEY_UP,         KEY_PPAGE,      ALT_PADMINUS,   KEY_LEFT,
 | |
|     KEY_B2,         KEY_RIGHT,      ALT_PADPLUS,    KEY_END,
 | |
|     KEY_DOWN,       KEY_NPAGE,      KEY_IC,         KEY_DC,
 | |
|     KEY_F(13),      KEY_F(14),      KEY_F(15),      KEY_F(16),
 | |
|     KEY_F(17),      KEY_F(18),      KEY_F(19),      KEY_F(20),
 | |
|     KEY_F(21),      KEY_F(22),      KEY_F(25),      KEY_F(26),
 | |
|     KEY_F(27),      KEY_F(28),      KEY_F(29),      KEY_F(30),
 | |
|     KEY_F(31),      KEY_F(32),      KEY_F(33),      KEY_F(34),
 | |
|     KEY_F(37),      KEY_F(38),      KEY_F(39),      KEY_F(40),
 | |
|     KEY_F(41),      KEY_F(42),      KEY_F(43),      KEY_F(44),
 | |
|     KEY_F(45),      KEY_F(46),      -1,             CTL_LEFT,
 | |
|     CTL_RIGHT,      CTL_END,        CTL_PGDN,       CTL_HOME,
 | |
|     ALT_1,          ALT_2,          ALT_3,          ALT_4,
 | |
|     ALT_5,          ALT_6,          ALT_7,          ALT_8,
 | |
|     ALT_9,          ALT_0,          ALT_MINUS,      ALT_EQUAL,
 | |
|     CTL_PGUP,       KEY_F(11),      KEY_F(12),      KEY_F(23),
 | |
|     KEY_F(24),      KEY_F(35),      KEY_F(36),      KEY_F(47),
 | |
|     KEY_F(48),      CTL_UP,         CTL_PADMINUS,   CTL_PADCENTER,
 | |
|     CTL_PADPLUS,    CTL_DOWN,       CTL_INS,        CTL_DEL,
 | |
|     CTL_TAB,        CTL_PADSLASH,   CTL_PADSTAR,    ALT_HOME,
 | |
|     ALT_UP,         ALT_PGUP,       -1,             ALT_LEFT,
 | |
|     -1,             ALT_RIGHT,      -1,             ALT_END,
 | |
|     ALT_DOWN,       ALT_PGDN,       ALT_INS,        ALT_DEL,
 | |
|     ALT_PADSLASH,   ALT_TAB,        ALT_PADENTER,   -1
 | |
| };
 | |
| 
 | |
| unsigned long pdc_key_modifiers = 0L;
 | |
| 
 | |
| static struct {unsigned short pressed, released;} button[3];
 | |
| 
 | |
| static bool mouse_avail = FALSE, mouse_vis = FALSE, mouse_moved = FALSE,
 | |
|             mouse_button = FALSE, key_pressed = FALSE;
 | |
| 
 | |
| static unsigned char mouse_scroll = 0;
 | |
| static PDCREGS ms_regs, old_ms;
 | |
| static unsigned short shift_status, old_shift = 0;
 | |
| static unsigned char keyboard_function = 0xff, shift_function = 0xff,
 | |
|                      check_function = 0xff;
 | |
| 
 | |
| static const unsigned short button_map[3] = {0, 2, 1};
 | |
| 
 | |
| unsigned long PDC_get_input_fd(void)
 | |
| {
 | |
|     PDC_LOG(("PDC_get_input_fd() - called\n"));
 | |
| 
 | |
|     return (unsigned long)fileno(stdin);
 | |
| }
 | |
| 
 | |
| void PDC_set_keyboard_binary(bool on)
 | |
| {
 | |
|     PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
 | |
| 
 | |
| #ifdef __DJGPP__
 | |
|     setmode(fileno(stdin), on ? O_BINARY : O_TEXT);
 | |
|     signal(SIGINT, on ? SIG_IGN : SIG_DFL);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /* check if a key or mouse event is waiting */
 | |
| 
 | |
| bool PDC_check_key(void)
 | |
| {
 | |
|     PDCREGS regs;
 | |
| 
 | |
|     if (shift_function == 0xff)
 | |
|     {
 | |
|         int scan;
 | |
| 
 | |
|         /* get shift status for all keyboards */
 | |
| 
 | |
|         regs.h.ah = 0x02;
 | |
|         PDCINT(0x16, regs);
 | |
|         scan = regs.h.al;
 | |
| 
 | |
|         /* get shift status for enhanced keyboards */
 | |
| 
 | |
|         regs.h.ah = 0x12;
 | |
|         PDCINT(0x16, regs);
 | |
| 
 | |
|         if (scan == regs.h.al && getdosmembyte(0x496) == 0x10)
 | |
|         {
 | |
|             keyboard_function = 0x10;
 | |
|             check_function = 0x11;
 | |
|             shift_function = 0x12;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             keyboard_function = 0;
 | |
|             check_function = 1;
 | |
|             shift_function = 2;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     regs.h.ah = shift_function;
 | |
|     PDCINT(0x16, regs);
 | |
| 
 | |
|     shift_status = regs.W.ax;
 | |
| 
 | |
|     if (mouse_vis)
 | |
|     {
 | |
|         unsigned short i;
 | |
| 
 | |
|         ms_regs.W.ax = 3;
 | |
|         PDCINT(0x33, ms_regs);
 | |
| 
 | |
|         mouse_button = FALSE;
 | |
| 
 | |
|         for (i = 0; i < 3; i++)
 | |
|         {
 | |
|             regs.W.ax = 6;
 | |
|             regs.W.bx = button_map[i];
 | |
|             PDCINT(0x33, regs);
 | |
|             button[i].released = regs.W.bx;
 | |
|             if (regs.W.bx)
 | |
|             {
 | |
|                 ms_regs.W.cx = regs.W.cx;
 | |
|                 ms_regs.W.dx = regs.W.dx;
 | |
|                 mouse_button = TRUE;
 | |
|             }
 | |
| 
 | |
|             regs.W.ax = 5;
 | |
|             regs.W.bx = button_map[i];
 | |
|             PDCINT(0x33, regs);
 | |
|             button[i].pressed = regs.W.bx;
 | |
|             if (regs.W.bx)
 | |
|             {
 | |
|                 ms_regs.W.cx = regs.W.cx;
 | |
|                 ms_regs.W.dx = regs.W.dx;
 | |
|                 mouse_button = TRUE;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         mouse_scroll = ms_regs.h.bh;
 | |
| 
 | |
|         mouse_moved = !mouse_button && ms_regs.h.bl &&
 | |
|                        ms_regs.h.bl == old_ms.h.bl &&
 | |
|                     (((ms_regs.W.cx ^ old_ms.W.cx) >> 3) ||
 | |
|                      ((ms_regs.W.dx ^ old_ms.W.dx) >> 3));
 | |
| 
 | |
|         if (mouse_scroll || mouse_button || mouse_moved)
 | |
|             return TRUE;
 | |
|     }
 | |
| 
 | |
|     if (old_shift && !shift_status)     /* modifier released */
 | |
|     {
 | |
|         if (!key_pressed && SP->return_key_modifiers)
 | |
|             return TRUE;
 | |
|     }
 | |
|     else if (!old_shift && shift_status)    /* modifier pressed */
 | |
|         key_pressed = FALSE;
 | |
| 
 | |
|     old_shift = shift_status;
 | |
| 
 | |
| #ifndef USE_KBHIT
 | |
|     regs.h.ah = check_function;
 | |
|     PDCINT(0x16, regs);
 | |
| 
 | |
|     return !(regs.W.flags & 64);
 | |
| #else
 | |
|     return kbhit();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static int _process_mouse_events(void)
 | |
| {
 | |
|     int i;
 | |
|     short shift_flags = 0;
 | |
| 
 | |
|     memset(&pdc_mouse_status, 0, sizeof(pdc_mouse_status));
 | |
| 
 | |
|     key_pressed = TRUE;
 | |
|     old_shift = shift_status;
 | |
|     SP->key_code = TRUE;
 | |
| 
 | |
|     /* Set shift modifiers */
 | |
| 
 | |
|     if (shift_status & 3)
 | |
|         shift_flags |= BUTTON_SHIFT;
 | |
| 
 | |
|     if (shift_status & 4)
 | |
|         shift_flags |= BUTTON_CONTROL;
 | |
| 
 | |
|     if (shift_status & 8)
 | |
|         shift_flags |= BUTTON_ALT;
 | |
| 
 | |
|     /* Scroll wheel support for CuteMouse */
 | |
| 
 | |
|     if (mouse_scroll)
 | |
|     {
 | |
|         pdc_mouse_status.changes = mouse_scroll & 0x80 ?
 | |
|             PDC_MOUSE_WHEEL_UP : PDC_MOUSE_WHEEL_DOWN;
 | |
| 
 | |
|         pdc_mouse_status.x = -1;
 | |
|         pdc_mouse_status.y = -1;
 | |
| 
 | |
|         return KEY_MOUSE;
 | |
|     }
 | |
| 
 | |
|     if (mouse_moved)
 | |
|     {
 | |
|         pdc_mouse_status.changes = PDC_MOUSE_MOVED;
 | |
| 
 | |
|         for (i = 0; i < 3; i++)
 | |
|         {
 | |
|             if (ms_regs.h.bl & (1 << button_map[i]))
 | |
|             {
 | |
|                 pdc_mouse_status.button[i] = BUTTON_MOVED | shift_flags;
 | |
|                 pdc_mouse_status.changes |= (1 << i);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else    /* button event */
 | |
|     {
 | |
|         for (i = 0; i < 3; i++)
 | |
|         {
 | |
|             if (button[i].pressed)
 | |
|             {
 | |
|                 /* Check for a click -- a PRESS followed
 | |
|                    immediately by a release */
 | |
| 
 | |
|                 if (!button[i].released)
 | |
|                 {
 | |
|                     if (SP->mouse_wait)
 | |
|                     {
 | |
|                         PDCREGS regs;
 | |
| 
 | |
|                         napms(SP->mouse_wait);
 | |
| 
 | |
|                         regs.W.ax = 6;
 | |
|                         regs.W.bx = button_map[i];
 | |
|                         PDCINT(0x33, regs);
 | |
| 
 | |
|                         pdc_mouse_status.button[i] = regs.W.bx ?
 | |
|                             BUTTON_CLICKED : BUTTON_PRESSED;
 | |
|                     }
 | |
|                     else
 | |
|                         pdc_mouse_status.button[i] = BUTTON_PRESSED;
 | |
|                 }
 | |
|                 else
 | |
|                     pdc_mouse_status.button[i] = BUTTON_CLICKED;
 | |
|             }
 | |
| 
 | |
|             if (button[i].pressed || button[i].released)
 | |
|             {
 | |
|                 pdc_mouse_status.button[i] |= shift_flags;
 | |
|                 pdc_mouse_status.changes |= (1 << i);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     pdc_mouse_status.x = ms_regs.W.cx >> 3;
 | |
|     pdc_mouse_status.y = ms_regs.W.dx >> 3;
 | |
| 
 | |
|     old_ms = ms_regs;
 | |
| 
 | |
|     return KEY_MOUSE;
 | |
| }
 | |
| 
 | |
| /* return the next available key or mouse event */
 | |
| 
 | |
| int PDC_get_key(void)
 | |
| {
 | |
|     PDCREGS regs;
 | |
|     int key, scan;
 | |
| 
 | |
|     pdc_key_modifiers = 0;
 | |
| 
 | |
|     if (mouse_vis && (mouse_scroll || mouse_button || mouse_moved))
 | |
|         return _process_mouse_events();
 | |
| 
 | |
|     /* Return modifiers as keys? */
 | |
| 
 | |
|     if (old_shift && !shift_status)
 | |
|     {
 | |
|         key = -1;
 | |
| 
 | |
|         if (old_shift & 1)
 | |
|             key = KEY_SHIFT_R;
 | |
| 
 | |
|         if (old_shift & 2)
 | |
|             key = KEY_SHIFT_L;
 | |
| 
 | |
|         if (shift_function == 0x12)
 | |
|         {
 | |
|             if (old_shift & 0x400)
 | |
|                 key = KEY_CONTROL_R;
 | |
| 
 | |
|             if (old_shift & 0x100)
 | |
|                 key = KEY_CONTROL_L;
 | |
| 
 | |
|             if (old_shift & 0x800)
 | |
|                 key = KEY_ALT_R;
 | |
| 
 | |
|             if (old_shift & 0x200)
 | |
|                 key = KEY_ALT_L;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (old_shift & 4)
 | |
|                 key = KEY_CONTROL_R;
 | |
| 
 | |
|             if (old_shift & 8)
 | |
|                 key = KEY_ALT_R;
 | |
|         }
 | |
| 
 | |
|         key_pressed = FALSE;
 | |
|         old_shift = shift_status;
 | |
| 
 | |
|         SP->key_code = TRUE;
 | |
|         return key;
 | |
|     }
 | |
| 
 | |
|     regs.h.ah = keyboard_function;
 | |
|     PDCINT(0x16, regs);
 | |
|     key = regs.h.al;
 | |
|     scan = regs.h.ah;
 | |
| 
 | |
|     if (SP->save_key_modifiers)
 | |
|     {
 | |
|         if (shift_status & 3)
 | |
|             pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
 | |
| 
 | |
|         if (shift_status & 4)
 | |
|             pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
 | |
| 
 | |
|         if (shift_status & 8)
 | |
|             pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT;
 | |
| 
 | |
|         if (shift_status & 0x20)
 | |
|             pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
 | |
|     }
 | |
| 
 | |
|     if (scan == 0x1c && key == 0x0a)    /* ^Enter */
 | |
|         key = CTL_ENTER;
 | |
|     else if (scan == 0xe0 && key == 0x0d)   /* PadEnter */
 | |
|         key = PADENTER;
 | |
|     else if (scan == 0xe0 && key == 0x0a)   /* ^PadEnter */
 | |
|         key = CTL_PADENTER;
 | |
|     else if (scan == 0x37 && key == 0x2a)   /* Star */
 | |
|         key = PADSTAR;
 | |
|     else if (scan == 0x4a && key == 0x2d)   /* Minus */
 | |
|         key = PADMINUS;
 | |
|     else if (scan == 0x4e && key == 0x2b)   /* Plus */
 | |
|         key = PADPLUS;
 | |
|     else if (scan == 0xe0 && key == 0x2f)   /* Slash */
 | |
|         key = PADSLASH;
 | |
|     else if (key == 0x00 || (key == 0xe0 && scan > 53 && scan != 86))
 | |
|         key = (scan > 0xa7) ? -1 : key_table[scan];
 | |
| 
 | |
|     if (shift_status & 3)
 | |
|     {
 | |
|         switch (key)
 | |
|         {
 | |
|         case KEY_HOME:  /* Shift Home */
 | |
|             key = KEY_SHOME;
 | |
|             break;
 | |
|         case KEY_UP:    /* Shift Up */
 | |
|             key = KEY_SUP;
 | |
|             break;
 | |
|         case KEY_PPAGE: /* Shift PgUp */
 | |
|             key = KEY_SPREVIOUS;
 | |
|             break;
 | |
|         case KEY_LEFT:  /* Shift Left */
 | |
|             key = KEY_SLEFT;
 | |
|             break;
 | |
|         case KEY_RIGHT: /* Shift Right */
 | |
|             key = KEY_SRIGHT;
 | |
|             break;
 | |
|         case KEY_END:   /* Shift End */
 | |
|             key = KEY_SEND;
 | |
|             break;
 | |
|         case KEY_DOWN:  /* Shift Down */
 | |
|             key = KEY_SDOWN;
 | |
|             break;
 | |
|         case KEY_NPAGE: /* Shift PgDn */
 | |
|             key = KEY_SNEXT;
 | |
|             break;
 | |
|         case KEY_IC:    /* Shift Ins */
 | |
|             key = KEY_SIC;
 | |
|             break;
 | |
|         case KEY_DC:    /* Shift Del */
 | |
|             key = KEY_SDC;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     key_pressed = TRUE;
 | |
|     SP->key_code = ((unsigned)key >= 256);
 | |
| 
 | |
|     return key;
 | |
| }
 | |
| 
 | |
| /* discard any pending keyboard or mouse input -- this is the core
 | |
|    routine for flushinp() */
 | |
| 
 | |
| void PDC_flushinp(void)
 | |
| {
 | |
|     PDC_LOG(("PDC_flushinp() - called\n"));
 | |
| 
 | |
|     /* Force the BIOS keyboard buffer head and tail pointers to be
 | |
|        the same...  Real nasty trick... */
 | |
| 
 | |
|     setdosmemword(0x41a, getdosmemword(0x41c));
 | |
| }
 | |
| 
 | |
| int PDC_mouse_set(void)
 | |
| {
 | |
|     PDCREGS regs;
 | |
|     unsigned long mbe = SP->_trap_mbe;
 | |
| 
 | |
|     if (mbe && !mouse_avail)
 | |
|     {
 | |
|         regs.W.ax = 0;
 | |
|         PDCINT(0x33, regs);
 | |
| 
 | |
|         mouse_avail = !!(regs.W.ax);
 | |
|     }
 | |
| 
 | |
|     if (mbe)
 | |
|     {
 | |
|         if (mouse_avail && !mouse_vis)
 | |
|         {
 | |
|             memset(&old_ms, 0, sizeof(old_ms));
 | |
| 
 | |
|             regs.W.ax = 1;
 | |
|             PDCINT(0x33, regs);
 | |
| 
 | |
|             mouse_vis = TRUE;
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if (mouse_avail && mouse_vis)
 | |
|         {
 | |
|             regs.W.ax = 2;
 | |
|             PDCINT(0x33, regs);
 | |
| 
 | |
|             mouse_vis = FALSE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (mouse_avail || !mbe) ? OK : ERR;
 | |
| }
 | |
| 
 | |
| int PDC_modifiers_set(void)
 | |
| {
 | |
|     key_pressed = FALSE;
 | |
| 
 | |
|     return OK;
 | |
| }
 |