1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
4 # include "../config.h"
8 #include "otk/display.hh"
14 #define _(str) gettext(str)
20 static void print_branch(BindingTree *first, std::string str)
22 BindingTree *p = first;
26 print_branch(p->first_child, str + " " + p->text);
28 printf("%d%s\n", p->id, (str + " " + p->text).c_str());
34 void OBBindings::display()
36 if (_tree.first_child)
37 print_branch(_tree.first_child, "");
42 bool OBBindings::translate(const std::string &str, Binding &b)
44 // parse out the base key name
45 std::string::size_type keybegin = str.find_last_of('-');
46 keybegin = (keybegin == std::string::npos) ? 0 : keybegin + 1;
47 std::string key(str, keybegin);
49 // parse out the requested modifier keys
50 unsigned int mods = 0;
51 std::string::size_type begin = 0, end;
52 while (begin != keybegin) {
53 end = str.find_first_of('-', begin);
55 std::string mod(str, begin, end-begin);
57 if (mod == "C") { // control
59 } else if (mod == "S") { // shift
61 } else if (mod == "A" || // alt/mod1
66 } else if (mod == "M2" || // mod2
69 } else if (mod == "M3" || // mod3
72 } else if (mod == "W" || // windows/mod4
76 } else if (mod == "M5" || // mod5
80 printf(_("Invalid modifier element in key binding: %s\n"), mod.c_str());
86 KeySym sym = XStringToKeysym(const_cast<char *>(key.c_str()));
87 if (sym == NoSymbol) return false;
89 b.key = XKeysymToKeycode(otk::OBDisplay::display, sym);
93 static void destroytree(BindingTree *tree)
96 BindingTree *c = tree->first_child;
102 BindingTree *OBBindings::buildtree(const StringVect &keylist, int id)
104 if (keylist.empty()) return 0; // nothing in the list.. return 0
106 BindingTree *ret = 0, *p;
108 StringVect::const_reverse_iterator it, end = keylist.rend();
109 for (it = keylist.rbegin(); it != end; ++it) {
111 ret = new BindingTree(id);
112 if (!p) ret->chain = false;
113 ret->first_child = p;
114 if (!translate(*it, ret->binding)) {
119 ret->text = *it; // XXX: rm me
125 OBBindings::OBBindings()
130 OBBindings::~OBBindings()
136 void OBBindings::assimilate(BindingTree *node)
138 BindingTree *a, *b, *tmp, *last;
140 if (!_tree.first_child) {
141 // there are no nodes at this level yet
142 _tree.first_child = node;
145 a = _tree.first_child;
150 if (a->binding != b->binding) {
159 if (last->binding != b->binding)
160 last->next_sibling = b;
162 last->first_child = b->first_child;
168 int OBBindings::find(BindingTree *search) {
170 a = _tree.first_child;
173 if (a->binding != b->binding) {
176 if (a->chain == b->chain) {
178 return a->id; // found it! (return the actual id, not the search's)
180 return -2; // the chain status' don't match (conflict!)
185 return -1; // it just isn't in here
189 static int find(BindingTree *parent, BindingTree *node) {
190 BindingTree *p, *lastsib, *nextparent, *nextnode = node->first_child;
192 if (!parent->first_child)
195 p = parent->first_child;
197 if (node->binding == p->binding) {
198 if (node->chain == p->chain) {
200 return p->id; // found it! (return the actual id, not the search's)
202 break; // go on to the next child in the chain
205 return -2; // the chain status' don't match (conflict!)
210 if (!p) return -1; // doesn't exist
213 assert(node->first_child);
214 return find(p, node->first_child);
216 return -1; // it just isnt in here
220 bool OBBindings::add(const StringVect &keylist, int id)
224 if (!(tree = buildtree(keylist, id)))
225 return false; // invalid binding requested
227 if (find(tree) < -1) {
228 // conflicts with another binding
233 // assimilate this built tree into the main tree
234 assimilate(tree); // assimilation destroys/uses the tree
239 int OBBindings::find(const StringVect &keylist)
244 if (!(tree = buildtree(keylist, 0)))
245 return false; // invalid binding requested
247 ret = find(tree) >= 0;
255 int OBBindings::remove(const StringVect &keylist)
258 assert(false); // XXX: function not implemented yet
262 static void remove_branch(BindingTree *first)
264 BindingTree *p = first;
268 remove_branch(p->first_child);
269 BindingTree *s = p->next_sibling;
276 void OBBindings::remove_all()
278 if (_tree.first_child)
279 remove_branch(_tree.first_child);