X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FKeyMap.cpp;h=d1c7040c7d0c83dfe8fa491a20edd3392910386a;hb=2df6a6a37876dcfaa755c9aaf6a5ddc1ad58c63e;hp=e923abd63ee1f12c8215c36e6235d5cf62154218;hpb=cc91c7e6ee8d6ac98959de86780169f446c23075;p=lyx.git diff --git a/src/KeyMap.cpp b/src/KeyMap.cpp index e923abd63e..d1c7040c7d 100644 --- a/src/KeyMap.cpp +++ b/src/KeyMap.cpp @@ -15,26 +15,24 @@ #include "KeyMap.h" -#include "debug.h" #include "KeySequence.h" #include "LyXAction.h" #include "Lexer.h" +#include "support/debug.h" +#include "support/docstream.h" +#include "support/FileName.h" #include "support/filetools.h" +#include #include #include -using std::endl; -using std::string; -using std::make_pair; - +using namespace std; +using namespace lyx::support; namespace lyx { -using support::FileName; -using support::i18nLibFileSearch; - string const KeyMap::printKeySym(KeySymbol const & key, KeyModifier mod) { @@ -42,12 +40,12 @@ string const KeyMap::printKeySym(KeySymbol const & key, KeyModifier mod) string const s = key.getSymbolName(); - if (mod & ShiftModifier) - buf += "S-"; if (mod & ControlModifier) buf += "C-"; if (mod & AltModifier) buf += "M-"; + if (mod & ShiftModifier) + buf += "S-"; buf += s; return buf; @@ -56,22 +54,66 @@ string const KeyMap::printKeySym(KeySymbol const & key, KeyModifier mod) size_t KeyMap::bind(string const & seq, FuncRequest const & func) { - LYXERR(Debug::KBMAP) << "BIND: Sequence `" - << seq << "' Action `" - << func.action << '\'' << endl; + LYXERR(Debug::KBMAP, "BIND: Sequence `" << seq << "' Action `" + << func.action << '\''); KeySequence k(0, 0); string::size_type const res = k.parse(seq); if (res == string::npos) { - defkey(&k, func); + bind(&k, func); } else { - LYXERR(Debug::KBMAP) << "Parse error at position " << res - << " in key sequence '" << seq << "'." - << endl; + LYXERR(Debug::KBMAP, "Parse error at position " << res + << " in key sequence '" << seq << "'."); } - return res; + return res == string::npos ? 0 : res; +} + + +size_t KeyMap::unbind(string const & seq, FuncRequest const & func) +{ + KeySequence k(0, 0); + + string::size_type const res = k.parse(seq); + if (res == string::npos) + unbind(&k, func); + else + LYXERR(Debug::KBMAP, "Parse error at position " << res + << " in key sequence '" << seq << "'."); + return res == string::npos ? 0 : res; +} + + +bool KeyMap::hasBinding(KeySequence const & seq, FuncRequest const & func, + unsigned int r) +{ + KeySymbol code = seq.sequence[r]; + if (!code.isOK()) + return false; + + KeyModifier const mod1 = seq.modifiers[r].first; + KeyModifier const mod2 = seq.modifiers[r].second; + + // check if key is already there + Table::iterator end = table.end(); + for (Table::iterator it = table.begin(); it != end; ++it) { + if (code == it->code + && mod1 == it->mod.first + && mod2 == it->mod.second) { + if (r + 1 == seq.length()) + return it->func == func; + else if (it->table.get()) + return it->table->hasBinding(seq, func, r + 1); + } + } + return false; +} + + +void KeyMap::clear() +{ + table.clear(); } @@ -79,18 +121,20 @@ namespace { enum BindTags { BN_BIND, - BN_BINDFILE + BN_BINDFILE, + BN_UNBIND, }; keyword_item bindTags[] = { { "\\bind", BN_BIND }, - { "\\bind_file", BN_BINDFILE } + { "\\bind_file", BN_BINDFILE }, + { "\\unbind", BN_UNBIND }, }; } -bool KeyMap::read(string const & bind_file) +bool KeyMap::read(string const & bind_file, KeyMap * unbind_map) { const int bindCount = sizeof(bindTags) / sizeof(keyword_item); @@ -106,7 +150,7 @@ bool KeyMap::read(string const & bind_file) return false; } - LYXERR(Debug::KBMAP) << "Reading bind file:" << tmp << endl; + LYXERR(Debug::KBMAP, "Reading bind file:" << tmp); bool error = false; while (lexrc.isOK()) { @@ -148,10 +192,44 @@ bool KeyMap::read(string const & bind_file) bind(seq, func); break; } + case BN_UNBIND: + { + string seq, cmd; + + if (lexrc.next()) { + seq = lexrc.getString(); + } else { + lexrc.printError("BN_UNBIND: Missing key sequence"); + error = true; + break; + } + + if (lexrc.next(true)) { + cmd = lexrc.getString(); + } else { + lexrc.printError("BN_UNBIND: missing command"); + error = true; + break; + } + + FuncRequest func = lyxaction.lookupFunc(cmd); + if (func. action == LFUN_UNKNOWN_ACTION) { + lexrc.printError("BN_UNBIND: Unknown LyX" + " function `$$Token'"); + error = true; + break; + } + + if (unbind_map) + unbind_map->bind(seq, func); + else + unbind(seq, func); + break; + } case BN_BINDFILE: if (lexrc.next()) { string const tmp(lexrc.getString()); - error |= !read(tmp); + error |= !read(tmp, unbind_map); } else { lexrc.printError("BN_BINDFILE: Missing file name"); error = true; @@ -169,6 +247,35 @@ bool KeyMap::read(string const & bind_file) } +void KeyMap::write(string const & bind_file, bool append, bool unbind) const +{ + ofstream os(bind_file.c_str(), + append ? (ios::app | ios::out) : ios::out); + + if (!append) + os << "## This file is automatically generated by lyx\n" + << "## All modifications will be lost\n\n"; + + string tag = unbind ? "\\unbind" : "\\bind"; + BindingList const list = listBindings(false); + BindingList::const_iterator it = list.begin(); + BindingList::const_iterator it_end = list.end(); + for (; it != it_end; ++it) { + FuncCode action = it->request.action; + string arg = to_utf8(it->request.argument()); + + os << tag << " \"" + << to_utf8(it->sequence.print(KeySequence::BindFile)) + << "\" \"" + << lyxaction.getActionName(action) + << (arg.empty() ? "" : " ") << arg + << "\"\n"; + } + os << "\n"; + os.close(); +} + + FuncRequest const & KeyMap::lookup(KeySymbol const &key, KeyModifier mod, KeySequence * seq) const { @@ -221,7 +328,7 @@ docstring const KeyMap::print(bool forgui) const } -void KeyMap::defkey(KeySequence * seq, FuncRequest const & func, unsigned int r) +void KeyMap::bind(KeySequence * seq, FuncRequest const & func, unsigned int r) { KeySymbol code = seq->sequence[r]; if (!code.isOK()) @@ -238,11 +345,9 @@ void KeyMap::defkey(KeySequence * seq, FuncRequest const & func, unsigned int r) && mod2 == it->mod.second) { // overwrite binding if (r + 1 == seq->length()) { - LYXERR(Debug::KBMAP) - << "Warning: New binding for '" - << to_utf8(seq->print(false)) - << "' is overriding old binding..." - << endl; + LYXERR(Debug::KBMAP, "Warning: New binding for '" + << to_utf8(seq->print(KeySequence::Portable)) + << "' is overriding old binding..."); if (it->table.get()) { it->table.reset(); } @@ -251,12 +356,12 @@ void KeyMap::defkey(KeySequence * seq, FuncRequest const & func, unsigned int r) return; } else if (!it->table.get()) { lyxerr << "Error: New binding for '" - << to_utf8(seq->print(false)) + << to_utf8(seq->print(KeySequence::Portable)) << "' is overriding old binding..." << endl; return; } else { - it->table->defkey(seq, func, r + 1); + it->table->bind(seq, func, r + 1); return; } } @@ -271,14 +376,52 @@ void KeyMap::defkey(KeySequence * seq, FuncRequest const & func, unsigned int r) newone->table.reset(); } else { newone->table.reset(new KeyMap); - newone->table->defkey(seq, func, r + 1); + newone->table->bind(seq, func, r + 1); + } +} + + +void KeyMap::unbind(KeySequence * seq, FuncRequest const & func, unsigned int r) +{ + KeySymbol code = seq->sequence[r]; + if (!code.isOK()) + return; + + KeyModifier const mod1 = seq->modifiers[r].first; + KeyModifier const mod2 = seq->modifiers[r].second; + + // check if key is already there + Table::iterator end = table.end(); + Table::iterator remove = end; + for (Table::iterator it = table.begin(); it != end; ++it) { + if (code == it->code + && mod1 == it->mod.first + && mod2 == it->mod.second) { + // remove + if (r + 1 == seq->length()) { + if (it->func == func) { + remove = it; + if (it->table.get()) + it->table.reset(); + } + } else if (it->table.get()) { + it->table->unbind(seq, func, r + 1); + if (it->table->empty()) + remove = it; + return; + } + } + } + if (remove != end) { + table.erase(remove); + return; } } -docstring const KeyMap::printbindings(FuncRequest const & func) const +docstring KeyMap::printBindings(FuncRequest const & func) const { - Bindings bindings = findbindings(func); + Bindings bindings = findBindings(func); if (bindings.empty()) return docstring(); @@ -286,34 +429,33 @@ docstring const KeyMap::printbindings(FuncRequest const & func) const Bindings::const_iterator cit = bindings.begin(); Bindings::const_iterator cit_end = bindings.end(); // prin the first item - res << cit->print(true); + res << cit->print(KeySequence::ForGui); // more than one shortcuts? for (++cit; cit != cit_end; ++cit) - res << ", " << cit->print(true); + res << ", " << cit->print(KeySequence::ForGui); return res.str(); } -KeyMap::Bindings KeyMap::findbindings(FuncRequest const & func) const +KeyMap::Bindings KeyMap::findBindings(FuncRequest const & func) const { - return findbindings(func, KeySequence(0, 0)); + return findBindings(func, KeySequence(0, 0)); } -KeyMap::Bindings KeyMap::findbindings(FuncRequest const & func, +KeyMap::Bindings KeyMap::findBindings(FuncRequest const & func, KeySequence const & prefix) const { Bindings res; - if (table.empty()) return res; + if (table.empty()) + return res; Table::const_iterator end = table.end(); - for (Table::const_iterator cit = table.begin(); - cit != end; ++cit) { + for (Table::const_iterator cit = table.begin(); cit != end; ++cit) { if (cit->table.get()) { KeySequence seq = prefix; seq.addkey(cit->code, cit->mod.first); - Bindings res2 = - cit->table->findbindings(func, seq); + Bindings res2 = cit->table->findBindings(func, seq); res.insert(res.end(), res2.begin(), res2.end()); } else if (cit->func == func) { KeySequence seq = prefix; @@ -326,25 +468,25 @@ KeyMap::Bindings KeyMap::findbindings(FuncRequest const & func, } -KeyMap::BindingList const KeyMap::listBindings(bool unbound) const +KeyMap::BindingList KeyMap::listBindings(bool unbound, int tag) const { BindingList list; - listBindings(list, KeySequence(0, 0)); + listBindings(list, KeySequence(0, 0), tag); if (unbound) { LyXAction::const_func_iterator fit = lyxaction.func_begin(); LyXAction::const_func_iterator fit_end = lyxaction.func_end(); for (; fit != fit_end; ++fit) { - kb_action action = fit->second; + FuncCode action = fit->second; bool has_action = false; BindingList::const_iterator it = list.begin(); BindingList::const_iterator it_end = list.end(); for (; it != it_end; ++it) - if (it->first.action == action) { + if (it->request.action == action) { has_action = true; break; } if (!has_action) - list.push_back(make_pair(action, KeySequence(0, 0))); + list.push_back(Binding(FuncRequest(action), KeySequence(0, 0), tag)); } } return list; @@ -352,7 +494,7 @@ KeyMap::BindingList const KeyMap::listBindings(bool unbound) const void KeyMap::listBindings(BindingList & list, - KeySequence const & prefix) const + KeySequence const & prefix, int tag) const { Table::const_iterator it = table.begin(); Table::const_iterator it_end = table.end(); @@ -361,11 +503,11 @@ void KeyMap::listBindings(BindingList & list, if (it->table.get()) { KeySequence seq = prefix; seq.addkey(it->code, it->mod.first); - it->table->listBindings(list, seq); + it->table->listBindings(list, seq, tag); } else { KeySequence seq = prefix; seq.addkey(it->code, it->mod.first); - list.push_back(make_pair(it->func, seq)); + list.push_back(Binding(it->func, seq, tag)); } } }