/* sys/consoleinterface.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include #include "sys/consoleinterface.h" namespace sys { const size_t DEFAULT_LOGSIZE = 2048; /* -- ANSI color code support -------------------------------------- */ bool con_ansicolor = false; bool con_timestamps = false; bool beginofline = true; bool console_timestamps() { return con_timestamps; } void set_console_timestamps(const bool timestamps) { con_timestamps = timestamps; } bool ansi() { return con_ansicolor; } void set_ansi(const bool ansi) { con_ansicolor = ansi; if (con_ansicolor) { // ANSI default color std::cout << "\033[0;39m"; } } void fallback_print_timestamp() { int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0; get_datetime(year, month, day, hour, min, sec); std::cout << year << "-" << month << "-" << day << " " << hour << ":" << min << ":" << sec << " "; } void fallback_print(const std::string &text) { 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; beginofline = true; } else if ((*c) == '^') { is_color_code = true; ansi_bold = 0; ansi_color = 39; switch (*(c + 1)) { case '0': // black 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 ansi_bold = 0; ansi_color = 39; break; case 'B': // bold ansi_bold = 1; ansi_color = 39; break; case 'D': // debug ansi_bold = 0; ansi_color = 39; break; case 'R': // error ansi_bold = 0; ansi_color = 31; break; case 'W': // warning ansi_bold = 1; ansi_color = 33; break; case 'F': // fancy ansi_bold = 0; ansi_color = 32; break; default: is_color_code = false; } if (is_color_code) { if (con_ansicolor) std::cout << "\033[" << ansi_bold << ";" << ansi_color << "m"; c++; } else { if (beginofline && con_timestamps) { fallback_print_timestamp(); } std::cout << *c; beginofline = false; } } else { if (beginofline && con_timestamps) { fallback_print_timestamp(); } std::cout << *c; beginofline = false; } c++; } } /* -- ConsoleBuffer ------------------------------------------------ */ int ConsoleBuffer::overflow(int c) { if (c == Traits::eof()) return Traits::not_eof(c); if (c == '\n') { if (ConsoleInterface::instance()) { /* * In the rcon case, the remote console will handle the timestamps */ if (con_timestamps && !ConsoleInterface::instance()->rcon()) { std::ostringstream str; int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0; get_datetime(year, month, day, hour, min, sec); str << "^B" << std::setw(4) << std::setfill('0') << year << "-" << std::setw(2) << std::setfill('0') << month << "-" << std::setw(2) << std::setfill('0') << day << " " << std::setw(2) << hour << ":" << std::setw(2) << min << ":" << std::setw(2) << sec << " " << std::setw(2) << con_buffer; ConsoleInterface::instance()->event_text(str.str()); } else { ConsoleInterface::instance()->event_text(con_buffer); } } else { fallback_print(con_buffer); std::cout << std::endl; } con_buffer.clear(); } else { con_buffer += c; } return c; } /* -- ConsoleStream ------------------------------------------------ */ ConsoleStream con_out; ConsoleStream::ConsoleStream() : std::basic_ostream(&con_buffer) { clear(); } ConsoleStream::~ConsoleStream() { 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; } 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(text); print(text); } } void ConsoleInterface::print(const std::string & text) { fallback_print(text); std::cout << std::endl; } } // namespace sys