📄 tminit.c
字号:
/******************************************************************************/
/* echo routines **************************************************************/
static void
__libc_termios_echo_ctrl (unsigned char ch)
{
ch ^= 0x40;
__direct_output ('^');
__direct_output (ch);
}
static void
__libc_termios_maybe_echo_ctrl (unsigned char ch)
{
if (__libc_tty_p->t_lflag & ECHOCTL)
__libc_termios_echo_ctrl (ch);
}
static void
__libc_termios_maybe_echo (unsigned char ch)
{
if (! (__libc_tty_p->t_lflag & ECHO))
{
/* don't echo but newline is required ? */
if (ch == '\n' && (__libc_tty_p->t_lflag & ECHONL))
{
if (__libc_tty_p->t_oflag & ONLCR)
__direct_output ('\r');
__direct_output ('\n');
}
return;
}
/* check literal flag */
if ((__libc_tty_p->t_status & _TS_LNCH) && (ch < 0x20))
{
__libc_termios_echo_ctrl (ch);
return;
}
/* output process if need */
if (__libc_tty_p->t_oflag & OPOST)
{
/* map NL to CRNL */
if (ch == '\n' && (__libc_tty_p->t_oflag & ONLCR))
{
__direct_output ('\r');
__direct_output ('\n');
return;
}
/* map CR to NL */
else if (ch == '\r' && (__libc_tty_p->t_oflag & OCRNL))
{
__direct_output ('\n');
return;
}
/* discard EOT */
else if (_CC_EQU (VEOF, ch) && (__libc_tty_p->t_oflag & ONOEOT))
{
return;
}
}
/* control character except newline */
if ((ch < 0x20 || ch == 0x7f) && (__libc_tty_p->t_lflag & ECHOCTL) && ch != '\n')
{
__libc_termios_echo_ctrl (ch);
return;
}
/* no effect */
__direct_output (ch);
}
/******************************************************************************/
/* edit routines **************************************************************/
static void
__libc_termios_maybe_erase1 (void)
{
if (__libc_tty_p->t_lflag & ECHO)
{
/* eat prev. character by BS SPC BS */
__direct_output ('\010');
if (__libc_tty_p->t_lflag & ECHOE)
{
__direct_output (' ');
__direct_output ('\010');
}
}
}
/* erase one prev. character of editline */
static void
__libc_termios_erase_editline (void)
{
int col;
char pf;
col = __libc_tty_editline.col;
if (col == 0) /* no more */
return;
/* get position flag */
pf = __libc_tty_editline.flag[col - 1];
if (pf == _TTY_EDITLINE_INVALID || pf < 0)
{
/* erase all invalid character */
while (col > 0 && __libc_tty_editline.flag[col - 1] < 0)
{
__libc_termios_maybe_erase1 ();
--col;
}
}
else if (pf == _TTY_EDITLINE_CTRL)
{
if (__libc_tty_p->t_lflag & ECHOCTL)
{
/* erase one of "^X" */
__libc_termios_maybe_erase1 ();
--col;
}
__libc_termios_maybe_erase1 ();
--col;
}
else
{
/* erase single or multibyte charcter */
while (--pf >= 0)
{
__libc_termios_maybe_erase1 ();
--col;
}
}
/* set next insert position */
__libc_tty_editline.col = col;
}
/* erase all editline */
static void
__libc_termios_kill_editline (void)
{
if (__libc_tty_p->t_lflag & ECHOKE)
{
while (__libc_tty_editline.col != 0)
__libc_termios_erase_editline ();
}
else
__libc_tty_editline.col = 0;
if (__libc_tty_p->t_lflag & ECHOK)
__libc_termios_maybe_echo ('\n');
}
static void
__libc_termios_insert_editline (unsigned char ch)
{
int mbsize;
int col;
col = __libc_tty_editline.col;
if (col >= _TTY_EDITLINE_SIZE)
{
/* detected over flow */
if (__libc_tty_p->t_iflag & IMAXBEL)
__direct_output ('\007');
return;
}
__libc_tty_editline.buf[col] = ch;
if (col == 0 || ((col > 0)
&& __libc_tty_editline.flag[col - 1] != _TTY_EDITLINE_INVALID))
{
/* check multibyte length */
mbsize = mblen (__libc_tty_editline.buf + col, 1);
if (mbsize == 1)
{
/* single character */
if ((ch < 0x20) || ch == 0x7f)
__libc_tty_editline.flag[col] = _TTY_EDITLINE_CTRL;
else
__libc_tty_editline.flag[col] = _TTY_EDITLINE_SINGLE;
__libc_termios_maybe_echo (ch);
}
else
{
/* first of multibyte or invalid character */
__libc_tty_editline.flag[col] = _TTY_EDITLINE_INVALID;
__libc_tty_p->t_status |= _TS_LNCH;
}
}
else
{
int pcol;
/* look for non fixed flag */
pcol = col;
while (__libc_tty_editline.flag[pcol - 1] == _TTY_EDITLINE_INVALID)
if (--pcol <= 0)
break;
/* check whether it's multibyte sequence */
mbsize = mblen (__libc_tty_editline.buf + pcol, (col - pcol + 1));
if (mbsize > 1)
{
/* multibyte sequence is good */
while (pcol < col)
{
/* set negative size for dividing sequence */
__libc_tty_editline.flag[pcol] = -mbsize;
__libc_termios_maybe_echo (__libc_tty_editline.buf[pcol]);
pcol++;
}
/* last flag is always positive size */
__libc_tty_editline.flag[col] = mbsize;
__libc_termios_maybe_echo (ch);
}
else
{
if ((col - pcol + 1) > MB_CUR_MAX)
{
/* it's terrible... */
while (pcol <= col)
{
/* replace all with valid character */
__libc_tty_editline.flag[pcol] = _TTY_EDITLINE_SINGLE;
__libc_tty_editline.buf[pcol] = 'X';
__libc_termios_maybe_echo ('X');
pcol++;
}
}
/* continuous multibyte character */
__libc_tty_editline.flag[col] = _TTY_EDITLINE_INVALID;
__libc_tty_p->t_status |= _TS_LNCH;
}
}
/* set next insert position */
col++;
__libc_tty_editline.col = col;
}
/******************************************************************************/
/* queued input routines ******************************************************/
static int
__libc_termios_exist_queue (void)
{
return __libc_tty_p->t_count;
}
static void
__libc_termios_clear_queue (void)
{
__libc_tty_p->t_count = 0;
__libc_tty_p->t_rpos = __libc_tty_p->t_top;
__libc_tty_p->t_wpos = __libc_tty_p->t_top;
}
static int
__libc_termios_get_queue (void)
{
int ch;
if (__libc_tty_p->t_count == 0)
return -1;
ch = *__libc_tty_p->t_rpos++;
__libc_tty_p->t_count--;
if (__libc_tty_p->t_rpos >= __libc_tty_p->t_bottom)
__libc_tty_p->t_rpos = __libc_tty_p->t_top;
return ch;
}
static int
__libc_termios_put_queue (unsigned char ch)
{
if (__libc_tty_p->t_count >= __libc_tty_p->t_size)
return -1;
*__libc_tty_p->t_wpos++ = ch;
__libc_tty_p->t_count++;
if (__libc_tty_p->t_wpos >= __libc_tty_p->t_bottom)
__libc_tty_p->t_wpos = __libc_tty_p->t_top;
return 0;
}
static void
__libc_termios_raise_signal (unsigned char ch, int sig)
{
#if 0
struct sigaction oldact;
if (sigaction (sig, NULL, &oldact) == 0)
if (oldact.sa_handler == SIG_DFL)
__libc_termios_maybe_echo_ctrl (ch);
#else
__libc_termios_maybe_echo_ctrl (ch);
#endif
kill (getpid(), sig);
}
static void
__libc_termios_fill_queue (void)
{
unsigned char ch;
while (1)
{
/* exhaust inputs ? */
if (! __direct_keysense ())
{
__dpmi_yield ();
/* wait for NL or EOT ? */
if (__libc_tty_p->t_lflag & ICANON)
continue;
return;
}
/* realy get */
ch = __direct_keyinput ();
/* replace CTRL+SPACE with 0x00 */
if (ch == ' ' && __direct_ctrlsense ())
ch = '\0';
/* input process if need */
if (! (__libc_tty_p->t_status & _TS_LNCH) || ch != (unsigned char) _POSIX_VDISABLE)
{
/* software signals */
if (__libc_tty_p->t_lflag & ISIG)
{
if (! (__libc_tty_p->t_iflag & IGNBRK) && _CC_EQU (VINTR, ch))
{
if (__libc_tty_p->t_iflag & BRKINT)
{
__libc_termios_raise_signal (ch, SIGINT);
continue;
}
else
{
ch = '\0';
goto proc_skip;
}
}
else if (_CC_EQU (VQUIT, ch))
{
__libc_termios_raise_signal (ch, SIGQUIT);
continue;
}
else if (_CC_EQU (VSUSP, ch))
{
#ifdef SIGTSTP
__libc_termios_raise_signal (ch, SIGTSTP);
#else /* djgpp don't have ... */
{
char oldcwd[PATH_MAX];
int fds[5] = { -1, -1, -1, -1, -1 };
int i;
for (i = 0; i < 5; i++)
if ((fds[i] = fcntl (i, F_DUPFD, 20)) < 0)
__direct_outputs ("Suspend: cannot save fds\r\n");
__direct_outputs ("\r\nSuspended\r\n");
/* keep cwd on exec */
getcwd (oldcwd, sizeof (oldcwd));
system ("");
chdir (oldcwd);
for (i = 0; i < 5; i++)
if (fds[i] >= 0)
{
dup2 (fds[i], i);
close (fds[i]);
}
}
#endif /* !SIGTSTP */
continue;
}
}
/* flow control... */
if (_CC_EQU (VSTART, ch) && (__libc_tty_p->t_iflag & IXOFF))
{
continue;
}
else if (_CC_EQU (VSTOP, ch) && (__libc_tty_p->t_iflag & IXOFF))
{
continue;
}
/* CR/LF process */
if (ch == '\r')
{
if (__libc_tty_p->t_iflag & IGNCR)
continue;
if (__libc_tty_p->t_iflag & ICRNL)
ch = '\n';
}
else if ((ch == '\n') && (__libc_tty_p->t_iflag & INLCR))
ch = '\r';
/* strip 8th-bit */
if (__libc_tty_p->t_iflag & ISTRIP)
ch &= 0x7f;
}
proc_skip:
if (__libc_tty_p->t_lflag & ICANON)
{
if (__libc_tty_p->t_status & _TS_LNCH)
{
__libc_tty_p->t_status &= ~_TS_LNCH;
__libc_termios_insert_editline (ch);
}
else
{
if (_CC_EQU (VERASE, ch))
__libc_termios_erase_editline ();
else if (_CC_EQU (VKILL, ch))
__libc_termios_kill_editline ();
else if (ch == '\n' || _CC_EQU (VEOF, ch) || _CC_EQU (VEOL, ch))
{
int col = __libc_tty_editline.col;
unsigned char *p = __libc_tty_editline.buf;
/* clear column for next access */
__libc_tty_editline.col = 0;
/* copy editline into tty queue */
while (--col >= 0)
__libc_termios_put_queue (*p++);
/* echo terminate character and put it */
__libc_termios_maybe_echo (ch);
if (_CC_NEQU (VEOF, ch))
__libc_termios_put_queue (ch);
return;
}
else
__libc_termios_insert_editline (ch);
} /* !_TS_LNCH */
}
else /* !ICANON */
{
__libc_termios_maybe_echo (ch);
__libc_tty_p->t_status &= ~_TS_LNCH;
__libc_termios_put_queue (ch);
}
} /* end of while (1) */
}
/******************************************************************************/
/* software signal checker ****************************************************/
void
__libc_termios_check_signals (void)
{
unsigned char ch;
if (! __direct_keysense ())
return;
/* software signals */
if (__libc_tty_p->t_lflag & ISIG)
{
ch = __direct_keyinput ();
if (! (__libc_tty_p->t_iflag & IGNBRK) && _CC_EQU (VINTR, ch))
{
if (__libc_tty_p->t_iflag & BRKINT)
{
__libc_termios_raise_signal (ch, SIGINT);
return;
}
}
else if (_CC_EQU (VQUIT, ch))
{
__libc_termios_raise_signal (ch, SIGQUIT);
return;
}
/* for compatiblity */
if (ch == 0x13 && !(__libc_tty_p->t_iflag & IXOFF))
{
/* CTRL+S */
while (! __direct_keysense ())
__dpmi_yield ();
ch = __direct_keyinput ();
return;
}
/* push back */
__direct_add_keystroke ((int) ch);
}
}
/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -