mc/slang/slw32tty.c

355 lines
9.0 KiB
C

/* Copyright (c) 1992, 1999, 2001, 2002 John E. Davis
* This file is part of the S-Lang library.
*
* You may distribute under the terms of either the GNU General Public
* License or the Perl Artistic License.
*/
#include "slinclud.h"
#include <windows.h>
#include <winbase.h>
#include "slang.h"
#include "_slang.h"
#ifdef __cplusplus
# define _DOTS_ ...
#else
# define _DOTS_ void
#endif
static int Process_Mouse_Events;
/*----------------------------------------------------------------------*\
* Function: static void set_ctrl_break (int state);
*
* set the control-break setting
\*----------------------------------------------------------------------*/
static void set_ctrl_break (int state)
{
}
/*----------------------------------------------------------------------*\
* Function: int SLang_init_tty (int abort_char, int no_flow_control,
* int opost);
*
* initialize the keyboard interface and attempt to set-up the interrupt 9
* handler if ABORT_CHAR is non-zero.
* NO_FLOW_CONTROL and OPOST are only for compatiblity and are ignored.
\*----------------------------------------------------------------------*/
HANDLE _SLw32_Hstdin = INVALID_HANDLE_VALUE;
int SLang_init_tty (int abort_char, int no_flow_control, int opost)
{
(void) opost;
(void) no_flow_control;
if (_SLw32_Hstdin != INVALID_HANDLE_VALUE)
return 0;
#if 1
/* stdin may have been redirected. So try this */
_SLw32_Hstdin = CreateFile ("CONIN$", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (_SLw32_Hstdin == INVALID_HANDLE_VALUE)
return -1;
#else
if (INVALID_HANDLE_VALUE == (_SLw32_Hstdin = GetStdHandle(STD_INPUT_HANDLE)))
return -1;
#endif
if (FALSE == SetConsoleMode(_SLw32_Hstdin, ENABLE_WINDOW_INPUT|ENABLE_MOUSE_INPUT))
{
_SLw32_Hstdin = INVALID_HANDLE_VALUE;
return -1;
}
if (abort_char > 0)
SLang_Abort_Char = abort_char;
return 0;
}
/* SLang_init_tty */
/*----------------------------------------------------------------------*\
* Function: void SLang_reset_tty (void);
*
* reset the tty before exiting
\*----------------------------------------------------------------------*/
void SLang_reset_tty (void)
{
_SLw32_Hstdin = INVALID_HANDLE_VALUE;
set_ctrl_break (1);
}
static int process_mouse_event (MOUSE_EVENT_RECORD *m)
{
char buf [8];
if (Process_Mouse_Events == 0)
return -1;
if (m->dwEventFlags)
return -1; /* double click or movement event */
/* A button was either pressed or released. Now make sure that
* the shift keys were not also pressed.
*/
if (m->dwControlKeyState
& (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED
|LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED
|SHIFT_PRESSED))
return -1;
/* We have a simple press or release. Encode it as an escape sequence
* and buffer the result. The encoding is:
* 'ESC [ M b x y'
* where b represents the button state, and x,y represent the coordinates.
* The ESC is handled by the calling routine.
*/
if (m->dwButtonState & 1) buf[3] = ' ';
else if (m->dwButtonState & 2) buf[3] = ' ' + 2;
else if (m->dwButtonState & 4) buf[3] = ' ' + 1;
else return -1;
buf[0] = 27;
buf[1] = '[';
buf[2] = 'M';
buf[4] = 1 + ' ' + m->dwMousePosition.X;
buf[5] = 1 + ' ' + m->dwMousePosition.Y;
return SLang_buffer_keystring ((unsigned char *)buf, 6);
}
static int process_key_event (KEY_EVENT_RECORD *key)
{
unsigned int key_state = 0;
unsigned int scan;
char c1;
DWORD d = key->dwControlKeyState;
unsigned char buf[4];
if (!key->bKeyDown) return 0;
if (d & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
key_state |= _SLTT_KEY_ALT;
if (d & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
key_state |= _SLTT_KEY_CTRL;
if (d & SHIFT_PRESSED)
key_state |= _SLTT_KEY_SHIFT;
scan = key->wVirtualScanCode;
switch (scan)
{
case 0x00E: /* backspace */
return SLang_buffer_keystring ((unsigned char *)"\x7F", 1);
case 0x003: /* 2 key */
if (key_state & _SLTT_KEY_ALT)
break;
/* Drop */
case 0x039: /* space */
if (key_state & _SLTT_KEY_CTRL)
return SLang_buffer_keystring ((unsigned char *)"\x00\x03", 2);
break;
case 0x007: /* 6 key */
if (_SLTT_KEY_CTRL == (key_state & (_SLTT_KEY_ALT|_SLTT_KEY_CTRL)))
return SLang_buffer_keystring ((unsigned char *)"\x1E", 1); /* Ctrl-^ */
break;
case 0x00C: /* -/_ key */
if (_SLTT_KEY_CTRL == (key_state & (_SLTT_KEY_ALT|_SLTT_KEY_CTRL)))
return SLang_buffer_keystring ((unsigned char *)"\x1F", 1);
break;
case 0x00F: /* TAB */
if (_SLTT_KEY_SHIFT == key_state)
return SLang_buffer_keystring ((unsigned char *)"\x00\x09", 2);
break;
case 0xE02F: /* KEYPAD SLASH */
case 0x037: /* KEYPAD STAR */
case 0x04A: /* KEYPAD MINUS */
case 0x04E: /* KEYPAD PLUS */
if (d & NUMLOCK_ON)
break;
case 0x047: /* KEYPAD HOME */
case 0x048: /* KEYPAD UP */
case 0x049: /* KEYPAD PGUP */
case 0x04B: /* KEYPAD LEFT */
case 0x04C: /* KEYPAD 5 */
case 0x04D: /* KEYPAD RIGHT */
case 0x04F: /* KEYPAD END */
case 0x050: /* KEYPAD DOWN */
case 0x051: /* KEYPAD PGDN */
case 0x052: /* KEYPAD INSERT */
case 0x053: /* KEYPAD DEL */
if (d & ENHANCED_KEY)
scan |= 0xE000;
else
{
if (d & NUMLOCK_ON)
break;
}
(void) _SLpc_convert_scancode (scan, key_state, 0);
return 0;
case 0x3b: /* F1 */
case 0x3c:
case 0x3d:
case 0x3e:
case 0x3f:
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x57:
case 0x58: /* F12 */
(void) _SLpc_convert_scancode (scan, key_state, 0);
}
c1 = key->uChar.AsciiChar;
if (c1 != 0)
{
if (_SLTT_KEY_ALT == (key_state & (_SLTT_KEY_ALT|_SLTT_KEY_CTRL)))
{
buf[0] = 27;
buf[1] = c1;
return SLang_buffer_keystring (buf, 2);
}
if (c1 == SLang_Abort_Char)
{
if (SLang_Ignore_User_Abort == 0) SLang_Error = USER_BREAK;
SLKeyBoard_Quit = 1;
}
buf[0] = c1;
return SLang_buffer_keystring (buf, 1);
}
return 0;
}
static void process_console_records(void)
{
INPUT_RECORD record;
DWORD bytesRead;
DWORD n = 0;
if (FALSE == GetNumberOfConsoleInputEvents(_SLw32_Hstdin, &n))
return;
while (n > 0)
{
ReadConsoleInput(_SLw32_Hstdin, &record, 1, &bytesRead);
switch (record.EventType)
{
case KEY_EVENT:
(void) process_key_event(&record.Event.KeyEvent);
break;
case MOUSE_EVENT:
process_mouse_event(&record.Event.MouseEvent);
break;
case WINDOW_BUFFER_SIZE_EVENT:
/* process_resize_records(&record.Event.WindowBufferSizeEvent); */
break;
}
n--;
}
}
/*----------------------------------------------------------------------*\
* Function: int _SLsys_input_pending (int tsecs);
*
* sleep for *tsecs tenths of a sec waiting for input
\*----------------------------------------------------------------------*/
int _SLsys_input_pending (int tsecs)
{
long ms;
if (_SLw32_Hstdin == INVALID_HANDLE_VALUE)
return -1;
if (tsecs < 0) ms = -tsecs; /* specifies 1/1000 */
else ms = tsecs * 100L; /* convert 1/10 to 1/1000 secs */
process_console_records ();
while ((ms > 0)
&& (SLang_Input_Buffer_Len == 0))
{
long t;
t = GetTickCount ();
(void) WaitForSingleObject (_SLw32_Hstdin, ms);
process_console_records ();
ms -= GetTickCount () - t;
}
return SLang_Input_Buffer_Len;
}
/*----------------------------------------------------------------------*\
* Function: unsigned int _SLsys_getkey (void);
*
* wait for and get the next available keystroke.
* Also re-maps some useful keystrokes.
*
* Backspace (^H) => Del (127)
* Ctrl-Space => ^@ (^@^3 - a pc NUL char)
* extended keys are prefixed by a null character
\*----------------------------------------------------------------------*/
unsigned int _SLsys_getkey (void)
{
/* Check the input buffer because _SLsys_input_pending may have been
* called prior to this to stuff the input buffer.
*/
if (SLang_Input_Buffer_Len)
return SLang_getkey ();
if (_SLw32_Hstdin == INVALID_HANDLE_VALUE)
return SLANG_GETKEY_ERROR;
while (1)
{
int status;
if (SLKeyBoard_Quit)
return SLang_Abort_Char;
status = _SLsys_input_pending (600);
if (status == -1)
return SLANG_GETKEY_ERROR;
if (status > 0)
return SLang_getkey ();
}
}
/*----------------------------------------------------------------------*\
* Function: int SLang_set_abort_signal (void (*handler)(int));
\*----------------------------------------------------------------------*/
int SLang_set_abort_signal (void (*handler)(int))
{
if (_SLw32_Hstdin == INVALID_HANDLE_VALUE)
return -1;
return 0;
}
int SLtt_set_mouse_mode (int mode, int force)
{
(void) force;
Process_Mouse_Events = mode;
return 0;
}