aboutsummaryrefslogtreecommitdiff
path: root/src/Keys.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Keys.cc')
-rw-r--r--src/Keys.cc67
1 files changed, 34 insertions, 33 deletions
diff --git a/src/Keys.cc b/src/Keys.cc
index 3f7c953..68ad6fa 100644
--- a/src/Keys.cc
+++ b/src/Keys.cc
@@ -137,17 +137,23 @@ const char default_keymode[] = "default_keymode";
137} // end of anonymous namespace 137} // end of anonymous namespace
138 138
139// helper class 'keytree' 139// helper class 'keytree'
140class Keys::t_key { 140class Keys::t_key: private FbTk::NotCopyable {
141public: 141public:
142 142
143 // typedefs 143 // typedefs
144 typedef std::list<RefKey> keylist_t; 144 typedef std::list<RefKey> keylist_t;
145 typedef std::pair<keylist_t::iterator, t_key &> FindPair;
145 146
146 static void initKeys(FbTk::Lua &l); 147 static void initKeys(FbTk::Lua &l);
147 static int addBindingWrapper(lua::state *l); 148 static int addBinding(lua::state *l);
148 static int newKeyMode(lua::state *l); 149 static int newKeyMode(lua::state *l);
149 150
150 // constructor / destructor 151 bool equalExact(const RefKey &x) {
152 return type == x->type && key == x->key && context == x->context
153 && isdouble == x->isdouble && mod == x->mod;
154 }
155
156 // constructor
151 t_key(int type = 0, unsigned int mod = 0, unsigned int key = 0, int context = 0, 157 t_key(int type = 0, unsigned int mod = 0, unsigned int key = 0, int context = 0,
152 bool isdouble = false); 158 bool isdouble = false);
153 159
@@ -166,18 +172,11 @@ public:
166 return RefKey(); 172 return RefKey();
167 } 173 }
168 174
169 RefKey find_or_insert(int type_, unsigned int mod_, unsigned int key_, 175 /**
170 int context_, bool isdouble_) { 176 * Returns the t_key object corresponding to the binding val and it's parent.
171 177 * The parent comes in handy when we want to remove the binding.
172 RefKey t = find(type_, mod_, key_, context_, isdouble_); 178 */
173 if(! t) { 179 FindPair findBinding(vector<string> val, bool insert);
174 t.reset(new t_key(type_, mod_, key_, context_, isdouble_));
175 keylist.push_back(t);
176 }
177 return t;
178 }
179
180 void addBinding(vector<string> val, const FbTk::RefCount<FbTk::Command<void> > &cmd );
181 180
182 // member variables 181 // member variables
183 182
@@ -193,14 +192,14 @@ public:
193 static FbTk::Lua::RegisterInitFunction registerInitKeys; 192 static FbTk::Lua::RegisterInitFunction registerInitKeys;
194}; 193};
195 194
196int Keys::t_key::addBindingWrapper(lua::state *l) 195int Keys::t_key::addBinding(lua::state *l)
197{ 196{
198 l->checkstack(2); 197 l->checkstack(2);
199 198
200 try { 199 try {
201 l->checkargno(3); 200 l->checkargno(3);
202 201
203 const RefKey &k = *l->checkudata<RefKey>(1, keymode_metatable); 202 RefKey k = *l->checkudata<RefKey>(1, keymode_metatable);
204 203
205 if(! l->isstring(2)) { 204 if(! l->isstring(2)) {
206 throw KeyError(_FB_CONSOLETEXT(Keys, Bad2ndArg, "2nd argument is not a string.", 205 throw KeyError(_FB_CONSOLETEXT(Keys, Bad2ndArg, "2nd argument is not a string.",
@@ -221,7 +220,11 @@ int Keys::t_key::addBindingWrapper(lua::state *l)
221 cmd.reset(new FbCommands::LuaCmd(*l)); 220 cmd.reset(new FbCommands::LuaCmd(*l));
222 } 221 }
223 222
224 k->addBinding(val, cmd); 223 FindPair p = k->findBinding(val, true);
224
225 k = *p.first;
226 k->m_command = cmd;
227 k->keylist.clear();
225 } 228 }
226 catch(std::runtime_error &e) { 229 catch(std::runtime_error &e) {
227 cerr << "addBinding: " << e.what() << endl; 230 cerr << "addBinding: " << e.what() << endl;
@@ -248,7 +251,7 @@ void Keys::t_key::initKeys(FbTk::Lua &l) {
248 l.rawsetfield(-2, "__gc"); 251 l.rawsetfield(-2, "__gc");
249 252
250 l.newtable(); { 253 l.newtable(); {
251 l.pushfunction(&addBindingWrapper); 254 l.pushfunction(&addBinding);
252 l.rawsetfield(-2, "addBinding"); 255 l.rawsetfield(-2, "addBinding");
253 256
254 l.pushfunction(&setKeyModeWrapper); 257 l.pushfunction(&setKeyModeWrapper);
@@ -270,13 +273,12 @@ Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_,
270 type(type_), 273 type(type_),
271 mod(mod_), 274 mod(mod_),
272 key(key_), 275 key(key_),
273 context(context_), 276 context(context_ ? context_ : GLOBAL),
274 isdouble(isdouble_), 277 isdouble(isdouble_),
275 m_command(0) { 278 m_command(0) {
276 context = context_ ? context_ : GLOBAL;
277} 279}
278 280
279void Keys::t_key::addBinding(vector<string> val, const FbTk::RefCount<FbTk::Command<void> > &cmd ) { 281Keys::t_key::FindPair Keys::t_key::findBinding(vector<string> val, bool insert ) {
280 282
281 unsigned int key = 0, mod = 0; 283 unsigned int key = 0, mod = 0;
282 int type = 0, context = 0; 284 int type = 0, context = 0;
@@ -372,24 +374,23 @@ void Keys::t_key::addBinding(vector<string> val, const FbTk::RefCount<FbTk::Comm
372 } // end while 374 } // end while
373 375
374 376
375 if (key == 0 && (type == KeyPress || type == ButtonPress || type == ButtonRelease)) 377 if (key == 0 && (type == 0 || type == KeyPress || type == ButtonPress || type == ButtonRelease))
376 throw KeyError("Invalid key combination:" + processed); 378 throw KeyError("Invalid key combination:" + processed);
377 379
378 if (type != ButtonPress) 380 if (type != ButtonPress)
379 isdouble = false; 381 isdouble = false;
380 382
381 RefKey new_key = find_or_insert(type, mod, key, context, isdouble); 383 RefKey new_key = RefKey(new t_key(type, mod, key, context, isdouble));
382 384 keylist_t::iterator new_it = std::find_if(keylist.begin(), keylist.end(),
383 if (new_key->m_command) 385 FbTk::MemFun(*new_key, &t_key::equalExact));
384 throw KeyError("Key combination already used:" + processed);
385 386
386 if(val.empty()) { 387 if(new_it == keylist.end() && insert)
387 if(! new_key->keylist.empty()) 388 new_it = keylist.insert(new_it, new_key);
388 throw KeyError("Key combination already used as a keychain:" + processed);
389 389
390 new_key->m_command = cmd; 390 if(new_it == keylist.end() || val.empty())
391 } else 391 return FindPair(new_it, *this);
392 new_key->addBinding(val, cmd); 392 else
393 return (*new_it)->findBinding(val, insert);
393} 394}
394 395
395 396