regedit: Some work on dialogs.
authorC. Davis <cd.rattan@gmail.com>
Tue, 7 Aug 2012 02:11:13 +0000 (19:11 -0700)
committerMichael Adam <obnox@samba.org>
Mon, 29 Apr 2013 11:06:03 +0000 (13:06 +0200)
* Make dialogs modal with a separate getch() loop to avoid extra
  complexity keeping track of dialogs and getting the result.

* Start work on the value editor dialog.

Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
source3/utils/regedit.c
source3/utils/regedit_dialog.c
source3/utils/regedit_dialog.h

index 14215cb77568e03fc89745b0a400921408ca17ff..cf9766849409b3d5a78e5517a95aace25a58b239 100644 (file)
@@ -38,7 +38,6 @@ struct regedit {
        struct value_list *vl;
        struct tree_view *keys;
        bool tree_input;
-       struct dialog *dia;
 };
 
 /* load all available hives */
@@ -102,32 +101,6 @@ static void print_heading(WINDOW *win, bool selected, const char *str)
        wrefresh(win);
 }
 
-static void delete_key_callback(struct dialog *dia, int selection, void *arg)
-{
-       struct regedit *regedit = arg;
-
-       //mvwprintw(regedit->main_window, 1, 0, "Selection: %d", selection);
-
-       if (selection == DIALOG_OK) {
-               /* TODO */
-       }
-
-       talloc_free(regedit->dia);
-       regedit->dia = NULL;
-}
-
-static void delete_value_callback(struct dialog *dia, int selection, void *arg)
-{
-       struct regedit *regedit = arg;
-
-       if (selection == DIALOG_OK) {
-               /* TODO */
-       }
-
-       talloc_free(regedit->dia);
-       regedit->dia = NULL;
-}
-
 static void handle_tree_input(struct regedit *regedit, int c)
 {
        struct tree_node *node;
@@ -165,15 +138,21 @@ static void handle_tree_input(struct regedit *regedit, int c)
                }
                break;
        case 'd':
-       case 'D':
+       case 'D': {
+               struct dialog *dia;
+               int sel;
+
                node = item_userptr(current_item(regedit->keys->menu));
-               regedit->dia = dialog_confirm_new(regedit, "Delete Key",
-                                                 regedit->main_window,
-                                                 "Really delete key \"%s\"?",
-                                                 node->name);
-               dialog_set_cb(regedit->dia, delete_key_callback, regedit);
+               dia = dialog_confirm_new(regedit, "Delete Key",
+                                        regedit->main_window,
+                                        "Really delete key \"%s\"?",
+                                        node->name);
+               sel = dialog_modal_loop(dia);
+               mvwprintw(regedit->main_window, 1, 0, "Sel: %d", sel);
+               /* TODO */
                break;
        }
+       }
 
        tree_view_show(regedit->keys);
        value_list_show(regedit->vl);
@@ -190,17 +169,28 @@ static void handle_value_input(struct regedit *regedit, int c)
        case KEY_UP:
                menu_driver(regedit->vl->menu, REQ_UP_ITEM);
                break;
+       case '\n':
        case KEY_ENTER:
+               vitem = item_userptr(current_item(regedit->vl->menu));
+               if (vitem) {
+                       struct tree_node *node;
+                       node = item_userptr(current_item(regedit->keys->menu));
+                       dialog_edit_value(regedit, node->key, vitem, regedit->main_window);
+               }
                break;
        case 'd':
        case 'D':
                vitem = item_userptr(current_item(regedit->vl->menu));
                if (vitem) {
-                       regedit->dia = dialog_confirm_new(regedit, "Delete Value",
-                                                         regedit->main_window,
-                                                         "Really delete value \"%s\"?",
-                                                         vitem->value_name);
-                       dialog_set_cb(regedit->dia, delete_value_callback, regedit);
+                       struct dialog *dia;
+                       int sel;
+
+                       dia = dialog_confirm_new(regedit, "Delete Value",
+                                                regedit->main_window,
+                                                "Really delete value \"%s\"?",
+                                                vitem->value_name);
+                       sel = dialog_modal_loop(dia);
+                       mvwprintw(regedit->main_window, 1, 0, "Sel: %d", sel);
                }
                break;
        }
@@ -208,22 +198,6 @@ static void handle_value_input(struct regedit *regedit, int c)
        value_list_show(regedit->vl);
 }
 
