#ifdef M_RCSID
#ifndef lint
static char rcsID[] =
"$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
"libxcurses/src/libc/xcurses/rcs/wgetch.c 1.23 1998/06/05 16:38:43 "
"cbates Exp $";
#endif
#endif
#include <private.h>
#include <string.h>
#include <errno.h>
static struct termios read_termios;
int
iqContainsFullLine(void)
{
int i;
if (!(PTERMIOS(_prog)->c_lflag & ICANON)) {
return (1);
}
if (read_termios.c_lflag & ICANON) {
return (1);
}
if ((read_termios.c_cc[VMIN] == 0) &&
(read_termios.c_cc[VTIME] != 0)) {
return (!iqIsEmpty());
}
for (i = __m_screen->_unget._count - 1; i >= 0; i--) {
int ch = __m_screen->_unget._stack[i];
if (PTERMIOS(_shell)->c_cc[VEOL] == ch)
return (1);
if ('\n' == ch)
return (1);
}
return (0);
}
void
iqPush(unsigned int ch)
{
if (__m_screen->_unget._count >= __m_screen->_unget._size)
return;
__m_screen->_unget._stack[__m_screen->_unget._count++] =
(int) ch;
}
void
iqAdd(unsigned int ch)
{
int count;
if (++(__m_screen->_unget._count) >= __m_screen->_unget._size)
__m_screen->_unget._count = __m_screen->_unget._size - 1;
count = __m_screen->_unget._count - 1;
if (count) {
(void) memmove(__m_screen->_unget._stack + 1,
__m_screen->_unget._stack, count * sizeof (int));
}
__m_screen->_unget._stack[0] = (int) ch;
}
int
iqIsEmpty(void)
{
return (__m_screen->_unget._count == 0);
}
void
iqReset(void)
{
__m_screen->_unget._count = 0;
}
int
iqPull(void)
{
int ch;
ch = __m_screen->_unget._stack[--(__m_screen->_unget._count)];
return (ch);
}
void
iqTrash(int n)
{
__m_screen->_unget._count -= n;
if (__m_screen->_unget._count < 0) {
__m_screen->_unget._count = 0;
}
}
int
iqGetNth(int n)
{
int ch;
if (__m_screen->_unget._count - n <= 0) {
return (EOF);
}
ch = __m_screen->_unget._stack[__m_screen->_unget._count - n - 1];
return (ch);
}
struct termios
__m_tty_override_mode(int vmin, int vtime)
{
struct termios rval;
struct termios newstuff;
rval = newstuff = *PTERMIOS(_actual);
if (!(vmin == 0 && vtime == 0) &&
(cur_term->_flags & __TERM_HALF_DELAY))
return (rval);
if (vmin == 1)
return (rval);
newstuff.c_cc[VMIN] = (cc_t) vmin;
newstuff.c_cc[VTIME] = (cc_t) vtime;
newstuff.c_lflag &= ~ICANON;
(void) __m_tty_set(&newstuff);
return (rval);
}
int
__m_read_input_char(int *pChar)
{
if (req_for_input != NULL) {
(void) TPUTS(req_for_input, 1, __m_outc);
}
clearerr(__m_screen->_if);
*pChar = 0;
read_termios = *PTERMIOS(_actual);
errno = 0;
if ((*pChar = fgetc(__m_screen->_if)) == EOF) {
return ((errno) ? ERR : OK);
}
if (((PTERMIOS(_prog)->c_cflag & CSIZE) != CS8) && (*pChar != EOF))
*pChar &= 0x7f;
return (OK);
}
int
__m_typeahead_read_input_char(int *pChar)
{
unsigned char ch;
ssize_t r;
if (req_for_input != NULL) {
(void) TPUTS(req_for_input, 1, __m_outc);
}
*pChar = 0;
read_termios = *PTERMIOS(_actual);
errno = 0;
if ((r = read(__m_screen->_kfd, (void *)&ch, 1)) > 0) {
if ((PTERMIOS(_prog)->c_cflag & CSIZE) != CS8) {
*pChar = ch & 0x7f;
} else {
*pChar = (int)ch;
}
return (OK);
} else if (r == 0) {
*pChar = EOF;
return (OK);
} else {
return (ERR);
}
}
static int klugeTypeaheadInGetch = 0;
int
pollTypeahead(void)
{
struct termios save;
int ch;
if (!(__m_screen->_flags & S_ISATTY) ||
!(__m_screen->_flags & S_TYPEAHEAD_OK)) {
return (0);
}
save = __m_tty_override_mode(0, 0);
while (__m_typeahead_read_input_char(&ch) == OK) {
if (ch == EOF)
break;
iqAdd(ch);
}
(void) __m_tty_set(&save);
return ((klugeTypeaheadInGetch) ? 0 : !iqIsEmpty());
}
int
ungetch(int ch)
{
iqPush(ch);
return (OK);
}
int
__xc_ferror(void *w)
{
return (ferror(__m_screen->_if));
}
int
__xc_ungetc(int ch, void *w)
{
iqPush(ch);
return (1);
}
int
__xc_feof(void *w)
{
return (feof(__m_screen->_if));
}
void
__xc_clearerr(void *w)
{
clearerr(__m_screen->_if);
}
int
__m_echo(WINDOW *w, int ch)
{
if (!(__m_screen->_flags & S_ECHO))
return (ch);
if (!(0 <= ch && ch != EOF)) {
(void) beep();
return (ERR);
}
if (ch == '\b') {
if (w->_curx <= 0) {
(void) beep();
return (ch);
}
w->_curx--;
(void) wdelch(w);
} else {
(void) waddch(w, ch);
}
(void) wrefresh(w);
return (ch);
}
int
wgetch(WINDOW *w)
{
t_decode *node;
int ch, i, timeout;
struct termios save;
__m_screen->_flags |= S_TYPEAHEAD_OK;
klugeTypeaheadInGetch = 1;
(void) wrefresh(w);
klugeTypeaheadInGetch = 0;
if (iqIsEmpty()) {
save = __m_tty_override_mode(w->_vmin, w->_vtime);
if (__m_read_input_char(&ch) == ERR) {
(void) __m_tty_set(&save);
return (ERR);
}
if (!((ch == EOF) && (PTERMIOS(_prog)->c_lflag & ICANON))) {
iqAdd(ch);
}
(void) __m_tty_set(&save);
}
ch = iqGetNth(0);
if (!iqContainsFullLine()) {
return (ERR);
}
if ((w->_flags & W_USE_KEYPAD) && 0 <= ch && ch != EOF) {
#ifdef _POSIX_VDISABLE
if (PTERMIOS(_shell)->c_cc[VERASE] != _POSIX_VDISABLE)
#endif
if (ch == PTERMIOS(_shell)->c_cc[VERASE]) {
(void) iqPull();
return (KEY_BACKSPACE);
}
node = (t_decode *) __m_screen->_decode;
timeout = w->_flags & W_USE_TIMEOUT;
for (i = 1; ; i++) {
while (node->ch != ch) {
node = node->sibling;
if (node == NULL)
goto uncoded;
}
if (node->key != 0) {
iqTrash(i);
return (__m_echo(w, node->key));
}
if ((ch = iqGetNth(i)) == EOF) {
if (timeout) {
(void) __m_tty_override_mode(0,
M_CURSES_INTERBYTE_TIME);
}
timeout = 0;
if (__m_read_input_char(&ch) == ERR)
return (ERR);
if (ch == EOF)
break;
iqAdd(ch);
}
node = node->child;
}
}
uncoded:
ch = iqPull();
return (__m_echo(w, ch));
}