From b2737e2bed5f013a4dfbf6e19650ca60498a9afd Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 10 Mar 2012 13:29:33 +0400 Subject: [PATCH] Pull out a colored text output interface out of the Console class. --- library/CMakeLists.txt | 2 + library/ColorText.cpp | 190 ++++++++++++++++++++++++++++++++++++ library/Console-linux.cpp | 186 +++++++++++++++++------------------ library/Console-windows.cpp | 176 +++++++++++++++------------------ library/include/ColorText.h | 144 +++++++++++++++++++++++++++ library/include/Console.h | 45 +++------ library/include/MiscUtils.h | 4 +- 7 files changed, 519 insertions(+), 228 deletions(-) create mode 100644 library/ColorText.cpp create mode 100644 library/include/ColorText.h diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index e310268a7..d1b36c68c 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -29,6 +29,7 @@ include/Internal.h include/DFHack.h include/Console.h include/Core.h +include/ColorText.h include/DataDefs.h include/Error.h include/Export.h @@ -66,6 +67,7 @@ include/modules/Graphic.h SET(PROJECT_SRCS Core.cpp +ColorText.cpp DataDefs.cpp DataStatics.cpp DataStaticsCtor.cpp diff --git a/library/ColorText.cpp b/library/ColorText.cpp new file mode 100644 index 000000000..fa5d57e0b --- /dev/null +++ b/library/ColorText.cpp @@ -0,0 +1,190 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2011 Petr Mrázek + +A thread-safe logging console with a line editor for windows. + +Based on linenoise win32 port, +copyright 2010, Jon Griffiths . +All rights reserved. +Based on linenoise, copyright 2010, Salvatore Sanfilippo . +The original linenoise can be found at: http://github.com/antirez/linenoise + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Redis nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "ColorText.h" +#include "MiscUtils.h" + +#include +#include +#include + +using namespace DFHack; + +#include "tinythread.h" +using namespace tthread; + +void color_ostream::flush_buffer(bool flush) +{ + auto buffer = buf(); + auto str = buffer->str(); + + if (!str.empty()) { + add_text(cur_color, buffer->str()); + buffer->str(std::string()); + } + + if (flush) + flush_proxy(); +} + +void color_ostream::begin_batch() +{ + flush_buffer(false); +} + +void color_ostream::end_batch() +{ + flush_proxy(); +} + +color_ostream::color_ostream() : ostream(new buffer(this)), cur_color(COLOR_RESET) +{ + // +} + +color_ostream::~color_ostream() +{ + delete buf(); +} + +void color_ostream::print(const char *format, ...) +{ + va_list args; + va_start(args, format); + vprint(format, args); + va_end(args); +} + +void color_ostream::vprint(const char *format, va_list args) +{ + std::string str = stl_vsprintf(format, args); + + if (!str.empty()) { + flush_buffer(false); + add_text(cur_color, str); + if (str[str.size()-1] == '\n') + flush_proxy(); + } +} + +void color_ostream::printerr(const char * format, ...) +{ + va_list args; + va_start(args, format); + vprinterr(format, args); + va_end(args); +} + +void color_ostream::vprinterr(const char *format, va_list args) +{ + color_value save = cur_color; + + fprintf(stderr, format, args); + + color(COLOR_LIGHTRED); + vprint(format, args); + color(save); +} + +void color_ostream::color(color_value c) +{ + if (c == cur_color) + return; + + flush_buffer(false); + cur_color = c; +} + +void color_ostream::reset_color(void) +{ + color(COLOR_RESET); +} + +void buffered_color_ostream::add_text(color_value color, const std::string &text) +{ + if (text.empty()) + return; + + if (buffer.empty()) + { + buffer.push_back(fragment_type(color, text)); + } + else + { + auto &back = buffer.back(); + + if (back.first != color || std::max(back.second.size(), text.size()) > 128) + buffer.push_back(fragment_type(color, text)); + else + buffer.back().second += text; + } +} + +void color_ostream_proxy::flush_proxy() +{ + if (!buffer.empty()) + { + target->begin_batch(); + + for (auto it = buffer.begin(); it != buffer.end(); ++it) + target->add_text(it->first, it->second); + + buffer.clear(); + + target->end_batch(); + } +} + +color_ostream_proxy::color_ostream_proxy(color_ostream &target) + : target(&target) +{ + // +} + +color_ostream_proxy::~color_ostream_proxy() +{ + *this << std::flush; +} diff --git a/library/Console-linux.cpp b/library/Console-linux.cpp index f471d6a10..c732a0178 100644 --- a/library/Console-linux.cpp +++ b/library/Console-linux.cpp @@ -126,13 +126,14 @@ const char * getANSIColor(const int c) namespace DFHack { - class Private : public std::stringbuf + class Private { public: Private() { dfout_C = NULL; rawmode = false; + in_batch = false; supported_terminal = false; state = con_unclaimed; }; @@ -164,68 +165,71 @@ namespace DFHack return true; } } - protected: - int sync() - { - print(str().c_str()); - str(std::string()); // Clear the string buffer - return 0; - } + public: - /// Print a formatted string, like printf - int print(const char * format, ...) + void print(const char *data) { - va_list args; - va_start( args, format ); - int ret = vprint( format, args ); - va_end( args ); - return ret; + fputs(data, dfout_C); } - int vprint(const char * format, va_list vl) + + void print_text(color_ostream::color_value clr, const std::string &chunk) { - if(state == con_lineedit) + if(!in_batch && state == con_lineedit) { disable_raw(); fprintf(dfout_C,"\x1b[1G"); fprintf(dfout_C,"\x1b[0K"); - int ret = vfprintf( dfout_C, format, vl ); + + color(clr); + print(chunk.c_str()); + + reset_color(); enable_raw(); prompt_refresh(); - return ret; } - else return vfprintf( dfout_C, format, vl ); + else + { + color(clr); + print(chunk.c_str()); + } } - int vprinterr(const char * format, va_list vl) + + void begin_batch() { - if(state == con_lineedit) + assert(!in_batch); + + in_batch = true; + + if (state == con_lineedit) { disable_raw(); - color(Console::COLOR_LIGHTRED); fprintf(dfout_C,"\x1b[1G"); fprintf(dfout_C,"\x1b[0K"); - int ret = vfprintf( dfout_C, format, vl ); - reset_color(); - enable_raw(); - prompt_refresh(); - return ret; } - else + } + + void end_batch() + { + assert(in_batch); + + flush(); + + in_batch = false; + + if (state == con_lineedit) { - color(Console::COLOR_LIGHTRED); - int ret = vfprintf( dfout_C, format, vl ); reset_color(); - return ret; + enable_raw(); + prompt_refresh(); } } - /// Print a formatted string, like printf, in red - int printerr(const char * format, ...) + + void flush() { - va_list args; - va_start( args, format ); - int ret = vprinterr( format, args ); - va_end( args ); - return ret; + if (!rawmode) + fflush(dfout_C); } + /// Clear the console, along with its scrollback void clear() { @@ -243,7 +247,9 @@ namespace DFHack /// Position cursor at x,y. 1,1 = top left corner void gotoxy(int x, int y) { - print("\033[%d;%dH", y,x); + char tmp[64]; + sprintf(tmp,"\033[%d;%dH", y,x); + print(tmp); } /// Set color (ANSI color number) void color(Console::color_value index) @@ -291,18 +297,19 @@ namespace DFHack /// beep. maybe? //void beep (void); /// A simple line edit (raw mode) - int lineedit(const std::string& prompt, std::string& output, mutex * lock, CommandHistory & ch) + int lineedit(const std::string& prompt, std::string& output, recursive_mutex * lock, CommandHistory & ch) { output.clear(); + reset_color(); this->prompt = prompt; if (!supported_terminal) { print(prompt.c_str()); fflush(dfout_C); // FIXME: what do we do here??? - //SDL_mutexV(lock); + //SDL_recursive_mutexV(lock); std::getline(std::cin, output); - //SDL_mutexP(lock); + //SDL_recursive_mutexP(lock); return output.size(); } else @@ -396,7 +403,7 @@ namespace DFHack if (::write(STDIN_FILENO,seq,strlen(seq)) == -1) return; } - int prompt_loop(mutex * lock, CommandHistory & history) + int prompt_loop(recursive_mutex * lock, CommandHistory & history) { int fd = STDIN_FILENO; size_t plen = prompt.size(); @@ -606,6 +613,7 @@ namespace DFHack con_unclaimed, con_lineedit } state; + bool in_batch; std::string prompt; // current prompt string std::string raw_buffer; // current raw mode buffer int raw_cursor; // cursor position in the buffer @@ -615,12 +623,12 @@ namespace DFHack }; } -Console::Console():std::ostream(0), std::ios(0) +Console::Console() { d = 0; inited = false; // we can't create the mutex at this time. the SDL functions aren't hooked yet. - wlock = new mutex(); + wlock = new recursive_mutex(); } Console::~Console() { @@ -643,7 +651,6 @@ bool Console::init(bool sharing) d = new Private(); // make our own weird streams so our IO isn't redirected d->dfout_C = fopen("/dev/tty", "w"); - rdbuf(d); std::cin.tie(this); clear(); d->supported_terminal = !isUnsupportedTerm() && isatty(STDIN_FILENO); @@ -660,7 +667,7 @@ bool Console::shutdown(void) { if(!d) return true; - lock_guard g(*wlock); + lock_guard g(*wlock); if(d->rawmode) d->disable_raw(); d->print("\n"); @@ -670,46 +677,41 @@ bool Console::shutdown(void) return true; } -int Console::print( const char* format, ... ) +void Console::begin_batch() { - va_list args; - lock_guard g(*wlock); - int ret; - if(!inited) ret = -1; - else - { - va_start( args, format ); - ret = d->vprint(format, args); - va_end(args); - } - return ret; + color_ostream::begin_batch(); + + wlock->lock(); + + if (inited) + d->begin_batch(); } -int Console::printerr( const char* format, ... ) +void Console::end_batch() { - va_list args; - lock_guard g(*wlock); - int ret; - // also mirror in error log - if(!inited) - { - va_start( args, format ); - ret = vfprintf(stderr, format, args); - va_end(args); - } - else - { - va_start( args, format ); - ret = d->vprinterr(format, args); - vfprintf(stderr, format, args); - va_end(args); - } - return ret; + if (inited) + d->end_batch(); + + wlock->unlock(); +} + +void Console::flush_proxy() +{ + lock_guard g(*wlock); + if (inited) + d->flush(); +} + +void Console::add_text(color_value color, const std::string &text) +{ + lock_guard g(*wlock); + if (inited) + d->print_text(color, text); } int Console::get_columns(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -1; if(inited) ret = d->get_columns(); @@ -718,7 +720,7 @@ int Console::get_columns(void) int Console::get_rows(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -1; if(inited) ret = d->get_rows(); @@ -727,42 +729,28 @@ int Console::get_rows(void) void Console::clear() { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->clear(); } void Console::gotoxy(int x, int y) { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->gotoxy(x,y); } -void Console::color(color_value index) -{ - lock_guard g(*wlock); - if(inited) - d->color(index); -} - -void Console::reset_color( void ) -{ - lock_guard g(*wlock); - if(inited) - d->reset_color(); -} - void Console::cursor(bool enable) { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->cursor(enable); } int Console::lineedit(const std::string & prompt, std::string & output, CommandHistory & ch) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -2; if(inited) ret = d->lineedit(prompt,output,wlock,ch); diff --git a/library/Console-windows.cpp b/library/Console-windows.cpp index de2c2aca8..ba3d2dd39 100644 --- a/library/Console-windows.cpp +++ b/library/Console-windows.cpp @@ -66,10 +66,10 @@ using namespace tthread; namespace DFHack { - class Private : public std::stringbuf + class Private { public: - Private() : basic_stringbuf::basic_stringbuf() + Private() { dfout_C = 0; rawmode = 0; @@ -78,69 +78,70 @@ namespace DFHack ConsoleWindow = 0; default_attributes = 0; state = con_unclaimed; + in_batch = false; raw_cursor = 0; }; virtual ~Private() { //sync(); } - protected: - int sync() - { - print (str().c_str()); - // Clear the string buffer - str(std::string()); - return 0; - } public: - /// Print a formatted string, like printf - int print(const char * format, ...) + void print(const char *data) { - va_list args; - va_start( args, format ); - int ret = vprint( format, args ); - va_end( args ); - return ret; + fputs(data, dfout_C); } - int vprint(const char * format, va_list vl) + + void print_text(color_ostream::color_value clr, const std::string &chunk) { - if(state == con_lineedit) + if(!in_batch && state == con_lineedit) { clearline(); - int ret = vfprintf( dfout_C, format, vl ); + + color(clr); + print(chunk.c_str()); + + reset_color(); prompt_refresh(); - return ret; } - else return vfprintf( dfout_C, format, vl ); + else + { + color(clr); + print(chunk.c_str()); + } } - int vprinterr(const char * format, va_list vl) + + void begin_batch() { - if(state == con_lineedit) + assert(!in_batch); + + in_batch = true; + + if (state == con_lineedit) { - color(Console::COLOR_LIGHTRED); clearline(); - int ret = vfprintf( dfout_C, format, vl ); - reset_color(); - prompt_refresh(); - return ret; } - else + } + + void end_batch() + { + assert(in_batch); + + flush(); + + in_batch = false; + + if (state == con_lineedit) { - color(Console::COLOR_LIGHTRED); - int ret = vfprintf( dfout_C, format, vl ); reset_color(); - return ret; + prompt_refresh(); } } - /// Print a formatted string, like printf, in red - int printerr(const char * format, ...) + + void flush() { - va_list args; - va_start( args, format ); - int ret = vprinterr( format, args ); - va_end( args ); - return ret; + fflush(dfout_C); } + int get_columns(void) { CONSOLE_SCREEN_BUFFER_INFO inf = { 0 }; @@ -250,7 +251,7 @@ namespace DFHack SetConsoleCursorPosition(console_out, inf.dwCursorPosition); } - int prompt_loop(mutex * lock, CommandHistory & history) + int prompt_loop(recursive_mutex * lock, CommandHistory & history) { raw_buffer.clear(); // make sure the buffer is empty! size_t plen = prompt.size(); @@ -359,9 +360,10 @@ namespace DFHack } } } - int lineedit(const std::string & prompt, std::string & output, mutex * lock, CommandHistory & ch) + int lineedit(const std::string & prompt, std::string & output, recursive_mutex * lock, CommandHistory & ch) { output.clear(); + reset_color(); int count; state = con_lineedit; this->prompt = prompt; @@ -386,6 +388,7 @@ namespace DFHack con_unclaimed, con_lineedit } state; + bool in_batch; std::string prompt; // current prompt string std::string raw_buffer; // current raw mode buffer int raw_cursor; // cursor position in the buffer @@ -393,7 +396,7 @@ namespace DFHack } -Console::Console():std::ostream(0), std::ios(0) +Console::Console() { d = 0; wlock = 0; @@ -453,7 +456,7 @@ bool Console::init(bool) // Allocate a console! AllocConsole(); d->ConsoleWindow = GetConsoleWindow(); - wlock = new mutex(); + wlock = new recursive_mutex(); HMENU hm = GetSystemMenu(d->ConsoleWindow,false); DeleteMenu(hm, SC_CLOSE, MF_BYCOMMAND); @@ -484,7 +487,6 @@ bool Console::init(bool) std::ios::sync_with_stdio(); // make our own weird streams so our IO isn't redirected - rdbuf(d); std::cin.tie(this); clear(); inited = true; @@ -495,51 +497,47 @@ bool Console::init(bool) // FIXME: looks awfully empty, doesn't it? bool Console::shutdown(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); FreeConsole(); inited = false; return true; } -int Console::print( const char* format, ... ) + +void Console::begin_batch() { - va_list args; - lock_guard g(*wlock); - int ret; - if(!inited) ret = -1; - else - { - va_start( args, format ); - ret = d->vprint(format, args); - va_end(args); - } - return ret; + color_ostream::begin_batch(); + + wlock->lock(); + + if (inited) + d->begin_batch(); } -int Console::printerr( const char* format, ... ) +void Console::end_batch() { - va_list args; - lock_guard g(*wlock); - int ret; - // also mirror in error log - if(!inited) - { - va_start( args, format ); - ret = vfprintf(stderr, format, args); - va_end(args); - } - else - { - va_start( args, format ); - ret = d->vprinterr(format, args); - vfprintf(stderr, format, args); - va_end(args); - } - return ret; + if (inited) + d->end_batch(); + + wlock->unlock(); +} + +void Console::flush_proxy() +{ + lock_guard g(*wlock); + if (inited) + d->flush(); +} + +void Console::add_text(color_value color, const std::string &text) +{ + lock_guard g(*wlock); + if (inited) + d->print_text(color, text); } int Console::get_columns(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -1; if(inited) ret = d->get_columns(); @@ -548,7 +546,7 @@ int Console::get_columns(void) int Console::get_rows(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -1; if(inited) ret = d->get_rows(); @@ -557,35 +555,21 @@ int Console::get_rows(void) void Console::clear() { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->clear(); } void Console::gotoxy(int x, int y) { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->gotoxy(x,y); } -void Console::color(color_value index) -{ - lock_guard g(*wlock); - if(inited) - d->color(index); -} - -void Console::reset_color( void ) -{ - lock_guard g(*wlock); - if(inited) - d->reset_color(); -} - void Console::cursor(bool enable) { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->cursor(enable); } diff --git a/library/include/ColorText.h b/library/include/ColorText.h new file mode 100644 index 000000000..6310eefda --- /dev/null +++ b/library/include/ColorText.h @@ -0,0 +1,144 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once +#include "Pragma.h" +#include "Export.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace DFHack +{ + class DFHACK_EXPORT color_ostream : public std::ostream + { + public: + enum color_value + { + COLOR_RESET = -1, + COLOR_BLACK = 0, + COLOR_BLUE, + COLOR_GREEN, + COLOR_CYAN, + COLOR_RED, + COLOR_MAGENTA, + COLOR_BROWN, + COLOR_GREY, + COLOR_DARKGREY, + COLOR_LIGHTBLUE, + COLOR_LIGHTGREEN, + COLOR_LIGHTCYAN, + COLOR_LIGHTRED, + COLOR_LIGHTMAGENTA, + COLOR_YELLOW, + COLOR_WHITE, + COLOR_MAX = COLOR_WHITE + }; + + private: + color_value cur_color; + + class buffer : public std::stringbuf + { + public: + color_ostream *owner; + + buffer(color_ostream *owner) : owner(owner) {} + virtual ~buffer() { } + + protected: + virtual int sync() { + owner->flush_buffer(true); + } + }; + + buffer *buf() { return (buffer*)rdbuf(); } + + void flush_buffer(bool flush); + + protected: + // These must be strictly balanced, because + // they might grab and hold mutexes. + virtual void begin_batch(); + virtual void end_batch(); + + virtual void add_text(color_value color, const std::string &text) = 0; + + virtual void flush_proxy() {}; + + friend class color_ostream_proxy; + public: + color_ostream(); + virtual ~color_ostream(); + + /// Print a formatted string, like printf + void print(const char *format, ...); + void vprint(const char *format, va_list args); + + /// Print a formatted string, like printf, in red + void printerr(const char *format, ...); + void vprinterr(const char *format, va_list args); + + /// Set color (ANSI color number) + void color(color_value c); + /// Reset color to default + void reset_color(void); + + virtual bool is_console() { return false; } + }; + + class DFHACK_EXPORT buffered_color_ostream : public color_ostream + { + protected: + virtual void add_text(color_value color, const std::string &text); + + public: + typedef std::pair fragment_type; + + buffered_color_ostream() {} + ~buffered_color_ostream() {} + + const std::list &fragments() { return buffer; } + + protected: + std::list buffer; + }; + + class DFHACK_EXPORT color_ostream_proxy : public buffered_color_ostream + { + protected: + color_ostream *target; + + virtual void flush_proxy(); + + public: + color_ostream_proxy(color_ostream &target); + ~color_ostream_proxy(); + }; +} diff --git a/library/include/Console.h b/library/include/Console.h index 70385d829..a0a098861 100644 --- a/library/include/Console.h +++ b/library/include/Console.h @@ -25,6 +25,7 @@ distribution. #pragma once #include "Pragma.h" #include "Export.h" +#include "ColorText.h" #include #include #include @@ -33,6 +34,7 @@ distribution. namespace tthread { class mutex; + class recursive_mutex; class condition_variable; class thread; } @@ -106,31 +108,18 @@ namespace DFHack std::size_t capacity; std::deque history; }; + class Private; - class DFHACK_EXPORT Console : public std::ostream + class DFHACK_EXPORT Console : public color_ostream { + protected: + virtual void begin_batch(); + virtual void add_text(color_value color, const std::string &text); + virtual void end_batch(); + + virtual void flush_proxy(); + public: - enum color_value - { - COLOR_RESET = -1, - COLOR_BLACK = 0, - COLOR_BLUE, - COLOR_GREEN, - COLOR_CYAN, - COLOR_RED, - COLOR_MAGENTA, - COLOR_BROWN, - COLOR_GREY, - COLOR_DARKGREY, - COLOR_LIGHTBLUE, - COLOR_LIGHTGREEN, - COLOR_LIGHTCYAN, - COLOR_LIGHTRED, - COLOR_LIGHTMAGENTA, - COLOR_YELLOW, - COLOR_WHITE, - COLOR_MAX = COLOR_WHITE - }; ///ctor, NOT thread-safe Console(); ///dtor, NOT thread-safe @@ -140,18 +129,10 @@ namespace DFHack /// shutdown the console. NOT thread-safe bool shutdown( void ); - /// Print a formatted string, like printf - int print(const char * format, ...); - /// Print a formatted string, like printf, in red - int printerr(const char * format, ...); /// Clear the console, along with its scrollback void clear(); /// Position cursor at x,y. 1,1 = top left corner void gotoxy(int x, int y); - /// Set color (ANSI color number) - void color(color_value c); - /// Reset color to default - void reset_color(void); /// Enable or disable the caret/cursor void cursor(bool enable = true); /// Waits given number of milliseconds before continuing. @@ -165,9 +146,11 @@ namespace DFHack /// A simple line edit (raw mode) int lineedit(const std::string& prompt, std::string& output, CommandHistory & history ); bool isInited (void) { return inited; }; + + bool is_console() { return true; } private: Private * d; - tthread::mutex * wlock; + tthread::recursive_mutex * wlock; bool inited; }; } diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 55dc9e404..039b75b20 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -35,7 +35,7 @@ distribution. using namespace std; template -void print_bits ( T val, DFHack::Console& out ) +void print_bits ( T val, ostream& out ) { stringstream strs; T n_bits = sizeof ( val ) * CHAR_BIT; @@ -63,7 +63,7 @@ void print_bits ( T val, DFHack::Console& out ) val >>= 1; } strs << endl; - out.print(strs.str().c_str()); + out << strs.str(); } /*