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;
|
|
}
|