From 1e0df536c2fae85c317ce9c3cc17603d5f98c911 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 15 Oct 2008 20:33:15 +0000 Subject: moved client console into a Widget --- src/sys/consoleinterface.cc | 288 ++++++++++++++++++++++++-------------------- src/sys/consoleinterface.h | 150 +++++++++++++++-------- src/sys/sys.cc | 32 ++--- src/sys/sys.h | 10 +- 4 files changed, 280 insertions(+), 200 deletions(-) (limited to 'src/sys') diff --git a/src/sys/consoleinterface.cc b/src/sys/consoleinterface.cc index 073f34b..284a48d 100644 --- a/src/sys/consoleinterface.cc +++ b/src/sys/consoleinterface.cc @@ -6,187 +6,213 @@ #include "sys/consoleinterface.h" -#include - -#include - namespace sys { -ConsoleInterface *ConsoleInterface::consoleinterface_instance = 0; - -ConsoleInterface::ConsoleInterface() -{ - consoleinterface_ansi = true; - if (consoleinterface_instance) { - std::cerr << "multiple sys::ConsoleInterface instances!" << std::endl; - sys::quit(2); - } - - consoleinterface_rcon = false; - - consoleinterface_instance = this; - consoleinterface_text.clear(); - consoleinterface_buffer.clear(); -} - -ConsoleInterface::~ConsoleInterface() -{ - consoleinterface_instance = 0; -} - -ConsoleInterface *ConsoleInterface::instance() -{ - return consoleinterface_instance; -} - -std::ostream & ConsoleInterface::messagestream() -{ - flush(); - return (consoleinterface_buffer << "^N"); -} +const size_t DEFAULT_LOGSIZE = 2048; -std::ostream & ConsoleInterface::warningstream() -{ - flush(); - return (consoleinterface_buffer << "^W"); -} +/* -- ANSI color code support -------------------------------------- */ -std::ostream & ConsoleInterface::errorstream() -{ - flush(); - return (consoleinterface_buffer << "^R"); -} +bool con_ansicolor = false; -std::ostream & ConsoleInterface::debugstream() +bool ansi() { - flush(); - return (consoleinterface_buffer << "^D"); + return con_ansicolor; } -void ConsoleInterface::flush() +void set_ansi(const bool ansi) { - if (rcon()) - return; - - char line[MAXCMDSIZE]; - - while(consoleinterface_buffer.getline(line, MAXCMDSIZE-1)) { - while (consoleinterface_text.size() >= MAXCONLINES) { - consoleinterface_text.pop_front(); - } - consoleinterface_text.push_back(std::string(line)); - - // print to stdout - print_ansi(line); - std::cout << std::endl; + con_ansicolor = ansi; + if (con_ansicolor) { + // ANSI default color + std::cout << "\033[0;39m"; } - - consoleinterface_buffer.clear(); -} - -void ConsoleInterface::resize() -{ } -void ConsoleInterface::print_ansi(const char *line) +void fallback_print(const std::string &text) { - if (consoleinterface_ansi) - std::cout << "\033[0;39m"; - - const char *c = line; + bool is_color_code = false; + int ansi_bold = 0; + int ansi_color = 39; + + const char *c = text.c_str(); while (*c) { + + if ((*c) == '\n') { + std::cout << std::endl; + + } else if ((*c) == '^') { - if ((*c == '^')) { - bool is_code = true; - int bold = 0; - int color = 39; - + is_color_code = true; + ansi_bold = 0; + ansi_color = 39; + switch (*(c+1)) { case '0': // black - color = 0; - bold = 1; - break; - case '1': // red - color = 31; - break; - case '2': // green - color = 32; - break; - case '3': // yellow - bold = 1; - color = 33; - break; - case '4': // blue - color = 34; - break; - case '5': // cyan - color = 36; - break; - case '6': // magenta - color = 35; - break; - case '7': // white is mapped to foreground color - bold = 1; - color = 39; + ansi_color = 0; + ansi_bold = 1; break; - + case '1': // red + ansi_color = 31; + break; + case '2': // green + ansi_color = 32; + break; + case '3': // yellow + ansi_color = 1; + ansi_color = 33; + break; + case '4': // blue + ansi_color = 34; + break; + case '5': // cyan + ansi_color = 36; + break; + case '6': // magenta + ansi_color = 35; + break; + case '7': // white is mapped to foreground color + ansi_bold = 1; + ansi_color = 39; + break; + case 'N': // normal - bold = 0; - color = 39; + ansi_bold = 0; + ansi_color = 39; break; case 'B': // bold - bold = 1; - color = 39; + ansi_bold = 1; + ansi_color = 39; break; case 'D': // debug - bold = 0; - color = 39; + ansi_bold = 0; + ansi_color = 39; break; case 'R': // error - bold = 0; - color = 31; + ansi_bold = 0; + ansi_color = 31; break; case 'W': // warning - bold = 1; - color = 33; + ansi_bold = 1; + ansi_color = 33; break; case 'F': // fancy - bold = 0; - color = 32; + ansi_bold = 0; + ansi_color = 32; break; default: - is_code = false; + is_color_code = false; } - if (is_code) { + + if (is_color_code) { + if (con_ansicolor) + std::cout << "\033[" << ansi_bold << ";" << ansi_color << "m"; c++; - if (consoleinterface_ansi) - std::cout << "\033[" << bold << ";" << color << "m"; - } else + } else { std::cout << *c; + } + } else { std::cout << *c; } + c++; } +} - if (consoleinterface_ansi) - std::cout << "\033[0;39m"; +/* -- ConsoleBuffer ------------------------------------------------ */ + +int ConsoleBuffer::overflow(int c) +{ + if (c == Traits::eof()) + return Traits::not_eof(c); + + if (c == '\n') { + if (ConsoleInterface::instance()) { + ConsoleInterface::instance()->event_text(con_buffer); + } else { + fallback_print(con_buffer); + std::cout << std::endl; + } + con_buffer.clear(); + } else { + con_buffer += c; + } + return c; } -void ConsoleInterface::set_ansi(bool enable) +/* -- ConsoleStream ------------------------------------------------ */ + +ConsoleStream con_out; + +ConsoleStream::ConsoleStream() : std::basic_ostream(&con_buffer) { - consoleinterface_ansi = enable; + clear(); } -void ConsoleInterface::set_rcon(bool enable) +ConsoleStream::~ConsoleStream() { - if (enable) { - flush(); + if (con_ansicolor) { + // ANSI default color + std::cout << "\033[0;39m" << std::endl; } +} + +/* -- Console ------------------------------------------------------ */ + +ConsoleInterface *ConsoleInterface::consoleinterface_instance = 0; + +ConsoleInterface::ConsoleInterface() +{ + if (consoleinterface_instance) { + std::cerr << "multiple sys::ConsoleInterface instances!" << std::endl; + sys::quit(2); + } + + consoleinterface_rcon = false; + consoleinterface_instance = this; + consoleinterface_logsize = DEFAULT_LOGSIZE; +} + +ConsoleInterface::~ConsoleInterface() +{ + consoleinterface_instance = 0; +} + +ConsoleInterface *ConsoleInterface::instance() +{ + return consoleinterface_instance; +} + +void ConsoleInterface::set_rcon(bool enable) +{ consoleinterface_rcon = enable; } -} // namespace sys +void ConsoleInterface::set_logsize(const size_t logsize) +{ + consoleinterface_logsize = logsize < 16 ? 16 : logsize; +} +void ConsoleInterface::event_text(const std::string & text) +{ + if (rcon()) { + consoleinterface_rconbuf.push_back(text); + } else { + while (consoleinterface_log.size() >= consoleinterface_logsize) { + consoleinterface_log.pop_front(); + } + + consoleinterface_log.push_back(std::string(text)); + print(text); + } +} + +void ConsoleInterface::print(const std::string & text) +{ + fallback_print(text); + std::cout << std::endl; +} + +} // namespace sys diff --git a/src/sys/consoleinterface.h b/src/sys/consoleinterface.h index 5411cb6..3a7d3ed 100644 --- a/src/sys/consoleinterface.h +++ b/src/sys/consoleinterface.h @@ -8,89 +8,141 @@ #define __INCLUDED_SYS_CONSOLEINTERFACE_H__ #include +#include +#include +#include #include #include #include "sys/sys.h" -/// global define to send a message to the system console -#define con_print sys::ConsoleInterface::instance()->messagestream() -/// global define to send a warning message to the system console -#define con_warn sys::ConsoleInterface::instance()->warningstream() -/// global define to send an error message to the system console -#define con_error sys::ConsoleInterface::instance()->errorstream() - -#ifdef HAVE_DEBUG_MESSAGES -/// global define to send a debug message to the system console -#define con_debug sys::ConsoleInterface::instance()->debugstream() -#else -#define con_debug if (0) *(std::ostream*)(0) -#endif namespace sys { -const size_t MAXCONLINES = 2048; +/// true if ANSI colors are enabled +bool ansi(); -/// interface for the client and server Console classes -class ConsoleInterface -{ -public: - /// default constructor - ConsoleInterface(); +/// enable or disable ANSI colors +void set_ansi(bool enable = true); - /// default destructor - virtual ~ConsoleInterface(); - - /// stream to send normal messages to - std::ostream & messagestream(); +/* -- ConsoleBuffer ------------------------------------------------ */ - /// stream to send warning messages to - std::ostream & warningstream(); +typedef std::char_traits Traits; - /// stream to send error messages to - std::ostream & errorstream(); +/// buffer back-end for console output +class ConsoleBuffer : public std::basic_streambuf +{ +public: + const std::string & str() const + { + return con_buffer; + } + +protected: + /// stream overflow + virtual int overflow(int c = Traits::eof()); + +private: + std::string con_buffer; +}; - /// stream to send debug messages to - std::ostream & debugstream(); - /// flush buffered messages - virtual void flush(); +/* -- ConsoleStream ------------------------------------------------ */ - /// resize the console (ncurses stub) - virtual void resize(); +/// provides global streams for console output +class ConsoleStream : public std::basic_ostream +{ +public: + ConsoleStream(); + ~ConsoleStream(); + + inline ConsoleBuffer & buf() + { + return con_buffer; + } + +private: + ConsoleBuffer con_buffer; +}; - /// return the console inputbuffer - inline std::stringstream & buffer() { return consoleinterface_buffer; } +/// global console output stream +extern ConsoleStream con_out; - inline bool rcon() { return consoleinterface_rcon; } - inline bool ansi() { return consoleinterface_ansi; } +/* -- Console ------------------------------------------------------ */ - /// enable or disable ANSI escape sequences - void set_ansi(bool enable = true); +/// interface for the client and server Console classes +class ConsoleInterface +{ +public: + /// default constructor + ConsoleInterface(); + + /// default destructor + virtual ~ConsoleInterface(); + + /// set maximal number of lines in the log + void set_logsize(const size_t logsize); + + /// return rcon state + inline bool rcon() + { + return consoleinterface_rcon; + } + /// enable or disable rcon void set_rcon(bool enable = true); - + + typedef std::deque Text; + + inline Text & rconbuf() + { + return consoleinterface_rconbuf; + } + + inline Text & log() + { + return consoleinterface_log; + } + /// a pointer to the current console instance static ConsoleInterface *instance(); - + + /// incoming text event handler + void event_text(const std::string & text); + + /// ncurses resize event + virtual void resize() + {}; + protected: - std::deque consoleinterface_text; - std::stringstream consoleinterface_buffer; + /// print one line of text + virtual void print(const std::string & text); - /// print a string to stdout with ansi color codes - void print_ansi(const char *line); - private: /// console singleton static ConsoleInterface *consoleinterface_instance; - bool consoleinterface_ansi; + bool consoleinterface_rcon; + Text consoleinterface_rconbuf; + + Text consoleinterface_log; + size_t consoleinterface_logsize; }; } // namespace sys +#define con_print sys::con_out << "^N" +#define con_warn sys::con_out << "^W" +#define con_error sys::con_out << "^R" +#ifdef HAVE_DEBUG_MESSAGES +#define con_debug sys::con_out << "^D" +#else +#define con_debug if (0) *(std::ostream*)(0) +#endif + + #endif // __INCLUDED_SYS_CONSOLEINTERFACE_H__ diff --git a/src/sys/sys.cc b/src/sys/sys.cc index db2be4d..59ed11d 100644 --- a/src/sys/sys.cc +++ b/src/sys/sys.cc @@ -29,18 +29,19 @@ #include "sys/sys.h" -namespace sys { +namespace sys +{ -bool isdirectory(std::string const &path) +bool isdirectory(const std::string &path) { #ifdef _WIN32 struct ::_stat path_stat; memset(&path_stat, 0, sizeof(struct ::_stat)); - + if (::_stat(path.c_str(), &path_stat) != 0) { return false; } - + if (path_stat.st_mode & _S_IFDIR) { return true; } @@ -48,11 +49,11 @@ bool isdirectory(std::string const &path) #else struct stat path_stat; memset(&path_stat, 0, sizeof(path_stat)); - + if (stat(path.c_str(), &path_stat) != 0) { return false; } - + if (path_stat.st_mode & S_IFDIR) { return true; } @@ -61,7 +62,7 @@ bool isdirectory(std::string const &path) #endif } -void mkdir(std::string const &path) +void mkdir(const std::string &path) { #ifdef _WIN32 std::string p(path); @@ -69,7 +70,7 @@ void mkdir(std::string const &path) if (p[i] == '/') p[i] = '\\'; if (p.size() && (p[p.size()-1] == '\\')) p.erase(p.size() -1, 1); - + if (_mkdir(p.c_str()) != 0) { con_warn << "Could not create directory '" << p << "'" << std::endl; } @@ -83,23 +84,23 @@ void signal(int signum, signalfunc handler) { #ifndef _WIN32 struct sigaction sa; - + sa.sa_sigaction = 0; memset(&sa.sa_mask, 0 ,sizeof(sigset_t)); sa.sa_flags = 0; sa.sa_handler = handler; - + ::sigaction(signum, &sa, 0); #endif } -unsigned long time() +unsigned long time() { #ifndef _WIN32 struct ::tm localtime; time_t epochtime = ::time(0); ::localtime_r(&epochtime, &localtime); - return ((unsigned long) (localtime.tm_sec + localtime.tm_min*60 + localtime.tm_hour*3600)); + return ((unsigned long)(localtime.tm_sec + localtime.tm_min*60 + localtime.tm_hour*3600)); #else return 0; #endif @@ -108,13 +109,14 @@ unsigned long time() void sleep(float seconds) { #ifndef _WIN32 - ::usleep((useconds_t) (seconds * 1000000.0f) ); + ::usleep((useconds_t)(seconds * 1000000.0f)); #else - Sleep((DWORD) (seconds*1000.0f)); + Sleep((DWORD)(seconds*1000.0f)); #endif } -void quit(int status) { +void quit(int status) +{ ::exit(status); } diff --git a/src/sys/sys.h b/src/sys/sys.h index 66040f0..81eba94 100644 --- a/src/sys/sys.h +++ b/src/sys/sys.h @@ -19,18 +19,18 @@ */ namespace sys { -typedef void (* signalfunc)(int signum); +typedef void(* signalfunc)(int signum); -/// check if a path exists and if it is a directory -bool isdirectory(std::string const &path); +/// returns true if a path exists and it is a directory +bool isdirectory(const std::string &path); /// create a directory -void mkdir(std::string const &path); +void mkdir(const std::string &path); /// intercept OS signals void signal(int signum, signalfunc handler); -/** +/** * @brief operation system exit() application * @param status return value */ -- cgit v1.2.3