X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fkeytree.c;h=93a0c7aa6a54aa9e6dc53b0346cf79171c1d3aa0;hb=2ea60e77c085a724b2ec28273e24e12ece0e84f3;hp=9aa2ea95455aa243b6a6db4eb7af2298ce01c585;hpb=c90da6da781932c2d178bfb7e39ec1d5003543b7;p=chaz%2Fopenbox diff --git a/openbox/keytree.c b/openbox/keytree.c index 9aa2ea95..93a0c7aa 100644 --- a/openbox/keytree.c +++ b/openbox/keytree.c @@ -1,5 +1,25 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + keytree.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + #include "keyboard.h" #include "translate.h" +#include "actions.h" #include void tree_destroy(KeyBindingTree *tree) @@ -7,20 +27,20 @@ void tree_destroy(KeyBindingTree *tree) KeyBindingTree *c; while (tree) { - tree_destroy(tree->next_sibling); - c = tree->first_child; - if (c == NULL) { - GList *it; + tree_destroy(tree->next_sibling); + c = tree->first_child; + if (c == NULL) { + GList *it; GSList *sit; - for (it = tree->keylist; it != NULL; it = it->next) - g_free(it->data); - g_list_free(tree->keylist); - for (sit = tree->actions; sit != NULL; sit = sit->next) - action_free(sit->data); - g_slist_free(tree->actions); - } - g_free(tree); - tree = c; + for (it = tree->keylist; it != NULL; it = it->next) + g_free(it->data); + g_list_free(tree->keylist); + for (sit = tree->actions; sit != NULL; sit = sit->next) + actions_act_unref(sit->data); + g_slist_free(tree->actions); + } + g_slice_free(KeyBindingTree, tree); + tree = c; } } @@ -30,24 +50,20 @@ KeyBindingTree *tree_build(GList *keylist) 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_new0(KeyBindingTree, 1); - 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 NULL; /* nothing in the list.. */ + + for (it = g_list_last(keylist); it; it = g_list_previous(it)) { + GList *kit; + + p = ret; + ret = g_slice_new0(KeyBindingTree); + + for (kit = it; kit != NULL; kit = g_list_previous(kit)) + ret->keylist = g_list_prepend(ret->keylist, + g_strdup(kit->data)); /* deep copy */ + ret->first_child = p; + if (p != NULL) p->parent = ret; + translate_key(it->data, &ret->state, &ret->key); } return ret; } @@ -57,29 +73,34 @@ void tree_assimilate(KeyBindingTree *node) KeyBindingTree *a, *b, *tmp, *last; if (keyboard_firstnode == NULL) { - /* there are no nodes at this level yet */ - keyboard_firstnode = node; + /* there are no nodes at this level yet */ + keyboard_firstnode = node; } else { - a = keyboard_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); - } + a = keyboard_firstnode; + last = a; + b = node; + while (a) { + last = a; + /* check b->key != 0 for key bindings that didn't get translated */ + if (!(a->state == b->state && a->key == b->key && b->key != 0)) { + a = a->next_sibling; + } else { + tmp = b; + b = b->first_child; + g_slice_free(KeyBindingTree, tmp); + a = a->first_child; + } + } + /* check b->key != 0, and save key bindings that didn't get translated + as siblings here */ + if (!(last->state == b->state && last->key == b->key && b->key != 0)) { + last->next_sibling = b; + b->parent = last->parent; + } else { + last->first_child = b->first_child; + last->first_child->parent = last; + g_slice_free(KeyBindingTree, b); + } } } @@ -92,21 +113,40 @@ KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict) a = keyboard_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; - } + /* check b->key != 0 for key bindings that didn't get translated, and + don't make them conflict with anything else so that they can all + live together in peace and harmony */ + if (!(a->state == b->state && a->key == b->key && b->key != 0)) { + 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 */ } + +gboolean tree_chroot(KeyBindingTree *tree, GList *keylist) +{ + guint key, state; + translate_key(keylist->data, &state, &key); + while (tree != NULL && !(tree->state == state && tree->key == key)) + tree = tree->next_sibling; + if (tree != NULL) { + if (keylist->next == NULL) { + tree->chroot = TRUE; + return TRUE; + } else + return tree_chroot(tree->first_child, keylist->next); + } + return FALSE; +}