all repos — openbox @ 51b93d9c4ce080f337fce7175a43d0de269dec81

openbox fork - make it a bit more like ryudo

plugins/keyboard/tree.c (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "keyboard.h"
#include "translate.h"
#include "keyaction.h"
#include <glib.h>

void tree_destroy(KeyBindingTree *tree)
{
    KeyBindingTree *c;

    while (tree) {
	tree_destroy(tree->next_sibling);
	c = tree->first_child;
	if (c == NULL) {
	    GList *it;
	    for (it = tree->keylist; it != NULL; it = it->next)
		g_free(it->data);
	    g_list_free(tree->keylist);
            keyaction_free(&tree->action);
	}
	g_free(tree);
	tree = c;
    }
}

KeyBindingTree *tree_build(GList *keylist)
{
    GList *it;
    KeyBindingTree *ret = NULL, *p;

    if (g_list_length(keylist) <= 0)
	return NULL; /* nothing in the list.. */

    for (it = g_list_last(keylist); it != NULL; it = it->prev) {
	p = ret;
	ret = g_new(KeyBindingTree, 1);
	ret->next_sibling = NULL;
	if (p == NULL) {
	    GList *it;

	    /* this is the first built node, the bottom node of the tree */
	    ret->keylist = g_list_copy(keylist); /* shallow copy */
	    for (it = ret->keylist; it != NULL; it = it->next) /* deep copy */
		it->data = g_strdup(it->data);
	}
	ret->first_child = p;
	if (!translate_key(it->data, &ret->state, &ret->key)) {
	    tree_destroy(ret);
	    return NULL;
	}
    }
    return ret;
}

void tree_assimilate(KeyBindingTree *node)
{
    KeyBindingTree *a, *b, *tmp, *last;

    if (firstnode == NULL) {
	/* there are no nodes at this level yet */
	firstnode = node;
    } else {
	a = firstnode;
	last = a;
	b = node;
	while (a) {
	    last = a;
	    if (!(a->state == b->state && a->key == b->key)) {
		a = a->next_sibling;
	    } else {
		tmp = b;
		b = b->first_child;
		g_free(tmp);
		a = a->first_child;
	    }
	}
	if (!(last->state == b->state && last->key == b->key))
	    last->next_sibling = b;
	else {
	    last->first_child = b->first_child;
	    g_free(b);
	}
    }
}

KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict)
{
    KeyBindingTree *a, *b;

    *conflict = FALSE;

    a = firstnode;
    b = search;
    while (a && b) {
	if (!(a->state == b->state && a->key == b->key)) {
	    a = a->next_sibling;
	} else {
	    if ((a->first_child == NULL) == (b->first_child == NULL)) {
		if (a->first_child == NULL) {
		    /* found it! (return the actual node, not the search's) */
		    return a;
		}
	    } else {
		*conflict = TRUE;
		return NULL; /* the chain status' don't match (conflict!) */
	    }
	    b = b->first_child;
	    a = a->first_child;
	}
    }
    return NULL; /* it just isn't in here */
}