Refactor TTY input handling

This commit is contained in:
Hanicef 2024-05-19 12:20:03 +02:00
parent 47bcad4ab1
commit 64df782287
2 changed files with 52 additions and 104 deletions

View file

@ -705,10 +705,9 @@ typedef struct
static feild_t tty_con; static feild_t tty_con;
// when printing general stuff to stdout stderr (Sys_Printf) // lock to prevent clearing partial lines, since not everything
// we need to disable the tty console stuff // printed ends on a newline.
// this increments so we can recursively disable static boolean ttycon_ateol = true;
static INT32 ttycon_hide = 0;
// some key codes that the terminal may be using // some key codes that the terminal may be using
// TTimo NOTE: I'm not sure how relevant this is // TTimo NOTE: I'm not sure how relevant this is
static INT32 tty_erase; static INT32 tty_erase;
@ -736,63 +735,31 @@ static inline void tty_FlushIn(void)
// TTimo NOTE: it seems on some terminals just sending '\b' is not enough // TTimo NOTE: it seems on some terminals just sending '\b' is not enough
// so for now, in any case we send "\b \b" .. yeah well .. // so for now, in any case we send "\b \b" .. yeah well ..
// (there may be a way to find out if '\b' alone would work though) // (there may be a way to find out if '\b' alone would work though)
// Hanicef NOTE: using \b this way is unreliable because of terminal state,
// it's better to use \r to reset the cursor to the beginning of the
// line and clear from there.
static void tty_Back(void) static void tty_Back(void)
{ {
char key; write(STDOUT_FILENO, "\r", 1);
ssize_t d; if (tty_con.cursor>0)
key = '\b'; {
d = write(STDOUT_FILENO, &key, 1); write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor);
key = ' '; }
d = write(STDOUT_FILENO, &key, 1); write(STDOUT_FILENO, " \b", 2);
key = '\b';
d = write(STDOUT_FILENO, &key, 1);
(void)d;
} }
static void tty_Clear(void) static void tty_Clear(void)
{ {
size_t i; size_t i;
write(STDOUT_FILENO, "\r", 1);
if (tty_con.cursor>0) if (tty_con.cursor>0)
{ {
for (i=0; i<tty_con.cursor; i++) for (i=0; i<tty_con.cursor; i++)
{ {
tty_Back(); write(STDOUT_FILENO, " ", 1);
} }
write(STDOUT_FILENO, "\r", 1);
} }
}
// clear the display of the line currently edited
// bring cursor back to beginning of line
static inline void tty_Hide(void)
{
//I_Assert(consolevent);
if (ttycon_hide)
{
ttycon_hide++;
return;
}
tty_Clear();
ttycon_hide++;
}
// show the current line
// FIXME TTimo need to position the cursor if needed??
static inline void tty_Show(void)
{
size_t i;
ssize_t d;
//I_Assert(consolevent);
I_Assert(ttycon_hide>0);
ttycon_hide--;
if (ttycon_hide == 0 && tty_con.cursor)
{
for (i=0; i<tty_con.cursor; i++)
{
d = write(STDOUT_FILENO, tty_con.buffer+i, 1);
}
}
(void)d;
} }
// never exit without calling this, or your terminal will be left in a pretty bad state // never exit without calling this, or your terminal will be left in a pretty bad state
@ -900,6 +867,11 @@ static void I_GetConsoleEvents(void)
tty_con.cursor = 0; tty_con.cursor = 0;
ev.key = KEY_ENTER; ev.key = KEY_ENTER;
} }
else if (key == 0x4) // ^D, aka EOF
{
// shut down, most unix programs behave this way
I_Quit();
}
else continue; else continue;
} }
else if (tty_con.cursor < sizeof(tty_con.buffer)) else if (tty_con.cursor < sizeof(tty_con.buffer))
@ -1152,18 +1124,20 @@ void I_OutputMsg(const char *fmt, ...)
} }
#else #else
#ifdef HAVE_TERMIOS #ifdef HAVE_TERMIOS
if (consolevent) if (consolevent && ttycon_ateol)
{ {
tty_Hide(); tty_Clear();
ttycon_ateol = false;
} }
#endif #endif
if (!framebuffer) if (!framebuffer)
fprintf(stderr, "%s", txt); fprintf(stderr, "%s", txt);
#ifdef HAVE_TERMIOS #ifdef HAVE_TERMIOS
if (consolevent) if (consolevent && txt[strlen(txt)-1] == '\n')
{ {
tty_Show(); write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor);
ttycon_ateol = true;
} }
#endif #endif

