3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
7 * \author Jean-Marc Lasgouttes
11 * Full author contact details are available in file CREDITS.
19 #include "KeySequence.h"
20 #include "LyXAction.h"
23 #include "support/filetools.h"
33 using support::FileName;
34 using support::i18nLibFileSearch;
37 string const KeyMap::printKeySym(KeySymbol const & key, KeyModifier mod)
41 string const s = key.getSymbolName();
43 if (mod & ShiftModifier)
45 if (mod & ControlModifier)
47 if (mod & AltModifier)
55 size_t KeyMap::bind(string const & seq, FuncRequest const & func)
57 LYXERR(Debug::KBMAP) << "BIND: Sequence `"
58 << seq << "' Action `"
59 << func.action << '\'' << endl;
63 string::size_type const res = k.parse(seq);
64 if (res == string::npos) {
67 LYXERR(Debug::KBMAP) << "Parse error at position " << res
68 << " in key sequence '" << seq << "'."
83 keyword_item bindTags[] = {
84 { "\\bind", BN_BIND },
85 { "\\bind_file", BN_BINDFILE }
91 bool KeyMap::read(string const & bind_file)
93 const int bindCount = sizeof(bindTags) / sizeof(keyword_item);
95 Lexer lexrc(bindTags, bindCount);
96 if (lyxerr.debugging(Debug::PARSER))
97 lexrc.printTable(lyxerr);
99 FileName const tmp(i18nLibFileSearch("bind", bind_file, "bind"));
102 lyxerr << "KeyMap::read: cannot open bind file:"
107 LYXERR(Debug::KBMAP) << "Reading bind file:" << tmp << endl;
110 while (lexrc.isOK()) {
111 switch (lexrc.lex()) {
112 case Lexer::LEX_UNDEF:
113 lexrc.printError("Unknown tag `$$Token'");
116 case Lexer::LEX_FEOF:
123 seq = lexrc.getString();
125 lexrc.printError("BN_BIND: Missing key sequence");
130 if (lexrc.next(true)) {
131 cmd = lexrc.getString();
133 lexrc.printError("BN_BIND: missing command");
138 FuncRequest func = lyxaction.lookupFunc(cmd);
139 if (func. action == LFUN_UNKNOWN_ACTION) {
140 lexrc.printError("BN_BIND: Unknown LyX"
141 " function `$$Token'");
151 string const tmp(lexrc.getString());
154 lexrc.printError("BN_BINDFILE: Missing file name");
164 lyxerr << "KeyMap::read: error while reading bind file:"
170 FuncRequest const & KeyMap::lookup(KeySymbol const &key,
171 KeyModifier mod, KeySequence * seq) const
173 static FuncRequest const unknown(LFUN_UNKNOWN_ACTION);
176 seq->curmap = seq->stdmap;
181 Table::const_iterator end = table.end();
182 for (Table::const_iterator cit = table.begin(); cit != end; ++cit) {
183 KeyModifier mask = cit->mod.second;
184 KeyModifier check = static_cast<KeyModifier>(mod & ~mask);
186 if (cit->code == key && cit->mod.first == check) {
188 if (cit->table.get()) {
189 // this is a prefix key - set new map
190 seq->curmap = cit->table.get();
191 static FuncRequest prefix(LFUN_COMMAND_PREFIX);
194 // final key - reset map
195 seq->curmap = seq->stdmap;
202 // error - key not found:
203 seq->curmap = seq->stdmap;
210 docstring const KeyMap::print(bool forgui) const
213 Table::const_iterator end = table.end();
214 for (Table::const_iterator cit = table.begin(); cit != end; ++cit) {
215 buf += cit->code.print(cit->mod.first, forgui);
222 void KeyMap::defkey(KeySequence * seq, FuncRequest const & func, unsigned int r)
224 KeySymbol code = seq->sequence[r];
228 KeyModifier const mod1 = seq->modifiers[r].first;
229 KeyModifier const mod2 = seq->modifiers[r].second;
231 // check if key is already there
232 Table::iterator end = table.end();
233 for (Table::iterator it = table.begin(); it != end; ++it) {
235 && mod1 == it->mod.first
236 && mod2 == it->mod.second) {
238 if (r + 1 == seq->length()) {
240 << "Warning: New binding for '"
241 << to_utf8(seq->print(false))
242 << "' is overriding old binding..."
244 if (it->table.get()) {
248 it->func.origin = FuncRequest::KEYBOARD;
250 } else if (!it->table.get()) {
251 lyxerr << "Error: New binding for '"
252 << to_utf8(seq->print(false))
253 << "' is overriding old binding..."
257 it->table->defkey(seq, func, r + 1);
263 Table::iterator newone = table.insert(table.end(), Key());
265 newone->mod = seq->modifiers[r];
266 if (r + 1 == seq->length()) {
268 newone->func.origin = FuncRequest::KEYBOARD;
269 newone->table.reset();
271 newone->table.reset(new KeyMap);
272 newone->table->defkey(seq, func, r + 1);
277 docstring const KeyMap::printbindings(FuncRequest const & func) const
279 Bindings bindings = findbindings(func);
280 if (bindings.empty())
283 odocstringstream res;
284 Bindings::const_iterator cit = bindings.begin();
285 Bindings::const_iterator cit_end = bindings.end();
286 // prin the first item
287 res << cit->print(true);
288 // more than one shortcuts?
289 for (++cit; cit != cit_end; ++cit)
290 res << ", " << cit->print(true);
295 KeyMap::Bindings KeyMap::findbindings(FuncRequest const & func) const
297 return findbindings(func, KeySequence(0, 0));
301 KeyMap::Bindings KeyMap::findbindings(FuncRequest const & func,
302 KeySequence const & prefix) const
305 if (table.empty()) return res;
307 Table::const_iterator end = table.end();
308 for (Table::const_iterator cit = table.begin();
310 if (cit->table.get()) {
311 KeySequence seq = prefix;
312 seq.addkey(cit->code, cit->mod.first);
314 cit->table->findbindings(func, seq);
315 res.insert(res.end(), res2.begin(), res2.end());
316 } else if (cit->func == func) {
317 KeySequence seq = prefix;
318 seq.addkey(cit->code, cit->mod.first);