summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/utils/regedit_treeview.c277
-rw-r--r--source3/utils/regedit_treeview.h60
-rwxr-xr-xsource3/wscript_build2
3 files changed, 338 insertions, 1 deletions
diff --git a/source3/utils/regedit_treeview.c b/source3/utils/regedit_treeview.c
new file mode 100644
index 0000000000..f902f60678
--- /dev/null
+++ b/source3/utils/regedit_treeview.c
@@ -0,0 +1,277 @@
+/*
+ * Samba Unix/Linux SMB client library
+ * Registry Editor
+ * Copyright (C) Christopher Davis 2012
+ *
+ * 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 3 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "regedit_treeview.h"
+
+struct tree_node *tree_node_new(TALLOC_CTX *ctx, struct tree_node *parent, const char *name)
+{
+ struct tree_node *node;
+
+ node = talloc_zero(ctx, struct tree_node);
+ if (!node) {
+ return NULL;
+ }
+
+ node->name = talloc_strdup(node, name);
+ if (!node->name) {
+ talloc_free(node);
+ return NULL;
+ }
+
+ if (parent) {
+ /* Check if this node is the first descendant of parent. */
+ if (!parent->child_head) {
+ parent->child_head = node;
+ }
+ node->parent = parent;
+ }
+
+ return node;
+}
+
+void tree_node_append(struct tree_node *left, struct tree_node *right)
+{
+ if (left->next) {
+ right->next = left->next;
+ left->next->previous = right;
+ }
+ left->next = right;
+ right->previous = left;
+}
+
+struct tree_node *tree_node_pop(struct tree_node **plist)
+{
+ struct tree_node *node;
+
+ node = *plist;
+
+ if (node == NULL)
+ return NULL;
+
+ *plist = node->previous;
+ if (*plist == NULL) {
+ *plist = node->next;
+ }
+ if (node->previous) {
+ node->previous->next = node->next;
+ }
+ if (node->next) {
+ node->next->previous = node->previous;
+ }
+
+ node->next = NULL;
+ node->previous = NULL;
+
+ return node;
+}
+
+struct tree_node *tree_node_first(struct tree_node *list)
+{
+ /* Grab the first node in this list from the parent if available. */
+ if (list->parent) {
+ return list->parent->child_head;
+ }
+
+ while (list && list->previous) {
+ list = list->previous;
+ }
+
+ return list;
+}
+
+void tree_node_free_recursive(struct tree_node *list)
+{
+ struct tree_node *node;
+
+ if (list == NULL) {
+ return;
+ }
+
+ while ((node = tree_node_pop(&list)) != NULL) {
+ if (node->child_head) {
+ tree_node_free_recursive(node->child_head);
+ }
+ node->child_head = NULL;
+ talloc_free(node);
+ }
+}
+
+static void tree_view_free_current_items(ITEM **items)
+{
+ size_t i;
+ struct tree_node *node;
+ ITEM *item;
+
+ if (items == NULL) {
+ return;
+ }
+
+ for (i = 0; items[i] != NULL; ++i) {
+ item = items[i];
+ node = item_userptr(item);
+ if (node && node->label) {
+ talloc_free(node->label);
+ node->label = NULL;
+ }
+ free_item(item);
+ }
+
+ talloc_free(items);
+}
+
+WERROR tree_view_update(struct tree_view *view, struct tree_node *list)
+{
+ ITEM **items;
+ struct tree_node *node;
+ size_t i, n_items;
+
+ if (list == NULL) {
+ list = view->root;
+ }
+ for (n_items = 0, node = list; node != NULL; node = node->next) {
+ n_items++;
+ }
+
+ items = talloc_zero_array(view, ITEM *, n_items + 1);
+ if (items == NULL) {
+ return WERR_NOMEM;
+ }
+
+ for (i = 0, node = list; node != NULL; ++i, node = node->next) {
+ const char *label = node->name;
+
+ /* Add a '+' marker to indicate that the item has
+ descendants. */
+ if (node->child_head) {
+ SMB_ASSERT(node->label == NULL);
+ node->label = talloc_asprintf(node, "+%s", node->name);
+ if (node->label == NULL) {
+ goto fail;
+ }
+ label = node->label;
+ }
+
+ items[i] = new_item(label, node->name);
+ set_item_userptr(items[i], node);
+ }
+
+ unpost_menu(view->menu);
+ set_menu_items(view->menu, items);
+ tree_view_free_current_items(view->current_items);
+ view->current_items = items;
+
+ return WERR_OK;
+
+fail:
+ tree_view_free_current_items(items);
+
+ return WERR_NOMEM;
+}
+
+void tree_view_show(struct tree_view *view)
+{
+ post_menu(view->menu);
+ wrefresh(view->window);
+}
+
+static int tree_view_free(struct tree_view *view)
+{
+ if (view->menu) {
+ unpost_menu(view->menu);
+ free_menu(view->menu);
+ }
+ tree_view_free_current_items(view->current_items);
+ tree_node_free_recursive(view->root);
+
+ return 0;
+}
+
+struct tree_view *tree_view_new(TALLOC_CTX *ctx, struct tree_node *root,
+ WINDOW *orig, int nlines, int ncols,
+ int begin_y, int begin_x)
+{
+ struct tree_view *view;
+ static const char *dummy = "1234";
+
+ view = talloc_zero(ctx, struct tree_view);
+ if (view == NULL) {
+ return NULL;
+ }
+
+ talloc_set_destructor(view, tree_view_free);
+
+ view->current_items = talloc_zero_array(ctx, ITEM *, 2);
+ if (view->current_items == NULL) {
+ goto fail;
+ }
+
+ view->current_items[0] = new_item(dummy, dummy);
+ if (view->current_items[0] == NULL) {
+ goto fail;
+ }
+
+ view->window = orig;
+ view->sub_window = derwin(orig, nlines, ncols, begin_y, begin_x);
+ view->root = root;
+
+ view->menu = new_menu(view->current_items);
+ if (view->menu == NULL) {
+ goto fail;
+ }
+ set_menu_format(view->menu, nlines, 1);
+ set_menu_win(view->menu, view->window);
+ set_menu_sub(view->menu, view->sub_window);
+ menu_opts_off(view->menu, O_SHOWDESC);
+ set_menu_mark(view->menu, "* ");
+
+ tree_view_update(view, root);
+
+ return view;
+
+fail:
+ talloc_free(view);
+
+ return NULL;
+}
+
+static void print_path_recursive(WINDOW *label, struct tree_node *node)
+{
+ if (node->parent)
+ print_path_recursive(label, node->parent);
+
+ wprintw(label, "%s/", node->name);
+}
+
+/* print the path of node to label */
+void tree_node_print_path(WINDOW *label, struct tree_node *node)
+{
+ if (node == NULL)
+ return;
+
+ wmove(label, 0, 0);
+ wclrtoeol(label);
+ wprintw(label, "/");
+ wmove(label, 0, 0);
+
+ if (node->parent)
+ print_path_recursive(label, node->parent);
+
+ wnoutrefresh(label);
+ wrefresh(label);
+}
diff --git a/source3/utils/regedit_treeview.h b/source3/utils/regedit_treeview.h
new file mode 100644
index 0000000000..1af6ad3458
--- /dev/null
+++ b/source3/utils/regedit_treeview.h
@@ -0,0 +1,60 @@
+/*
+ * Samba Unix/Linux SMB client library
+ * Registry Editor
+ * Copyright (C) Christopher Davis 2012
+ *
+ * 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 3 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _REGEDIT_TREEVIEW_H_
+#define _REGEDIT_TREEVIEW_H_
+
+#include "includes.h"
+#include <ncurses.h>
+#include <menu.h>
+
+struct tree_node {
+
+ char *name;
+ char *label;
+
+ struct tree_node *parent;
+ struct tree_node *child_head;
+ struct tree_node *previous;
+ struct tree_node *next;
+};
+
+struct tree_view {
+
+ struct tree_node *root;
+ WINDOW *window;
+ WINDOW *sub_window;
+ MENU *menu;
+ ITEM **current_items;
+};
+
+struct tree_node *tree_node_new(TALLOC_CTX *ctx, struct tree_node *parent,
+ const char *name);
+void tree_node_append(struct tree_node *left, struct tree_node *right);
+struct tree_node *tree_node_pop(struct tree_node **plist);
+struct tree_node *tree_node_first(struct tree_node *list);
+void tree_node_free_recursive(struct tree_node *list);
+void tree_node_print_path(WINDOW *label, struct tree_node *node);
+struct tree_view *tree_view_new(TALLOC_CTX *ctx, struct tree_node *root,
+ WINDOW *orig, int nlines, int ncols,
+ int begin_y, int begin_x);
+void tree_view_show(struct tree_view *view);
+WERROR tree_view_update(struct tree_view *view, struct tree_node *list);
+
+#endif
diff --git a/source3/wscript_build b/source3/wscript_build
index 61acb377e0..13001a7dfc 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -1642,7 +1642,7 @@ bld.SAMBA3_PYTHON('pylibsmb',
)
bld.SAMBA3_BINARY('regedit',
- source='utils/regedit.c utils/regedit_samba3.c utils/regedit_wrap.c',
+ source='utils/regedit.c utils/regedit_samba3.c utils/regedit_wrap.c utils/regedit_treeview.c',
deps='ncurses menu registry param popt_samba3 smbregistry',
enabled=bld.env.build_regedit,
vars=locals())