diff options
author | Andrey Nazarov <skuller@skuller.net> | 2012-08-06 01:41:52 +0400 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2012-08-12 19:38:29 +0400 |
commit | ae904634871dab4127472ab07a0b06108d71f327 (patch) | |
tree | 469b6d6d60272aaccec4e590fcbb2893d3923b22 | |
parent | b79ddecd015a57b2b52654fb8b9c3af519a5e31a (diff) |
Split TTY code into separate file.
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | inc/system/system.h | 3 | ||||
-rw-r--r-- | src/unix/system.c | 492 | ||||
-rw-r--r-- | src/unix/tty.c | 480 | ||||
-rw-r--r-- | src/unix/tty.h | 30 |
5 files changed, 526 insertions, 484 deletions
@@ -508,6 +508,11 @@ else OBJS_s += src/unix/hunk.o src/unix/system.o OBJS_c += src/unix/hunk.o src/unix/system.o + ifndef CONFIG_NO_SYSTEM_CONSOLE + OBJS_s += src/unix/tty.o + OBJS_c += src/unix/tty.o + endif + # System libs LIBS_s += -lm -ldl LIBS_c += -lm -ldl diff --git a/inc/system/system.h b/inc/system/system.h index 40bd530..059db6d 100644 --- a/inc/system/system.h +++ b/inc/system/system.h @@ -56,8 +56,5 @@ extern cvar_t *sys_basedir; extern cvar_t *sys_libdir; extern cvar_t *sys_homedir; extern cvar_t *sys_forcegamelib; -#if USE_SYSCON && !(defined _WIN32) -extern cvar_t *sys_console; -#endif #endif // SYSTEM_H diff --git a/src/unix/system.c b/src/unix/system.c index 443eefa..0911627 100644 --- a/src/unix/system.c +++ b/src/unix/system.c @@ -20,26 +20,22 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/cmd.h" #include "common/common.h" #include "common/cvar.h" -#include "common/field.h" #include "common/files.h" -#include "common/net/net.h" -#include "common/prompt.h" #if USE_REF #include "client/video.h" #endif #include "system/system.h" +#include "tty.h" #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/mman.h> -#include <sys/ioctl.h> #include <unistd.h> #include <fcntl.h> #include <signal.h> #include <dirent.h> #include <dlfcn.h> -#include <termios.h> #include <errno.h> cvar_t *sys_basedir; @@ -52,419 +48,6 @@ cvar_t *sys_parachute; /* =============================================================================== -TERMINAL SUPPORT - -=============================================================================== -*/ - -#if USE_SYSCON - -cvar_t *sys_console; - -static qboolean tty_enabled; -static struct termios tty_orig; -static commandPrompt_t tty_prompt; -static int tty_hidden; -static ioentry_t *tty_io; - -static int stdout_sleep(void) -{ - struct timeval tv; - fd_set fd; - - tv.tv_sec = 0; - tv.tv_usec = 10000; - - FD_ZERO(&fd); - FD_SET(STDOUT_FILENO, &fd); - - return select(STDOUT_FILENO + 1, NULL, &fd, NULL, &tv); -} - -// handles partial writes correctly, but never spins too much -// blocks for 100 ms before giving up and losing data -static void stdout_write(const char *buf, size_t len) -{ - const char *what; - int ret, spins; - - for (spins = 0; spins < 10; spins++) { - if (len == 0) - break; - - ret = write(STDOUT_FILENO, buf, len); - if (q_unlikely(ret < 0)) { - if (errno == EINTR) - continue; - - if (errno == EAGAIN) { - ret = stdout_sleep(); - if (ret >= 0) - continue; - what = "select"; - } else { - what = "write"; - } - - // avoid recursive calls - sys_console = NULL; - tty_enabled = qfalse; - - Com_Error(ERR_FATAL, "%s: %s() failed: %s", - __func__, what, strerror(errno)); - } - - buf += ret; - len -= ret; - } -} - -static void tty_hide_input(void) -{ - int i; - - if (!tty_hidden) { - for (i = 0; i <= tty_prompt.inputLine.cursorPos; i++) { - stdout_write("\b \b", 3); - } - } - tty_hidden++; -} - -static void tty_show_input(void) -{ - if (!tty_hidden) { - return; - } - - tty_hidden--; - if (!tty_hidden) { - stdout_write("]", 1); - stdout_write(tty_prompt.inputLine.text, - tty_prompt.inputLine.cursorPos); - } -} - -static void tty_init_input(void) -{ - struct termios tty; -#ifdef TIOCGWINSZ - struct winsize ws; -#endif - int width; - - if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) { - Com_Printf("stdin/stdout don't both refer to a TTY\n"); - Cvar_Set("sys_console", "1"); - return; - } - - tcgetattr(STDIN_FILENO, &tty_orig); - tty = tty_orig; - tty.c_iflag &= ~(INPCK | ISTRIP); - tty.c_lflag &= ~(ICANON | ECHO); - tty.c_cc[VMIN] = 1; - tty.c_cc[VTIME] = 0; - tcsetattr(STDIN_FILENO, TCSADRAIN, &tty); - - // determine terminal width - width = 80; -#ifdef TIOCGWINSZ - if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) { - if (ws.ws_col) { - width = ws.ws_col; - } - } -#endif - tty_prompt.widthInChars = width; - tty_prompt.printf = Sys_Printf; - tty_enabled = qtrue; - - // figure out input line width - width--; - if (width > MAX_FIELD_TEXT - 1) { - width = MAX_FIELD_TEXT - 1; - } - IF_Init(&tty_prompt.inputLine, width, width); - - // display command prompt - stdout_write("]", 1); -} - -static void tty_shutdown_input(void) -{ - if (tty_io) { - NET_RemoveFd(STDIN_FILENO); - tty_io = NULL; - } - if (tty_enabled) { - tty_hide_input(); - tcsetattr(STDIN_FILENO, TCSADRAIN, &tty_orig); - tty_enabled = qfalse; - } -} - -void Sys_SetConsoleColor(color_index_t color) -{ - static const char color_to_ansi[8] = - { '0', '1', '2', '3', '4', '6', '5', '7' }; - char buf[5]; - size_t len; - - if (!sys_console || !sys_console->integer) { - return; - } - - if (!tty_enabled) { - return; - } - - buf[0] = '\033'; - buf[1] = '['; - switch (color) { - case COLOR_NONE: - buf[2] = '0'; - buf[3] = 'm'; - len = 4; - break; - case COLOR_ALT: - buf[2] = '3'; - buf[3] = '2'; - buf[4] = 'm'; - len = 5; - break; - default: - buf[2] = '3'; - buf[3] = color_to_ansi[color]; - buf[4] = 'm'; - len = 5; - break; - } - - if (color != COLOR_NONE) { - tty_hide_input(); - } - stdout_write(buf, len); - if (color == COLOR_NONE) { - tty_show_input(); - } -} - -static void tty_write_output(const char *text) -{ - char buf[MAXPRINTMSG]; - size_t len; - - for (len = 0; len < MAXPRINTMSG; len++) { - int c = *text++; - if (!c) { - break; - } - buf[len] = Q_charascii(c); - } - - stdout_write(buf, len); -} - -/* -================= -Sys_ConsoleOutput -================= -*/ -void Sys_ConsoleOutput(const char *text) -{ - if (!sys_console || !sys_console->integer) { - return; - } - - if (!tty_enabled) { - tty_write_output(text); - } else { - tty_hide_input(); - tty_write_output(text); - tty_show_input(); - } -} - -void Sys_SetConsoleTitle(const char *title) -{ - char buf[MAX_STRING_CHARS]; - size_t len; - - if (!sys_console || !sys_console->integer) { - return; - } - - if (!tty_enabled) { - return; - } - - buf[0] = '\033'; - buf[1] = ']'; - buf[2] = '0'; - buf[3] = ';'; - - for (len = 4; len < MAX_STRING_CHARS - 1; len++) { - int c = *title++; - if (!c) { - break; - } - buf[len] = Q_charascii(c); - } - - buf[len++] = '\007'; - - stdout_write(buf, len); -} - -static void tty_parse_input(const char *text) -{ - inputField_t *f; - char *s; - int i, key; - - f = &tty_prompt.inputLine; - while (*text) { - key = *text++; - - if (key == tty_orig.c_cc[VERASE] || key == 127 || key == 8) { - if (f->cursorPos) { - f->text[--f->cursorPos] = 0; - stdout_write("\b \b", 3); - } - continue; - } - - if (key == tty_orig.c_cc[VKILL]) { - for (i = 0; i < f->cursorPos; i++) { - stdout_write("\b \b", 3); - } - f->cursorPos = 0; - continue; - } - - if (key >= 32) { - if (f->cursorPos == f->maxChars - 1) { - stdout_write(va("\b \b%c", key), 4); - f->text[f->cursorPos + 0] = key; - f->text[f->cursorPos + 1] = 0; - } else { - stdout_write(va("%c", key), 1); - f->text[f->cursorPos + 0] = key; - f->text[f->cursorPos + 1] = 0; - f->cursorPos++; - } - continue; - } - - if (key == '\n') { - tty_hide_input(); - s = Prompt_Action(&tty_prompt); - if (s) { - if (*s == '\\' || *s == '/') { - s++; - } - Sys_Printf("]%s\n", s); - Cbuf_AddText(&cmd_buffer, s); - } else { - stdout_write("]\n", 2); - } - tty_show_input(); - continue; - } - - if (key == '\t') { - tty_hide_input(); - Prompt_CompleteCommand(&tty_prompt, qfalse); - f->cursorPos = strlen(f->text); // FIXME - tty_show_input(); - continue; - } - - if (*text) { - key = *text++; - if (key == '[' || key == 'O') { - if (*text) { - key = *text++; - switch (key) { - case 'A': - tty_hide_input(); - Prompt_HistoryUp(&tty_prompt); - tty_show_input(); - break; - case 'B': - tty_hide_input(); - Prompt_HistoryDown(&tty_prompt); - tty_show_input(); - break; -#if 0 - case 'C': - if (f->text[f->cursorPos]) { - stdout_write("\033[C", 3); - f->cursorPos++; - } - break; - case 'D': - if (f->cursorPos) { - stdout_write("\033[D", 3); - f->cursorPos--; - } - break; -#endif - } - } - } - } - } -} - -void Sys_RunConsole(void) -{ - char text[MAX_STRING_CHARS]; - ssize_t ret; - - if (!sys_console || !sys_console->integer) { - return; - } - - if (!tty_io || !tty_io->canread) { - return; - } - - ret = read(STDIN_FILENO, text, sizeof(text) - 1); - if (!ret) { - Com_DPrintf("Read EOF from stdin.\n"); - tty_shutdown_input(); - Cvar_Set("sys_console", "0"); - return; - } - - // make sure the next call will not block - tty_io->canread = qfalse; - - if (ret < 0) { - if (errno == EAGAIN || errno == EINTR) { - return; - } - Com_Error(ERR_FATAL, "%s: read() failed: %s", - __func__, strerror(errno)); - } - - text[ret] = 0; - - if (!tty_enabled) { - Cbuf_AddText(&cmd_buffer, text); - return; - } - - tty_parse_input(text); -} - -#endif // USE_SYSCON - -/* -=============================================================================== - GENERAL ROUTINES =============================================================================== @@ -494,9 +77,7 @@ This function never returns. */ void Sys_Quit(void) { -#if USE_SYSCON tty_shutdown_input(); -#endif exit(EXIT_SUCCESS); } @@ -567,9 +148,7 @@ static void term_handler(int signum) static void kill_handler(int signum) { -#if USE_SYSCON tty_shutdown_input(); -#endif #if USE_CLIENT && USE_REF VID_FatalShutdown(); @@ -619,40 +198,11 @@ void Sys_Init(void) sys_libdir = Cvar_Get("libdir", LIBDIR, CVAR_NOSET); sys_forcegamelib = Cvar_Get("sys_forcegamelib", "", CVAR_NOSET); -#if USE_SYSCON - // we want TTY support enabled if started from terminal, - // but don't want any output by default if launched without one - // (from X session for example) - sys_console = Cvar_Get("sys_console", isatty(STDIN_FILENO) && - isatty(STDOUT_FILENO) ? "2" : "0", CVAR_NOSET); - - if (sys_console->integer > 0) { - int ret; - - // change stdin to non-blocking - ret = fcntl(STDIN_FILENO, F_GETFL, 0); - if (!(ret & O_NONBLOCK)) - fcntl(STDIN_FILENO, F_SETFL, ret | O_NONBLOCK); - - // change stdout to non-blocking - ret = fcntl(STDOUT_FILENO, F_GETFL, 0); - if (!(ret & O_NONBLOCK)) - fcntl(STDOUT_FILENO, F_SETFL, ret | O_NONBLOCK); - - // add stdin to the list of descriptors to wait on - tty_io = NET_AddFd(STDIN_FILENO); - tty_io->wantread = qtrue; - - // init optional TTY support - if (sys_console->integer > 1) - tty_init_input(); - + if (tty_init_input()) { signal(SIGHUP, term_handler); - } else -#endif - if (COM_DEDICATED) { - signal(SIGHUP, hup_handler); - } + } else if (COM_DEDICATED) { + signal(SIGHUP, hup_handler); + } sys_parachute = Cvar_Get("sys_parachute", "1", CVAR_NOSET); @@ -665,25 +215,6 @@ void Sys_Init(void) } } -#if USE_SYSCON -/* -================ -Sys_Printf -================ -*/ -void Sys_Printf(const char *fmt, ...) -{ - va_list argptr; - char msg[MAXPRINTMSG]; - - va_start(argptr, fmt); - Q_vsnprintf(msg, sizeof(msg), fmt, argptr); - va_end(argptr); - - Sys_ConsoleOutput(msg); -} -#endif - /* ================= Sys_Error @@ -694,9 +225,7 @@ void Sys_Error(const char *error, ...) va_list argptr; char text[MAXERRORMSG]; -#if USE_SYSCON tty_shutdown_input(); -#endif #if USE_CLIENT && USE_REF VID_FatalShutdown(); @@ -706,7 +235,8 @@ void Sys_Error(const char *error, ...) Q_vsnprintf(text, sizeof(text), error, argptr); va_end(argptr); - fprintf(stderr, "********************\n" + fprintf(stderr, + "********************\n" "FATAL: %s\n" "********************\n", text); exit(EXIT_FAILURE); @@ -916,18 +446,18 @@ int main(int argc, char **argv) if (argc > 1) { if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) { fprintf(stderr, "%s\n", com_version_string); - return 0; + return EXIT_SUCCESS; } if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { fprintf(stderr, "Usage: %s [+command arguments] [...]\n", argv[0]); - return 0; + return EXIT_SUCCESS; } } if (!getuid() || !geteuid()) { - fprintf(stderr, "You can not run " PRODUCT " as superuser " + fprintf(stderr, "You can not run " PRODUCT " as superuser " "for security reasons!\n"); - return 1; + return EXIT_FAILURE; } Qcommon_Init(argc, argv); diff --git a/src/unix/tty.c b/src/unix/tty.c new file mode 100644 index 0000000..345447b --- /dev/null +++ b/src/unix/tty.c @@ -0,0 +1,480 @@ +/* +Copyright (C) 2012 Andrey Nazarov + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "shared/shared.h" +#include "common/cmd.h" +#include "common/common.h" +#include "common/cvar.h" +#include "common/field.h" +#include "common/net/net.h" +#include "common/prompt.h" +#include "system/system.h" +#include "tty.h" + +#include <sys/time.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <termios.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +static cvar_t *sys_console; + +static qboolean tty_enabled; +static struct termios tty_orig; +static commandPrompt_t tty_prompt; +static int tty_hidden; +static ioentry_t *tty_io; + +static void tty_fatal_error(const char *what) +{ + // avoid recursive calls + sys_console = NULL; + tty_enabled = qfalse; + tty_io = NULL; + + Com_Error(ERR_FATAL, "%s: %s() failed: %s", + __func__, what, strerror(errno)); +} + +static int tty_stdout_sleep(void) +{ + struct timeval tv; + fd_set fd; + + tv.tv_sec = 0; + tv.tv_usec = 10000; + + FD_ZERO(&fd); + FD_SET(STDOUT_FILENO, &fd); + + return select(STDOUT_FILENO + 1, NULL, &fd, NULL, &tv); +} + +// handles partial writes correctly, but never spins too much +// blocks for 100 ms before giving up and losing data +static void tty_stdout_write(const char *buf, size_t len) +{ + int ret, spins; + + for (spins = 0; spins < 10; spins++) { + if (len == 0) + break; + + ret = write(STDOUT_FILENO, buf, len); + if (q_unlikely(ret < 0)) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN) { + ret = tty_stdout_sleep(); + if (ret >= 0) + continue; + tty_fatal_error("select"); + } else { + tty_fatal_error("write"); + } + + } + + buf += ret; + len -= ret; + } +} + +static void tty_hide_input(void) +{ + int i; + + if (!tty_hidden) { + for (i = 0; i <= tty_prompt.inputLine.cursorPos; i++) { + tty_stdout_write("\b \b", 3); + } + } + tty_hidden++; +} + +static void tty_show_input(void) +{ + if (!tty_hidden) { + return; + } + + tty_hidden--; + if (!tty_hidden) { + tty_stdout_write("]", 1); + tty_stdout_write(tty_prompt.inputLine.text, + tty_prompt.inputLine.cursorPos); + } +} + +static void tty_write_output(const char *text) +{ + char buf[MAXPRINTMSG]; + size_t len; + + for (len = 0; len < MAXPRINTMSG; len++) { + int c = *text++; + if (!c) { + break; + } + buf[len] = Q_charascii(c); + } + + tty_stdout_write(buf, len); +} + +static void tty_parse_input(const char *text) +{ + inputField_t *f; + char *s; + int i, key; + + f = &tty_prompt.inputLine; + while (*text) { + key = *text++; + + if (key == tty_orig.c_cc[VERASE] || key == 127 || key == 8) { + if (f->cursorPos) { + f->text[--f->cursorPos] = 0; + tty_stdout_write("\b \b", 3); + } + continue; + } + + if (key == tty_orig.c_cc[VKILL]) { + for (i = 0; i < f->cursorPos; i++) { + tty_stdout_write("\b \b", 3); + } + f->cursorPos = 0; + continue; + } + + if (key >= 32) { + if (f->cursorPos == f->maxChars - 1) { + tty_stdout_write(va("\b \b%c", key), 4); + f->text[f->cursorPos + 0] = key; + f->text[f->cursorPos + 1] = 0; + } else { + tty_stdout_write(va("%c", key), 1); + f->text[f->cursorPos + 0] = key; + f->text[f->cursorPos + 1] = 0; + f->cursorPos++; + } + continue; + } + + if (key == '\n') { + tty_hide_input(); + s = Prompt_Action(&tty_prompt); + if (s) { + if (*s == '\\' || *s == '/') { + s++; + } + Sys_Printf("]%s\n", s); + Cbuf_AddText(&cmd_buffer, s); + } else { + tty_stdout_write("]\n", 2); + } + tty_show_input(); + continue; + } + + if (key == '\t') { + tty_hide_input(); + Prompt_CompleteCommand(&tty_prompt, qfalse); + f->cursorPos = strlen(f->text); // FIXME + tty_show_input(); + continue; + } + + if (*text) { + key = *text++; + if (key == '[' || key == 'O') { + if (*text) { + key = *text++; + switch (key) { + case 'A': + tty_hide_input(); + Prompt_HistoryUp(&tty_prompt); + tty_show_input(); + break; + case 'B': + tty_hide_input(); + Prompt_HistoryDown(&tty_prompt); + tty_show_input(); + break; +#if 0 + case 'C': + if (f->text[f->cursorPos]) { + tty_stdout_write("\033[C", 3); + f->cursorPos++; + } + break; + case 'D': + if (f->cursorPos) { + tty_stdout_write("\033[D", 3); + f->cursorPos--; + } + break; +#endif + } + } + } + } + } +} + +static int tty_get_width(void) +{ +#ifdef TIOCGWINSZ + struct winsize ws; + + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0) + return ws.ws_col; +#endif + + return 80; +} + +qboolean tty_init_input(void) +{ + struct termios tty; + int ret, width, is_tty = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO); + + // we want TTY support enabled if started from terminal, but don't want any + // output by default if launched without one (from X session for example) + sys_console = Cvar_Get("sys_console", is_tty ? "2" : "0", CVAR_NOSET); + if (sys_console->integer == 0) + return qfalse; + + // change stdin to non-blocking + ret = fcntl(STDIN_FILENO, F_GETFL, 0); + if (!(ret & O_NONBLOCK)) + fcntl(STDIN_FILENO, F_SETFL, ret | O_NONBLOCK); + + // change stdout to non-blocking + ret = fcntl(STDOUT_FILENO, F_GETFL, 0); + if (!(ret & O_NONBLOCK)) + fcntl(STDOUT_FILENO, F_SETFL, ret | O_NONBLOCK); + + // add stdin to the list of descriptors to wait on + tty_io = NET_AddFd(STDIN_FILENO); + tty_io->wantread = qtrue; + + if (sys_console->integer == 1) + goto no_tty1; + + // init optional TTY support + if (!is_tty) + goto no_tty2; + + if (tcgetattr(STDIN_FILENO, &tty_orig)) + goto no_tty2; + + tty = tty_orig; + tty.c_iflag &= ~(INPCK | ISTRIP); + tty.c_lflag &= ~(ICANON | ECHO); + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 0; + if (tcsetattr(STDIN_FILENO, TCSADRAIN, &tty)) + goto no_tty2; + + // determine terminal width + width = tty_get_width(); + tty_prompt.widthInChars = width; + tty_prompt.printf = Sys_Printf; + tty_enabled = qtrue; + + // figure out input line width + width--; + if (width > MAX_FIELD_TEXT - 1) + width = MAX_FIELD_TEXT - 1; + IF_Init(&tty_prompt.inputLine, width, width); + + // display command prompt + tty_stdout_write("]", 1); + return qtrue; + +no_tty2: + Com_Printf("Couldn't initialize TTY support.\n"); + Cvar_Set("sys_console", "1"); +no_tty1: + return qtrue; +} + +void tty_shutdown_input(void) +{ + if (tty_io) { + NET_RemoveFd(STDIN_FILENO); + tty_io = NULL; + } + if (tty_enabled) { + tty_hide_input(); + tcsetattr(STDIN_FILENO, TCSADRAIN, &tty_orig); + tty_enabled = qfalse; + } +} + +void Sys_RunConsole(void) +{ + char text[MAX_STRING_CHARS]; + ssize_t ret; + + if (!sys_console || !sys_console->integer) { + return; + } + + if (!tty_io || !tty_io->canread) { + return; + } + + ret = read(STDIN_FILENO, text, sizeof(text) - 1); + if (!ret) { + Com_DPrintf("Read EOF from stdin.\n"); + tty_shutdown_input(); + Cvar_Set("sys_console", "0"); + return; + } + + // make sure the next call will not block + tty_io->canread = qfalse; + + if (ret < 0) { + if (errno == EAGAIN || errno == EINTR) { + return; + } + tty_fatal_error("read"); + } + + text[ret] = 0; + + if (!tty_enabled) { + Cbuf_AddText(&cmd_buffer, text); + return; + } + + tty_parse_input(text); +} + +void Sys_ConsoleOutput(const char *text) +{ + if (!sys_console || !sys_console->integer) { + return; + } + + if (!tty_enabled) { + tty_write_output(text); + } else { + tty_hide_input(); + tty_write_output(text); + tty_show_input(); + } +} + +void Sys_SetConsoleTitle(const char *title) +{ + char buf[MAX_STRING_CHARS]; + size_t len; + + if (!sys_console || !sys_console->integer) { + return; + } + + if (!tty_enabled) { + return; + } + + buf[0] = '\033'; + buf[1] = ']'; + buf[2] = '0'; + buf[3] = ';'; + + for (len = 4; len < MAX_STRING_CHARS - 1; len++) { + int c = *title++; + if (!c) { + break; + } + buf[len] = Q_charascii(c); + } + + buf[len++] = '\007'; + + tty_stdout_write(buf, len); +} + +void Sys_SetConsoleColor(color_index_t color) +{ + static const char color_to_ansi[8] = { + '0', '1', '2', '3', '4', '6', '5', '7' + }; + char buf[5]; + size_t len; + + if (!sys_console || !sys_console->integer) { + return; + } + + if (!tty_enabled) { + return; + } + + buf[0] = '\033'; + buf[1] = '['; + switch (color) { + case COLOR_NONE: + buf[2] = '0'; + buf[3] = 'm'; + len = 4; + break; + case COLOR_ALT: + buf[2] = '3'; + buf[3] = '2'; + buf[4] = 'm'; + len = 5; + break; + default: + buf[2] = '3'; + buf[3] = color_to_ansi[color]; + buf[4] = 'm'; + len = 5; + break; + } + + if (color != COLOR_NONE) { + tty_hide_input(); + } + tty_stdout_write(buf, len); + if (color == COLOR_NONE) { + tty_show_input(); + } +} + +void Sys_Printf(const char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + + va_start(argptr, fmt); + Q_vsnprintf(msg, sizeof(msg), fmt, argptr); + va_end(argptr); + + Sys_ConsoleOutput(msg); +} + diff --git a/src/unix/tty.h b/src/unix/tty.h new file mode 100644 index 0000000..6cc80c5 --- /dev/null +++ b/src/unix/tty.h @@ -0,0 +1,30 @@ +/* +Copyright (C) 2012 Andrey Nazarov + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef TTY_H +#define TTY_H + +#if USE_SYSCON +qboolean tty_init_input(void); +void tty_shutdown_input(void); +#else +#define tty_init_input() qfalse +#define tty_shutdown_input() (void)0 +#endif + +#endif // TTY_H |