X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FKeyMap.cpp;h=c530f5f1f2e93640960669da67f37265dffff1c9;hb=4ed0312c51704780af1c452d3a82a84171b3725a;hp=9592e0144aef25d1ee355798fbca42f7df980465;hpb=b79d8e5e2d20e8f294d47fe924c20de17dbd5c0b;p=lyx.git diff --git a/src/KeyMap.cpp b/src/KeyMap.cpp index 9592e0144a..c530f5f1f2 100644 --- a/src/KeyMap.cpp +++ b/src/KeyMap.cpp @@ -25,6 +25,7 @@ #include "support/filetools.h" #include "support/gettext.h" #include "support/lstrings.h" +#include "support/TempFile.h" #include "frontends/alert.h" @@ -37,7 +38,6 @@ using namespace lyx::support; namespace lyx { - string const KeyMap::printKeySym(KeySymbol const & key, KeyModifier mod) { string buf; @@ -46,8 +46,15 @@ string const KeyMap::printKeySym(KeySymbol const & key, KeyModifier mod) if (mod & ControlModifier) buf += "C-"; +#if defined(USE_MACOSX_PACKAGING) || defined(USE_META_KEYBINDING) + if (mod & MetaModifier) + buf += "M-"; + if (mod & AltModifier) + buf += "A-"; +#else if (mod & AltModifier) buf += "M-"; +#endif if (mod & ShiftModifier) buf += "S-"; @@ -61,7 +68,7 @@ size_t KeyMap::bind(string const & seq, FuncRequest const & func) LYXERR(Debug::KBMAP, "BIND: Sequence `" << seq << "' Action `" << func.action() << '\''); - KeySequence k(0, 0); + KeySequence k(nullptr, nullptr); string::size_type const res = k.parse(seq); if (res == string::npos) { @@ -77,7 +84,7 @@ size_t KeyMap::bind(string const & seq, FuncRequest const & func) size_t KeyMap::unbind(string const & seq, FuncRequest const & func) { - KeySequence k(0, 0); + KeySequence k(nullptr, nullptr); string::size_type const res = k.parse(seq); if (res == string::npos) @@ -99,6 +106,8 @@ void KeyMap::bind(KeySequence * seq, FuncRequest const & func, unsigned int r) KeyModifier const mod2 = seq->modifiers[r].second; // check if key is already there + // FIXME perf: Profiling shows that this is responsible of 99% of the + // cost of GuiPrefs::applyView() Table::iterator end = table.end(); for (Table::iterator it = table.begin(); it != end; ++it) { if (code == it->code @@ -109,13 +118,12 @@ void KeyMap::bind(KeySequence * seq, FuncRequest const & func, unsigned int r) LYXERR(Debug::KBMAP, "Warning: New binding for '" << to_utf8(seq->print(KeySequence::Portable)) << "' is overriding old binding..."); - if (it->prefixes.get()) { + if (it->prefixes) it->prefixes.reset(); - } it->func = func; it->func.setOrigin(FuncRequest::KEYBOARD); return; - } else if (!it->prefixes.get()) { + } else if (!it->prefixes) { lyxerr << "Error: New binding for '" << to_utf8(seq->print(KeySequence::Portable)) << "' is overriding old binding..." @@ -152,29 +160,30 @@ void KeyMap::unbind(KeySequence * seq, FuncRequest const & func, unsigned int r) KeyModifier const mod2 = seq->modifiers[r].second; // check if key is already there + vector removes; 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()) + if (it->func == func || func == FuncRequest::unknown) { + removes.push_back(it); + if (it->prefixes) it->prefixes.reset(); } - } else if (it->prefixes.get()) { + } else if (it->prefixes) { it->prefixes->unbind(seq, func, r + 1); if (it->prefixes->empty()) - remove = it; + removes.push_back(it); return; } } } - if (remove != end) - table.erase(remove); + + for (unsigned i = removes.size(); i > 0; --i) + table.erase(removes[i-1]); } @@ -195,7 +204,7 @@ FuncRequest KeyMap::getBinding(KeySequence const & seq, unsigned int r) && mod2 == it->mod.second) { if (r + 1 == seq.length()) return it->func; - else if (it->prefixes.get()) + else if (it->prefixes) return it->prefixes->getBinding(seq, r + 1); } } @@ -209,9 +218,10 @@ void KeyMap::clear() } -bool KeyMap::read(string const & bind_file, KeyMap * unbind_map, BindReadType rt) +bool KeyMap::read(string const & bind_file, KeyMap * unbind_map, BindReadType rt, bool i18n) { - FileName bf = i18nLibFileSearch("bind", bind_file, "bind"); + FileName bf = i18n ? i18nLibFileSearch("bind", bind_file, "bind") + : libFileSearch("bind", bind_file, "bind"); if (bf.empty()) { if (rt == MissingOK) return true; @@ -243,17 +253,39 @@ bool KeyMap::read(string const & bind_file, KeyMap * unbind_map, BindReadType rt bool KeyMap::read(FileName const & bind_file, KeyMap * unbind_map) +{ + ReturnValues retval = readWithoutConv(bind_file, unbind_map); + if (retval != FormatMismatch) + return retval == ReadOK; + + LYXERR(Debug::FILES, "Converting bind file to " << LFUN_FORMAT); + TempFile tmp("convert_bind"); + FileName const tempfile = tmp.name(); + bool const success = prefs2prefs(bind_file, tempfile, true); + if (!success) { + LYXERR0 ("Unable to convert " << bind_file << + " to format " << LFUN_FORMAT); + return false; + } + retval = readWithoutConv(tempfile, unbind_map); + return retval == ReadOK; +} + + +KeyMap::ReturnValues KeyMap::readWithoutConv(FileName const & bind_file, KeyMap * unbind_map) { enum { BN_BIND, BN_BINDFILE, - BN_UNBIND, + BN_FORMAT, + BN_UNBIND }; LexerKeyword bindTags[] = { { "\\bind", BN_BIND }, { "\\bind_file", BN_BINDFILE }, { "\\unbind", BN_UNBIND }, + { "format", BN_FORMAT } }; Lexer lexrc(bindTags); @@ -262,12 +294,14 @@ bool KeyMap::read(FileName const & bind_file, KeyMap * unbind_map) lexrc.setFile(bind_file); if (!lexrc.isOK()) { - LYXERR0("KeyMap::read: cannot open bind file:" << bind_file.absFilename()); - return false; + LYXERR0("KeyMap::read: cannot open bind file:" << bind_file.absFileName()); + return FileError; } - LYXERR(Debug::KBMAP, "Reading bind file:" << bind_file.absFilename()); + LYXERR(Debug::KBMAP, "Reading bind file:" << bind_file.absFileName()); + // format of pre-2.0 bind files, before this tag was introduced. + int format = 0; bool error = false; while (lexrc.isOK()) { switch (lexrc.lex()) { @@ -280,6 +314,11 @@ bool KeyMap::read(FileName const & bind_file, KeyMap * unbind_map) case Lexer::LEX_FEOF: continue; + case BN_FORMAT: + if (lexrc.next()) + format = lexrc.getInteger(); + break; + case BN_BIND: { if (!lexrc.next()) { lexrc.printError("BN_BIND: Missing key sequence"); @@ -296,7 +335,7 @@ bool KeyMap::read(FileName const & bind_file, KeyMap * unbind_map) string cmd = lexrc.getString(); FuncRequest func = lyxaction.lookupFunc(cmd); - if (func.action() == LFUN_UNKNOWN_ACTION) { + if (func == FuncRequest::unknown) { lexrc.printError("BN_BIND: Unknown LyX function `$$Token'"); error = true; break; @@ -320,15 +359,18 @@ bool KeyMap::read(FileName const & bind_file, KeyMap * unbind_map) break; } string cmd = lexrc.getString(); - - FuncRequest func = lyxaction.lookupFunc(cmd); - if (func.action() == LFUN_UNKNOWN_ACTION) { - lexrc.printError("BN_UNBIND: Unknown LyX" - " function `$$Token'"); - error = true; - break; + FuncRequest func; + if (cmd == "*") + func = FuncRequest::unknown; + else { + func = lyxaction.lookupFunc(cmd); + if (func == FuncRequest::unknown) { + lexrc.printError("BN_UNBIND: Unknown LyX function `$$Token'"); + error = true; + break; + } } - + if (unbind_map) unbind_map->bind(seq, func); else @@ -342,41 +384,55 @@ bool KeyMap::read(FileName const & bind_file, KeyMap * unbind_map) error = true; break; } - string const tmp = lexrc.getString(); - error |= !read(tmp, unbind_map); + string tmp = lexrc.getString(); + if (prefixIs(tmp, "../")) { + tmp = split(tmp, '/'); + // look in top dir + error |= !read(tmp, unbind_map, Default, false); + } else + // i18n search + error |= !read(tmp, unbind_map); break; } + + // This is triggered the first time through the loop unless + // we hit a format tag. + if (format != LFUN_FORMAT) + return FormatMismatch; } - if (error) - LYXERR0("KeyMap::read: error while reading bind file:" << bind_file.absFilename()); - return !error; + if (error) { + LYXERR0("KeyMap::read: error while reading bind file:" << bind_file.absFileName()); + return ReadError; + } + return ReadOK; } void KeyMap::write(string const & bind_file, bool append, bool unbind) const { - ofstream os(bind_file.c_str(), + 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()); + << "## All modifications will be lost\n\n" + << "Format " << LFUN_FORMAT << "\n\n"; + string tag = unbind ? "\\unbind" : "\\bind"; + for (auto const & bnd : listBindings(false)) { + FuncCode const action = bnd.request.action(); + string const arg = to_utf8(bnd.request.argument()); + + string cmd; + if (unbind && bnd.request == FuncRequest::unknown) + cmd = "*"; + else + cmd = lyxaction.getActionName(action) + (arg.empty() ? string() : " " + arg); os << tag << " \"" - << to_utf8(it->sequence.print(KeySequence::BindFile)) - << "\" \"" - << lyxaction.getActionName(action) - << (arg.empty() ? "" : " ") << arg - << "\"\n"; + << to_utf8(bnd.sequence.print(KeySequence::BindFile)) + << "\" " << Lexer::quoteString(cmd) + << "\n"; } os << "\n"; os.close(); @@ -398,11 +454,10 @@ FuncRequest const & KeyMap::lookup(KeySymbol const &key, if (cit->code == key && cit->mod.first == check) { // match found - if (cit->prefixes.get()) { + if (cit->prefixes) { // this is a prefix key - set new map seq->curmap = cit->prefixes.get(); - static FuncRequest prefix(LFUN_COMMAND_PREFIX); - return prefix; + return FuncRequest::prefix; } else { // final key - reset map seq->reset(); @@ -431,27 +486,28 @@ docstring const KeyMap::print(bool forgui) const docstring KeyMap::printBindings(FuncRequest const & func, - KeySequence::outputFormat format) const + KeySequence::outputFormat format, + bool const untranslated) const { Bindings bindings = findBindings(func); if (bindings.empty()) return docstring(); - + odocstringstream res; Bindings::const_iterator cit = bindings.begin(); Bindings::const_iterator cit_end = bindings.end(); // print the first item - res << cit->print(format); + res << cit->print(format, untranslated); // more than one shortcuts? for (++cit; cit != cit_end; ++cit) - res << ", " << cit->print(format); + res << ", " << cit->print(format, untranslated); return res.str(); } KeyMap::Bindings KeyMap::findBindings(FuncRequest const & func) const { - return findBindings(func, KeySequence(0, 0)); + return findBindings(func, KeySequence(nullptr, nullptr)); } @@ -464,7 +520,7 @@ 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->prefixes.get()) { + if (cit->prefixes) { KeySequence seq = prefix; seq.addkey(cit->code, cit->mod.first); Bindings res2 = cit->prefixes->findBindings(func, seq); @@ -483,12 +539,10 @@ KeyMap::Bindings KeyMap::findBindings(FuncRequest const & func, KeyMap::BindingList KeyMap::listBindings(bool unbound, KeyMap::ItemType tag) const { BindingList list; - listBindings(list, KeySequence(0, 0), tag); + listBindings(list, KeySequence(nullptr, nullptr), tag); if (unbound) { - LyXAction::const_iterator fit = lyxaction.func_begin(); - LyXAction::const_iterator const fen = lyxaction.func_end(); - for (; fit != fen; ++fit) { - FuncCode action = fit->second; + for (auto const & name_code : lyxaction) { + FuncCode action = name_code.second; bool has_action = false; BindingList::const_iterator bit = list.begin(); BindingList::const_iterator const ben = list.end(); @@ -498,8 +552,8 @@ KeyMap::BindingList KeyMap::listBindings(bool unbound, KeyMap::ItemType tag) con break; } if (!has_action) - list.push_back(Binding(FuncRequest(action), KeySequence(0, 0), tag)); - } + list.push_back(Binding(FuncRequest(action), KeySequence(nullptr, nullptr), tag)); + } } return list; } @@ -512,7 +566,7 @@ void KeyMap::listBindings(BindingList & list, Table::const_iterator it_end = table.end(); for (; it != it_end; ++it) { // a LFUN_COMMAND_PREFIX - if (it->prefixes.get()) { + if (it->prefixes) { KeySequence seq = prefix; seq.addkey(it->code, it->mod.first); it->prefixes->listBindings(list, seq, tag);