📄 tminit.c
字号:
/*
* tminit.c - initializer and main part of termios emulation.
* designed for DJGPP by Daisuke Aoyama <jack@st.rim.or.jp>
* special thanks to Ryo Shimizu
*/
#include <libc/stubs.h>
#include <conio.h>
#include <fcntl.h>
#include <go32.h>
#include <io.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/farptr.h>
#include <sys/fsext.h>
#include <libc/bss.h>
#include <libc/file.h>
#include <libc/dosio.h>
#include <libc/ttyprvt.h>
#define _DEV_STDIN 0x0001
#define _DEV_STDOUT 0x0002
#define _DEV_NUL 0x0004
#define _DEV_CLOCK 0x0008
#define _DEV_RAW 0x0020
#define _DEV_CDEV 0x0080
#define _DEV_IOCTRL 0x4000
#define CPMEOF 0x1a /* Ctrl+Z */
#define _REG_STATUS_CF 0x01
#define _REG_STATUS_ZF 0x40
#define _KEY_INS 0x80
#define _KEY_CAPS 0x40
#define _KEY_NUM 0x20
#define _KEY_SCRL 0x10
#define _KEY_ALT 0x08
#define _KEY_CTRL 0x04
#define _KEY_LSFT 0x02
#define _KEY_RSFT 0x01
#define _KEYE_SYSRQ 0x80
#define _KEYE_CAPS 0x40
#define _KEYE_NUM 0x20
#define _KEYE_SCRL 0x10
#define _KEYE_RALT 0x08
#define _KEYE_RCTRL 0x04
#define _KEYE_LALT 0x02
#define _KEYE_LCTRL 0x01
#define CHECKBYTES 32
/* tty buffers */
unsigned char __libc_tty_queue_buffer[_TTY_QUEUE_SIZE];
struct tty __libc_tty_internal = TTYDEFAULT;
struct tty *__libc_tty_p = &__libc_tty_internal;
struct tty_editline __libc_tty_editline = { 0, { 0 }, { 0 }, };
/* global only in the termios functions */
int __libc_termios_hook_common_count = -1;
/* static variables */
static int __libc_use_function_and_arrow_keys = 1;
static int __libc_has_enhanced_keyboard = 0;
static unsigned int __libc_has_extended_keystroke = 0;
static unsigned char __libc_extended_keystroke[16] = { 0, };
static ssize_t __libc_termios_check_bytes = CHECKBYTES;
/* static functions */
static void __libc_termios_fflushall (void);
static void __libc_termios_init_direct_functions (void);
static ssize_t __libc_termios_read (int handle, void *buffer, size_t count, ssize_t *rv);
static ssize_t __libc_termios_read_cooked_tty (int handle, void *buffer, size_t count);
static ssize_t __libc_termios_read_raw_tty (int handle, void *buffer, size_t count);
static ssize_t __libc_termios_write (int handle, const void *buffer, size_t count, ssize_t *rv);
static ssize_t __libc_termios_write_cooked_tty (int handle, const void *buffer, size_t count);
static ssize_t __libc_termios_write_raw_tty (int handle, const void *buffer, size_t count);
#if 0
static int __libc_termios_fsext (__FSEXT_Fnumber n, int *rv, va_list ap);
#endif
static void __libc_termios_echo_ctrl (unsigned char ch);
static void __libc_termios_maybe_echo_ctrl (unsigned char ch);
static void __libc_termios_maybe_echo (unsigned char ch);
static void __libc_termios_maybe_erase1 (void);
static void __libc_termios_erase_editline (void);
static void __libc_termios_kill_editline (void);
static void __libc_termios_insert_editline (unsigned char ch);
static int __libc_termios_exist_queue (void);
static void __libc_termios_clear_queue (void);
static int __libc_termios_get_queue (void);
static int __libc_termios_put_queue (unsigned char ch);
static void __libc_termios_raise_signal (unsigned char ch, int sig);
static void __libc_termios_fill_queue (void);
void __libc_termios_check_signals (void);
/* direct I/O functions */
static void __direct_add_keystroke (int c);
static void __direct_add_keystrokes (char *s);
static void __direct_check_extended_keystroke_at (int scan);
/* AT keyboard */
static int __direct_keysense_at (void);
static unsigned char __direct_keyinput_at (void);
static int __direct_ctrlsense_at (void);
/* AT enhanced keyboard */
static int __direct_keysense_at_enh (void);
static unsigned char __direct_keyinput_at_enh (void);
static int __direct_ctrlsense_at_enh (void);
/* Output functions */
static void __direct_output_tab_at (void);
static void __direct_output_at (unsigned char ch);
static void __direct_outputns_at (int n, const unsigned char *s);
static void __direct_outputs_at (const unsigned char *s);
/* function pointers */
static int (*__direct_keysense) (void) = __direct_keysense_at;
static unsigned char (*__direct_keyinput) (void) = __direct_keyinput_at;
static int (*__direct_ctrlsense) (void) = __direct_ctrlsense_at;
static void (*__direct_output) (unsigned char ch) = __direct_output_at;
static void (*__direct_outputns) (int n, const unsigned char *s) = __direct_outputns_at;
static void (*__direct_outputs) (const unsigned char *s) = __direct_outputs_at;
/******************************************************************************/
/* initialize function ********************************************************/
static void
__libc_termios_fflushall (void)
{
#if 1 /* should now work on djgpp */
fflush (NULL);
#else
_fwalk ((void (*) (FILE*)) fflush);
#endif
}
static void
__libc_termios_init_direct_functions (void)
{
__libc_has_enhanced_keyboard = 0;
__libc_has_extended_keystroke = 0;
if (_farpeekb (_dos_ds, 0x496) & 0x10)
__libc_has_enhanced_keyboard = 1;
if (__libc_has_enhanced_keyboard)
{
__direct_keysense = __direct_keysense_at_enh;
__direct_keyinput = __direct_keyinput_at_enh;
__direct_ctrlsense = __direct_ctrlsense_at_enh;
}
else
{
__direct_keysense = __direct_keysense_at;
__direct_keyinput = __direct_keyinput_at;
__direct_ctrlsense = __direct_ctrlsense_at;
}
__direct_output = __direct_output_at;
__direct_outputns = __direct_outputns_at;
__direct_outputs = __direct_outputs_at;
}
void
__libc_termios_init (void)
{
if (__libc_termios_hook_common_count != __bss_count)
{
__libc_termios_hook_common_count = __bss_count;
/* flush all buffered streams */
__libc_termios_fflushall ();
/* check enhanced keyboard, etc */
__libc_termios_init_direct_functions ();
/* set special hooks */
__libc_read_termios_hook = __libc_termios_read;
__libc_write_termios_hook = __libc_termios_write;
/* import parameters */
/* __libc_tty_p = ...; */
/* fsext */
#if 0
(void) __FSEXT_set_function (0, __libc_termios_fsext);
(void) __FSEXT_set_function (1, __libc_termios_fsext);
(void) __FSEXT_set_function (2, __libc_termios_fsext);
#endif
__libc_termios_check_bytes = CHECKBYTES;
}
}
int
__libc_termios_disable_function_and_arrow_keys (void)
{
int old_value;
old_value = __libc_use_function_and_arrow_keys;
__libc_use_function_and_arrow_keys = 0;
return old_value;
}
int
__libc_termios_enable_function_and_arrow_keys (void)
{
int old_value;
old_value = __libc_use_function_and_arrow_keys;
__libc_use_function_and_arrow_keys = 1;
return old_value;
}
/******************************************************************************/
/* direct I/O function ********************************************************/
/* function key trans function */
static void
__direct_add_keystroke (int c)
{
if (__libc_has_extended_keystroke + 1 > sizeof (__libc_extended_keystroke))
return;
__libc_extended_keystroke[__libc_has_extended_keystroke++] = (unsigned char) c;
}
static void
__direct_add_keystrokes (char *s)
{
int len;
len = strlen (s);
if (__libc_has_extended_keystroke + len > sizeof (__libc_extended_keystroke))
return;
while (--len >= 0)
__libc_extended_keystroke[__libc_has_extended_keystroke++] = (unsigned char) s[len];
}
#define _NDUMMY (0xffU)
#define _N(c) (0x00U|(c)) /* no shift */
#define _S(c) (0x40U|(c)) /* w/shift */
#define _C(c) (0x80U|(c)) /* w/ctrl */
#define _A(c) (0xc0U|(c)) /* w/alt */
#define _TRANS_NOSHIFT "\x1b["
#define _TRANS_SHIFT "\x1b[1"
#define _TRANS_CTRL "\x1b[2"
#define _TRANS_ALT "\x1b[3"
static unsigned char trans_alphabet_chars[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
static unsigned char trans_mapping_chars_at[] =
{
/* 000-037: A-Z, 040-077: XA-XZ */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 00-07 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 08-0F */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 10-17 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 18-1F */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 20-27 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 28-2F */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 30-37 */
_NDUMMY, _NDUMMY, _NDUMMY, _N(040), _N(041), _N(042), _N(043), _N(044), /* 38-3F */
_N(045), _N(046), _N(047), _N(050), _N(051), _NDUMMY, _NDUMMY, _N(006), /* 40-47 */
_N(000), _N(010), _NDUMMY, _N(003), _NDUMMY, _N(002), _NDUMMY, _N(007), /* 48-4F */
_N(001), _N(011), _N(004), _N(005), _S(040), _S(041), _S(042), _S(043), /* 50-57 */
_S(044), _S(045), _S(046), _S(047), _S(050), _S(051), _C(040), _C(041), /* 58-5F */
_C(042), _C(043), _C(044), _C(045), _C(046), _C(047), _C(050), _C(051), /* 60-67 */
_A(040), _A(041), _A(042), _A(043), _A(044), _A(045), _A(046), _A(047), /* 68-6F */
_A(050), _A(051), _NDUMMY, _C(003), _C(002), _C(007), _C(011), _C(006), /* 70-77 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 78-7F */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _C(010), _N(052), _N(053), _S(052), /* 80-87 */
_S(053), _C(052), _C(053), _A(052), _A(053), _C(000), _NDUMMY, _NDUMMY, /* 88-8F */
_NDUMMY, _C(001), _C(004), _C(005), _NDUMMY, _NDUMMY, _NDUMMY, _A(006), /* 90-97 */
_A(000), _A(010), _NDUMMY, _A(003), _NDUMMY, _A(002), _NDUMMY, _A(007), /* 98-9F */
_A(001), _A(011), _A(004), _A(005), _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* A0-A7 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* A8-AF */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* B0-B7 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* B8-BF */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* C0-C7 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* C8-CF */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* D0-D7 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* D8-DF */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* E0-E7 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* E8-EF */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* F0-F7 */
_NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* F8-FF */
};
static void
__direct_check_extended_keystroke_at (int scan)
{
int c, shift;
if (!__libc_use_function_and_arrow_keys || scan < 0 || scan > 0xff)
return;
c = (int) trans_mapping_chars_at[scan];
if (c == (int) _NDUMMY)
return;
shift = c & 0xc0;
c &= ~0xc0;
__direct_add_keystroke (trans_alphabet_chars[c]);
if (c >= 040)
__direct_add_keystroke ('X');
if (shift == 0x00)
__direct_add_keystrokes (_TRANS_NOSHIFT);
else if (shift == 0x40)
__direct_add_keystrokes (_TRANS_SHIFT);
else if (shift == 0x80)
__direct_add_keystrokes (_TRANS_CTRL);
else if (shift == 0xc0)
__direct_add_keystrokes (_TRANS_ALT);
}
/* Input form AT keyboard */
static int
__direct_keysense_at (void)
{
__dpmi_regs r;
if (__libc_has_extended_keystroke)
return 1;
r.h.ah = 0x01;
__dpmi_int (0x16, &r);
if (r.x.flags & _REG_STATUS_ZF)
return 0;
return 1;
}
static unsigned char
__direct_keyinput_at (void)
{
__dpmi_regs r;
if (__libc_has_extended_keystroke)
return __libc_extended_keystroke[--__libc_has_extended_keystroke];
r.h.ah = 0x00;
__dpmi_int (0x16, &r);
if (r.h.al != 0x00)
return r.h.al;
__direct_check_extended_keystroke_at (r.h.ah);
if (__libc_has_extended_keystroke)
return __libc_extended_keystroke[--__libc_has_extended_keystroke];
return 0;
}
static int
__direct_ctrlsense_at (void)
{
__dpmi_regs r;
if (__libc_has_extended_keystroke)
return 0;
r.h.ah = 0x02;
__dpmi_int (0x16, &r);
if (r.h.al & _KEY_CTRL)
return 1;
return 0;
}
/* Input from AT enhanced keyboard */
static int
__direct_keysense_at_enh (void)
{
__dpmi_regs r;
if (__libc_has_extended_keystroke)
return 1;
r.h.ah = 0x11;
__dpmi_int (0x16, &r);
if (r.x.flags & _REG_STATUS_ZF)
return 0;
return 1;
}
static unsigned char
__direct_keyinput_at_enh (void)
{
__dpmi_regs r;
if (__libc_has_extended_keystroke)
return __libc_extended_keystroke[--__libc_has_extended_keystroke];
r.h.ah = 0x10;
__dpmi_int (0x16, &r);
if (r.h.al != 0x00 && (r.h.al < 0xe0U
|| (r.h.al != 0xe0 && r.h.al != 0xf0)))
return r.h.al;
__direct_check_extended_keystroke_at (r.h.ah);
if (__libc_has_extended_keystroke)
return __libc_extended_keystroke[--__libc_has_extended_keystroke];
return 0;
}
static int
__direct_ctrlsense_at_enh (void)
{
__dpmi_regs r;
if (__libc_has_extended_keystroke)
return 0;
r.h.ah = 0x12;
__dpmi_int (0x16, &r);
if (r.h.al & _KEY_CTRL) /* either CTRL */
return 1;
return 0;
}
/* output to Screen */
static void
__direct_output_tab_at (void)
{
__dpmi_regs r;
int page, col;
int x, y;
page = _farpeekb (_dos_ds, 0x462);
col = _farpeekw (_dos_ds, 0x44a);
r.h.ah = 3;
r.h.bh = page;
__dpmi_int (0x10, &r);
x = r.h.dl;
y = r.h.dh;
x += 8;
x &= ~7;
if (x > col)
{
#if 1
r.h.al = '\r';
__dpmi_int (0x29, &r);
r.h.al = '\n';
__dpmi_int (0x29, &r);
#else
(void) putch ('\r');
(void) putch ('\n');
#endif
}
else
{
r.h.ah = 2;
r.h.bh = page;
r.h.dl = x;
r.h.dh = y;
__dpmi_int (0x10, &r);
}
}
static void
__direct_output_at (unsigned char ch)
{
#if 1
__dpmi_regs r;
#endif
if (ch == 0x09)
{
__direct_output_tab_at ();
return;
}
else if (ch == 0xff)
return;
#if 1
r.h.al = ch;
__dpmi_int (0x29, &r);
#else
(void) putch (ch);
#endif
}
static void
__direct_outputns_at (int n, const unsigned char *s)
{
#if 1
__dpmi_regs r;
#endif
unsigned char ch;
while (--n >= 0)
{
ch = *s++;
if (ch == 0x09)
__direct_output_tab_at ();
else if (ch != 0xff)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -