From db5295a7dc61056092b43523409fd11b147e031d Mon Sep 17 00:00:00 2001 From: "C. Davis" Date: Mon, 6 Aug 2012 19:11:13 -0700 Subject: regedit: Some work on dialogs. * 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 Reviewed-by: Michael Adam --- source3/utils/regedit.c | 89 ++++++---------- source3/utils/regedit_dialog.c | 229 ++++++++++++++++++++++++++++++++++++++--- source3/utils/regedit_dialog.h | 20 +--- 3 files changed, 246 insertions(+), 92 deletions(-) diff --git a/source3/utils/regedit.c b/source3/utils/regedit.c index 14215cb775..cf97668494 100644 --- a/source3/utils/regedit.c +++ b/source3/utils/regedit.c @@ -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(); } diff --git a/source3/utils/regedit_dialog.c b/source3/utils/regedit_dialog.c index b5e41ee901..7c4a0bb918 100644 --- a/source3/utils/regedit_dialog.c +++ b/source3/utils/regedit_dialog.c @@ -19,7 +19,11 @@ #include "includes.h" #include "regedit_dialog.h" +#include "regedit_valuelist.h" +#include "util_reg.h" +#include "lib/registry/registry.h" #include +#include 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; } diff --git a/source3/utils/regedit_dialog.h b/source3/utils/regedit_dialog.h index 461de43b82..de6c5bc982 100644 --- a/source3/utils/regedit_dialog.h +++ b/source3/utils/regedit_dialog.h @@ -24,10 +24,6 @@ #include #include -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 -- cgit