]> Dogcows Code - chaz/openbox/blob - openbox/keytree.c
best fit only one direction
[chaz/openbox] / openbox / keytree.c
1 #include "keyboard.h"
2 #include "translate.h"
3 #include <glib.h>
4
5 void tree_destroy(KeyBindingTree *tree)
6 {
7 KeyBindingTree *c;
8
9 while (tree) {
10 tree_destroy(tree->next_sibling);
11 c = tree->first_child;
12 if (c == NULL) {
13 GList *it;
14 GSList *sit;
15 for (it = tree->keylist; it != NULL; it = it->next)
16 g_free(it->data);
17 g_list_free(tree->keylist);
18 for (sit = tree->actions; sit != NULL; sit = sit->next)
19 action_free(sit->data);
20 g_slist_free(tree->actions);
21 }
22 g_free(tree);
23 tree = c;
24 }
25 }
26
27 KeyBindingTree *tree_build(GList *keylist)
28 {
29 GList *it;
30 KeyBindingTree *ret = NULL, *p;
31
32 if (g_list_length(keylist) <= 0)
33 return NULL; /* nothing in the list.. */
34
35 for (it = g_list_last(keylist); it != NULL; it = it->prev) {
36 p = ret;
37 ret = g_new0(KeyBindingTree, 1);
38 if (p == NULL) {
39 GList *it;
40
41 /* this is the first built node, the bottom node of the tree */
42 ret->keylist = g_list_copy(keylist); /* shallow copy */
43 for (it = ret->keylist; it != NULL; it = it->next) /* deep copy */
44 it->data = g_strdup(it->data);
45 }
46 ret->first_child = p;
47 if (!translate_key(it->data, &ret->state, &ret->key)) {
48 tree_destroy(ret);
49 return NULL;
50 }
51 }
52 return ret;
53 }
54
55 void tree_assimilate(KeyBindingTree *node)
56 {
57 KeyBindingTree *a, *b, *tmp, *last;
58
59 if (keyboard_firstnode == NULL) {
60 /* there are no nodes at this level yet */
61 keyboard_firstnode = node;
62 } else {
63 a = keyboard_firstnode;
64 last = a;
65 b = node;
66 while (a) {
67 last = a;
68 if (!(a->state == b->state && a->key == b->key)) {
69 a = a->next_sibling;
70 } else {
71 tmp = b;
72 b = b->first_child;
73 g_free(tmp);
74 a = a->first_child;
75 }
76 }
77 if (!(last->state == b->state && last->key == b->key))
78 last->next_sibling = b;
79 else {
80 last->first_child = b->first_child;
81 g_free(b);
82 }
83 }
84 }
85
86 KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict)
87 {
88 KeyBindingTree *a, *b;
89
90 *conflict = FALSE;
91
92 a = keyboard_firstnode;
93 b = search;
94 while (a && b) {
95 if (!(a->state == b->state && a->key == b->key)) {
96 a = a->next_sibling;
97 } else {
98 if ((a->first_child == NULL) == (b->first_child == NULL)) {
99 if (a->first_child == NULL) {
100 /* found it! (return the actual node, not the search's) */
101 return a;
102 }
103 } else {
104 *conflict = TRUE;
105 return NULL; /* the chain status' don't match (conflict!) */
106 }
107 b = b->first_child;
108 a = a->first_child;
109 }
110 }
111 return NULL; /* it just isn't in here */
112 }
This page took 0.038389 seconds and 4 git commands to generate.