X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fkbmap.C;h=b026b8630fee0a19c8565bfd159533b79080bc18;hb=c68f3da771a54ef78bd309b8f1a81c374d2fea4c;hp=8b528c49f1d046bae6fb066cd8b101b692dcbc66;hpb=737cd9d8f3c2c075474f18779e335fe7a02535a6;p=lyx.git diff --git a/src/kbmap.C b/src/kbmap.C index 8b528c49f1..b026b8630f 100644 --- a/src/kbmap.C +++ b/src/kbmap.C @@ -1,259 +1,344 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team. +/** + * \file kbmap.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * - * ====================================================== */ + * \author Lars Gullik Bjønnes + * \author Jean-Marc Lasgouttes + * \author John Levon + * \author André Pönitz + * + * Full author contact details are available in file CREDITS. + */ #include -//#include -#include - -#ifdef __GNUG__ -#pragma implementation -#endif - #include "kbmap.h" -#include "kbsequence.h" + #include "debug.h" +#include "kbsequence.h" +#include "LyXAction.h" +#include "lyxlex.h" -using std::endl; +#include "frontends/LyXKeySym.h" -// The only modifiers that we handle. We want to throw away things -// like NumLock. -enum { ModsMask = ShiftMask | ControlMask | Mod1Mask }; +#include "support/filetools.h" +#include -// === static functions =================================================== +namespace lyx { -/* ---F+------------------------------------------------------------------ *\ - Function : printKeysym - Called by : kb_sequence::print and printKeyMap. RVDK_PATCH_5 - Purpose : prints a keysym, including modifiers. - Parameters: key - keysym - mod - modifiers - buf - string where the result goes - maxlen - length of string (including '\0') - Returns : length of printed string if ok, 0 otherwise. -\* ---F------------------------------------------------------------------- */ -void printKeysym(unsigned int key, unsigned int mod, string & buf) -{ - mod &= ModsMask; - - char const * const s = XKeysymToString(key); - - if (mod & ShiftMask) buf += "S-"; - if (mod & ControlMask) buf += "C-"; - if (mod & Mod1Mask) buf += "M-"; - if (s) buf += s; -} +using support::FileName; +using support::i18nLibFileSearch; +using std::endl; +using std::string; -/* ---F+------------------------------------------------------------------ *\ - Function : printKeyTab - Called by : kb_keymap::print - Purpose : print the keysyms found in the given key table. RVDK_PATCH_5 - Parameters: tabPt - keytable pointer - buf - string where the result goes - maxLen - length of string (including '\0') - Returns : length of printed string. -\* ---F------------------------------------------------------------------- */ -void kb_keymap::printKey(kb_key const & key, string & buf) +string const kb_keymap::printKeySym(LyXKeySym const & key, + key_modifier::state mod) { - printKeysym(key.code, key.mod & 0xffff, buf); + string buf; + + string const s = key.getSymbolName(); + + if (mod & key_modifier::shift) + buf += "S-"; + if (mod & key_modifier::ctrl) + buf += "C-"; + if (mod & key_modifier::alt) + buf += "M-"; + + buf += s; + return buf; } -// This binds a key to an action -string::size_type kb_keymap::bind(string const & seq, int action) +string::size_type kb_keymap::bind(string const & seq, FuncRequest const & func) { if (lyxerr.debugging(Debug::KBMAP)) { lyxerr << "BIND: Sequence `" << seq << "' Action `" - << action << "'" << endl; + << func.action << '\'' << endl; } - - kb_sequence k; + + kb_sequence k(0, 0); string::size_type const res = k.parse(seq); if (res == string::npos) { - defkey(&k, action); - } else + defkey(&k, func); + } else { lyxerr[Debug::KBMAP] << "Parse error at position " << res << " in key sequence '" << seq << "'." << endl; + } + return res; } -/* ---F+------------------------------------------------------------------ *\ - Function : kb_keymap::lookup - Called by : [user], kb_sequence::add() - Purpose : look up a key press in a given keymap - Parameters: key - the keysym of the key press - mod - the modifier mask of the keypress - seq - the key-sequence retrieved so far - Returns : user defined action; 0 for prefix key, -1 if key not found -\* ---F------------------------------------------------------------------- */ +namespace { -int kb_keymap::lookup(unsigned int key, - unsigned int mod, kb_sequence * seq) const +enum BindTags { + BN_BIND, + BN_BINDFILE +}; + +keyword_item bindTags[] = { + { "\\bind", BN_BIND }, + { "\\bind_file", BN_BINDFILE } +}; + +} + + +bool kb_keymap::read(string const & bind_file) { + const int bindCount = sizeof(bindTags) / sizeof(keyword_item); + + LyXLex lexrc(bindTags, bindCount); + if (lyxerr.debugging(Debug::PARSER)) + lexrc.printTable(lyxerr); + + FileName const tmp(i18nLibFileSearch("bind", bind_file, "bind")); + lexrc.setFile(tmp); + if (!lexrc.isOK()) { + lyxerr << "kb_keymap::read: cannot open bind file:" + << tmp << endl; + return false; + } + + lyxerr[Debug::KBMAP] << "Reading bind file:" << tmp << endl; + + bool error = false; + while (lexrc.isOK()) { + switch (lexrc.lex()) { + case LyXLex::LEX_UNDEF: + lexrc.printError("Unknown tag `$$Token'"); + error = true; + continue; + case LyXLex::LEX_FEOF: + continue; + case BN_BIND: + { + string seq, cmd; + + if (lexrc.next()) { + seq = lexrc.getString(); + } else { + lexrc.printError("BN_BIND: Missing key sequence"); + error = true; + break; + } + + if (lexrc.next(true)) { + cmd = lexrc.getString(); + } else { + lexrc.printError("BN_BIND: missing command"); + error = true; + break; + } + + FuncRequest func = lyxaction.lookupFunc(cmd); + if (func. action == LFUN_UNKNOWN_ACTION) { + lexrc.printError("BN_BIND: Unknown LyX" + " function `$$Token'"); + error = true; + break; + } + + bind(seq, func); + break; + } + case BN_BINDFILE: + if (lexrc.next()) { + string const tmp(lexrc.getString()); + error |= !read(tmp); + } else { + lexrc.printError("BN_BINDFILE: Missing file name"); + error = true; + break; + + } + break; + } + } + + if (error) + lyxerr << "kb_keymap::read: error while reading bind file:" + << tmp << endl; + return !error; +} + + +FuncRequest const & +kb_keymap::lookup(LyXKeySymPtr key, + key_modifier::state mod, kb_sequence * seq) const +{ + static FuncRequest const unknown(LFUN_UNKNOWN_ACTION); + if (table.empty()) { seq->curmap = seq->stdmap; - seq->delseq(); - return -1; + seq->mark_deleted(); + return unknown; } - //unsigned int msk1, msk0; - //suppress modifier bits we do not handle - mod &= ModsMask; + Table::const_iterator end = table.end(); + for (Table::const_iterator cit = table.begin(); cit != end; ++cit) { + key_modifier::state mask(cit->mod.second); + key_modifier::state check = + static_cast(mod & ~mask); - for (Table::const_iterator cit = table.begin(); - cit != table.end(); ++cit) { - unsigned int const msk1 = cit->mod & 0xffff; - unsigned int const msk0 = (cit->mod >> 16) & 0xffff; - if (cit->code == key && (mod & ~msk0) == msk1) { - // math found: + if (*(cit->code) == *key && cit->mod.first == check) { + // match found if (cit->table.get()) { // this is a prefix key - set new map seq->curmap = cit->table.get(); - return 0; + static FuncRequest prefix(LFUN_COMMAND_PREFIX); + return prefix; } else { // final key - reset map seq->curmap = seq->stdmap; - seq->delseq(); - return cit->action; + seq->mark_deleted(); + return cit->func; } } } // error - key not found: seq->curmap = seq->stdmap; - seq->delseq(); - return -1; -} + seq->mark_deleted(); + return unknown; +} -/* ---F+------------------------------------------------------------------ *\ - Function : kb_keymap::print - Called by : [user] - Purpose : Prints all the available keysyms. RVDK_PATCH_5 - Parameters: buf - string where output goes. - maxLen - available length in string, including `\0'. - Returns : updated maxLen. -\* ---F------------------------------------------------------------------- */ -void kb_keymap::print(string & buf) const +docstring const kb_keymap::print(bool forgui) const { - for (Table::const_iterator cit = table.begin(); - cit != table.end(); ++cit) { - printKey((*cit), buf); + docstring buf; + Table::const_iterator end = table.end(); + for (Table::const_iterator cit = table.begin(); cit != end; ++cit) { + buf += cit->code->print(cit->mod.first, forgui); buf += ' '; } + return buf; } -/* ---F+------------------------------------------------------------------ *\ - Function : kb_keymap::defkey - Called by : [user] - Purpose : define an action for a key sequence - Parameters: seq - the key sequence - action - the action to be defined - idx - recursion depth - Returns : 0 if ok. -\* ---F------------------------------------------------------------------- */ - -int kb_keymap::defkey(kb_sequence * seq, int action, int idx /*= 0*/) +void kb_keymap::defkey(kb_sequence * seq, + FuncRequest const & func, unsigned int r) { - unsigned int const code = seq->sequence[idx]; - if (code == NoSymbol) return -1; + LyXKeySymPtr code = seq->sequence[r]; + if (!code->isOK()) + return; - unsigned int const modmsk = seq->modifiers[idx]; + key_modifier::state const mod1 = seq->modifiers[r].first; + key_modifier::state const mod2 = seq->modifiers[r].second; - // --- check if key is already there -------------------------------- - if (table.size() != 0) { // without this I get strange crashes - Table::iterator end = table.end(); + // check if key is already there + Table::iterator end = table.end(); for (Table::iterator it = table.begin(); it != end; ++it) { - if (code == it->code && modmsk == it->mod) { + if (*(code) == *(it->code) + && mod1 == it->mod.first + && mod2 == it->mod.second) { // overwrite binding - if (idx + 1 == seq->length) { - string buf; - seq->print(buf, true); + if (r + 1 == seq->length()) { lyxerr[Debug::KBMAP] << "Warning: New binding for '" - << buf + << to_utf8(seq->print(false)) << "' is overriding old binding..." << endl; if (it->table.get()) { - it->table.reset(0); + it->table.reset(); } - it->action = action; - return 0; + it->func = func; + it->func.origin = FuncRequest::KEYBOARD; + return; } else if (!it->table.get()) { - string buf; - seq->print(buf, true); - lyxerr << "Error: New binding for '" << buf + lyxerr << "Error: New binding for '" + << to_utf8(seq->print(false)) << "' is overriding old binding..." - << endl; - return -1; + << endl; + return; } else { - return it->table->defkey(seq, action, - idx + 1); + it->table->defkey(seq, func, r + 1); + return; } } } - } - + Table::iterator newone = table.insert(table.end(), kb_key()); newone->code = code; - newone->mod = modmsk; - if (idx + 1 == seq->length) { - newone->action = action; - newone->table.reset(0); - return 0; + 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 kb_keymap); - return newone->table->defkey(seq, action, idx + 1); + newone->table->defkey(seq, func, r + 1); } } -string const kb_keymap::keyname(kb_key const & k) +docstring const kb_keymap::printbindings(FuncRequest const & func) const { - string buf; - printKeysym(k.code, k.mod, buf); - return buf; + odocstringstream res; + Bindings bindings = findbindings(func); + for (Bindings::const_iterator cit = bindings.begin(); + cit != bindings.end() ; ++cit) + res << '[' << cit->print(true) << ']'; + return res.str(); } -// Finds a key for a keyaction, if possible -string const kb_keymap::findbinding(int act, string const & prefix) const +kb_keymap::Bindings +kb_keymap::findbindings(FuncRequest const & func) const { - string res; + return findbindings(func, kb_sequence(0, 0)); +} + + +kb_keymap::Bindings +kb_keymap::findbindings(FuncRequest const & func, + kb_sequence const & prefix) const +{ + Bindings res; if (table.empty()) return res; Table::const_iterator end = table.end(); for (Table::const_iterator cit = table.begin(); cit != end; ++cit) { if (cit->table.get()) { - res += cit->table->findbinding(act, - prefix - + keyname((*cit)) - + " "); - } else if (cit->action == act) { - res += "["; - res += prefix + keyname((*cit)); - res += "] "; + kb_sequence seq = prefix; + seq.addkey(cit->code, cit->mod.first); + Bindings res2 = + cit->table->findbindings(func, seq); + res.insert(res.end(), res2.begin(), res2.end()); + } else if (cit->func == func) { + kb_sequence seq = prefix; + seq.addkey(cit->code, cit->mod.first); + res.push_back(seq); } } + return res; } -/* === End of File: kbmap.C ============================================== */ + +std::pair +kb_keymap::find1keybinding(FuncRequest const & func) const +{ + Table::const_iterator end = table.end(); + for (Table::const_iterator cit = table.begin(); + cit != end; ++cit) { + if (!cit->table.get() && cit->func == func) + return std::make_pair(cit->code.get(), cit->mod.first); + } + + return std::make_pair(0, key_modifier::none); +} + + +} // namespace lyx