View file

@ -466,10 +466,9 @@ typedef struct
feild_t tty_con; feild_t tty_con;
// when printing general stuff to stdout stderr (Sys_Printf) // lock to prevent clearing partial lines, since not everything
// we need to disable the tty console stuff // printed ends on a newline.
// this increments so we can recursively disable static boolean ttycon_ateol = true;
static INT32 ttycon_hide = 0;
// some key codes that the terminal may be using // some key codes that the terminal may be using
// TTimo NOTE: I'm not sure how relevant this is // TTimo NOTE: I'm not sure how relevant this is
static INT32 tty_erase; static INT32 tty_erase;
@ -497,63 +496,31 @@ static inline void tty_FlushIn(void)
// TTimo NOTE: it seems on some terminals just sending '\b' is not enough // TTimo NOTE: it seems on some terminals just sending '\b' is not enough
// so for now, in any case we send "\b \b" .. yeah well .. // so for now, in any case we send "\b \b" .. yeah well ..
// (there may be a way to find out if '\b' alone would work though) // (there may be a way to find out if '\b' alone would work though)
// Hanicef NOTE: using \b this way is unreliable because of terminal state,
// it's better to use \r to reset the cursor to the beginning of the
// line and clear from there.
static void tty_Back(void) static void tty_Back(void)
{ {
char key; write(STDOUT_FILENO, "\r", 1);
ssize_t d; if (tty_con.cursor>0)
key = '\b'; {
d = write(STDOUT_FILENO, &key, 1); write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor);
key = ' '; }
d = write(STDOUT_FILENO, &key, 1); write(STDOUT_FILENO, " \b", 2);
key = '\b';
d = write(STDOUT_FILENO, &key, 1);
(void)d;
} }
static void tty_Clear(void) static void tty_Clear(void)
{ {
size_t i; size_t i;
write(STDOUT_FILENO, "\r", 1);
if (tty_con.cursor>0) if (tty_con.cursor>0)
{ {
for (i=0; i<tty_con.cursor; i++) for (i=0; i<tty_con.cursor; i++)
{ {
tty_Back(); write(STDOUT_FILENO, " ", 1);
} }
write(STDOUT_FILENO, "\r", 1);
} }
}
// clear the display of the line currently edited
// bring cursor back to beginning of line
static inline void tty_Hide(void)
{
//I_Assert(consolevent);
if (ttycon_hide)
{
ttycon_hide++;
return;
}
tty_Clear();
ttycon_hide++;
}
// show the current line
// FIXME TTimo need to position the cursor if needed??
static inline void tty_Show(void)
{
size_t i;
ssize_t d;
//I_Assert(consolevent);
I_Assert(ttycon_hide>0);
ttycon_hide--;
if (ttycon_hide == 0 && tty_con.cursor)
{
for (i=0; i<tty_con.cursor; i++)
{
d = write(STDOUT_FILENO, tty_con.buffer+i, 1);
}
}
(void)d;
} }
// never exit without calling this, or your terminal will be left in a pretty bad state // never exit without calling this, or your terminal will be left in a pretty bad state
@ -661,6 +628,11 @@ void I_GetConsoleEvents(void)
tty_con.cursor = 0; tty_con.cursor = 0;
ev.key = KEY_ENTER; ev.key = KEY_ENTER;
} }
else if (key == 0x4) // ^D, aka EOF
{
// shut down, most unix programs behave this way
I_Quit();
}
else continue; else continue;
} }
else if (tty_con.cursor < sizeof (tty_con.buffer)) else if (tty_con.cursor < sizeof (tty_con.buffer))
@ -959,18 +931,20 @@ void I_OutputMsg(const char *fmt, ...)
} }
#else #else
#ifdef HAVE_TERMIOS #ifdef HAVE_TERMIOS
if (consolevent) if (consolevent && ttycon_ateol)
{ {
tty_Hide(); tty_Clear();
ttycon_ateol = false;
} }
#endif #endif
if (!framebuffer) if (!framebuffer)
fprintf(stderr, "%s", txt); fprintf(stderr, "%s", txt);
#ifdef HAVE_TERMIOS #ifdef HAVE_TERMIOS
if (consolevent) if (consolevent && txt[strlen(txt)-1] == '\n')
{ {
tty_Show(); write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor);
ttycon_ateol = true;
} }
#endif #endif