aboutsummaryrefslogtreecommitdiffhomepage
path: root/libslang/src/slw32tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'libslang/src/slw32tty.c')
-rw-r--r--libslang/src/slw32tty.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/libslang/src/slw32tty.c b/libslang/src/slw32tty.c
new file mode 100644
index 0000000..3d758ce
--- /dev/null
+++ b/libslang/src/slw32tty.c
@@ -0,0 +1,354 @@
+/* Copyright (c) 1992, 1999, 2001, 2002, 2003 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;
+}