|  |  |  | @ -12,11 +12,13 @@ | 
		
	
		
			
				|  |  |  |  | #include <set> | 
		
	
		
			
				|  |  |  |  | #include <list> | 
		
	
		
			
				|  |  |  |  | #include <utility> | 
		
	
		
			
				|  |  |  |  | #include <vector> | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #include "df/interface_key.h" | 
		
	
		
			
				|  |  |  |  | #include "df/ui.h" | 
		
	
		
			
				|  |  |  |  | #include "df/graphic.h" | 
		
	
		
			
				|  |  |  |  | #include "df/enabler.h" | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | using namespace DFHack; | 
		
	
		
			
				|  |  |  |  | using namespace df::enums; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -24,6 +26,8 @@ using df::global::ui; | 
		
	
		
			
				|  |  |  |  | using df::global::gps; | 
		
	
		
			
				|  |  |  |  | using df::global::enabler; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | std::vector<std::string> command_history; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | class viewscreen_commandpromptst; | 
		
	
		
			
				|  |  |  |  | class prompt_ostream:public buffered_color_ostream | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					|  |  |  | @ -44,12 +48,25 @@ public: | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     void render(); | 
		
	
		
			
				|  |  |  |  |     void help() { } | 
		
	
		
			
				|  |  |  |  |     int8_t movies_okay() { return 0; } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     std::string getFocusString() { return "commandprompt"; } | 
		
	
		
			
				|  |  |  |  |     viewscreen_commandpromptst(std::string entry):is_response(false),entry(entry) | 
		
	
		
			
				|  |  |  |  |     viewscreen_commandpromptst(std::string entry):is_response(false) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         show_fps=df::global::gps->display_frames; | 
		
	
		
			
				|  |  |  |  |         df::global::gps->display_frames=0; | 
		
	
		
			
				|  |  |  |  |         cursor_pos = 0; | 
		
	
		
			
				|  |  |  |  |         frame = 0; | 
		
	
		
			
				|  |  |  |  |         history_idx = command_history.size(); | 
		
	
		
			
				|  |  |  |  |         if (history_idx > 0) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (command_history[history_idx - 1] == "") | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 command_history.pop_back(); | 
		
	
		
			
				|  |  |  |  |                 history_idx--; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         command_history.push_back(entry); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     ~viewscreen_commandpromptst() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
	
		
			
				
					|  |  |  | @ -65,12 +82,50 @@ public: | 
		
	
		
			
				|  |  |  |  |             responses.push_back(std::make_pair(v, part + '\n')); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     std::string get_entry() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         return command_history[history_idx]; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     void set_entry(std::string entry) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         command_history[history_idx] = entry; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     void back_word() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         std::string entry = get_entry(); | 
		
	
		
			
				|  |  |  |  |         if (cursor_pos == 0) | 
		
	
		
			
				|  |  |  |  |             return; | 
		
	
		
			
				|  |  |  |  |         cursor_pos--; | 
		
	
		
			
				|  |  |  |  |         while (cursor_pos > 0 && !isalnum(entry[cursor_pos])) | 
		
	
		
			
				|  |  |  |  |             cursor_pos--; | 
		
	
		
			
				|  |  |  |  |         while (cursor_pos > 0 && isalnum(entry[cursor_pos])) | 
		
	
		
			
				|  |  |  |  |             cursor_pos--; | 
		
	
		
			
				|  |  |  |  |         if (!isalnum(entry[cursor_pos]) && cursor_pos != 0) | 
		
	
		
			
				|  |  |  |  |             cursor_pos++; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     void forward_word() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         std::string entry = get_entry(); | 
		
	
		
			
				|  |  |  |  |         int len = entry.size(); | 
		
	
		
			
				|  |  |  |  |         if (cursor_pos == len) | 
		
	
		
			
				|  |  |  |  |             return; | 
		
	
		
			
				|  |  |  |  |         cursor_pos++; | 
		
	
		
			
				|  |  |  |  |         while (cursor_pos <= len && !isalnum(entry[cursor_pos])) | 
		
	
		
			
				|  |  |  |  |             cursor_pos++; | 
		
	
		
			
				|  |  |  |  |         while (cursor_pos <= len && isalnum(entry[cursor_pos])) | 
		
	
		
			
				|  |  |  |  |             cursor_pos++; | 
		
	
		
			
				|  |  |  |  |         if (cursor_pos > len) | 
		
	
		
			
				|  |  |  |  |             cursor_pos = len; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | protected: | 
		
	
		
			
				|  |  |  |  |     std::list<std::pair<color_value,std::string> > responses; | 
		
	
		
			
				|  |  |  |  |     int cursor_pos; | 
		
	
		
			
				|  |  |  |  |     int history_idx; | 
		
	
		
			
				|  |  |  |  |     bool is_response; | 
		
	
		
			
				|  |  |  |  |     bool show_fps; | 
		
	
		
			
				|  |  |  |  |     int frame; | 
		
	
		
			
				|  |  |  |  |     void submit(); | 
		
	
		
			
				|  |  |  |  |     std::string entry; | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | void prompt_ostream::flush_proxy() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
	
		
			
				
					|  |  |  | @ -82,6 +137,9 @@ void prompt_ostream::flush_proxy() | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | void viewscreen_commandpromptst::render() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     ++frame; | 
		
	
		
			
				|  |  |  |  |     if (frame >= df::global::enabler->gfps) | 
		
	
		
			
				|  |  |  |  |         frame = 0; | 
		
	
		
			
				|  |  |  |  |     if (Screen::isDismissed(this)) | 
		
	
		
			
				|  |  |  |  |         return; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -101,14 +159,25 @@ void viewscreen_commandpromptst::render() | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         std::string entry = get_entry(); | 
		
	
		
			
				|  |  |  |  |         Screen::fillRect(Screen::Pen(' ', 7, 0),0,0,dim.x,0); | 
		
	
		
			
				|  |  |  |  |         Screen::paintString(Screen::Pen(' ', 7, 0), 0, 0,"[DFHack]#"); | 
		
	
		
			
				|  |  |  |  |         if(entry.size()<dim.x) | 
		
	
		
			
				|  |  |  |  |         std::string cursor = (frame < df::global::enabler->gfps / 2) ? "_" : " "; | 
		
	
		
			
				|  |  |  |  |         if(cursor_pos < (dim.x - 10)) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             Screen::paintString(Screen::Pen(' ', 7, 0), 10,0 , entry); | 
		
	
		
			
				|  |  |  |  |             if (entry.size() > dim.x - 10) | 
		
	
		
			
				|  |  |  |  |                 Screen::paintTile(Screen::Pen('\032', 7, 0), dim.x - 1, 0); | 
		
	
		
			
				|  |  |  |  |             if (cursor != " ") | 
		
	
		
			
				|  |  |  |  |                 Screen::paintString(Screen::Pen(' ', 10, 0), 10 + cursor_pos, 0, cursor); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             Screen::paintTile(Screen::Pen('>', 7, 0), 9, 0); | 
		
	
		
			
				|  |  |  |  |             Screen::paintString(Screen::Pen(' ', 7, 0), 10, 0, entry.substr(entry.size()-dim.x)); | 
		
	
		
			
				|  |  |  |  |             size_t start = cursor_pos - dim.x + 10 + 1; | 
		
	
		
			
				|  |  |  |  |             Screen::paintTile(Screen::Pen('\033', 7, 0), 9, 0); | 
		
	
		
			
				|  |  |  |  |             Screen::paintString(Screen::Pen(' ', 7, 0), 10, 0, entry.substr(start)); | 
		
	
		
			
				|  |  |  |  |             if (cursor != " ") | 
		
	
		
			
				|  |  |  |  |                 Screen::paintString(Screen::Pen(' ', 10, 0), dim.x - 1, 0, cursor); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | @ -120,9 +189,8 @@ void viewscreen_commandpromptst::submit() | 
		
	
		
			
				|  |  |  |  |         Screen::dismiss(this); | 
		
	
		
			
				|  |  |  |  |         return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     //color_ostream_proxy out(Core::getInstance().getConsole());
 | 
		
	
		
			
				|  |  |  |  |     prompt_ostream out(this); | 
		
	
		
			
				|  |  |  |  |     Core::getInstance().runCommand(out, entry); | 
		
	
		
			
				|  |  |  |  |     Core::getInstance().runCommand(out, get_entry()); | 
		
	
		
			
				|  |  |  |  |     if(out.empty() && responses.empty()) | 
		
	
		
			
				|  |  |  |  |         Screen::dismiss(this); | 
		
	
		
			
				|  |  |  |  |     else | 
		
	
	
		
			
				
					|  |  |  | @ -132,7 +200,8 @@ void viewscreen_commandpromptst::submit() | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | void viewscreen_commandpromptst::feed(std::set<df::interface_key> *events) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     int old_pos = cursor_pos; | 
		
	
		
			
				|  |  |  |  |     std::string entry = get_entry(); | 
		
	
		
			
				|  |  |  |  |     bool leave_all = events->count(interface_key::LEAVESCREEN_ALL); | 
		
	
		
			
				|  |  |  |  |     if (leave_all || events->count(interface_key::LEAVESCREEN)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
	
		
			
				
					|  |  |  | @ -144,30 +213,91 @@ void viewscreen_commandpromptst::feed(std::set<df::interface_key> *events) | 
		
	
		
			
				|  |  |  |  |             parent->feed(events); | 
		
	
		
			
				|  |  |  |  |             events->clear(); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         //if (command_history.size() && !entry.size())
 | 
		
	
		
			
				|  |  |  |  |         //    command_history.pop_back();
 | 
		
	
		
			
				|  |  |  |  |         return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     if(events->count(interface_key::SELECT)) | 
		
	
		
			
				|  |  |  |  |     if (events->count(interface_key::SELECT)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         submit(); | 
		
	
		
			
				|  |  |  |  |         return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     if(is_response) | 
		
	
		
			
				|  |  |  |  |     if (is_response) | 
		
	
		
			
				|  |  |  |  |         return; | 
		
	
		
			
				|  |  |  |  |     for (auto it = events->begin(); it != events->end(); ++it) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         auto key = *it; | 
		
	
		
			
				|  |  |  |  |         if (key==interface_key::STRING_A000) //delete?
 | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if(entry.size()) | 
		
	
		
			
				|  |  |  |  |                 entry.resize(entry.size()-1); | 
		
	
		
			
				|  |  |  |  |             if(entry.size() && cursor_pos > 0) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 entry.erase(cursor_pos - 1, 1); | 
		
	
		
			
				|  |  |  |  |                 cursor_pos--; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             if(cursor_pos > entry.size()) | 
		
	
		
			
				|  |  |  |  |                 cursor_pos = entry.size(); | 
		
	
		
			
				|  |  |  |  |             continue; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         if (key >= interface_key::STRING_A000 && | 
		
	
		
			
				|  |  |  |  |             key <= interface_key::STRING_A255) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             entry.push_back(char(key - interface_key::STRING_A000)); | 
		
	
		
			
				|  |  |  |  |             entry.insert(cursor_pos, 1, char(key - interface_key::STRING_A000)); | 
		
	
		
			
				|  |  |  |  |             cursor_pos++; | 
		
	
		
			
				|  |  |  |  |             set_entry(entry); | 
		
	
		
			
				|  |  |  |  |             return; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     // Prevent number keys from moving cursor
 | 
		
	
		
			
				|  |  |  |  |     if(events->count(interface_key::CURSOR_RIGHT)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         cursor_pos++; | 
		
	
		
			
				|  |  |  |  |         if (cursor_pos > entry.size()) | 
		
	
		
			
				|  |  |  |  |             cursor_pos = entry.size(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if(events->count(interface_key::CURSOR_LEFT)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         cursor_pos--; | 
		
	
		
			
				|  |  |  |  |         if (cursor_pos < 0) cursor_pos = 0; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if(events->count(interface_key::CURSOR_RIGHT_FAST)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         forward_word(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if(events->count(interface_key::CURSOR_LEFT_FAST)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         back_word(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if(events->count(interface_key::CUSTOM_CTRL_A)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         cursor_pos = 0; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if(events->count(interface_key::CUSTOM_CTRL_E)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         cursor_pos = entry.size(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if(events->count(interface_key::CURSOR_UP)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         history_idx--; | 
		
	
		
			
				|  |  |  |  |         if (history_idx < 0) | 
		
	
		
			
				|  |  |  |  |             history_idx = 0; | 
		
	
		
			
				|  |  |  |  |         entry = get_entry(); | 
		
	
		
			
				|  |  |  |  |         cursor_pos = entry.size(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     else if(events->count(interface_key::CURSOR_DOWN)) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (history_idx < command_history.size() - 1) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             history_idx++; | 
		
	
		
			
				|  |  |  |  |             if (history_idx >= command_history.size()) | 
		
	
		
			
				|  |  |  |  |                 history_idx = command_history.size() - 1; | 
		
	
		
			
				|  |  |  |  |             entry = get_entry(); | 
		
	
		
			
				|  |  |  |  |             cursor_pos = entry.size(); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     set_entry(entry); | 
		
	
		
			
				|  |  |  |  |     if (old_pos != cursor_pos) | 
		
	
		
			
				|  |  |  |  |         frame = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | DFHACK_PLUGIN("command-prompt"); | 
		
	
		
			
				|  |  |  |  | command_result show_prompt(color_ostream &out, std::vector <std::string> & parameters) | 
		
	
	
		
			
				
					|  |  |  | 
 |