X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FKeyMap.cpp;h=8c28b50031263e981064e2de056da0c0f67c0a11;hb=21514ad5129df123605cc11b1dc04d525ce4a295;hp=19ce93464df2eb61d646b12122f62587a5925ea6;hpb=ad0ecf86a70f54246ed2022553c20cb588d0bb6e;p=lyx.git diff --git a/src/KeyMap.cpp b/src/KeyMap.cpp index 19ce93464d..8c28b50031 100644 --- a/src/KeyMap.cpp +++ b/src/KeyMap.cpp @@ -3,10 +3,10 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * \author Jean-Marc Lasgouttes * \author John Levon - * \author André Pönitz + * \author André Pönitz * * Full author contact details are available in file CREDITS. */ @@ -23,6 +23,10 @@ #include "support/docstream.h" #include "support/FileName.h" #include "support/filetools.h" +#include "support/gettext.h" +#include "support/lstrings.h" + +#include "frontends/alert.h" #include #include @@ -55,7 +59,7 @@ 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 << '\''); + << func.action() << '\''); KeySequence k(0, 0); @@ -85,12 +89,100 @@ size_t KeyMap::unbind(string const & seq, FuncRequest const & func) } -bool KeyMap::hasBinding(KeySequence const & 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()) + 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(); + for (Table::iterator it = table.begin(); it != end; ++it) { + if (code == it->code + && mod1 == it->mod.first + && mod2 == it->mod.second) { + // overwrite binding + if (r + 1 == seq->length()) { + LYXERR(Debug::KBMAP, "Warning: New binding for '" + << to_utf8(seq->print(KeySequence::Portable)) + << "' is overriding old binding..."); + if (it->prefixes.get()) { + it->prefixes.reset(); + } + it->func = func; + it->func.setOrigin(FuncRequest::KEYBOARD); + return; + } else if (!it->prefixes.get()) { + lyxerr << "Error: New binding for '" + << to_utf8(seq->print(KeySequence::Portable)) + << "' is overriding old binding..." + << endl; + return; + } else { + it->prefixes->bind(seq, func, r + 1); + return; + } + } + } + + Table::iterator newone = table.insert(table.end(), Key()); + newone->code = code; + newone->mod = seq->modifiers[r]; + if (r + 1 == seq->length()) { + newone->func = func; + newone->func.setOrigin(FuncRequest::KEYBOARD); + newone->prefixes.reset(); + } else { + newone->prefixes.reset(new KeyMap); + newone->prefixes->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->prefixes.get()) + it->prefixes.reset(); + } + } else if (it->prefixes.get()) { + it->prefixes->unbind(seq, func, r + 1); + if (it->prefixes->empty()) + remove = it; + return; + } + } + } + if (remove != end) + table.erase(remove); +} + + +FuncRequest KeyMap::getBinding(KeySequence const & seq, unsigned int r) { KeySymbol code = seq.sequence[r]; if (!code.isOK()) - return false; + return FuncRequest::unknown; KeyModifier const mod1 = seq.modifiers[r].first; KeyModifier const mod2 = seq.modifiers[r].second; @@ -102,12 +194,12 @@ bool KeyMap::hasBinding(KeySequence const & seq, FuncRequest const & func, && 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 it->func; + else if (it->prefixes.get()) + return it->prefixes->getBinding(seq, r + 1); } } - return false; + return FuncRequest::unknown; } @@ -117,7 +209,40 @@ void KeyMap::clear() } -bool KeyMap::read(string const & bind_file, KeyMap * unbind_map) +bool KeyMap::read(string const & bind_file, KeyMap * unbind_map, BindReadType rt) +{ + FileName bf = i18nLibFileSearch("bind", bind_file, "bind"); + if (bf.empty()) { + if (rt == MissingOK) + return true; + + lyxerr << "Could not find bind file: " << bind_file; + if (rt == Default) { + frontend::Alert::warning(_("Could not find bind file"), + bformat(_("Unable to find the bind file\n%1$s.\n" + "Please check your installation."), from_utf8(bind_file))); + return false; + } + + static string const defaultBindfile = "cua"; + if (bind_file == defaultBindfile) { + frontend::Alert::warning(_("Could not find `cua.bind' file"), + _("Unable to find the default bind file `cua.bind'.\n" + "Please check your installation.")); + return false; + } + + // Try it with the default file. + frontend::Alert::warning(_("Could not find bind file"), + bformat(_("Unable to find the bind file\n%1$s.\n" + "Falling back to default."), from_utf8(bind_file))); + return read(defaultBindfile, unbind_map); + } + return read(bf, unbind_map); +} + + +bool KeyMap::read(FileName const & bind_file, KeyMap * unbind_map) { enum { BN_BIND, @@ -135,14 +260,13 @@ bool KeyMap::read(string const & bind_file, KeyMap * unbind_map) if (lyxerr.debugging(Debug::PARSER)) lexrc.printTable(lyxerr); - FileName const tmp = i18nLibFileSearch("bind", bind_file, "bind"); - lexrc.setFile(tmp); + lexrc.setFile(bind_file); if (!lexrc.isOK()) { - LYXERR0("KeyMap::read: cannot open bind file:" << tmp); + LYXERR0("KeyMap::read: cannot open bind file:" << bind_file.absFileName()); return false; } - LYXERR(Debug::KBMAP, "Reading bind file:" << tmp); + LYXERR(Debug::KBMAP, "Reading bind file:" << bind_file.absFileName()); bool error = false; while (lexrc.isOK()) { @@ -172,7 +296,7 @@ bool KeyMap::read(string const & bind_file, KeyMap * unbind_map) string cmd = lexrc.getString(); FuncRequest func = lyxaction.lookupFunc(cmd); - if (func.action == LFUN_UNKNOWN_ACTION) { + if (func.action() == LFUN_UNKNOWN_ACTION) { lexrc.printError("BN_BIND: Unknown LyX function `$$Token'"); error = true; break; @@ -198,7 +322,7 @@ bool KeyMap::read(string const & bind_file, KeyMap * unbind_map) string cmd = lexrc.getString(); FuncRequest func = lyxaction.lookupFunc(cmd); - if (func.action == LFUN_UNKNOWN_ACTION) { + if (func.action() == LFUN_UNKNOWN_ACTION) { lexrc.printError("BN_UNBIND: Unknown LyX" " function `$$Token'"); error = true; @@ -225,7 +349,7 @@ bool KeyMap::read(string const & bind_file, KeyMap * unbind_map) } if (error) - LYXERR0("KeyMap::read: error while reading bind file:" << tmp); + LYXERR0("KeyMap::read: error while reading bind file:" << bind_file.absFileName()); return !error; } @@ -244,7 +368,7 @@ void KeyMap::write(string const & bind_file, bool append, bool unbind) const BindingList::const_iterator it = list.begin(); BindingList::const_iterator it_end = list.end(); for (; it != it_end; ++it) { - FuncCode action = it->request.action; + FuncCode action = it->request.action(); string arg = to_utf8(it->request.argument()); os << tag << " \"" @@ -262,12 +386,9 @@ void KeyMap::write(string const & bind_file, bool append, bool unbind) const FuncRequest const & KeyMap::lookup(KeySymbol const &key, KeyModifier mod, KeySequence * seq) const { - static FuncRequest const unknown(LFUN_UNKNOWN_ACTION); - if (table.empty()) { - seq->curmap = seq->stdmap; - seq->mark_deleted(); - return unknown; + seq->reset(); + return FuncRequest::unknown; } Table::const_iterator end = table.end(); @@ -277,25 +398,23 @@ FuncRequest const & KeyMap::lookup(KeySymbol const &key, if (cit->code == key && cit->mod.first == check) { // match found - if (cit->table.get()) { + if (cit->prefixes.get()) { // this is a prefix key - set new map - seq->curmap = cit->table.get(); + seq->curmap = cit->prefixes.get(); static FuncRequest prefix(LFUN_COMMAND_PREFIX); return prefix; } else { // final key - reset map - seq->curmap = seq->stdmap; - seq->mark_deleted(); + seq->reset(); return cit->func; } } } // error - key not found: - seq->curmap = seq->stdmap; - seq->mark_deleted(); + seq->reset(); - return unknown; + return FuncRequest::unknown; } @@ -311,96 +430,8 @@ docstring const KeyMap::print(bool forgui) const } -void KeyMap::bind(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(); - for (Table::iterator it = table.begin(); it != end; ++it) { - if (code == it->code - && mod1 == it->mod.first - && mod2 == it->mod.second) { - // overwrite binding - if (r + 1 == seq->length()) { - LYXERR(Debug::KBMAP, "Warning: New binding for '" - << to_utf8(seq->print(KeySequence::Portable)) - << "' is overriding old binding..."); - if (it->table.get()) { - it->table.reset(); - } - it->func = func; - it->func.origin = FuncRequest::KEYBOARD; - return; - } else if (!it->table.get()) { - lyxerr << "Error: New binding for '" - << to_utf8(seq->print(KeySequence::Portable)) - << "' is overriding old binding..." - << endl; - return; - } else { - it->table->bind(seq, func, r + 1); - return; - } - } - } - - Table::iterator newone = table.insert(table.end(), Key()); - newone->code = code; - newone->mod = seq->modifiers[r]; - if (r + 1 == seq->length()) { - newone->func = func; - newone->func.origin = FuncRequest::KEYBOARD; - newone->table.reset(); - } else { - newone->table.reset(new KeyMap); - 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); -} - - -docstring KeyMap::printBindings(FuncRequest const & func) const +docstring KeyMap::printBindings(FuncRequest const & func, + KeySequence::outputFormat format) const { Bindings bindings = findBindings(func); if (bindings.empty()) @@ -409,11 +440,11 @@ docstring KeyMap::printBindings(FuncRequest const & func) const odocstringstream res; Bindings::const_iterator cit = bindings.begin(); Bindings::const_iterator cit_end = bindings.end(); - // prin the first item - res << cit->print(KeySequence::ForGui); + // print the first item + res << cit->print(format); // more than one shortcuts? for (++cit; cit != cit_end; ++cit) - res << ", " << cit->print(KeySequence::ForGui); + res << ", " << cit->print(format); return res.str(); } @@ -433,10 +464,10 @@ KeyMap::Bindings KeyMap::findBindings(FuncRequest const & func, Table::const_iterator end = table.end(); for (Table::const_iterator cit = table.begin(); cit != end; ++cit) { - if (cit->table.get()) { + if (cit->prefixes.get()) { KeySequence seq = prefix; seq.addkey(cit->code, cit->mod.first); - Bindings res2 = cit->table->findBindings(func, seq); + Bindings res2 = cit->prefixes->findBindings(func, seq); res.insert(res.end(), res2.begin(), res2.end()); } else if (cit->func == func) { KeySequence seq = prefix; @@ -454,15 +485,15 @@ KeyMap::BindingList KeyMap::listBindings(bool unbound, KeyMap::ItemType tag) con BindingList list; 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) { + LyXAction::const_iterator fit = lyxaction.func_begin(); + LyXAction::const_iterator const fen = lyxaction.func_end(); + for (; fit != fen; ++fit) { 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->request.action == action) { + BindingList::const_iterator bit = list.begin(); + BindingList::const_iterator const ben = list.end(); + for (; bit != ben; ++bit) + if (bit->request.action() == action) { has_action = true; break; } @@ -481,10 +512,10 @@ void KeyMap::listBindings(BindingList & list, Table::const_iterator it_end = table.end(); for (; it != it_end; ++it) { // a LFUN_COMMAND_PREFIX - if (it->table.get()) { + if (it->prefixes.get()) { KeySequence seq = prefix; seq.addkey(it->code, it->mod.first); - it->table->listBindings(list, seq, tag); + it->prefixes->listBindings(list, seq, tag); } else { KeySequence seq = prefix; seq.addkey(it->code, it->mod.first);