/* Copyright (c) 1992, 1995 John E. Davis
* All rights reserved.
*
* You may distribute under the terms of either the GNU General Public
* License or the Perl Artistic License.
*/
#include "config.h"
#include "sl-feat.h"
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
#include "slang.h"
#include "_slang.h"
#ifdef __cplusplus
# define _DOTS_ ...
#else
# define _DOTS_ void
#endif
/*----------------------------------------------------------------------*\
* 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 hStdout, hStdin;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
int SLang_init_tty (int abort_char, int no_flow_control, int opost)
{
SMALL_RECT windowRect;
COORD newPosition;
DWORD flags;
/* first off, create a new console so the old one can be restored on exit */
HANDLE console = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ |FILE_SHARE_WRITE,
0,
CONSOLE_TEXTMODE_BUFFER,
0);
if (SetConsoleActiveScreenBuffer(console) == FALSE)
{
return -1;
}
/* start things off at the origin */
newPosition.X = 0;
newPosition.Y = 0;
/* still read in characters from stdin, but output to the new console */
/* this way, on program exit, the original screen is restored */
hStdin = GetStdHandle(STD_INPUT_HANDLE);
/* hStdout = GetStdHandle(STD_OUTPUT_HANDLE); */
/* hStdin = console; */
hStdout = console;
if (hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE)
{
return -1; /* failure */
}
if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
return -1; /* failure */
}
// if
windowRect.Left = 0;
windowRect.Top = 0;
windowRect.Right = csbiInfo.dwSize.X - 1;
windowRect.Bottom = csbiInfo.dwSize.Y - 1;
if (!SetConsoleWindowInfo(hStdout, TRUE, &windowRect))
{
return -1;
}
if (SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT) == FALSE)
{
return -1; /* failure */
}
if (SetConsoleMode(hStdout, 0) == FALSE)
{
return -1; /* failure */
}
if (GetConsoleMode(hStdin, &flags))
{
if (flags & ENABLE_PROCESSED_INPUT)
{
return -1;
}
}
(void) SetConsoleCursorPosition(hStdout, newPosition);
/* success */
return 0;
}
/* SLang_init_tty */
/*----------------------------------------------------------------------*\
* Function: void SLang_reset_tty (void);
*
* reset the tty before exiting
\*----------------------------------------------------------------------*/
void SLang_reset_tty (void)
{
set_ctrl_break (1);
}
/* Return TRUE if the Shift, Ctrl, Alt, Caps Lock, or Num Lock key was pressed.
*/
static int is_shift_key (INPUT_RECORD *pRecord)
{
unsigned k = (pRecord->Event.KeyEvent.uChar.AsciiChar |
(pRecord->Event.KeyEvent.wVirtualScanCode << 8));
return ((k == 0x1d00)
|| (k == 0x2a00)
|| (k == 0x3600)
|| (k == 0x3800)
|| (k == 0x3a00)
|| (k == 0x4500));
}
/*----------------------------------------------------------------------*\
* Function: int _SLsys_input_pending (int tsecs);
*
* sleep for *tsecs tenths of a sec waiting for input
\*----------------------------------------------------------------------*/
int _SLsys_input_pending (int tsecs)
{
INPUT_RECORD record;
DWORD events_read;
while (1)
{
if (0 == PeekConsoleInput(hStdin, &record, 1, &events_read))
/* function failed */
return 0;
if (events_read != 1)
return 0;
if ((record.EventType == KEY_EVENT)
&& record.Event.KeyEvent.bKeyDown
&& (0 == is_shift_key (&record)))
/* ok, there is a keypress here */
return 1;
/* something else is here, so read it and try again */
(void) ReadConsoleInput(hStdin, &record, 1, &events_read);
}
}
/*----------------------------------------------------------------------*\
* 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)
{
unsigned int ch;
DWORD events_read;
INPUT_RECORD record;
while (1)
{
if (!ReadConsoleInput(hStdin, &record, 1, &events_read))
return 0;
if ((record.EventType == KEY_EVENT)
&& record.Event.KeyEvent.bKeyDown
&& !is_shift_key (&record))
{
#ifdef CYGWIN32
ch = record.Event.KeyEvent.AsciiChar;
#else
ch = record.Event.KeyEvent.uChar.AsciiChar;
#endif
if (ch == 0 || ch == 0xE0)
{
SLang_ungetkey(record.Event.KeyEvent.wVirtualScanCode);
}
return ch;
}
}
/* ReadFile(hStdin, &key, 1, &events_read, NULL); */
/* return key; */
}
/*----------------------------------------------------------------------*\
* Function: int SLang_set_abort_signal (void (*handler)(int));
\*----------------------------------------------------------------------*/
int SLang_set_abort_signal (void (*handler)(int))
{
return 0;
}