]> Dogcows Code - chaz/openbox/blob - src/bindings.cc
73c11b0b8c69b4bf74f2519c3b98bf4d2eb8e893
[chaz/openbox] / src / bindings.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 #include "bindings.hh"
8 #include "otk/display.hh"
9
10 extern "C" {
11 #include <X11/Xlib.h>
12
13 #include "gettext.h"
14 #define _(str) gettext(str)
15 }
16
17 namespace ob {
18
19 #include <stdio.h>
20 static void print_branch(BindingTree *first, std::string str)
21 {
22 BindingTree *p = first;
23
24 while (p) {
25 if (p->first_child)
26 print_branch(p->first_child, str + " " + p->text);
27 if (!p->chain)
28 printf("%d%s\n", p->id, (str + " " + p->text).c_str());
29 p = p->next_sibling;
30 }
31 }
32
33
34 void OBBindings::display()
35 {
36 if (_tree.first_child)
37 print_branch(_tree.first_child, "");
38 }
39
40
41
42 bool OBBindings::translate(const std::string &str, Binding &b)
43 {
44 unsigned int mods = 0;
45
46 // parse out the base key name
47 std::string::size_type keybegin = str.find_last_of('-');
48 keybegin = (keybegin == std::string::npos) ? 0 : keybegin + 1;
49 std::string key(str, keybegin);
50
51 // XXX: get some modifiers up in the hizzie
52 // parse out the requested modifier keys
53 std::string::size_type begin = 0, end;
54 while (begin != keybegin) {
55 end = str.find_first_of('-', begin);
56
57 std::string mod(str, begin, end-begin);
58
59 if (mod == "C") { // control
60 mods |= ControlMask;
61 } else if (mod == "S") { // shift
62 mods |= ShiftMask;
63 } else if (mod == "A" || // alt/mod1
64 mod == "M" ||
65 mod == "M1" ||
66 mod == "Mod1") {
67 mods |= Mod1Mask;
68 } else if (mod == "M2" || // mod2
69 mod == "Mod2") {
70 mods |= Mod2Mask;
71 } else if (mod == "M3" || // mod3
72 mod == "Mod3") {
73 mods |= Mod3Mask;
74 } else if (mod == "W" || // windows/mod4
75 mod == "M4" ||
76 mod == "Mod4") {
77 mods |= Mod4Mask;
78 } else if (mod == "M5" || // mod5
79 mod == "Mod5") {
80 mods |= Mod5Mask;
81 } else { // invalid
82 printf(_("Invalid modifier element in key binding: %s\n"), mod.c_str());
83 return false;
84 }
85 begin = end + 1;
86 }
87
88 KeySym sym = XStringToKeysym(const_cast<char *>(key.c_str()));
89 if (sym == NoSymbol) return false;
90 b.modifiers = mods;
91 b.key = XKeysymToKeycode(otk::OBDisplay::display, sym);
92 return b.key != 0;
93 }
94
95 BindingTree *OBBindings::buildtree(const StringVect &keylist, int id)
96 {
97 if (keylist.empty()) return 0; // nothing in the list.. return 0
98
99 BindingTree *ret = new BindingTree(id), *p = 0;
100
101 StringVect::const_iterator it, end = keylist.end();
102 for (it = keylist.begin(); it != end; ++it) {
103 if (p)
104 p = p->first_child = new BindingTree(id);
105 else
106 p = ret; // the first node
107
108 if (!translate(*it, p->binding))
109 break;
110 p->text = *it;
111 }
112 if (it != end) {
113 // build failed.. clean up and return 0
114 p = ret;
115 while (p->first_child) {
116 BindingTree *c = p->first_child;
117 delete p;
118 p = c;
119 }
120 delete p;
121 return 0;
122 } else {
123 // set the proper chain status on the last node
124 p->chain = false;
125 }
126
127 // printf("BUILDING:\n");
128 // print_branch(ret, "");
129
130 // successfully built a tree
131 return ret;
132 }
133
134 static void destroytree(BindingTree *tree)
135 {
136 while (tree) {
137 BindingTree *c = tree->first_child;
138 delete tree;
139 tree = c;
140 }
141 }
142
143 OBBindings::OBBindings()
144 {
145 }
146
147
148 OBBindings::~OBBindings()
149 {
150 remove_all();
151 }
152
153
154 void OBBindings::assimilate(BindingTree *node)
155 {
156 BindingTree *a, *b, *tmp, *last;
157
158 if (!_tree.first_child) {
159 // there are no nodes at this level yet
160 _tree.first_child = node;
161 return;
162 } else {
163 a = _tree.first_child;
164 last = a;
165 b = node;
166 while (a) {
167 last = a;
168 if (a->binding != b->binding) {
169 a = a->next_sibling;
170 } else {
171 tmp = b;
172 b = b->first_child;
173 delete tmp;
174 a = a->first_child;
175 }
176 }
177 if (last->binding != b->binding)
178 last->next_sibling = b;
179 else
180 last->first_child = b->first_child;
181 delete b;
182 }
183 }
184
185
186 int OBBindings::find(BindingTree *search) {
187 BindingTree *a, *b;
188 a = _tree.first_child;
189 b = search;
190 while (a && b) {
191 if (a->binding != b->binding) {
192 a = a->next_sibling;
193 } else {
194 if (a->chain == b->chain) {
195 if (!a->chain)
196 return a->id; // found it! (return the actual id, not the search's)
197 } else
198 return -2; // the chain status' don't match (conflict!)
199 b = b->first_child;
200 a = a->first_child;
201 }
202 }
203 return -1; // it just isn't in here
204 }
205
206 /*
207 static int find(BindingTree *parent, BindingTree *node) {
208 BindingTree *p, *lastsib, *nextparent, *nextnode = node->first_child;
209
210 if (!parent->first_child)
211 return -1;
212
213 p = parent->first_child;
214 while (p) {
215 if (node->binding == p->binding) {
216 if (node->chain == p->chain) {
217 if (!node->chain) {
218 return p->id; // found it! (return the actual id, not the search's)
219 } else {
220 break; // go on to the next child in the chain
221 }
222 } else {
223 return -2; // the chain status' don't match (conflict!)
224 }
225 }
226 p = p->next_sibling;
227 }
228 if (!p) return -1; // doesn't exist
229
230 if (node->chain) {
231 assert(node->first_child);
232 return find(p, node->first_child);
233 } else
234 return -1; // it just isnt in here
235 }
236 */
237
238 bool OBBindings::add(const StringVect &keylist, int id)
239 {
240 BindingTree *tree;
241
242 if (!(tree = buildtree(keylist, id)))
243 return false; // invalid binding requested
244
245 if (find(tree) < -1) {
246 // conflicts with another binding
247 destroytree(tree);
248 return false;
249 }
250
251 // assimilate this built tree into the main tree
252 assimilate(tree); // assimilation destroys/uses the tree
253 return true;
254 }
255
256
257 int OBBindings::find(const StringVect &keylist)
258 {
259 BindingTree *tree;
260 bool ret;
261
262 if (!(tree = buildtree(keylist, 0)))
263 return false; // invalid binding requested
264
265 ret = find(tree) >= 0;
266
267 destroytree(tree);
268
269 return ret;
270 }
271
272
273 int OBBindings::remove(const StringVect &keylist)
274 {
275 (void)keylist;
276 assert(false); // XXX: function not implemented yet
277 }
278
279
280 static void remove_branch(BindingTree *first)
281 {
282 BindingTree *p = first;
283
284 while (p) {
285 if (p->first_child)
286 remove_branch(p->first_child);
287 BindingTree *s = p->next_sibling;
288 delete p;
289 p = s;
290 }
291 }
292
293
294 void OBBindings::remove_all()
295 {
296 if (_tree.first_child)
297 remove_branch(_tree.first_child);
298 }
299
300 }
This page took 0.047589 seconds and 4 git commands to generate.