coreboot-kgpe-d16/payloads/libpayload/curses/PDCurses-3.4/sdl1/pdckbd.c
Patrick Georgi 3b77b723ca libpayload: Add PDCurses and ncurses' libform/libmenu
PDCurses provides an alternative implementation of the curses library
standard in addition to tinycurses.
Where tinycurses is really tiny, PDCurses is more complete and provides
virtually unlimited windows and the full API.
The PDCurses code is brought in "vanilla", with all local changes
residing in curses/pdcurses-backend/

In addition to a curses library, this change also provides libpanel (as
part of the PDCurses code), and libform and libmenu which were derived
from ncurses-5.9.
As they rely on ncurses internals (and PDCurses is not ncurses), more
changes were required for these libraries to work.

The build system is extended to install the right set of header files
depending on the selected curses implementation.

Change-Id: I9e5b920f94b6510da01da2f656196a993170d1c5
Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com>
Reviewed-on: http://review.coreboot.org/106
Tested-by: build bot (Jenkins)
Reviewed-by: Marc Jones <marcj303@gmail.com>
2011-08-04 08:10:41 +02:00

389 lines
11 KiB
C

/* Public Domain Curses */
#include "pdcsdl.h"
RCSID("$Id: pdckbd.c,v 1.20 2008/07/14 04:24:52 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****************************************************************/
#include <string.h>
unsigned long pdc_key_modifiers = 0L;
static SDL_Event event;
static SDLKey oldkey;
static MOUSE_STATUS old_mouse_status;
static struct
{
SDLKey keycode;
bool numkeypad;
unsigned short normal;
unsigned short shifted;
unsigned short control;
unsigned short alt;
} key_table[] =
{
/* keycode keypad normal shifted control alt*/
{SDLK_LEFT, FALSE, KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT},
{SDLK_RIGHT, FALSE, KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT},
{SDLK_UP, FALSE, KEY_UP, KEY_SUP, CTL_UP, ALT_UP},
{SDLK_DOWN, FALSE, KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN},
{SDLK_HOME, FALSE, KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME},
{SDLK_END, FALSE, KEY_END, KEY_SEND, CTL_END, ALT_END},
{SDLK_PAGEUP, FALSE, KEY_PPAGE, KEY_SPREVIOUS,CTL_PGUP, ALT_PGUP},
{SDLK_PAGEDOWN,FALSE, KEY_NPAGE, KEY_SNEXT, CTL_PGDN, ALT_PGDN},
{SDLK_INSERT, FALSE, KEY_IC, KEY_SIC, CTL_INS, ALT_INS},
{SDLK_DELETE, FALSE, KEY_DC, KEY_SDC, CTL_DEL, ALT_DEL},
{SDLK_F1, FALSE, KEY_F(1), KEY_F(13), KEY_F(25), KEY_F(37)},
{SDLK_F2, FALSE, KEY_F(2), KEY_F(14), KEY_F(26), KEY_F(38)},
{SDLK_F3, FALSE, KEY_F(3), KEY_F(15), KEY_F(27), KEY_F(39)},
{SDLK_F4, FALSE, KEY_F(4), KEY_F(16), KEY_F(28), KEY_F(40)},
{SDLK_F5, FALSE, KEY_F(5), KEY_F(17), KEY_F(29), KEY_F(41)},
{SDLK_F6, FALSE, KEY_F(6), KEY_F(18), KEY_F(30), KEY_F(42)},
{SDLK_F7, FALSE, KEY_F(7), KEY_F(19), KEY_F(31), KEY_F(43)},
{SDLK_F8, FALSE, KEY_F(8), KEY_F(20), KEY_F(32), KEY_F(44)},
{SDLK_F9, FALSE, KEY_F(9), KEY_F(21), KEY_F(33), KEY_F(45)},
{SDLK_F10, FALSE, KEY_F(10), KEY_F(22), KEY_F(34), KEY_F(46)},
{SDLK_F11, FALSE, KEY_F(11), KEY_F(23), KEY_F(35), KEY_F(47)},
{SDLK_F12, FALSE, KEY_F(12), KEY_F(24), KEY_F(36), KEY_F(48)},
{SDLK_F13, FALSE, KEY_F(13), KEY_F(25), KEY_F(37), KEY_F(49)},
{SDLK_F14, FALSE, KEY_F(14), KEY_F(26), KEY_F(38), KEY_F(50)},
{SDLK_F15, FALSE, KEY_F(15), KEY_F(27), KEY_F(39), KEY_F(51)},
{SDLK_BACKSPACE,FALSE, 0x08, 0x08, CTL_BKSP, ALT_BKSP},
{SDLK_TAB, FALSE, 0x09, KEY_BTAB, CTL_TAB, ALT_TAB},
{SDLK_PRINT, FALSE, KEY_PRINT, KEY_SPRINT, KEY_PRINT, KEY_PRINT},
{SDLK_PAUSE, FALSE, KEY_SUSPEND, KEY_SSUSPEND, KEY_SUSPEND, KEY_SUSPEND},
{SDLK_CLEAR, FALSE, KEY_CLEAR, KEY_CLEAR, KEY_CLEAR, KEY_CLEAR},
{SDLK_BREAK, FALSE, KEY_BREAK, KEY_BREAK, KEY_BREAK, KEY_BREAK},
{SDLK_HELP, FALSE, KEY_HELP, KEY_SHELP, KEY_LHELP, KEY_HELP},
{SDLK_MENU, FALSE, KEY_OPTIONS, KEY_SOPTIONS, KEY_OPTIONS, KEY_OPTIONS},
{SDLK_ESCAPE, FALSE, 0x1B, 0x1B, 0x1B, ALT_ESC},
{SDLK_KP_ENTER,TRUE, PADENTER, PADENTER, CTL_PADENTER,ALT_PADENTER},
{SDLK_KP_PLUS, TRUE, PADPLUS, '+', CTL_PADPLUS, ALT_PADPLUS},
{SDLK_KP_MINUS,TRUE, PADMINUS, '-', CTL_PADMINUS,ALT_PADMINUS},
{SDLK_KP_MULTIPLY,TRUE,PADSTAR, '*', CTL_PADSTAR, ALT_PADSTAR},
{SDLK_KP_DIVIDE,TRUE, PADSLASH, '/', CTL_PADSLASH,ALT_PADSLASH},
{SDLK_KP_PERIOD,TRUE, PADSTOP, '.', CTL_PADSTOP, ALT_PADSTOP},
{SDLK_KP0, TRUE, PAD0, '0', CTL_PAD0, ALT_PAD0},
{SDLK_KP1, TRUE, KEY_C1, '1', CTL_PAD1, ALT_PAD1},
{SDLK_KP2, TRUE, KEY_C2, '2', CTL_PAD2, ALT_PAD2},
{SDLK_KP3, TRUE, KEY_C3, '3', CTL_PAD3, ALT_PAD3},
{SDLK_KP4, TRUE, KEY_B1, '4', CTL_PAD4, ALT_PAD4},
{SDLK_KP5, TRUE, KEY_B2, '5', CTL_PAD5, ALT_PAD5},
{SDLK_KP6, TRUE, KEY_B3, '6', CTL_PAD6, ALT_PAD6},
{SDLK_KP7, TRUE, KEY_A1, '7', CTL_PAD7, ALT_PAD7},
{SDLK_KP8, TRUE, KEY_A2, '8', CTL_PAD8, ALT_PAD8},
{SDLK_KP9, TRUE, KEY_A3, '9', CTL_PAD9, ALT_PAD9},
{0, 0, 0, 0, 0, 0}
};
unsigned long PDC_get_input_fd(void)
{
PDC_LOG(("PDC_get_input_fd() - called\n"));
return 0L; /* test this */
}
void PDC_set_keyboard_binary(bool on)
{
PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
}
/* check if a key or mouse event is waiting */
bool PDC_check_key(void)
{
Uint32 current = SDL_GetTicks();
int haveevent = SDL_PollEvent(&event);
/* if we have an event, or 30 ms have passed without a screen
update, or the timer has wrapped, update now */
if (haveevent ||
current < pdc_lastupdate || ((current - pdc_lastupdate) > 30))
PDC_update_rects();
return haveevent;
}
static int _process_key_event(void)
{
int i, key = 0;
pdc_key_modifiers = 0L;
SP->key_code = FALSE;
if (event.type == SDL_KEYUP)
{
if (SP->return_key_modifiers && event.key.keysym.sym == oldkey)
{
switch (oldkey)
{
case SDLK_RSHIFT:
return KEY_SHIFT_R;
case SDLK_LSHIFT:
return KEY_SHIFT_L;
case SDLK_RCTRL:
return KEY_CONTROL_R;
case SDLK_LCTRL:
return KEY_CONTROL_L;
case SDLK_RALT:
return KEY_ALT_R;
case SDLK_LALT:
return KEY_ALT_L;
default:
break;
}
}
return -1;
}
oldkey = event.key.keysym.sym;
if (SP->save_key_modifiers)
{
if (event.key.keysym.mod & KMOD_NUM)
pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
if (event.key.keysym.mod & KMOD_SHIFT)
pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
if (event.key.keysym.mod & KMOD_CTRL)
pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
if (event.key.keysym.mod & KMOD_ALT)
pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT;
}
for (i = 0; key_table[i].keycode; i++)
{
if (key_table[i].keycode == event.key.keysym.sym)
{
if ((event.key.keysym.mod & KMOD_SHIFT) ||
(key_table[i].numkeypad && (event.key.keysym.mod & KMOD_NUM)))
{
key = key_table[i].shifted;
}
else if (event.key.keysym.mod & KMOD_CTRL)
{
key = key_table[i].control;
}
else if (event.key.keysym.mod & KMOD_ALT)
{
key = key_table[i].alt;
}
/* To get here, we ignore all other modifiers */
else
key = key_table[i].normal;
SP->key_code = (key > 0x100);
break;
}
}
if (!key)
{
key = event.key.keysym.unicode;
if (key > 0x7f)
key = 0;
}
/* Handle ALT letters and numbers */
if (event.key.keysym.mod & KMOD_ALT)
{
if (key >= 'A' && key <= 'Z')
{
key += ALT_A - 'A';
SP->key_code = TRUE;
}
if (key >= 'a' && key <= 'z')
{
key += ALT_A - 'a';
SP->key_code = TRUE;
}
if (key >= '0' && key <= '9')
{
key += ALT_0 - '0';
SP->key_code = TRUE;
}
}
return key ? key : -1;
}
static int _process_mouse_event(void)
{
SDLMod keymods;
short shift_flags = 0;
memset(&pdc_mouse_status, 0, sizeof(MOUSE_STATUS));
keymods = SDL_GetModState();
if (keymods & KMOD_SHIFT)
shift_flags |= BUTTON_SHIFT;
if (keymods & KMOD_CTRL)
shift_flags |= BUTTON_CONTROL;
if (keymods & KMOD_ALT)
shift_flags |= BUTTON_ALT;
if (event.type == SDL_MOUSEMOTION)
{
int i;
pdc_mouse_status.x = event.motion.x / pdc_fwidth;
pdc_mouse_status.y = event.motion.y / pdc_fheight;
if (!event.motion.state ||
(pdc_mouse_status.x == old_mouse_status.x &&
pdc_mouse_status.y == old_mouse_status.y))
return -1;
pdc_mouse_status.changes = PDC_MOUSE_MOVED;
for (i = 0; i < 3; i++)
{
if (event.motion.state & SDL_BUTTON(i + 1))
{
pdc_mouse_status.button[i] = BUTTON_MOVED | shift_flags;
pdc_mouse_status.changes |= (1 << i);
}
}
}
else
{
short action = (event.button.state == SDL_PRESSED) ?
BUTTON_PRESSED : BUTTON_RELEASED;
Uint8 btn = event.button.button;
/* handle scroll wheel */
if ((btn == 4 || btn == 5) && action == BUTTON_RELEASED)
{
pdc_mouse_status.x = pdc_mouse_status.y = -1;
pdc_mouse_status.changes = (btn == 5) ?
PDC_MOUSE_WHEEL_DOWN : PDC_MOUSE_WHEEL_UP;
return KEY_MOUSE;
}
if (btn < 1 || btn > 3)
return -1;
/* check for a click -- a press followed immediately by a release */
if (action == BUTTON_PRESSED && SP->mouse_wait)
{
SDL_Event rel;
napms(SP->mouse_wait);
if (SDL_PollEvent(&rel))
{
if (rel.type == SDL_MOUSEBUTTONUP && rel.button.button == btn)
action = BUTTON_CLICKED;
else
SDL_PushEvent(&rel);
}
}
pdc_mouse_status.x = event.button.x / pdc_fwidth;
pdc_mouse_status.y = event.button.y / pdc_fheight;
btn--;
pdc_mouse_status.button[btn] = action | shift_flags;
pdc_mouse_status.changes = (1 << btn);
}
old_mouse_status = pdc_mouse_status;
return KEY_MOUSE;
}
/* return the next available key or mouse event */
int PDC_get_key(void)
{
switch (event.type)
{
case SDL_QUIT:
exit(1);
case SDL_VIDEORESIZE:
if (pdc_own_screen &&
(event.resize.h / pdc_fheight != LINES ||
event.resize.w / pdc_fwidth != COLS))
{
pdc_sheight = event.resize.h;
pdc_swidth = event.resize.w;
if (!SP->resized)
{
SP->resized = TRUE;
return KEY_RESIZE;
}
}
break;
case SDL_MOUSEMOTION:
SDL_ShowCursor(SDL_ENABLE);
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
oldkey = SDLK_SPACE;
if (SP->_trap_mbe)
return _process_mouse_event();
break;
case SDL_KEYUP:
case SDL_KEYDOWN:
PDC_mouse_set();
return _process_key_event();
}
return -1;
}
/* discard any pending keyboard or mouse input -- this is the core
routine for flushinp() */
void PDC_flushinp(void)
{
PDC_LOG(("PDC_flushinp() - called\n"));
while (PDC_check_key());
}
int PDC_mouse_set(void)
{
SDL_ShowCursor(SP->_trap_mbe ? SDL_ENABLE : SDL_DISABLE);
return OK;
}
int PDC_modifiers_set(void)
{
return OK;
}