From 7b3fc13b224fc320663698ca913687a807cb053b Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Sat, 5 Nov 2011 20:09:10 +0200 Subject: [PATCH] Port the generic control stuff from wxwidgets work --- generic/command.cpp | 54 ++++++++++++++++++++ generic/command.hpp | 18 ++++++- generic/keymapper.cpp | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ generic/keymapper.hpp | 43 +++++++++++++++- generic/mainloop.cpp | 34 +------------ generic/memorywatch.cpp | 67 +++++++++++++++++++++++++ generic/memorywatch.hpp | 5 ++ generic/settings.cpp | 13 +++++ generic/settings.hpp | 6 +++ generic/window.cpp | 21 ++++++++ generic/window.hpp | 16 ++++++ 11 files changed, 370 insertions(+), 35 deletions(-) diff --git a/generic/command.cpp b/generic/command.cpp index d7fa4ad9..47ab496a 100644 --- a/generic/command.cpp +++ b/generic/command.cpp @@ -174,6 +174,60 @@ std::string command::get_long_help() throw(std::bad_alloc) return "No help available on command " + commandname; } +std::set command::get_aliases() throw(std::bad_alloc) +{ + std::set r; + for(auto i : aliases) + r.insert(i.first); + return r; +} + +std::string command::get_alias_for(const std::string& aname) throw(std::bad_alloc) +{ + if(!valid_alias_name(aname)) + return ""; + if(aliases.count(aname)) { + std::string x; + for(auto i : aliases[aname]) + x = x + i + "\n"; + return x; + } else + return ""; +} + +void command::set_alias_for(const std::string& aname, const std::string& avalue) throw(std::bad_alloc) +{ + if(!valid_alias_name(aname)) + return; + std::list newlist; + size_t avitr = 0; + while(avitr < avalue.length()) { + size_t nextsplit = avalue.find_first_of("\n"); + if(nextsplit >= avalue.length()) + nextsplit = avalue.length(); + std::string x = avalue.substr(avitr, nextsplit - avitr); + if(x.length() > 0 && x[x.length() - 1] == '\r') + x = x.substr(0, x.length() - 1); + if(x.length() > 0) + newlist.push_back(x); + avitr = nextsplit + 1; + } + if(newlist.empty()) + aliases.erase(aname); + else + aliases[aname] = newlist; +} + +bool command::valid_alias_name(const std::string& aliasname) throw(std::bad_alloc) +{ + if(aliasname.length() == 0 || aliasname[0] == '?' || aliasname[0] == '*') + return false; + if(aliasname.find_first_of(" \t") < aliasname.length()) + return false; + return true; +} + + tokensplitter::tokensplitter(const std::string& _line) throw(std::bad_alloc) { line = _line; diff --git a/generic/command.hpp b/generic/command.hpp index d575e1a3..ce434ddc 100644 --- a/generic/command.hpp +++ b/generic/command.hpp @@ -3,6 +3,7 @@ #include #include +#include /** @@ -39,7 +40,22 @@ public: * parameter cmd: Command to exeucte. */ static void invokeC(const std::string& cmd) throw(); - +/** + * Get set of aliases. + */ + static std::set get_aliases() throw(std::bad_alloc); +/** + * Get alias + */ + static std::string get_alias_for(const std::string& aname) throw(std::bad_alloc); +/** + * Set alias + */ + static void set_alias_for(const std::string& aname, const std::string& avalue) throw(std::bad_alloc); +/** + * Is alias name valid. + */ + static bool valid_alias_name(const std::string& aname) throw(std::bad_alloc); /** * Get short help for command. */ diff --git a/generic/keymapper.cpp b/generic/keymapper.cpp index 52f1f06f..f54b88c3 100644 --- a/generic/keymapper.cpp +++ b/generic/keymapper.cpp @@ -2,6 +2,7 @@ #include #include "window.hpp" #include "lua.hpp" +#include #include #include #include @@ -122,6 +123,14 @@ modifier::~modifier() throw() modifier_linkages().erase(modname); } +std::set modifier::get_set() throw(std::bad_alloc) +{ + std::set r; + for(auto i : known_modifiers()) + r.insert(i.first); + return r; +} + modifier& modifier::lookup(const std::string& name) throw(std::bad_alloc, std::runtime_error) { if(!known_modifiers().count(name)) { @@ -137,6 +146,14 @@ std::string modifier::name() const throw(std::bad_alloc) return modname; } +std::string modifier::linked_name() const throw(std::bad_alloc) +{ + const modifier* p = get_linked_modifier(this); + if(p == this) + return ""; + return p->modname; +} + void modifier_set::add(const modifier& mod, bool really) throw(std::bad_alloc) { @@ -473,6 +490,72 @@ void keygroup::set_exclusive_key_listener(key_listener* l) throw() exclusive = l; } +keygroup* keygroup::lookup_by_name(const std::string& name) throw() +{ + if(keygroups().count(name)) + return keygroups()[name]; + else + return NULL; +} + +std::set keygroup::get_axis_set() throw(std::bad_alloc) +{ + std::set r; + for(auto i : keygroups()) { + keygroup::parameters p = i.second->get_parameters(); + std::string type = ""; + switch(p.ktype) { + case keygroup::KT_DISABLED: + case keygroup::KT_AXIS_PAIR: + case keygroup::KT_AXIS_PAIR_INVERSE: + case keygroup::KT_PRESSURE_0M: + case keygroup::KT_PRESSURE_0P: + case keygroup::KT_PRESSURE_M0: + case keygroup::KT_PRESSURE_MP: + case keygroup::KT_PRESSURE_P0: + case keygroup::KT_PRESSURE_PM: + r.insert(i.first); + break; + default: + break; + }; + } + return r; +} + +std::set keygroup::get_keys() throw(std::bad_alloc) +{ + std::set r; + for(auto i : keygroups()) { + switch(i.second->ktype) { + case KT_KEY: + case KT_PRESSURE_M0: + case KT_PRESSURE_MP: + case KT_PRESSURE_0M: + case KT_PRESSURE_0P: + case KT_PRESSURE_PM: + case KT_PRESSURE_P0: + r.insert(i.first); + break; + case KT_AXIS_PAIR: + case KT_AXIS_PAIR_INVERSE: + r.insert(i.first + "+"); + r.insert(i.first + "-"); + break; + case KT_HAT: + r.insert(i.first + "n"); + r.insert(i.first + "e"); + r.insert(i.first + "s"); + r.insert(i.first + "w"); + break; + default: + break; + }; + } + return r; +} + + namespace { @@ -665,6 +748,20 @@ namespace } }; + triple parse_to_triple(const std::string& keyspec) + { + triple k("", "", ""); + std::string _keyspec = keyspec; + size_t split1 = _keyspec.find_first_of("/"); + size_t split2 = _keyspec.find_first_of("|"); + if(split1 >= keyspec.length() || split2 >= keyspec.length() || split1 > split2) + throw std::runtime_error("Bad keyspec " + keyspec); + k.a = _keyspec.substr(0, split1); + k.b = _keyspec.substr(split1 + 1, split2 - split1 - 1); + k.c = _keyspec.substr(split2 + 1); + return k; + } + std::map keybindings; } @@ -705,3 +802,34 @@ void keymapper::dumpbindings() throw(std::bad_alloc) messages << i.first.c << std::endl; } } + +std::set keymapper::get_bindings() throw(std::bad_alloc) +{ + std::set r; + for(auto i : keybindings) + r.insert(i.first.a + "/" + i.first.b + "|" + i.first.c); + return r; +} + +std::string keymapper::get_command_for(const std::string& keyspec) throw(std::bad_alloc) +{ + triple k("", "", ""); + try { + k = parse_to_triple(keyspec); + } catch(std::exception& e) { + return ""; + } + if(!keybindings.count(k)) + return ""; + return keybindings[k].command; +} + +void keymapper::bind_for(const std::string& keyspec, const std::string& cmd) throw(std::bad_alloc, std::runtime_error) +{ + triple k("", "", ""); + k = parse_to_triple(keyspec); + if(cmd != "") + bind(k.a, k.b, k.c, cmd); + else + unbind(k.a, k.b, k.c); +} diff --git a/generic/keymapper.hpp b/generic/keymapper.hpp index c7e29fbe..6078270c 100644 --- a/generic/keymapper.hpp +++ b/generic/keymapper.hpp @@ -71,6 +71,17 @@ public: * throws: std::bad_alloc: Not enough memory. */ std::string name() const throw(std::bad_alloc); +/** + * Get name of linked modifier. + * + * returns: The name of linked modifier, "" if none. + * throws: std::bad_alloc: Not enough memory. + */ + std::string linked_name() const throw(std::bad_alloc); +/** + * Get set of all modifiers. + */ + static std::set get_set() throw(std::bad_alloc); private: modifier(const modifier&); modifier& operator=(const modifier&); @@ -207,6 +218,20 @@ public: */ ~keygroup() throw(); /** + * Lookup key group by name. + * + * Parameter name: The key group name. + * Returns: The looked up key group, or NULL if not found. + */ + static keygroup* lookup_by_name(const std::string& name) throw(); +/** + * Get the set of axes. + * + * Returns: The axis set (all axes). + * Throws std::bad_alloc: Not enough memory. + */ + static std::set get_axis_set() throw(std::bad_alloc); +/** * Change type of key group. * * parameter t: New type for the key group. @@ -250,6 +275,10 @@ public: */ std::string name() throw(std::bad_alloc); /** + * Get set of all keys (including subkeys). + */ + static std::set get_keys() throw(std::bad_alloc); +/** * Keyboard key listener. */ struct key_listener @@ -363,13 +392,25 @@ public: */ static void unbind(std::string mod, std::string modmask, std::string keyname) throw(std::bad_alloc, std::runtime_error); - /** * Dump list of bindigns as message to console. * * throws std::bad_alloc: Not enough memory. */ static void dumpbindings() throw(std::bad_alloc); +/** + * Get keys bound. + */ + static std::set get_bindings() throw(std::bad_alloc); +/** + * Get command for key. + */ + static std::string get_command_for(const std::string& keyspec) throw(std::bad_alloc); +/** + * Bind command for key. + */ + static void bind_for(const std::string& keyspec, const std::string& cmd) throw(std::bad_alloc, + std::runtime_error); }; #endif diff --git a/generic/mainloop.cpp b/generic/mainloop.cpp index eb51eb24..616aafa6 100644 --- a/generic/mainloop.cpp +++ b/generic/mainloop.cpp @@ -49,8 +49,6 @@ namespace ADVANCE_PAUSE, //Unconditional pause. }; - //Memory watches. - std::map memory_watches; //Previous mouse mask. int prev_mouse_mask = 0; //Flags related to repeating advance. @@ -278,12 +276,7 @@ void update_movie_state() _status["Saveslot"] = save_jukebox[save_jukebox_pointer]; else _status.erase("Saveslot"); - for(auto i : memory_watches) { - try { - _status["M[" + i.first + "]"] = evaluate_watch(i.second); - } catch(...) { - } - } + do_watch_memory(); controls_t c; if(movb.get_movie().readonly_mode()) @@ -626,31 +619,6 @@ namespace redraw_framebuffer(); }); - function_ptr_command add_watch("add-watch", "Add a memory watch", - "Syntax: add-watch \nAdds a new memory watch\n", - [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) { - std::string name = t; - if(name == "" || t.tail() == "") - throw std::runtime_error("syntax: add-watch "); - std::cerr << "Add watch: '" << name << "'" << std::endl; - memory_watches[name] = t.tail(); - update_movie_state(); - }); - - function_ptr_command remove_watch("remove-watch", "Remove a memory watch", - "Syntax: remove-watch \nRemoves a memory watch\n", - [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) { - std::string name = t; - if(name == "" || t.tail() != "") { - messages << "syntax: remove-watch " << std::endl; - return; - } - std::cerr << "Erase watch: '" << name << "'" << std::endl; - memory_watches.erase(name); - auto& _status = window::get_emustatus(); - _status.erase("M[" + name + "]"); - update_movie_state(); - }); function_ptr_command<> test1("test-1", "no description available", "No help available\n", diff --git a/generic/memorywatch.cpp b/generic/memorywatch.cpp index ae226aa7..23e5b3ad 100644 --- a/generic/memorywatch.cpp +++ b/generic/memorywatch.cpp @@ -1,5 +1,7 @@ #include "memorywatch.hpp" #include "memorymanip.hpp" +#include "window.hpp" +#include "command.hpp" #include #include #include @@ -7,6 +9,12 @@ #include #include #include +#include + +namespace +{ + std::map watches; +} std::string evaluate_watch(const std::string& expr) throw(std::bad_alloc) { @@ -220,3 +228,62 @@ std::string evaluate_watch(const std::string& expr) throw(std::bad_alloc) return buffer; } } + +std::set get_watches() throw(std::bad_alloc) +{ + std::set r; + for(auto i : watches) + r.insert(i.first); + return r; +} + +std::string get_watchexpr_for(const std::string& w) throw(std::bad_alloc) +{ + if(watches.count(w)) + return watches[w]; + else + return ""; +} + +void set_watchexpr_for(const std::string& w, const std::string& expr) throw(std::bad_alloc) +{ + auto& status = window::get_emustatus(); + if(expr != "") { + watches[w] = expr; + status["M[" + w + "]"] = evaluate_watch(expr); + } else { + watches.erase(w); + status.erase("M[" + w + "]"); + } + window::notify_screen_update(); +} + +void do_watch_memory() +{ + auto& status = window::get_emustatus(); + for(auto i : watches) + status["M[" + i.first + "]"] = evaluate_watch(i.second); +} + +namespace +{ + function_ptr_command add_watch("add-watch", "Add a memory watch", + "Syntax: add-watch \nAdds a new memory watch\n", + [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) { + std::string name = t; + if(name == "" || t.tail() == "") + throw std::runtime_error("syntax: add-watch "); + set_watchexpr_for(name, t.tail()); + }); + + function_ptr_command remove_watch("remove-watch", "Remove a memory watch", + "Syntax: remove-watch \nRemoves a memory watch\n", + [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) { + std::string name = t; + if(name == "" || t.tail() != "") { + throw std::runtime_error("syntax: remove-watch "); + return; + } + set_watchexpr_for(name, ""); + }); +} \ No newline at end of file diff --git a/generic/memorywatch.hpp b/generic/memorywatch.hpp index 75a7d42b..e1d6c655 100644 --- a/generic/memorywatch.hpp +++ b/generic/memorywatch.hpp @@ -3,7 +3,12 @@ #include #include +#include std::string evaluate_watch(const std::string& expr) throw(std::bad_alloc); +std::set get_watches() throw(std::bad_alloc); +std::string get_watchexpr_for(const std::string& w) throw(std::bad_alloc); +void set_watchexpr_for(const std::string& w, const std::string& expr) throw(std::bad_alloc); +void do_watch_memory(); #endif \ No newline at end of file diff --git a/generic/settings.cpp b/generic/settings.cpp index 8f586575..f12e754f 100644 --- a/generic/settings.cpp +++ b/generic/settings.cpp @@ -5,6 +5,7 @@ #include "misc.hpp" #include "command.hpp" #include "globalwrap.hpp" +#include "window.hpp" #include namespace @@ -71,6 +72,7 @@ void setting::set(const std::string& _setting, const std::string& value) throw(s throw std::runtime_error("No such setting '" + _setting + "'"); try { settings()[_setting]->set(value); + window_callback::do_setting_change(_setting, value); } catch(std::bad_alloc& e) { throw; } catch(std::exception& e) { @@ -84,6 +86,8 @@ void setting::blank(const std::string& _setting) throw(std::bad_alloc, std::runt throw std::runtime_error("No such setting '" + _setting + "'"); try { settings()[_setting]->blank(); + window_callback::do_setting_clear(_setting); + } catch(std::bad_alloc& e) { throw; } catch(std::exception& e) { @@ -115,6 +119,15 @@ void setting::print_all() throw(std::bad_alloc) } } +std::set setting::get_settings_set() throw(std::bad_alloc) +{ + std::set r; + for(auto i : settings()) + r.insert(i.first); + return r; +} + + numeric_setting::numeric_setting(const std::string& sname, int32_t minv, int32_t maxv, int32_t dflt) throw(std::bad_alloc) : setting(sname) diff --git a/generic/settings.hpp b/generic/settings.hpp index d834609e..13accf91 100644 --- a/generic/settings.hpp +++ b/generic/settings.hpp @@ -2,6 +2,7 @@ #define _settings__hpp__included__ #include +#include #include #include @@ -100,6 +101,11 @@ public: * throws std::bad_alloc: Not enough memory. */ static void print_all() throw(std::bad_alloc); + +/** + * Get set of all settings. + */ + static std::set get_settings_set() throw(std::bad_alloc); protected: std::string settingname; }; diff --git a/generic/window.cpp b/generic/window.cpp index 50642cca..76a8a50e 100644 --- a/generic/window.cpp +++ b/generic/window.cpp @@ -350,3 +350,24 @@ void window_callback::do_autohold_reconfigure() for(auto i : wcbs()) i->on_autohold_reconfigure(); } + +void window_callback::do_setting_change(const std::string& _setting, const std::string& value) +{ + for(auto i : wcbs()) + i->on_setting_change(_setting, value); +} + +void window_callback::do_setting_clear(const std::string& _setting) +{ + for(auto i : wcbs()) + i->on_setting_clear(_setting); +} + +void window_callback::on_setting_change(const std::string& setting, const std::string& value) +{ +} + +void window_callback::on_setting_clear(const std::string& setting) +{ +} + diff --git a/generic/window.hpp b/generic/window.hpp index d6822724..60b70316 100644 --- a/generic/window.hpp +++ b/generic/window.hpp @@ -58,6 +58,14 @@ public: */ virtual void on_autohold_reconfigure(); /** + * Called when setting is changed. + */ + virtual void on_setting_change(const std::string& setting, const std::string& value); +/** + * Called when setting is cleared. + */ + virtual void on_setting_clear(const std::string& setting); +/** * Do try to close the window. */ static void do_close() throw(); @@ -85,6 +93,14 @@ public: * Do on_autohold_reconfigure */ static void do_autohold_reconfigure(); +/** + * Do on_setting_change + */ + static void do_setting_change(const std::string& setting, const std::string& value); +/** + * Do on_setting_clear + */ + static void do_setting_clear(const std::string& setting); private: window_callback(window_callback&); window_callback& operator=(window_callback&); -- 2.11.4.GIT