regedit: Initial import of treeview code
authorC. Davis <cd.rattan@gmail.com>
Tue, 10 Jul 2012 13:23:33 +0000 (06:23 -0700)
committerMichael Adam <obnox@samba.org>
Mon, 29 Apr 2013 11:05:45 +0000 (13:05 +0200)
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/utils/regedit_treeview.c [new file with mode: 0644]
source3/utils/regedit_treeview.h [new file with mode: 0644]
source3/wscript_build

diff --git a/source3/utils/regedit_treeview.c b/source3/utils/regedit_treeview.c
new file mode 100644 (file)
index 0000000..f902f60
--- /dev/null
@@ -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 (file)
index 0000000..1af6ad3
--- /dev/null
@@ -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
index 61acb377e0f7ceda2a981e0a949127535f63493a..13001a7dfc8f918146ddb54a370a998995893803 100755 (executable)
@@ -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())