diff options
-rw-r--r-- | src/Keys.cc | 67 |
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' |
140 | class Keys::t_key { | 140 | class Keys::t_key: private FbTk::NotCopyable { |
141 | public: | 141 | public: |
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 | ||
196 | int Keys::t_key::addBindingWrapper(lua::state *l) | 195 | int 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 | ||
279 | void Keys::t_key::addBinding(vector<string> val, const FbTk::RefCount<FbTk::Command<void> > &cmd ) { | 281 | Keys::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 | ||