From 792d272fbf3a1a80d597757300b9a33ea083bcc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 14 Jul 2011 04:05:27 +0200 Subject: [PATCH] Windows side of the Console rewrite --- CMakeLists.txt | 3 + library/Console-linux.cpp | 108 +++----- library/Console-windows.cpp | 280 +++++++++++++++++++-- library/Core.cpp | 30 +-- library/FakeSDL-windows.cpp | 5 + library/PluginManager.cpp | 7 +- library/VersionInfoFactory.cpp | 8 +- library/include/dfhack/Console.h | 7 +- library/include/dfhack/Core.h | 1 - library/include/dfhack/extra/stdiostream.h | 2 +- library/modules/Maps.cpp | 2 +- library/modules/Translation.cpp | 6 +- plugins/prospector.cpp | 47 ++-- plugins/reveal.cpp | 28 +-- plugins/vdig.cpp | 12 +- plugins/weather.cpp | 25 +- 16 files changed, 386 insertions(+), 185 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 93db2e817..d24dd2cf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,9 @@ SET(DFHACK_OUTPUT_DIR "${dfhack_BINARY_DIR}/bin" CACHE STRING "Where should be t SET(DFHACK_PLUGIN_OUTPUT_DIR "${DFHACK_OUTPUT_DIR}/plugins") ## where to put things during the build (force MSVC to behave) +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${DFHACK_OUTPUT_DIR}) +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${DFHACK_OUTPUT_DIR}) +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${DFHACK_OUTPUT_DIR}) SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${DFHACK_OUTPUT_DIR}) SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${DFHACK_OUTPUT_DIR}) SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${DFHACK_OUTPUT_DIR}) diff --git a/library/Console-linux.cpp b/library/Console-linux.cpp index 6a846828c..c25e4cdce 100644 --- a/library/Console-linux.cpp +++ b/library/Console-linux.cpp @@ -66,6 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "dfhack/Console.h" +#include "dfhack/extra/stdiostream.h" #include #include #include @@ -78,6 +79,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace DFHack; #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 @@ -94,28 +96,7 @@ namespace DFHack dfout_C = 0; stream_o = 0; rawmode = 0; - history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; - history_len = 0; - history = NULL; }; - int get_columns(void) - { - winsize ws; - if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) return 80; - return ws.ws_col; - } - - int get_rows(void) - { - winsize ws; - if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) return 25; - return ws.ws_row; - } - void clear() - { - const char * clr = "\033c\033[3J\033[H"; - write(STDIN_FILENO,clr,strlen(clr)); - } int isUnsupportedTerm(void) { @@ -132,13 +113,10 @@ namespace DFHack duthomhas::stdiobuf * stream_o; termios orig_termios; /* in order to restore at exit */ int rawmode; /* for atexit() function to check if restore is needed*/ - int history_max_len; - int history_len; - char **history; + std::deque history; }; } -// FIXME: prime candidate for being a singleton... -Console::Console() +Console::Console():std::ostream(0), std::ios(0) { d = new Private(); } @@ -175,18 +153,30 @@ int Console::print( const char* format, ... ) int Console::get_columns(void) { - return d->get_columns(); + winsize ws; + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) return 80; + return ws.ws_col; } int Console::get_rows(void) { - return d->get_rows(); + winsize ws; + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) return 25; + return ws.ws_row; } void Console::clear() { - *this << "\033c"; - *this << "\033[3J\033[H"; + if(d->rawmode) + { + const char * clr = "\033c\033[3J\033[H"; + ::write(STDIN_FILENO,clr,strlen(clr)); + } + else + { + *this << "\033c"; + *this << "\033[3J\033[H"; + } } void Console::gotoxy(int x, int y) @@ -344,7 +334,7 @@ int Console::prompt_loop(const std::string & prompt, std::string & buffer) int fd = STDIN_FILENO; size_t plen = prompt.size(); size_t pos = 0; - size_t cols = d->get_columns(); + size_t cols = get_columns(); int history_index = 0; /* The latest history entry is always our current buffer, that @@ -386,7 +376,7 @@ int Console::prompt_loop(const std::string & prompt, std::string & buffer) switch(c) { case 13: /* enter */ - history.pop_front(); + d->history.pop_front(); return buffer.size(); case 3: /* ctrl-c */ errno = EAGAIN; @@ -400,41 +390,6 @@ int Console::prompt_loop(const std::string & prompt, std::string & buffer) prompt_refresh(prompt,buffer,pos); } break; - // I fail to see how is this useful to anyone but hardcore emacs users - /* - case 4: // ctrl-d, remove char at right of cursor - if (len > 1 && pos < (len-1)) { - memmove(buf+pos,buf+pos+1,len-pos); - len--; - buf[len] = '\0'; - prompt_refresh(prompt,buffer,pos); - } else if (len == 0) { - history_len--; - free(history[history_len]); - return -1; - } - break; - case 20: // ctrl-t - if (pos > 0 && pos < len) { - int aux = buf[pos-1]; - buf[pos-1] = buf[pos]; - buf[pos] = aux; - if (pos != len-1) pos++; - prompt_refresh(prompt,buffer,pos); - } - break; - case 2: // ctrl-b - goto left_arrow; - case 6: // ctrl-f - goto right_arrow; - case 16: // ctrl-p - seq[1] = 65; - goto up_down_arrow; - case 14: // ctrl-n - seq[1] = 66; - goto up_down_arrow; - break; - */ case 27: /* escape sequence */ if (::read(fd,seq,2) == -1) break; if(seq[0] == '[') @@ -460,13 +415,12 @@ int Console::prompt_loop(const std::string & prompt, std::string & buffer) } else if (seq[1] == 'A' || seq[1] == 'B') { - up_down_arrow: /* up and down arrow: history */ - if (history.size() > 1) + if (d->history.size() > 1) { /* Update the current history entry before to * overwrite it with tne next one. */ - history[history_index] = buffer; + d->history[history_index] = buffer; /* Show the new entry */ history_index += (seq[1] == 'A') ? 1 : -1; if (history_index < 0) @@ -474,12 +428,12 @@ int Console::prompt_loop(const std::string & prompt, std::string & buffer) history_index = 0; break; } - else if (history_index >= history.size()) + else if (history_index >= d->history.size()) { - history_index = history.size()-1; + history_index = d->history.size()-1; break; } - buffer = history[history_index]; + buffer = d->history[history_index]; pos = buffer.size(); prompt_refresh(prompt,buffer,pos); } @@ -562,11 +516,11 @@ int Console::prompt_loop(const std::string & prompt, std::string & buffer) // push to front, remove from back if we are above maximum. ignore immediate duplicates void Console::history_add(const std::string & command) { - if(history.front() == command) + if(d->history.front() == command) return; - history.push_front(command); - if(history.size() > 100) - history.pop_back(); + d->history.push_front(command); + if(d->history.size() > 100) + d->history.pop_back(); } int Console::lineedit(const std::string & prompt, std::string & output) diff --git a/library/Console-windows.cpp b/library/Console-windows.cpp index 3655b66da..8c1480935 100644 --- a/library/Console-windows.cpp +++ b/library/Console-windows.cpp @@ -25,6 +25,7 @@ distribution. #include #include +#include "dfhack/extra/stdiostream.h" #include < process.h> #include #include @@ -39,21 +40,57 @@ distribution. #include #include #include +#include using namespace DFHack; // FIXME: maybe make configurable with an ini option? #define MAX_CONSOLE_LINES 999; -duthomhas::stdiostream dfout; -FILE * dfout_C = 0; -duthomhas::stdiobuf * stream_o = 0; +namespace DFHack +{ + class Private + { + public: + Private() + { + dfout_C = 0; + stream_o = 0; + rawmode = 0; + console_in = 0; + console_out = 0; + ConsoleWindow = 0; + default_attributes = 0; + }; + void output(const char* str, size_t len, int x, int y) + { + COORD pos = { (SHORT)x, (SHORT)y }; + DWORD count = 0; + WriteConsoleOutputCharacterA(console_out, str, len, pos, &count); + } + + FILE * dfout_C; + duthomhas::stdiobuf * stream_o; + int rawmode; /* for atexit() function to check if restore is needed*/ + std::deque history; + + HANDLE console_in; + HANDLE console_out; + HWND ConsoleWindow; + WORD default_attributes; + }; +} + + +Console::Console():std::ostream(0), std::ios(0) +{ + d = new Private(); +} -HANDLE g_hConsoleOut; // Handle to debug console -HWND ConsoleWindow; -WORD default_attributes; +Console::~Console() +{ +} -// FIXME: prime candidate for being a singleton... indeed. -Console::Console() +bool Console::init(void) { int hConHandle; long lStdHandle; @@ -63,25 +100,26 @@ Console::Console() // Allocate a console! AllocConsole(); - ConsoleWindow = GetConsoleWindow(); - HMENU hm = GetSystemMenu(ConsoleWindow,false); + d->ConsoleWindow = GetConsoleWindow(); + HMENU hm = GetSystemMenu(d->ConsoleWindow,false); DeleteMenu(hm, SC_CLOSE, MF_BYCOMMAND); // set the screen buffer to be big enough to let us scroll text GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); - default_attributes = coninfo.wAttributes; + d->default_attributes = coninfo.wAttributes; coninfo.dwSize.Y = MAX_CONSOLE_LINES; // How many lines do you want to have in the console buffer SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); // redirect unbuffered STDOUT to the console - g_hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE); - lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); + d->console_out = GetStdHandle(STD_OUTPUT_HANDLE); + lStdHandle = (long)d->console_out; hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); - dfout_C = _fdopen( hConHandle, "w" ); - setvbuf( dfout_C, NULL, _IONBF, 0 ); + d->dfout_C = _fdopen( hConHandle, "w" ); + setvbuf( d->dfout_C, NULL, _IONBF, 0 ); // redirect unbuffered STDIN to the console - lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); + d->console_in = GetStdHandle(STD_INPUT_HANDLE); + lStdHandle = (long)d->console_in; hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); fp = _fdopen( hConHandle, "r" ); *stdin = *fp; @@ -92,16 +130,40 @@ Console::Console() std::ios::sync_with_stdio(); // make our own weird streams so our IO isn't redirected - stream_o = new duthomhas::stdiobuf(dfout_C); - dfout.rdbuf(stream_o); - std::cin.tie(&dfout); + d->stream_o = new duthomhas::stdiobuf(d->dfout_C); + rdbuf(d->stream_o); + std::cin.tie(this); clear(); - // result is a terminal controlled by the parasitic code! + return true; } -Console::~Console() +bool Console::shutdown(void) { FreeConsole(); + return true; +} + +int Console::print( const char* format, ... ) +{ + va_list args; + va_start( args, format ); + int ret = vfprintf( d->dfout_C, format, args ); + va_end( args ); + return ret; +} + +int Console::get_columns(void) +{ + CONSOLE_SCREEN_BUFFER_INFO inf = { 0 }; + GetConsoleScreenBufferInfo(d->console_out, &inf); + return (size_t)inf.dwSize.X; +} + +int Console::get_rows(void) +{ + CONSOLE_SCREEN_BUFFER_INFO inf = { 0 }; + GetConsoleScreenBufferInfo(d->console_out, &inf); + return (size_t)inf.dwSize.Y; } void Console::clear() @@ -124,7 +186,7 @@ void Console::color(int index) void Console::reset_color( void ) { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(hConsole, default_attributes); + SetConsoleTextAttribute(hConsole, d->default_attributes); } @@ -153,4 +215,178 @@ void Console::cursor(bool enable) void Console::msleep (unsigned int msec) { Sleep(msec); +} + +int Console::enable_raw() +{ + return 0; +} + +void Console::disable_raw() +{ + /* Nothing to do yet */ +} + +void Console::prompt_refresh( const std::string& prompt, const std::string& buffer, size_t pos) +{ + size_t cols = get_columns(); + size_t plen = prompt.size(); + const char * buf = buffer.c_str(); + size_t len = buffer.size(); + + while ((plen + pos) >= cols) + { + buf++; + len--; + pos--; + } + while (plen + len > cols) + { + len--; + } + + CONSOLE_SCREEN_BUFFER_INFO inf = { 0 }; + GetConsoleScreenBufferInfo(d->console_out, &inf); + d->output(prompt.c_str(), plen, 0, inf.dwCursorPosition.Y); + d->output(buf, len, plen, inf.dwCursorPosition.Y); + if (plen + len < (size_t)inf.dwSize.X) + { + /* Blank to EOL */ + char* tmp = (char*)malloc(inf.dwSize.X - (plen + len)); + memset(tmp, ' ', inf.dwSize.X - (plen + len)); + d->output(tmp, inf.dwSize.X - (plen + len), len + plen, inf.dwCursorPosition.Y); + free(tmp); + } + inf.dwCursorPosition.X = (SHORT)(pos + plen); + SetConsoleCursorPosition(d->console_out, inf.dwCursorPosition); +} + +int Console::prompt_loop(const std::string & prompt, std::string & buffer) +{ + buffer.clear(); // make sure the buffer is empty! + size_t plen = prompt.size(); + size_t pos = 0; + int history_index = 0; + + /* The latest history entry is always our current buffer, that + * initially is just an empty string. */ + history_add(""); + + CONSOLE_SCREEN_BUFFER_INFO inf = { 0 }; + GetConsoleScreenBufferInfo(d->console_out, &inf); + size_t cols = inf.dwSize.X; + d->output(prompt.c_str(), plen, 0, inf.dwCursorPosition.Y); + inf.dwCursorPosition.X = (SHORT)plen; + SetConsoleCursorPosition(d->console_out, inf.dwCursorPosition); + + while (1) + { + INPUT_RECORD rec; + DWORD count; + ReadConsoleInputA(d->console_in, &rec, 1, &count); + if (rec.EventType != KEY_EVENT || !rec.Event.KeyEvent.bKeyDown) + continue; + switch (rec.Event.KeyEvent.wVirtualKeyCode) + { + case VK_RETURN: // enter + d->history.pop_front(); + return buffer.size(); + case VK_BACK: // backspace + if (pos > 0 && buffer.size() > 0) + { + buffer.erase(pos-1,1); + pos--; + prompt_refresh(prompt,buffer,pos); + } + break; + case VK_LEFT: // left arrow + if (pos > 0) + { + pos--; + prompt_refresh(prompt,buffer,pos); + } + break; + case VK_RIGHT: // right arrow + if (pos != buffer.size()) + { + pos++; + prompt_refresh(prompt,buffer,pos); + } + break; + case VK_UP: + case VK_DOWN: + /* up and down arrow: history */ + if (d->history.size() > 1) + { + /* Update the current history entry before to + * overwrite it with tne next one. */ + d->history[history_index] = buffer; + /* Show the new entry */ + history_index += (rec.Event.KeyEvent.wVirtualKeyCode == VK_UP) ? 1 : -1; + if (history_index < 0) + { + history_index = 0; + break; + } + else if (history_index >= d->history.size()) + { + history_index = d->history.size()-1; + break; + } + buffer = d->history[history_index]; + pos = buffer.size(); + prompt_refresh(prompt,buffer,pos); + } + break; + case VK_DELETE: + // delete + if (buffer.size() > 0 && pos < buffer.size()) + { + buffer.erase(pos,1); + prompt_refresh(prompt,buffer,pos); + } + break; + case VK_HOME: + pos = 0; + prompt_refresh(prompt,buffer,pos); + break; + case VK_END: + pos = buffer.size(); + prompt_refresh(prompt,buffer,pos); + break; + default: + if (rec.Event.KeyEvent.uChar.AsciiChar < ' ' || + rec.Event.KeyEvent.uChar.AsciiChar > '~') + continue; + if (buffer.size() == pos) + buffer.append(1,rec.Event.KeyEvent.uChar.AsciiChar); + else + buffer.insert(pos,1,rec.Event.KeyEvent.uChar.AsciiChar); + pos++; + prompt_refresh(prompt,buffer,pos); + break; + } + } +} + +// push to front, remove from back if we are above maximum. ignore immediate duplicates +void Console::history_add(const std::string & command) +{ + if(d->history.front() == command) + return; + d->history.push_front(command); + if(d->history.size() > 100) + d->history.pop_back(); +} + +int Console::lineedit(const std::string & prompt, std::string & output) +{ + output.clear(); + int count; + if (enable_raw() == -1) + return -1; + count = prompt_loop(prompt,output); + disable_raw(); + *this << std::endl; + return count; } \ No newline at end of file diff --git a/library/Core.cpp b/library/Core.cpp index 72e607c54..5c9358cfc 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -121,22 +121,24 @@ int fHKthread(void * iodata) // A thread function... for the interactive console. int fIOthread(void * iodata) { - Core * core = ((IODATA*) iodata)->core; + IODATA * iod = ((IODATA*) iodata); + Core * core = iod->core; PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr; + Console & con = core->con; if(plug_mgr == 0 || core == 0) { - core->con << "Something horrible happened to the plugin manager in Core's constructor..." << std::endl; + con.print("Something horrible happened to the plugin manager in Core's constructor...\n"); return 0; } - core->con.print("DFHack is ready. Have a nice day! Type in '?' or 'help' for help.\n"); + con.print("DFHack is ready. Have a nice day! Type in '?' or 'help' for help.\n"); //dfterm << << endl; int clueless_counter = 0; while (true) { string command = ""; - core->con.lineedit("[DFHack]# ",command); - core->con.history_add(command); - //core->con <<"[DFHack]# "; + con.lineedit("[DFHack]# ",command); + con.history_add(command); + //con <<"[DFHack]# "; //char * line = linenoise("[DFHack]# ", core->con.dfout_C); // dfout <<"[DFHack]# "; /* @@ -149,20 +151,20 @@ int fIOthread(void * iodata) //getline(cin, command); if(command=="help" || command == "?") { - core->con << "Available commands" << endl; - core->con << "------------------" << endl; + con.print("Available commands\n"); + con.print("------------------\n"); for(int i = 0; i < plug_mgr->size();i++) { const Plugin * plug = (plug_mgr->operator[](i)); if(!plug->size()) continue; - core->con << "Plugin " << plug->getName() << " :" << std::endl; + con.print("Plugin %s :\n", plug->getName().c_str()); for (int j = 0; j < plug->size();j++) { const PluginCommand & pcmd = (plug->operator[](j)); - core->con << setw(12) << pcmd.name << "| " << pcmd.description << endl; + con << setw(12) << pcmd.name << "| " << pcmd.description << endl; } - core->con << endl; + con << endl; } } else if( command == "" ) @@ -184,18 +186,18 @@ int fIOthread(void * iodata) command_result res = plug_mgr->InvokeCommand(first, parts); if(res == CR_NOT_IMPLEMENTED) { - core->con << "Invalid command." << endl; + con << "Invalid command." << endl; clueless_counter ++; } else if(res == CR_FAILURE) { - core->con << "ERROR!" << endl; + con << "ERROR!" << endl; } } } if(clueless_counter == 3) { - core->con << "Do 'help' or '?' for the list of available commands." << endl; + con << "Do 'help' or '?' for the list of available commands." << endl; clueless_counter = 0; } } diff --git a/library/FakeSDL-windows.cpp b/library/FakeSDL-windows.cpp index 06e032fa6..7c2e58343 100644 --- a/library/FakeSDL-windows.cpp +++ b/library/FakeSDL-windows.cpp @@ -538,6 +538,10 @@ DFhackCExport size_t SDL_strlcpy(char *dst, const char *src, size_t maxlen) if(!_SDL_strlcpy) { HMODULE realSDLlib = LoadLibrary("SDLreal.dll"); + if(!realSDLlib) + { + exit(-111); + } _SDL_strlcpy = (size_t (*)(char*, const char*, size_t))GetProcAddress(realSDLlib,"SDL_strlcpy"); } return _SDL_strlcpy(dst,src,maxlen); @@ -698,6 +702,7 @@ bool FirstCall() fprintf(stderr, "Can't load SDLreal.dll\n"); return 0; } + fprintf(stderr, "FirstCall()\n"); // stuff for DF _SDL_AddTimer = (void*(*)(uint32_t, void*, void*)) GetProcAddress(realSDLlib,"SDL_AddTimer"); _SDL_CondSignal = (int (*)(SDL::Cond*))GetProcAddress(realSDLlib,"SDL_CondSignal"); diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index 77515f891..da51d0569 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -71,6 +71,7 @@ bool hasEnding (std::string const &fullString, std::string const &ending) Plugin::Plugin(Core * core, const std::string & file) { filename = file; + Console & con = core->con; plugin_lib = 0; plugin_init = 0; plugin_shutdown = 0; @@ -80,20 +81,20 @@ Plugin::Plugin(Core * core, const std::string & file) DFLibrary * plug = OpenPlugin(file.c_str()); if(!plug) { - core->con << "Can't load plugin " << filename << endl; + con << "Can't load plugin " << filename << endl; return; } const char * (*_PlugName)() =(const char * (*)()) LookupPlugin(plug, "plugin_name"); if(!_PlugName) { - core->con << "Plugin " << filename << " has no name." << endl; + con << "Plugin " << filename << " has no name." << endl; ClosePlugin(plug); return; } plugin_init = (command_result (*)(Core *, std::vector &)) LookupPlugin(plug, "plugin_init"); if(!plugin_init) { - core->con << "Plugin " << filename << " has no init function." << endl; + con << "Plugin " << filename << " has no init function." << endl; ClosePlugin(plug); return; } diff --git a/library/VersionInfoFactory.cpp b/library/VersionInfoFactory.cpp index 3e676ece1..15f3f8a6a 100644 --- a/library/VersionInfoFactory.cpp +++ b/library/VersionInfoFactory.cpp @@ -168,13 +168,13 @@ void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem) string type = pClassEntry->Value(); const char *cstr_name = pClassEntry->Attribute("name"); const char *cstr_vtable = pClassEntry->Attribute("vtable"); - uint32_t vtable = 0; + uint32_t vtable_num = 0; if(cstr_vtable) - vtable = strtol(cstr_vtable, NULL, 16); + vtable_num = strtol(cstr_vtable, NULL, 16); // it's a simple class if(type== "class") { - mem->setClass(cstr_name, vtable); + mem->setClass(cstr_name, vtable_num); } // it's a multi-type class else if (type == "multiclass") @@ -184,7 +184,7 @@ void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem) uint32_t typeoffset = 0; if(cstr_typeoffset) typeoffset = strtol(cstr_typeoffset, NULL, 16); - t_class * mclass = mem->setClass(cstr_name, vtable, typeoffset); + t_class * mclass = mem->setClass(cstr_name, vtable_num, typeoffset); // parse class sub-entries pClassSubEntry = pClassEntry->FirstChildElement(); for(;pClassSubEntry;pClassSubEntry=pClassSubEntry->NextSiblingElement()) diff --git a/library/include/dfhack/Console.h b/library/include/dfhack/Console.h index de8cfdca9..828dfbf96 100644 --- a/library/include/dfhack/Console.h +++ b/library/include/dfhack/Console.h @@ -25,13 +25,11 @@ distribution. #pragma once #include "dfhack/Pragma.h" #include "dfhack/Export.h" -#include "dfhack/extra/stdiostream.h" -#include - +#include namespace DFHack { class Private; - class DFHACK_EXPORT Console : public duthomhas::stdiostream + class DFHACK_EXPORT Console : public std::ostream { public: Console(); @@ -69,7 +67,6 @@ namespace DFHack void prompt_refresh( const std::string & prompt, const std::string & buffer, size_t pos); int enable_raw(); void disable_raw(); - std::deque history; void history_clear(); Private * d; }; diff --git a/library/include/dfhack/Core.h b/library/include/dfhack/Core.h index 381d68194..f2610edfe 100644 --- a/library/include/dfhack/Core.h +++ b/library/include/dfhack/Core.h @@ -50,7 +50,6 @@ namespace DFHack class Constructions; class VersionInfo; class VersionInfoFactory; - class Console; class PluginManager; class Core; // anon type, pretty much diff --git a/library/include/dfhack/extra/stdiostream.h b/library/include/dfhack/extra/stdiostream.h index 133c17e59..154ef92f1 100644 --- a/library/include/dfhack/extra/stdiostream.h +++ b/library/include/dfhack/extra/stdiostream.h @@ -213,7 +213,7 @@ protected: std::ios_base::openmode which = std::ios_base::in | std::ios_base::out ) { pushbacks.clear(); - return std::fseek( fp, position, SEEK_SET ) + return std::fseek( fp, (long) position, SEEK_SET ) ? (-1) : std::ftell( fp ); } diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index e306eacd4..995153120 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -787,7 +787,7 @@ bool Maps::SortBlockEvents(uint32_t x, uint32_t y, uint32_t z, vector if(veins) veins->clear(); if(ices) ices->clear(); if(splatter) splatter->clear(); - if(grass) splatter->clear(); + if(grass) grass->clear(); if(constructions) constructions->clear(); Private::t_offsets &off = d->offsets; diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index 2cb88788b..057b24ae2 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -106,10 +106,10 @@ bool Translation::Start() for (uint32_t i = 0;i < genericVec.size();i++) { uint32_t genericNamePtr = genericVec.at(i); - for(int i=0; i<10;i++) + for(int j=0; j<10;i++) { - string word = p->readSTLString (genericNamePtr + i * d->sizeof_string); - translations[i].push_back (word); + string word = p->readSTLString (genericNamePtr + j * d->sizeof_string); + translations[j].push_back (word); } } diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 9c78264d4..da8877e26 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -89,6 +89,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par bool showPlants = true; bool showSlade = true; bool showTemple = true; + Console & con = c->con; if(parameters.size() && parameters[0] == "all") { showHidden = true; @@ -98,7 +99,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par DFHack::Maps *maps = c->getMaps(); if (!maps->Start()) { - c->con << "Cannot get map info!" << std::endl; + con << "Cannot get map info!" << std::endl; c->Resume(); return CR_FAILURE; } @@ -108,13 +109,13 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par DFHack::Materials *mats = c->getMaterials(); if (!mats->ReadInorganicMaterials()) { - c->con << "Unable to read inorganic material definitons!" << std::endl; + con << "Unable to read inorganic material definitons!" << std::endl; c->Resume(); return CR_FAILURE; } if (showPlants && !mats->ReadOrganicMaterials()) { - c->con << "Unable to read organic material definitons; plants won't be listed!" << std::endl; + con << "Unable to read organic material definitons; plants won't be listed!" << std::endl; showPlants = false; } @@ -134,21 +135,21 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par if (!(showSlade && maps->ReadGlobalFeatures(globalFeatures))) { - c->con << "Unable to read global features; slade won't be listed!" << std::endl; + con << "Unable to read global features; slade won't be listed!" << std::endl; } if (!maps->ReadLocalFeatures(localFeatures)) { - c->con << "Unable to read local features; adamantine " - << (showTemple ? "and demon temples " : "") - << "won't be listed!" << std::endl; + con << "Unable to read local features; adamantine " + << (showTemple ? "and demon temples " : "") + << "won't be listed!" << std::endl; } uint32_t vegCount = 0; DFHack::Vegetation *veg = c->getVegetation(); if (showPlants && !veg->Start()) { - c->con << "Unable to read vegetation; plants won't be listed!" << std::endl; + con << "Unable to read vegetation; plants won't be listed!" << std::endl; } for(uint32_t z = 0; z < z_max; z++) @@ -217,7 +218,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par if (!info) { - c->con << "Bad type: " << type << std::endl; + con << "Bad type: " << type << std::endl; continue; } @@ -306,39 +307,39 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par MatMap::const_iterator it; - c->con << "Base materials:" << std::endl; + con << "Base materials:" << std::endl; for (it = baseMats.begin(); it != baseMats.end(); ++it) { - c->con << std::setw(25) << DFHack::TileMaterialString[it->first] << " : " << it->second << std::endl; + con << std::setw(25) << DFHack::TileMaterialString[it->first] << " : " << it->second << std::endl; } - c->con << std::endl << "Layer materials:" << std::endl; - printMats(c->con, layerMats, mats->inorganic); + con << std::endl << "Layer materials:" << std::endl; + printMats(con, layerMats, mats->inorganic); - c->con << "Vein materials:" << std::endl; - printMats(c->con, veinMats, mats->inorganic); + con << "Vein materials:" << std::endl; + printMats(con, veinMats, mats->inorganic); if (showPlants) { - c->con << "Shrubs:" << std::endl; - printMats(c->con, plantMats, mats->organic); - c->con << "Wood in trees:" << std::endl; - printMats(c->con, treeMats, mats->organic); + con << "Shrubs:" << std::endl; + printMats(con, plantMats, mats->organic); + con << "Wood in trees:" << std::endl; + printMats(con, treeMats, mats->organic); } if (hasAquifer) { - c->con << "Has aquifer" << std::endl; + con << "Has aquifer" << std::endl; } if (hasDemonTemple) { - c->con << "Has demon temple" << std::endl; + con << "Has demon temple" << std::endl; } if (hasLair) { - c->con << "Has lair" << std::endl; + con << "Has lair" << std::endl; } // Cleanup @@ -349,6 +350,6 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector & par mats->Finish(); maps->Finish(); c->Resume(); - c->con << std::endl; + con << std::endl; return CR_OK; } diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp index 474cdee50..efdf61339 100644 --- a/plugins/reveal.cpp +++ b/plugins/reveal.cpp @@ -101,10 +101,10 @@ DFhackCExport command_result reveal(DFHack::Core * c, std::vector & { no_hell = false; } - + Console & con = c->con; if(revealed != NOT_REVEALED) { - c->con << "Map is already revealed or this is a different map." << std::endl; + con << "Map is already revealed or this is a different map." << std::endl; return CR_FAILURE; } @@ -115,20 +115,20 @@ DFhackCExport command_result reveal(DFHack::Core * c, std::vector & World->ReadGameMode(gm); if(gm.g_mode != GAMEMODE_DWARF) { - c->con << "Only in fortress mode." << std::endl; + con << "Only in fortress mode." << std::endl; c->Resume(); return CR_FAILURE; } if(!Maps->Start()) { - c->con << "Can't init map." << std::endl; + con << "Can't init map." << std::endl; c->Resume(); return CR_FAILURE; } if(no_hell && !Maps->StartFeatures()) { - c->con << "Unable to read local features; can't reveal map safely" << std::endl; + con << "Unable to read local features; can't reveal map safely" << std::endl; c->Resume(); return CR_FAILURE; } @@ -175,19 +175,19 @@ DFhackCExport command_result reveal(DFHack::Core * c, std::vector & World->SetPauseState(true); } c->Resume(); - c->con << "Map revealed." << std::endl; + con << "Map revealed." << std::endl; if(!no_hell) - c->con << "Unpausing can unleash the forces of hell, so it has been temporarily disabled." << std::endl; - c->con << "Run 'unreveal' to revert to previous state." << std::endl; + con << "Unpausing can unleash the forces of hell, so it has been temporarily disabled." << std::endl; + con << "Run 'unreveal' to revert to previous state." << std::endl; return CR_OK; } DFhackCExport command_result unreveal(DFHack::Core * c, std::vector & params) { - DFHack::designations40d designations; + Console & con = c->con; if(!revealed) { - c->con << "There's nothing to revert!" << std::endl; + con << "There's nothing to revert!" << std::endl; return CR_FAILURE; } c->Suspend(); @@ -197,14 +197,14 @@ DFhackCExport command_result unreveal(DFHack::Core * c, std::vector World->ReadGameMode(gm); if(gm.g_mode != GAMEMODE_DWARF) { - c->con << "Only in fortress mode." << std::endl; + con << "Only in fortress mode." << std::endl; c->Resume(); return CR_FAILURE; } Maps = c->getMaps(); if(!Maps->Start()) { - c->con << "Can't init map." << std::endl; + con << "Can't init map." << std::endl; c->Resume(); return CR_FAILURE; } @@ -214,7 +214,7 @@ DFhackCExport command_result unreveal(DFHack::Core * c, std::vector Maps->getSize(x_max_b,y_max_b,z_max_b); if(x_max != x_max_b || y_max != y_max_b || z_max != z_max_b) { - c->con << "The map is not of the same size..." << std::endl; + con << "The map is not of the same size..." << std::endl; c->Resume(); return CR_FAILURE; } @@ -233,7 +233,7 @@ DFhackCExport command_result unreveal(DFHack::Core * c, std::vector // give back memory. hidesaved.clear(); revealed = NOT_REVEALED; - c->con << "Map hidden!" << std::endl; + con << "Map hidden!" << std::endl; c->Resume(); return CR_OK; } diff --git a/plugins/vdig.cpp b/plugins/vdig.cpp index 5fcbed96c..459bf2240 100644 --- a/plugins/vdig.cpp +++ b/plugins/vdig.cpp @@ -43,13 +43,15 @@ DFhackCExport command_result vdig (Core * c, vector & parameters) if(parameters.size() && parameters[0]=="x") updown = true; + Console & con = c->con; + c->Suspend(); DFHack::Maps * Maps = c->getMaps(); DFHack::Gui * Gui = c->getGui(); // init the map if(!Maps->Start()) { - c->con << "Can't init map. Make sure you have a map loaded in DF.\n"; + con << "Can't init map. Make sure you have a map loaded in DF.\n"; c->Resume(); return CR_FAILURE; } @@ -61,14 +63,14 @@ DFhackCExport command_result vdig (Core * c, vector & parameters) Gui->getCursorCoords(cx,cy,cz); while(cx == -30000) { - c->con << "Cursor is not active. Point the cursor at a vein.\n"; + con << "Cursor is not active. Point the cursor at a vein.\n"; c->Resume(); return CR_FAILURE; } DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1) { - c->con << "I won't dig the borders. That would be cheating!\n"; + con << "I won't dig the borders. That would be cheating!\n"; c->Resume(); return CR_FAILURE; } @@ -78,12 +80,12 @@ DFhackCExport command_result vdig (Core * c, vector & parameters) int16_t veinmat = MCache->veinMaterialAt(xy); if( veinmat == -1 ) { - c->con << "This tile is not a vein.\n"; + con << "This tile is not a vein.\n"; delete MCache; c->Resume(); return CR_FAILURE; } - c->con.print("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole); + con.print("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole); stack flood; flood.push(xy); diff --git a/plugins/weather.cpp b/plugins/weather.cpp index 0e2ed180b..bc3c39b33 100644 --- a/plugins/weather.cpp +++ b/plugins/weather.cpp @@ -38,6 +38,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result weather (Core * c, vector & parameters) { + Console & con = c->con; bool lock = false; bool unlock = false; bool snow = false; @@ -58,7 +59,7 @@ DFhackCExport command_result weather (Core * c, vector & parameters) } if(lock && unlock) { - c->con << "Lock or unlock? DECIDE!" << std::endl; + con << "Lock or unlock? DECIDE!" << std::endl; return CR_FAILURE; } int cnt = 0; @@ -67,7 +68,7 @@ DFhackCExport command_result weather (Core * c, vector & parameters) cnt += clear; if(cnt > 1) { - c->con << "Rain, snow or clear sky? DECIDE!" << std::endl; + con << "Rain, snow or clear sky? DECIDE!" << std::endl; return CR_FAILURE; } bool something = lock || unlock || rain || snow || clear; @@ -75,14 +76,14 @@ DFhackCExport command_result weather (Core * c, vector & parameters) DFHack::World * w = c->getWorld(); if(!w->wmap) { - c->con << "Weather support seems broken :(" << std::endl; + con << "Weather support seems broken :(" << std::endl; c->Resume(); return CR_FAILURE; } if(!something) { // paint weather map - c->con << "Weather map (C = clear, R = rain, S = snow):" << std::endl; + con << "Weather map (C = clear, R = rain, S = snow):" << std::endl; for(int y = 0; y<5;y++) { for(int x = 0; x<5;x++) @@ -90,20 +91,20 @@ DFhackCExport command_result weather (Core * c, vector & parameters) switch((*w->wmap)[x][y]) { case DFHack::CLEAR: - c->con << "C "; + con << "C "; break; case DFHack::RAINING: - c->con << "R "; + con << "R "; break; case DFHack::SNOWING: - c->con << "S "; + con << "S "; break; default: - c->con << (int) (*w->wmap)[x][y] << " "; + con << (int) (*w->wmap)[x][y] << " "; break; } } - c->con << std::endl; + con << std::endl; } } else @@ -111,17 +112,17 @@ DFhackCExport command_result weather (Core * c, vector & parameters) // weather changing action! if(rain) { - c->con << "Here comes the rain." << std::endl; + con << "Here comes the rain." << std::endl; w->SetCurrentWeather(RAINING); } if(snow) { - c->con << "Snow everywhere!" << std::endl; + con << "Snow everywhere!" << std::endl; w->SetCurrentWeather(SNOWING); } if(clear) { - c->con << "Suddenly, sunny weather!" << std::endl; + con << "Suddenly, sunny weather!" << std::endl; w->SetCurrentWeather(CLEAR); } // FIXME: weather lock needs map ID to work reliably... needs to be implemented.