-static void handle_dialog_input(struct regedit *regedit, int c)
-{
-       switch (c) {
-       case KEY_LEFT:
-               dialog_driver(regedit->dia, DIALOG_LEFT);
-               break;
-       case KEY_RIGHT:
-               dialog_driver(regedit->dia, DIALOG_RIGHT);
-               break;
-       case '\n':
-       case KEY_ENTER:
-               dialog_driver(regedit->dia, DIALOG_ENTER);
-               break;
-       }
-}
-
 static void handle_main_input(struct regedit *regedit, int c)
 {
        switch (c) {
@@ -296,12 +270,7 @@ static void display_test_window(TALLOC_CTX *mem_ctx,
        update_panels();
        doupdate();
        while ((c = wgetch(regedit->main_window)) != 'q') {
-               if (regedit->dia) {
-                       handle_dialog_input(regedit, c);
-               } else {
-                       handle_main_input(regedit, c);
-               }
-
+               handle_main_input(regedit, c);
                update_panels();
                doupdate();
        }
index b5e41ee9010b1c3758036c3ce73aae83dd3779d8..7c4a0bb918a8b42fe1fc6cb5cd50008b639aad05 100644 (file)
 
 #include "includes.h"
 #include "regedit_dialog.h"
+#include "regedit_valuelist.h"
+#include "util_reg.h"
+#include "lib/registry/registry.h"
 #include <stdarg.h>
+#include <form.h>
 
 static int dialog_free(struct dialog *dia)
 {
@@ -226,30 +230,221 @@ struct dialog *dialog_confirm_new(TALLOC_CTX *ctx, const char *title,
        return dia;
 }
 
-void dialog_set_cb(struct dialog *dia, dialogfn fn, void *arg)
+static int handle_menu_input(MENU *menu, int c)
 {
-       dia->dialogcb = fn;
-       dia->dialogarg = arg;
+       ITEM *item;
+
+       switch (c) {
+       case KEY_LEFT:
+               menu_driver(menu, REQ_LEFT_ITEM);
+               break;
+       case KEY_RIGHT:
+               menu_driver(menu, REQ_RIGHT_ITEM);
+               break;
+       case KEY_ENTER:
+       case '\n':
+               item = current_item(menu);
+               return (int)(uintptr_t)item_userptr(item);
+       }
+
+       return -1;
+}
+
+int dialog_modal_loop(struct dialog *dia)
+{
+       int c;
+       int selection = -1;
+
+       keypad(dia->window, true);
+       update_panels();
+       doupdate();
+
+       while (selection == -1) {
+               c = wgetch(dia->window);
+               selection = handle_menu_input(dia->choices, c);
+               update_panels();
+               doupdate();
+       }
+
+       talloc_free(dia);
+
+       return selection;
 }
 
-void dialog_driver(struct dialog *dia, enum dialog_op op)
+static void handle_form_input(FORM *frm, int c)
 {
-       switch (op) {
-       case DIALOG_LEFT:
-               menu_driver(dia->choices, REQ_LEFT_ITEM);
+       switch (c) {
+       case '\n':
+               form_driver(frm, REQ_NEW_LINE);
+               break;
+       case KEY_UP:
+               form_driver(frm, REQ_UP_CHAR);
+               break;
+       case KEY_DOWN:
+               form_driver(frm, REQ_DOWN_CHAR);
+               break;
+       case '\b':
+       case KEY_BACKSPACE:
+               form_driver(frm, REQ_DEL_PREV);
+               break;
+       case KEY_LEFT:
+               form_driver(frm, REQ_LEFT_CHAR);
                break;
-       case DIALOG_RIGHT:
-               menu_driver(dia->choices, REQ_RIGHT_ITEM);
+       case KEY_RIGHT:
+               form_driver(frm, REQ_RIGHT_CHAR);
                break;
-       case DIALOG_ENTER:
-               if (dia->dialogcb) {
-                       ITEM *item;
-                       int selection;
-
-                       item = current_item(dia->choices);
-                       selection = (int)(uintptr_t)item_userptr(item);
-                       dia->dialogcb(dia, selection, dia->dialogarg);
+       default:
+               form_driver(frm, c);
+               break;
+       }
+}
+
+#define MAX_FIELDS 8
+
+enum input_section {
+       IN_NAME,
+       IN_DATA,
+       IN_MENU
+};
+
+static void fill_value_buffer(TALLOC_CTX *ctx, FIELD *fld, const struct value_item *vitem)
+{
+       char *tmp;
+
+       switch (vitem->type) {
+       case REG_DWORD: {
+               uint32_t v = 0;
+               if (vitem->data.length >= 4) {
+                       v = IVAL(vitem->data.data, 0);
                }
+               tmp = talloc_asprintf(ctx, "0x%x", v);
+               set_field_buffer(fld, 0, tmp);
+               talloc_free(tmp);
                break;
        }
+       case REG_SZ:
+       case REG_EXPAND_SZ: {
+               const char *s;
+
+               if (!pull_reg_sz(ctx, &vitem->data, &s)) {
+                       break;
+               }
+               set_field_buffer(fld, 0, s);
+               break;
+       }
+
+       }
+}
+
+static void set_value(TALLOC_CTX *ctx, FIELD *fld, struct registry_key *key,
+                     const struct value_item *vitem)
+{
+}
+
+int dialog_edit_value(TALLOC_CTX *ctx, struct registry_key *key,
+                     const struct value_item *vitem, WINDOW *below)
+{
+       struct dialog *dia;
+       const char *choices[] = {
+               "Ok",
+               "Cancel",
+               NULL
+       };
+       char *title;
+       int nlines, ncols;
+       int rv = -1;
+       WINDOW *input_win;
+       FORM *input;
+       FIELD *field[MAX_FIELDS];
+       enum input_section section;
+
+       title = talloc_asprintf(ctx, "Edit %s value", str_regtype(vitem->type));
+       if (title == NULL) {
+               return -1;
+       }
+
+       nlines = 15;
+       ncols = 50;
+       dia = dialog_choice_center_new(ctx, title, choices, nlines, ncols, below);
+       if (dia == NULL) {
+               goto finish;
+       }
+
+       memset(field, '\0', sizeof(*field) * MAX_FIELDS);
+       field[0] = new_field(1, ncols - 4, 1, 1, 0, 0);
+       field[1] = new_field(1, ncols - 4, 4, 1, 0, 0);
+
+       set_field_back(field[0], A_UNDERLINE);
+       set_field_back(field[1], A_UNDERLINE);
+       field_opts_off(field[0], O_BLANK | O_AUTOSKIP | O_STATIC);
+       field_opts_off(field[1], O_BLANK | O_AUTOSKIP | O_STATIC);
+
+       if (vitem) {
+               set_field_buffer(field[0], 0, vitem->value_name);
+               field_opts_off(field[0], O_EDIT);
+               fill_value_buffer(dia, field[1], vitem);
+       }
+
+       input = new_form(field);
+       form_opts_off(input, O_NL_OVERLOAD | O_BS_OVERLOAD);
+
+       input_win = derwin(dia->sub_window, nlines - 3, ncols - 3, 0, 0);
+
+       set_form_win(input, dia->sub_window);
+       set_form_sub(input, input_win);
+       post_form(input);
+       mvwprintw(dia->sub_window, 0, 0, "Name");
+       mvwprintw(dia->sub_window, 3, 0, "Data");
+
+       keypad(dia->window, true);
+       update_panels();
+       doupdate();
+
+       section = IN_NAME;
+
+       while (1) {
+               int c = wgetch(dia->window);
+               if (c == '\t') {
+                       switch (section) {
+                       case IN_NAME:
+                               section = IN_DATA;
+                               set_current_field(input, field[1]);
+                               break;
+                       case IN_DATA:
+                               section = IN_MENU;
+                               menu_driver(dia->choices, REQ_FIRST_ITEM);
+                               break;
+                       case IN_MENU:
+                               section = IN_NAME;
+                               set_current_field(input, field[0]);
+                               break;
+                       }
+                       continue;
+               }
+
+               if (section == IN_NAME || section == IN_DATA) {
+                       handle_form_input(input, c);
+               } else {
+                       rv = handle_menu_input(dia->choices, c);
+                       if (rv != -1) {
+                               goto finish;
+                       }
+               }
+
+               update_panels();
+               doupdate();
+       }
+
+finish:
+       if (title) {
+               talloc_free(title);
+       }
+       if (dia) {
+               talloc_free(dia);
+       }
+       if (rv == DIALOG_OK) {
+               //set_value
+       }
+
+       return rv;
 }
index 461de43b82136d66b4f30df077520cee263edd8a..de6c5bc9826eb6d463b6712ca716eb853511e968 100644 (file)
 #include <panel.h>
 #include <menu.h>
 
-struct dialog;
-
-typedef void (*dialogfn)(struct dialog *, int, void *);
-
 struct dialog {
        WINDOW *window;
        WINDOW *sub_window;
@@ -35,8 +31,6 @@ struct dialog {
        PANEL *panel;
        MENU *choices;
        ITEM **choice_items;
-       dialogfn dialogcb;
-       void *dialogarg;
 };
 
 struct dialog *dialog_new(TALLOC_CTX *ctx, const char *title, int nlines,
@@ -56,19 +50,15 @@ struct dialog *dialog_choice_center_new(TALLOC_CTX *ctx, const char *title,
 struct dialog *dialog_confirm_new(TALLOC_CTX *ctx, const char *title,
                                  WINDOW *below, const char *msg, ...);
 
-void dialog_set_cb(struct dialog *dia, dialogfn fn, void *arg);
-
-enum dialog_op {
-       DIALOG_LEFT,
-       DIALOG_RIGHT,
-       DIALOG_ENTER
-};
-
 enum dialog_selection {
        DIALOG_OK = 0,
        DIALOG_CANCEL = 1
 };
 
-void dialog_driver(struct dialog *dia, enum dialog_op op);
+int dialog_modal_loop(struct dialog *dia);
+
+struct registry_key;
+struct value_item;
 
+int dialog_edit_value(TALLOC_CTX *ctx, struct registry_key *key, const struct value_item *vitem, WINDOW *below);
 #endif