2 * Samba Unix/Linux SMB client library
4 * Copyright (C) Christopher Davis 2012
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "regedit_dialog.h"
23 #include "regedit_valuelist.h"
24 #include "regedit_hexedit.h"
26 #include "lib/registry/registry.h"
30 static char *string_trim_n(TALLOC_CTX *ctx, const char *buf, size_t n)
34 str = talloc_strndup(ctx, buf, n);
37 trim_string(str, " ", " ");
43 static char *string_trim(TALLOC_CTX *ctx, const char *buf)
47 str = talloc_strdup(ctx, buf);
50 trim_string(str, " ", " ");
56 static int dialog_free(struct dialog *dia)
63 static bool default_validator(struct dialog *dia, struct dialog_section *sect,
69 struct dialog *dialog_new(TALLOC_CTX *ctx, short color, const char *title,
74 dia = talloc_zero(ctx, struct dialog);
79 talloc_set_destructor(dia, dialog_free);
81 dia->title = talloc_strdup(dia, title);
82 if (dia->title == NULL) {
88 dia->submit = default_validator;
99 void dialog_set_submit_cb(struct dialog *dia, dialog_submit_cb cb, void *arg)
102 dia->submit_arg = arg;
105 static void center_above_window(int *nlines, int *ncols, int *y, int *x)
107 int centery, centerx;
114 if (*nlines > LINES) {
121 if (*nlines/2 < centery) {
122 *y = centery - *nlines / 2;
124 if (*ncols/2 < centerx) {
125 *x = centerx - *ncols / 2;
129 void dialog_section_destroy(struct dialog_section *section)
131 if (section->ops->destroy) {
132 section->ops->destroy(section);
134 if (section->window) {
135 delwin(section->window);
136 section->window = NULL;
140 void dialog_section_init(struct dialog_section *section,
141 const struct dialog_section_ops *ops,
142 int nlines, int ncols)
145 section->nlines = nlines;
146 section->ncols = ncols;
149 const char *dialog_section_get_name(struct dialog_section *section)
151 return section->name;
154 void dialog_section_set_name(struct dialog_section *section, const char *name)
156 TALLOC_FREE(section->name);
157 section->name = talloc_strdup(section, name);
160 void dialog_section_set_justify(struct dialog_section *section,
161 enum section_justify justify)
163 section->justify = justify;
166 /* append a section to the dialog's circular list */
167 void dialog_append_section(struct dialog *dia,
168 struct dialog_section *section)
170 SMB_ASSERT(section != NULL);
172 if (!dia->head_section) {
173 dia->head_section = section;
175 if (dia->tail_section) {
176 dia->tail_section->next = section;
178 section->prev = dia->tail_section;
179 section->next = dia->head_section;
180 dia->head_section->prev = section;
181 dia->tail_section = section;
184 struct dialog_section *dialog_find_section(struct dialog *dia, const char *name)
186 struct dialog_section *section = dia->head_section;
189 if (section->name && strequal(section->name, name)) {
192 section = section->next;
193 } while (section != dia->head_section);
198 static void section_on_input(struct dialog *dia, int c)
200 struct dialog_section *section = dia->current_section;
202 if (!section->ops->on_input) {
205 section->ops->on_input(dia, section, c);
208 static bool section_on_tab(struct dialog *dia)
210 struct dialog_section *section = dia->current_section;
212 if (!section || !section->ops->on_tab) {
215 return section->ops->on_tab(dia, section);
218 static bool section_on_btab(struct dialog *dia)
220 struct dialog_section *section = dia->current_section;
222 if (!section || !section->ops->on_btab) {
225 return section->ops->on_btab(dia, section);
228 static bool section_on_up(struct dialog *dia)
230 struct dialog_section *section = dia->current_section;
232 if (!section || !section->ops->on_up) {
235 return section->ops->on_up(dia, section);
238 static bool section_on_down(struct dialog *dia)
240 struct dialog_section *section = dia->current_section;
242 if (!section || !section->ops->on_down) {
245 return section->ops->on_down(dia, section);
248 static bool section_on_left(struct dialog *dia)
250 struct dialog_section *section = dia->current_section;
252 if (!section || !section->ops->on_left) {
255 return section->ops->on_left(dia, section);
258 static bool section_on_right(struct dialog *dia)
260 struct dialog_section *section = dia->current_section;
262 if (!section || !section->ops->on_right) {
265 return section->ops->on_right(dia, section);
268 static enum dialog_action section_on_enter(struct dialog *dia)
270 struct dialog_section *section = dia->current_section;
272 if (!section || !section->ops->on_enter) {
275 return section->ops->on_enter(dia, section);
278 static bool section_on_focus(struct dialog *dia, bool forward)
280 struct dialog_section *section = dia->current_section;
282 if (!section->ops->on_focus) {
285 return section->ops->on_focus(dia, section, forward);
288 static void section_on_leave_focus(struct dialog *dia)
290 struct dialog_section *section = dia->current_section;
292 if (section->ops->on_leave_focus) {
293 section->ops->on_leave_focus(dia, section);
297 static void section_set_next_focus(struct dialog *dia)
299 section_on_leave_focus(dia);
302 dia->current_section = dia->current_section->next;
303 } while (!section_on_focus(dia, true));
306 static void section_set_previous_focus(struct dialog *dia)
308 section_on_leave_focus(dia);
311 dia->current_section = dia->current_section->prev;
312 } while (!section_on_focus(dia, false));
315 WERROR dialog_create(struct dialog *dia)
320 struct dialog_section *section;
324 SMB_ASSERT(dia->head_section != NULL);
326 /* calculate total size based on sections */
327 section = dia->head_section;
329 nlines += section->nlines;
330 ncols = MAX(ncols, section->ncols);
331 section = section->next;
332 } while (section != dia->head_section);
334 /* fill in widths for sections that expand */
335 section = dia->head_section;
337 if (section->ncols < 0) {
338 section->ncols = ncols;
340 section = section->next;
341 } while (section != dia->head_section);
343 /* create window for dialog */
346 dia->pad = newpad(nlines, ncols);
347 if (dia->pad == NULL) {
348 rv = WERR_NOT_ENOUGH_MEMORY;
351 dia->centered = false;
352 if (dia->y < 0 || dia->x < 0) {
353 dia->centered = true;
354 center_above_window(&nlines, &ncols, &dia->y, &dia->x);
356 dia->window = newwin(nlines, ncols, dia->y, dia->x);
357 if (dia->window == NULL) {
358 rv = WERR_NOT_ENOUGH_MEMORY;
361 dia->panel = new_panel(dia->window);
362 if (dia->panel == NULL) {
363 rv = WERR_NOT_ENOUGH_MEMORY;
367 /* setup color and border */
368 getmaxyx(dia->pad, nlines, ncols);
369 wbkgdset(dia->pad, ' ' | COLOR_PAIR(dia->color));
371 mvwhline(dia->pad, 1, 2, 0, ncols - 4);
372 mvwhline(dia->pad, nlines - 2, 2, 0, ncols - 4);
373 mvwvline(dia->pad, 2, 1, 0, nlines - 4);
374 mvwvline(dia->pad, 2, ncols - 2, 0, nlines - 4);
375 mvwaddch(dia->pad, 1, 1, ACS_ULCORNER);
376 mvwaddch(dia->pad, 1, ncols - 2, ACS_URCORNER);
377 mvwaddch(dia->pad, nlines - 2, 1, ACS_LLCORNER);
378 mvwaddch(dia->pad, nlines - 2, ncols - 2, ACS_LRCORNER);
379 col = ncols / 2 - MIN(strlen(dia->title) + 2, ncols) / 2;
380 mvwprintw(dia->pad, 1, col, " %s ", dia->title);
382 /* create subwindows for each section */
384 section = dia->head_section;
388 switch (section->justify) {
389 case SECTION_JUSTIFY_LEFT:
391 case SECTION_JUSTIFY_CENTER:
392 col += (ncols - 6)/ 2 - section->ncols / 2;
394 case SECTION_JUSTIFY_RIGHT:
398 section->window = subpad(dia->pad, section->nlines,
399 section->ncols, row, col);
400 if (section->window == NULL) {
401 rv = WERR_NOT_ENOUGH_MEMORY;
404 SMB_ASSERT(section->ops->create != NULL);
405 rv = section->ops->create(dia, section);
406 row += section->nlines;
407 section = section->next;
408 } while (section != dia->head_section && W_ERROR_IS_OK(rv));
410 dia->current_section = dia->head_section;
411 section_set_next_focus(dia);
417 void dialog_show(struct dialog *dia)
425 getmaxyx(dia->window, nlines, ncols);
426 getmaxyx(dia->pad, pad_y, pad_x);
428 if (pad_y > nlines) {
429 y = (pad_y - nlines) / 2;
433 x = (pad_x - ncols) / 2;
435 rv = copywin(dia->pad, dia->window, y, x, 0, 0,
436 nlines - 1, ncols - 1, false);
437 SMB_ASSERT(rv == OK);
439 getyx(dia->pad, pad_y, pad_x);
440 wmove(dia->window, pad_y - y, pad_x - x);
441 touchwin(dia->window);
442 wnoutrefresh(dia->window);
445 void dialog_destroy(struct dialog *dia)
447 struct dialog_section *section;
449 section = dia->head_section;
451 dialog_section_destroy(section);
452 section = section->next;
453 } while (section != dia->head_section);
456 del_panel(dia->panel);
465 static int dialog_getch(struct dialog *dia)
470 if (c == KEY_RESIZE) {
471 int nlines, ncols, y, x;
472 int pad_nlines, pad_ncols;
473 int win_nlines, win_ncols;
475 getmaxyx(dia->window, win_nlines, win_ncols);
476 getmaxyx(dia->pad, pad_nlines, pad_ncols);
477 getbegyx(dia->window, y, x);
483 center_above_window(&nlines, &ncols, &y, &x);
485 if (nlines + y > LINES) {
486 if (nlines > LINES) {
492 if (ncols + x > COLS) {
500 if (nlines != win_nlines || ncols != win_ncols) {
501 wresize(dia->window, nlines, ncols);
502 replace_panel(dia->panel, dia->window);
504 move_panel(dia->panel, y, x);
510 bool dialog_handle_input(struct dialog *dia, WERROR *err,
511 enum dialog_action *action)
517 c = dialog_getch(dia);
521 if (!section_on_tab(dia)) {
522 section_set_next_focus(dia);
526 if (!section_on_btab(dia)) {
527 section_set_previous_focus(dia);
531 if (!section_on_up(dia)) {
532 section_set_previous_focus(dia);
536 if (!section_on_down(dia)) {
537 section_set_next_focus(dia);
541 if (!section_on_left(dia)) {
542 section_set_previous_focus(dia);
546 if (!section_on_right(dia)) {
547 section_set_next_focus(dia);
552 *action = section_on_enter(dia);
559 return !dia->submit(dia, dia->current_section,
566 section_on_input(dia, c);
573 void dialog_modal_loop(struct dialog *dia, WERROR *err,
574 enum dialog_action *action)
580 } while (dialog_handle_input(dia, err, action));
584 struct dialog_section_label {
585 struct dialog_section section;
589 static WERROR label_create(struct dialog *dia, struct dialog_section *section)
592 struct dialog_section_label *label =
593 talloc_get_type_abort(section, struct dialog_section_label);
595 for (row = 0; row < section->nlines; ++row) {
596 mvwaddstr(section->window, row, 0, label->text[row]);
602 struct dialog_section_ops label_ops = {
603 .create = label_create,
606 static int label_free(struct dialog_section_label *label)
608 dialog_section_destroy(&label->section);
612 struct dialog_section *dialog_section_label_new_va(TALLOC_CTX *ctx,
613 const char *msg, va_list ap)
615 struct dialog_section_label *label;
616 char *tmp, *ptmp, *line, *saveptr;
619 label = talloc_zero(ctx, struct dialog_section_label);
623 talloc_set_destructor(label, label_free);
624 tmp = talloc_vasprintf(label, msg, ap);
629 for (nlines = 0, ncols = 0, ptmp = tmp;
630 (line = strtok_r(ptmp, "\n", &saveptr)) != NULL;
633 label->text = talloc_realloc(label, label->text,
635 if (label->text == NULL) {
638 ncols = MAX(ncols, strlen(line));
639 label->text[nlines] = talloc_strdup(label->text, line);
640 if (label->text[nlines] == NULL) {
645 dialog_section_init(&label->section, &label_ops, nlines, ncols);
647 return &label->section;
654 struct dialog_section *dialog_section_label_new(TALLOC_CTX *ctx,
655 const char *msg, ...)
658 struct dialog_section *rv;
661 rv = dialog_section_label_new_va(ctx, msg, ap);
667 /* horizontal separator */
668 struct dialog_section_hsep {
669 struct dialog_section section;
673 static WERROR hsep_create(struct dialog *dia, struct dialog_section *section)
676 struct dialog_section_hsep *hsep =
677 talloc_get_type_abort(section, struct dialog_section_hsep);
679 whline(section->window, hsep->sep, section->ncols);
681 if (hsep->sep == 0 || hsep->sep == ACS_HLINE) {
682 /* change the border characters around this section to
684 getparyx(section->window, y, x);
685 mvwaddch(dia->pad, y, x - 1, ACS_HLINE);
686 mvwaddch(dia->pad, y, x - 2, ACS_LTEE);
687 mvwaddch(dia->pad, y, x + section->ncols, ACS_HLINE);
688 mvwaddch(dia->pad, y, x + section->ncols + 1, ACS_RTEE);
694 struct dialog_section_ops hsep_ops = {
695 .create = hsep_create
698 static int hsep_free(struct dialog_section_hsep *hsep)
700 dialog_section_destroy(&hsep->section);
704 struct dialog_section *dialog_section_hsep_new(TALLOC_CTX *ctx, int sep)
706 struct dialog_section_hsep *hsep;
708 hsep = talloc_zero(ctx, struct dialog_section_hsep);
710 talloc_set_destructor(hsep, hsep_free);
711 dialog_section_init(&hsep->section, &hsep_ops, 1, -1);
715 return &hsep->section;
718 /* text input field */
719 struct dialog_section_text_field {
720 struct dialog_section section;
727 static int get_cursor_col(struct dialog_section_text_field *field)
731 col = field->form->curcol + field->form->begincol;
736 static WERROR text_field_create(struct dialog *dia,
737 struct dialog_section *section)
739 struct dialog_section_text_field *text_field =
740 talloc_get_type_abort(section, struct dialog_section_text_field);
742 text_field->field[0] = new_field(section->nlines, section->ncols,
744 if (text_field->field[0] == NULL) {
745 return WERR_NOT_ENOUGH_MEMORY;
747 set_field_back(text_field->field[0], A_REVERSE);
748 set_field_opts(text_field->field[0], text_field->opts);
750 text_field->form = new_form(text_field->field);
751 if (text_field->form == NULL) {
752 return WERR_NOT_ENOUGH_MEMORY;
755 set_form_win(text_field->form, dia->window);
756 set_form_sub(text_field->form, section->window);
757 set_current_field(text_field->form, text_field->field[0]);
758 post_form(text_field->form);
763 static void text_field_destroy(struct dialog_section *section)
765 struct dialog_section_text_field *text_field =
766 talloc_get_type_abort(section, struct dialog_section_text_field);
768 if (text_field->form) {
769 unpost_form(text_field->form);
770 free_form(text_field->form);
771 text_field->form = NULL;
773 if (text_field->field[0]) {
774 free_field(text_field->field[0]);
775 text_field->field[0] = NULL;
779 static void text_field_on_input(struct dialog *dia,
780 struct dialog_section *section,
783 struct dialog_section_text_field *text_field =
784 talloc_get_type_abort(section, struct dialog_section_text_field);
788 if (text_field->length) {
789 text_field->length--;
791 form_driver(text_field->form, REQ_DEL_PREV);
795 if (text_field->length) {
796 text_field->length--;
798 form_driver(text_field->form, REQ_DEL_CHAR);
801 text_field->length++;
802 form_driver(text_field->form, c);
807 static bool text_field_on_up(struct dialog *dia,
808 struct dialog_section *section)
810 struct dialog_section_text_field *text_field =
811 talloc_get_type_abort(section, struct dialog_section_text_field);
813 if (section->nlines > 1) {
814 form_driver(text_field->form, REQ_UP_CHAR);
820 static bool text_field_on_down(struct dialog *dia,
821 struct dialog_section *section)
823 struct dialog_section_text_field *text_field =
824 talloc_get_type_abort(section, struct dialog_section_text_field);
826 if (section->nlines > 1) {
827 form_driver(text_field->form, REQ_DOWN_CHAR);
833 static bool text_field_on_left(struct dialog *dia,
834 struct dialog_section *section)
836 struct dialog_section_text_field *text_field =
837 talloc_get_type_abort(section, struct dialog_section_text_field);
839 form_driver(text_field->form, REQ_LEFT_CHAR);
844 static bool text_field_on_right(struct dialog *dia,
845 struct dialog_section *section)
847 struct dialog_section_text_field *text_field =
848 talloc_get_type_abort(section, struct dialog_section_text_field);
850 if (section->nlines > 1 ||
851 get_cursor_col(text_field) < text_field->length) {
852 form_driver(text_field->form, REQ_RIGHT_CHAR);
858 static enum dialog_action text_field_on_enter(struct dialog *dia,
859 struct dialog_section *section)
861 struct dialog_section_text_field *text_field =
862 talloc_get_type_abort(section, struct dialog_section_text_field);
864 if (section->nlines > 1) {
865 text_field->length += text_field->form->cols;
866 form_driver(text_field->form, REQ_NEW_LINE);
867 return DIALOG_IGNORE;
873 static bool text_field_on_focus(struct dialog *dia,
874 struct dialog_section *section, bool forward)
876 struct dialog_section_text_field *text_field =
877 talloc_get_type_abort(section, struct dialog_section_text_field);
879 pos_form_cursor(text_field->form);
884 struct dialog_section_ops text_field_ops = {
885 .create = text_field_create,
886 .destroy = text_field_destroy,
887 .on_input = text_field_on_input,
888 .on_up = text_field_on_up,
889 .on_down = text_field_on_down,
890 .on_left = text_field_on_left,
891 .on_right = text_field_on_right,
892 .on_enter = text_field_on_enter,
893 .on_focus = text_field_on_focus
896 static int text_field_free(struct dialog_section_text_field *text_field)
898 dialog_section_destroy(&text_field->section);
902 struct dialog_section *dialog_section_text_field_new(TALLOC_CTX *ctx,
903 int height, int width)
905 struct dialog_section_text_field *text_field;
907 text_field = talloc_zero(ctx, struct dialog_section_text_field);
908 if (text_field == NULL) {
911 talloc_set_destructor(text_field, text_field_free);
912 dialog_section_init(&text_field->section, &text_field_ops,
914 text_field->opts = O_ACTIVE | O_PUBLIC | O_EDIT | O_VISIBLE | O_NULLOK;
916 return &text_field->section;
919 const char *dialog_section_text_field_get(TALLOC_CTX *ctx,
920 struct dialog_section *section)
922 struct dialog_section_text_field *text_field =
923 talloc_get_type_abort(section, struct dialog_section_text_field);
925 form_driver(text_field->form, REQ_VALIDATION);
927 return string_trim(ctx, field_buffer(text_field->field[0], 0));
930 void dialog_section_text_field_set(struct dialog_section *section,
933 struct dialog_section_text_field *text_field =
934 talloc_get_type_abort(section, struct dialog_section_text_field);
936 text_field->length = strlen(s);
937 set_field_buffer(text_field->field[0], 0, s);
940 const char **dialog_section_text_field_get_lines(TALLOC_CTX *ctx,
941 struct dialog_section *section)
947 struct dialog_section_text_field *text_field =
948 talloc_get_type_abort(section, struct dialog_section_text_field);
950 form_driver(text_field->form, REQ_VALIDATION);
951 buf = field_buffer(text_field->field[0], 0);
953 dynamic_field_info(text_field->field[0], &rows, &cols, &max);
955 arr = talloc_zero_array(ctx, const char *, rows + 1);
959 for (i = 0; *buf; ++i, buf += cols) {
960 SMB_ASSERT(i < rows);
961 arr[i] = string_trim_n(arr, buf, cols);
967 WERROR dialog_section_text_field_set_lines(TALLOC_CTX *ctx,
968 struct dialog_section *section,
972 size_t padding, length, idx;
975 struct dialog_section_text_field *text_field =
976 talloc_get_type_abort(section, struct dialog_section_text_field);
978 dynamic_field_info(text_field->field[0], &rows, &cols, &max);
979 /* try to fit each string on it's own line. each line
980 needs to be padded with whitespace manually, since
981 ncurses fields do not have newlines. */
982 for (idx = 0, arrayp = array; *arrayp != NULL; ++arrayp) {
983 length = MIN(strlen(*arrayp), cols);
984 padding = cols - length;
985 buf = talloc_realloc(ctx, buf, char,
986 talloc_array_length(buf) +
987 length + padding + 1);
989 return WERR_NOT_ENOUGH_MEMORY;
991 memcpy(&buf[idx], *arrayp, length);
993 memset(&buf[idx], ' ', padding);
998 set_field_buffer(text_field->field[0], 0, buf);
1004 bool dialog_section_text_field_get_int(struct dialog_section *section,
1010 struct dialog_section_text_field *text_field =
1011 talloc_get_type_abort(section, struct dialog_section_text_field);
1013 form_driver(text_field->form, REQ_VALIDATION);
1015 buf = string_trim(section, field_buffer(text_field->field[0], 0));
1019 *out = strtoll(buf, &endp, 0);
1021 if (endp == buf || endp == NULL || endp[0] != '\0') {
1029 bool dialog_section_text_field_get_uint(struct dialog_section *section,
1030 unsigned long long *out)
1035 struct dialog_section_text_field *text_field =
1036 talloc_get_type_abort(section, struct dialog_section_text_field);
1038 form_driver(text_field->form, REQ_VALIDATION);
1040 buf = string_trim(section, field_buffer(text_field->field[0], 0));
1044 *out = strtoull(buf, &endp, 0);
1046 if (endp == buf || endp == NULL || endp[0] != '\0') {
1053 /* hex editor field */
1054 struct dialog_section_hexedit {
1055 struct dialog_section section;
1056 struct hexedit *buf;
1059 #define HEXEDIT_MIN_SIZE 1
1060 static WERROR hexedit_create(struct dialog *dia,
1061 struct dialog_section *section)
1063 struct dialog_section_hexedit *hexedit =
1064 talloc_get_type_abort(section, struct dialog_section_hexedit);
1066 hexedit->buf = hexedit_new(dia, section->window, NULL,
1068 if (hexedit->buf == NULL) {
1069 return WERR_NOT_ENOUGH_MEMORY;
1072 hexedit_refresh(hexedit->buf);
1077 static void hexedit_destroy(struct dialog_section *section)
1079 struct dialog_section_hexedit *hexedit =
1080 talloc_get_type_abort(section, struct dialog_section_hexedit);
1083 TALLOC_FREE(hexedit->buf);
1087 static void hexedit_on_input(struct dialog *dia,
1088 struct dialog_section *section,
1091 struct dialog_section_hexedit *hexedit =
1092 talloc_get_type_abort(section, struct dialog_section_hexedit);
1096 hexedit_driver(hexedit->buf, HE_BACKSPACE);
1100 hexedit_driver(hexedit->buf, HE_DELETE);
1103 hexedit_driver(hexedit->buf, c);
1108 static bool hexedit_on_up(struct dialog *dia,
1109 struct dialog_section *section)
1111 struct dialog_section_hexedit *hexedit =
1112 talloc_get_type_abort(section, struct dialog_section_hexedit);
1114 hexedit_driver(hexedit->buf, HE_CURSOR_UP);
1119 static bool hexedit_on_down(struct dialog *dia,
1120 struct dialog_section *section)
1122 struct dialog_section_hexedit *hexedit =
1123 talloc_get_type_abort(section, struct dialog_section_hexedit);
1125 hexedit_driver(hexedit->buf, HE_CURSOR_DOWN);
1130 static bool hexedit_on_left(struct dialog *dia,
1131 struct dialog_section *section)
1133 struct dialog_section_hexedit *hexedit =
1134 talloc_get_type_abort(section, struct dialog_section_hexedit);
1136 hexedit_driver(hexedit->buf, HE_CURSOR_LEFT);
1141 static bool hexedit_on_right(struct dialog *dia,
1142 struct dialog_section *section)
1144 struct dialog_section_hexedit *hexedit =
1145 talloc_get_type_abort(section, struct dialog_section_hexedit);
1147 hexedit_driver(hexedit->buf, HE_CURSOR_RIGHT);
1152 static enum dialog_action hexedit_on_enter(struct dialog *dia,
1153 struct dialog_section *section)
1155 return DIALOG_IGNORE;
1158 static bool hexedit_on_focus(struct dialog *dia,
1159 struct dialog_section *section, bool forward)
1161 struct dialog_section_hexedit *hexedit =
1162 talloc_get_type_abort(section, struct dialog_section_hexedit);
1164 hexedit_set_cursor(hexedit->buf);
1169 struct dialog_section_ops hexedit_ops = {
1170 .create = hexedit_create,
1171 .destroy = hexedit_destroy,
1172 .on_input = hexedit_on_input,
1173 .on_up = hexedit_on_up,
1174 .on_down = hexedit_on_down,
1175 .on_left = hexedit_on_left,
1176 .on_right = hexedit_on_right,
1177 .on_enter = hexedit_on_enter,
1178 .on_focus = hexedit_on_focus
1181 static int hexedit_free(struct dialog_section_hexedit *hexedit)
1183 dialog_section_destroy(&hexedit->section);
1187 struct dialog_section *dialog_section_hexedit_new(TALLOC_CTX *ctx, int height)
1189 struct dialog_section_hexedit *hexedit;
1191 hexedit = talloc_zero(ctx, struct dialog_section_hexedit);
1192 if (hexedit == NULL) {
1195 talloc_set_destructor(hexedit, hexedit_free);
1196 dialog_section_init(&hexedit->section, &hexedit_ops,
1197 height, LINE_WIDTH);
1199 return &hexedit->section;
1202 WERROR dialog_section_hexedit_set_buf(struct dialog_section *section,
1203 const void *data, size_t size)
1206 struct dialog_section_hexedit *hexedit =
1207 talloc_get_type_abort(section, struct dialog_section_hexedit);
1209 SMB_ASSERT(hexedit->buf != NULL);
1211 rv = hexedit_set_buf(hexedit->buf, data, size);
1212 if (W_ERROR_IS_OK(rv)) {
1213 hexedit_refresh(hexedit->buf);
1214 hexedit_set_cursor(hexedit->buf);
1220 void dialog_section_hexedit_get_buf(struct dialog_section *section,
1221 const void **data, size_t *size)
1223 struct dialog_section_hexedit *hexedit =
1224 talloc_get_type_abort(section, struct dialog_section_hexedit);
1226 SMB_ASSERT(hexedit->buf != NULL);
1227 *data = hexedit_get_buf(hexedit->buf);
1228 *size = hexedit_get_buf_len(hexedit->buf);
1231 WERROR dialog_section_hexedit_resize(struct dialog_section *section,
1235 struct dialog_section_hexedit *hexedit =
1236 talloc_get_type_abort(section, struct dialog_section_hexedit);
1238 SMB_ASSERT(hexedit->buf != NULL);
1239 rv = hexedit_resize_buffer(hexedit->buf, size);
1240 if (W_ERROR_IS_OK(rv)) {
1241 hexedit_refresh(hexedit->buf);
1249 struct dialog_section_buttons {
1250 struct dialog_section section;
1251 struct button_spec *spec;
1255 static void buttons_unhighlight(struct dialog_section_buttons *buttons)
1261 * Some GCC versions will complain if the macro version of
1262 * wattr_get is used. So we should enforce the use of the
1263 * function instead. See:
1264 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1266 (wattr_get)(buttons->section.window, &attr, &pair, NULL);
1267 mvwchgat(buttons->section.window, 0, 0, -1, A_NORMAL, pair, NULL);
1268 wnoutrefresh(buttons->section.window);
1271 static void buttons_highlight(struct dialog_section_buttons *buttons)
1273 struct button_spec *spec = &buttons->spec[buttons->current_button];
1278 * Some GCC versions will complain if the macro version of
1279 * wattr_get is used. So we should enforce the use of the
1280 * function instead. See:
1281 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1283 (wattr_get)(buttons->section.window, &attr, &pair, NULL);
1284 mvwchgat(buttons->section.window, 0, 0, -1, A_NORMAL, pair, NULL);
1285 mvwchgat(buttons->section.window, 0, spec->col,
1286 strlen(spec->label), A_REVERSE, pair, NULL);
1287 wmove(buttons->section.window, 0, spec->col + 2);
1288 wcursyncup(buttons->section.window);
1289 wnoutrefresh(buttons->section.window);
1292 static bool buttons_highlight_next(struct dialog_section_buttons *buttons)
1294 if (buttons->current_button < talloc_array_length(buttons->spec) - 1) {
1295 buttons->current_button++;
1296 buttons_highlight(buttons);
1302 static bool buttons_highlight_previous(struct dialog_section_buttons *buttons)
1304 if (buttons->current_button > 0) {
1305 buttons->current_button--;
1306 buttons_highlight(buttons);
1312 static WERROR buttons_create(struct dialog *dia,
1313 struct dialog_section *section)
1316 struct dialog_section_buttons *buttons =
1317 talloc_get_type_abort(section, struct dialog_section_buttons);
1319 nbuttons = talloc_array_length(buttons->spec);
1320 for (i = 0; i < nbuttons; ++i) {
1321 struct button_spec *spec = &buttons->spec[i];
1322 mvwaddstr(section->window, 0, spec->col, spec->label);
1325 buttons->current_button = 0;
1330 static bool buttons_on_btab(struct dialog *dia, struct dialog_section *section)
1332 struct dialog_section_buttons *buttons =
1333 talloc_get_type_abort(section, struct dialog_section_buttons);
1335 return buttons_highlight_previous(buttons);
1338 static bool buttons_on_tab(struct dialog *dia, struct dialog_section *section)
1340 struct dialog_section_buttons *buttons =
1341 talloc_get_type_abort(section, struct dialog_section_buttons);
1343 return buttons_highlight_next(buttons);
1346 static enum dialog_action buttons_on_enter(struct dialog *dia,
1347 struct dialog_section *section)
1349 struct dialog_section_buttons *buttons =
1350 talloc_get_type_abort(section, struct dialog_section_buttons);
1351 struct button_spec *spec = &buttons->spec[buttons->current_button];
1353 if (spec->on_enter) {
1354 return spec->on_enter(dia, section);
1357 return spec->action;
1360 static bool buttons_on_focus(struct dialog *dia,
1361 struct dialog_section *section,
1364 struct dialog_section_buttons *buttons =
1365 talloc_get_type_abort(section, struct dialog_section_buttons);
1368 buttons->current_button = 0;
1370 buttons->current_button = talloc_array_length(buttons->spec) - 1;
1372 buttons_highlight(buttons);
1377 static void buttons_on_leave_focus(struct dialog *dia,
1378 struct dialog_section *section)
1380 struct dialog_section_buttons *buttons =
1381 talloc_get_type_abort(section, struct dialog_section_buttons);
1382 buttons_unhighlight(buttons);
1385 struct dialog_section_ops buttons_ops = {
1386 .create = buttons_create,
1387 .on_tab = buttons_on_tab,
1388 .on_btab = buttons_on_btab,
1389 .on_up = buttons_on_btab,
1390 .on_down = buttons_on_tab,
1391 .on_left = buttons_on_btab,
1392 .on_right = buttons_on_tab,
1393 .on_enter = buttons_on_enter,
1394 .on_focus = buttons_on_focus,
1395 .on_leave_focus = buttons_on_leave_focus
1398 static int buttons_free(struct dialog_section_buttons *buttons)
1400 dialog_section_destroy(&buttons->section);
1404 struct dialog_section *dialog_section_buttons_new(TALLOC_CTX *ctx,
1405 const struct button_spec *spec)
1407 struct dialog_section_buttons *buttons;
1411 buttons = talloc_zero(ctx, struct dialog_section_buttons);
1412 if (buttons == NULL) {
1415 talloc_set_destructor(buttons, buttons_free);
1417 for (nbuttons = 0; spec[nbuttons].label; ++nbuttons) {
1419 buttons->spec = talloc_zero_array(buttons, struct button_spec, nbuttons);
1420 if (buttons->spec == NULL) {
1424 for (width = 0, i = 0; i < nbuttons; ++i) {
1425 buttons->spec[i] = spec[i];
1426 buttons->spec[i].label = talloc_asprintf(buttons->spec,
1429 if (!buttons->spec[i].label) {
1433 buttons->spec[i].col = width;
1434 width += strlen(buttons->spec[i].label);
1435 if (i != nbuttons - 1) {
1440 dialog_section_init(&buttons->section, &buttons_ops, 1, width);
1442 return &buttons->section;
1445 talloc_free(buttons);
1450 struct dialog_section_options {
1451 struct dialog_section section;
1452 struct option_spec *spec;
1457 static void options_unhighlight(struct dialog_section_options *options)
1464 * Some GCC versions will complain if the macro version of
1465 * wattr_get is used. So we should enforce the use of the
1466 * function instead. See:
1467 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1469 (wattr_get)(options->section.window, &attr, &pair, NULL);
1470 for (row = 0; row < options->section.nlines; ++row) {
1471 mvwchgat(options->section.window, row, 0, -1, A_NORMAL, pair, NULL);
1473 wnoutrefresh(options->section.window);
1476 static void options_highlight(struct dialog_section_options *options)
1478 struct option_spec *spec = &options->spec[options->current_option];
1484 * Some GCC versions will complain if the macro version of
1485 * wattr_get is used. So we should enforce the use of the
1486 * function instead. See:
1487 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1489 (wattr_get)(options->section.window, &attr, &pair, NULL);
1490 for (row = 0; row < options->section.nlines; ++row) {
1491 mvwchgat(options->section.window, row, 0, -1, A_NORMAL, pair, NULL);
1493 mvwchgat(options->section.window, spec->row, spec->col,
1494 strlen(spec->label), A_REVERSE, pair, NULL);
1495 wmove(options->section.window, spec->row, spec->col + 4);
1496 wcursyncup(options->section.window);
1497 wnoutrefresh(options->section.window);
1500 static void options_render_state(struct dialog_section_options *options)
1504 noptions = talloc_array_length(options->spec);
1505 for (i = 0; i < noptions; ++i) {
1506 struct option_spec *spec = &options->spec[i];
1510 mvwaddch(options->section.window,
1511 spec->row, spec->col + 1, c);
1512 wnoutrefresh(options->section.window);
1516 static bool options_highlight_next(struct dialog_section_options *options)
1518 if (options->current_option < talloc_array_length(options->spec) - 1) {
1519 options->current_option++;
1520 options_highlight(options);
1526 static bool options_highlight_previous(struct dialog_section_options *options)
1528 if (options->current_option > 0) {
1529 options->current_option--;
1530 options_highlight(options);
1536 static WERROR options_create(struct dialog *dia,
1537 struct dialog_section *section)
1540 struct dialog_section_options *options =
1541 talloc_get_type_abort(section, struct dialog_section_options);
1543 noptions = talloc_array_length(options->spec);
1544 for (i = 0; i < noptions; ++i) {
1545 struct option_spec *spec = &options->spec[i];
1546 mvwaddstr(section->window, spec->row, spec->col,
1550 options->current_option = 0;
1551 options_render_state(options);
1556 static bool options_on_btab(struct dialog *dia, struct dialog_section *section)
1558 struct dialog_section_options *options =
1559 talloc_get_type_abort(section, struct dialog_section_options);
1561 return options_highlight_previous(options);
1564 static bool options_on_tab(struct dialog *dia, struct dialog_section *section)
1566 struct dialog_section_options *options =
1567 talloc_get_type_abort(section, struct dialog_section_options);
1569 return options_highlight_next(options);
1572 static void options_on_input(struct dialog *dia, struct dialog_section *section, int c)
1574 struct dialog_section_options *options =
1575 talloc_get_type_abort(section, struct dialog_section_options);
1578 struct option_spec *spec = &options->spec[options->current_option];
1579 if (options->single_select) {
1581 noptions = talloc_array_length(options->spec);
1582 for (i = 0; i < noptions; ++i) {
1583 *(options->spec[i].state) = false;
1586 *spec->state = !*spec->state;
1587 options_unhighlight(options);
1588 options_render_state(options);
1589 options_highlight(options);
1593 static enum dialog_action options_on_enter(struct dialog *dia, struct dialog_section *section)
1595 options_on_input(dia, section, ' ');
1599 static bool options_on_focus(struct dialog *dia,
1600 struct dialog_section *section,
1603 struct dialog_section_options *options =
1604 talloc_get_type_abort(section, struct dialog_section_options);
1607 options->current_option = 0;
1609 options->current_option = talloc_array_length(options->spec) - 1;
1611 options_highlight(options);
1616 static void options_on_leave_focus(struct dialog *dia,
1617 struct dialog_section *section)
1619 struct dialog_section_options *options =
1620 talloc_get_type_abort(section, struct dialog_section_options);
1621 options_unhighlight(options);
1624 struct dialog_section_ops options_ops = {
1625 .create = options_create,
1626 .on_tab = options_on_tab,
1627 .on_btab = options_on_btab,
1628 .on_up = options_on_btab,
1629 .on_down = options_on_tab,
1630 .on_left = options_on_btab,
1631 .on_right = options_on_tab,
1632 .on_input = options_on_input,
1633 .on_enter = options_on_enter,
1634 .on_focus = options_on_focus,
1635 .on_leave_focus = options_on_leave_focus
1638 static int options_free(struct dialog_section_options *options)
1640 dialog_section_destroy(&options->section);
1644 struct dialog_section *dialog_section_options_new(TALLOC_CTX *ctx,
1645 const struct option_spec *spec,
1646 int maxcol, bool single_select)
1648 struct dialog_section_options *options;
1650 int width, maxwidth, maxrows;
1652 options = talloc_zero(ctx, struct dialog_section_options);
1653 if (options == NULL) {
1656 talloc_set_destructor(options, options_free);
1658 for (noptions = 0; spec[noptions].label; ++noptions) {
1660 options->spec = talloc_zero_array(options, struct option_spec, noptions);
1661 if (options->spec == NULL) {
1665 maxrows = noptions / maxcol;
1666 if (noptions % maxcol) {
1670 for (width = 0, maxwidth = 0, i = 0; i < noptions; ++i) {
1671 options->spec[i] = spec[i];
1672 options->spec[i].label = talloc_asprintf(options->spec,
1675 if (!options->spec[i].label) {
1679 options->spec[i].col = maxwidth;
1680 options->spec[i].row = i % maxrows;
1681 width = MAX(strlen(options->spec[i].label), width);
1682 if (options->spec[i].row == maxrows - 1 || i == noptions - 1) {
1683 maxwidth += width + 1;
1688 dialog_section_init(&options->section, &options_ops, maxrows, maxwidth - 1);
1689 options->single_select = single_select;
1691 return &options->section;
1694 talloc_free(options);
1707 enum input_type type;
1710 unsigned long *out_ulong;
1712 const char **out_str;
1716 static bool input_on_submit(struct dialog *dia, struct dialog_section *section,
1719 struct input_req *req = arg;
1720 struct dialog_section *data;
1721 unsigned long long out_ulong;
1724 data = dialog_find_section(dia, "input");
1726 switch (req->type) {
1728 if (!dialog_section_text_field_get_int(data, &out_long)) {
1729 dialog_notice(dia, DIA_ALERT, "Error",
1730 "Input must be a number.");
1733 if (out_long < LONG_MIN || out_long > LONG_MAX) {
1734 dialog_notice(dia, DIA_ALERT, "Error",
1735 "Number is out of range.");
1738 *req->out.out_long = out_long;
1741 if (!dialog_section_text_field_get_uint(data, &out_ulong)) {
1742 dialog_notice(dia, DIA_ALERT, "Error",
1743 "Input must be a number greater than zero.");
1746 if (out_ulong > ULONG_MAX) {
1747 dialog_notice(dia, DIA_ALERT, "Error",
1748 "Number is out of range.");
1751 *req->out.out_ulong = out_ulong;
1754 *req->out.out_str = dialog_section_text_field_get(req->ctx, data);
1761 static int dialog_input_internal(TALLOC_CTX *ctx, void *output,
1762 enum input_type type,
1764 const char *msg, va_list ap)
1765 PRINTF_ATTRIBUTE(5,0);
1767 static int dialog_input_internal(TALLOC_CTX *ctx, void *output,
1768 enum input_type type,
1770 const char *msg, va_list ap)
1773 struct input_req req;
1774 enum dialog_action action;
1776 struct dialog_section *section;
1777 struct button_spec spec[] = {
1778 {.label = "OK", .action = DIALOG_OK},
1779 {.label = "Cancel", .action = DIALOG_CANCEL},
1785 req.out.out = output;
1786 *req.out.out_str = NULL;
1788 dia = dialog_new(ctx, PAIR_BLACK_CYAN, title, -1, -1);
1789 dialog_set_submit_cb(dia, input_on_submit, &req);
1790 section = dialog_section_label_new_va(dia, msg, ap);
1791 dialog_append_section(dia, section);
1792 section = dialog_section_hsep_new(dia, ' ');
1793 dialog_append_section(dia, section);
1794 section = dialog_section_text_field_new(dia, 1, -1);
1795 dialog_section_set_name(section, "input");
1796 dialog_append_section(dia, section);
1797 section = dialog_section_hsep_new(dia, 0);
1798 dialog_append_section(dia, section);
1799 section = dialog_section_buttons_new(dia, spec);
1800 dialog_section_set_justify(section, SECTION_JUSTIFY_CENTER);
1801 dialog_append_section(dia, section);
1805 dialog_modal_loop(dia, &err, &action);
1811 int dialog_input(TALLOC_CTX *ctx, const char **output, const char *title,
1812 const char *msg, ...)
1818 rv = dialog_input_internal(ctx, output, DLG_IN_STR, title, msg, ap);
1824 int dialog_input_ulong(TALLOC_CTX *ctx, unsigned long *output,
1825 const char *title, const char *msg, ...)
1831 rv = dialog_input_internal(ctx, output, DLG_IN_ULONG, title, msg, ap);
1837 int dialog_input_long(TALLOC_CTX *ctx, long *output,
1838 const char *title, const char *msg, ...)
1844 rv = dialog_input_internal(ctx, output, DLG_IN_LONG, title, msg, ap);
1850 int dialog_notice(TALLOC_CTX *ctx, enum dialog_type type,
1851 const char *title, const char *msg, ...)
1855 enum dialog_action action;
1857 struct dialog_section *section;
1858 struct button_spec spec[3];
1860 memset(&spec, '\0', sizeof(spec));
1861 spec[0].label = "OK";
1862 spec[0].action = DIALOG_OK;
1863 if (type == DIA_CONFIRM) {
1864 spec[1].label = "Cancel";
1865 spec[1].action = DIALOG_CANCEL;
1868 dia = dialog_new(ctx, PAIR_BLACK_CYAN, title, -1, -1);
1870 section = dialog_section_label_new_va(dia, msg, ap);
1872 dialog_append_section(dia, section);
1873 section = dialog_section_hsep_new(dia, 0);
1874 dialog_append_section(dia, section);
1875 section = dialog_section_buttons_new(dia, spec);
1876 dialog_section_set_justify(section, SECTION_JUSTIFY_CENTER);
1877 dialog_append_section(dia, section);
1881 dialog_modal_loop(dia, &err, &action);
1891 struct registry_key *key;
1892 const struct value_item *vitem;
1895 static WERROR fill_value_buffer(struct dialog *dia, struct edit_req *edit)
1898 struct dialog_section *data;
1900 if (edit->vitem == NULL) {
1904 data = dialog_find_section(dia, "data");
1905 SMB_ASSERT(data != NULL);
1907 switch (edit->mode) {
1910 if (edit->vitem->data.length >= 4) {
1911 v = IVAL(edit->vitem->data.data, 0);
1913 tmp = talloc_asprintf(dia, "%u", (unsigned)v);
1915 return WERR_NOT_ENOUGH_MEMORY;
1917 dialog_section_text_field_set(data, tmp);
1922 case REG_EXPAND_SZ: {
1925 if (!pull_reg_sz(dia, &edit->vitem->data, &s)) {
1926 return WERR_NOT_ENOUGH_MEMORY;
1928 dialog_section_text_field_set(data, s);
1931 case REG_MULTI_SZ: {
1934 if (!pull_reg_multi_sz(dia, &edit->vitem->data, &array)) {
1935 return WERR_NOT_ENOUGH_MEMORY;
1937 return dialog_section_text_field_set_lines(dia, data, array);
1941 return dialog_section_hexedit_set_buf(data,
1942 edit->vitem->data.data,
1943 edit->vitem->data.length);
1949 static bool value_exists(TALLOC_CTX *ctx, const struct registry_key *key,
1956 rv = reg_key_get_value_by_name(ctx, key, name, &type, &blob);
1958 return W_ERROR_IS_OK(rv);
1961 static bool edit_on_submit(struct dialog *dia, struct dialog_section *section,
1964 struct edit_req *edit = arg;
1968 struct dialog_section *name_section, *data;
1970 name_section = dialog_find_section(dia, "name");
1972 name = dialog_section_text_field_get(dia, name_section);
1973 if (*name == '\0') {
1974 dialog_notice(dia, DIA_ALERT, "Error",
1975 "Value name must not be blank.");
1978 if (value_exists(dia, edit->key, name)) {
1979 dialog_notice(dia, DIA_ALERT, "Error",
1980 "Value named \"%s\" already exists.",
1985 SMB_ASSERT(edit->vitem);
1986 name = edit->vitem->value_name;
1990 data = dialog_find_section(dia, "data");
1991 SMB_ASSERT(data != NULL);
1994 switch (edit->mode) {
1996 unsigned long long v;
1999 if (!dialog_section_text_field_get_uint(data, &v)) {
2000 dialog_notice(dia, DIA_ALERT, "Error",
2001 "REG_DWORD value must be an integer.");
2004 if (v > UINT32_MAX) {
2005 dialog_notice(dia, DIA_ALERT, "Error",
2006 "REG_DWORD value must less than %lu.",
2007 (unsigned long)UINT32_MAX);
2011 blob = data_blob_talloc(dia, NULL, sizeof(val));
2012 SIVAL(blob.data, 0, val);
2016 case REG_EXPAND_SZ: {
2019 buf = dialog_section_text_field_get(dia, data);
2020 if (!buf || !push_reg_sz(dia, &blob, buf)) {
2021 rv = WERR_NOT_ENOUGH_MEMORY;
2025 case REG_MULTI_SZ: {
2028 lines = dialog_section_text_field_get_lines(dia, data);
2029 if (!lines || !push_reg_multi_sz(dia, &blob, lines)) {
2030 rv = WERR_NOT_ENOUGH_MEMORY;
2038 dialog_section_hexedit_get_buf(data, &buf, &len);
2039 blob = data_blob_talloc(dia, buf, len);
2044 if (W_ERROR_IS_OK(rv)) {
2045 rv = reg_val_set(edit->key, name, edit->type, blob);
2048 if (!W_ERROR_IS_OK(rv)) {
2049 const char *msg = get_friendly_werror_msg(rv);
2050 dialog_notice(dia, DIA_ALERT, "Error",
2051 "Error saving value:\n%s", msg);
2060 static enum dialog_action edit_on_resize(struct dialog *dia,
2061 struct dialog_section *section)
2063 struct dialog_section *data;
2067 data = dialog_find_section(dia, "data");
2068 rv = dialog_input_ulong(dia, &size, "Resize", "Enter size of buffer");
2069 if (rv == DIALOG_OK) {
2070 dialog_section_hexedit_resize(data, size);
2073 return DIALOG_IGNORE;
2076 int dialog_edit_value(TALLOC_CTX *ctx, struct registry_key *key,
2077 uint32_t type, const struct value_item *vitem,
2078 bool force_binary, WERROR *err,
2081 enum dialog_action action;
2083 struct dialog_section *section;
2084 struct edit_req edit;
2085 struct button_spec buttons[] = {
2086 {.label = "OK", .action = DIALOG_OK},
2087 {.label = "Cancel", .action = DIALOG_CANCEL},
2090 struct button_spec buttons_hexedit[] = {
2091 {.label = "OK", .action = DIALOG_OK},
2092 {.label = "Resize Buffer", .on_enter = edit_on_resize},
2093 {.label = "Cancel", .action = DIALOG_CANCEL},
2102 if (force_binary || (vitem && vitem->unprintable)) {
2103 edit.mode = REG_BINARY;
2106 dia = dialog_new(ctx, PAIR_BLACK_CYAN, "Edit Value", -1, -1);
2107 dialog_set_submit_cb(dia, edit_on_submit, &edit);
2109 section = dialog_section_label_new(dia, "Type");
2110 dialog_append_section(dia, section);
2111 section = dialog_section_label_new(dia, "%s",
2113 dialog_append_section(dia, section);
2114 section = dialog_section_hsep_new(dia, ' ');
2115 dialog_append_section(dia, section);
2117 section = dialog_section_label_new(dia, "Name");
2118 dialog_append_section(dia, section);
2120 section = dialog_section_label_new(dia, "%s",
2123 section = dialog_section_text_field_new(dia, 1, 50);
2124 dialog_section_set_name(section, "name");
2126 dialog_append_section(dia, section);
2127 section = dialog_section_hsep_new(dia, ' ');
2128 dialog_append_section(dia, section);
2130 section = dialog_section_label_new(dia, "Data");
2131 dialog_append_section(dia, section);
2133 switch (edit.mode) {
2137 section = dialog_section_text_field_new(dia, 1, 50);
2140 section = dialog_section_text_field_new(dia, 10, 50);
2144 section = dialog_section_hexedit_new(dia, 10);
2148 dialog_section_set_name(section, "data");
2149 dialog_append_section(dia, section);
2151 section = dialog_section_hsep_new(dia, 0);
2152 dialog_append_section(dia, section);
2153 if (edit.mode == REG_BINARY) {
2154 section = dialog_section_buttons_new(dia, buttons_hexedit);
2156 section = dialog_section_buttons_new(dia, buttons);
2158 dialog_section_set_justify(section, SECTION_JUSTIFY_CENTER);
2159 dialog_append_section(dia, section);
2163 *err = fill_value_buffer(dia, &edit);
2164 if (!W_ERROR_IS_OK(*err)) {
2165 return DIALOG_CANCEL;
2169 dialog_modal_loop(dia, err, &action);
2171 if (action == DIALOG_OK && name) {
2173 *name = talloc_strdup(ctx, vitem->value_name);
2174 } else if ((section = dialog_find_section(dia, "name"))) {
2175 *name = dialog_section_text_field_get(ctx, section);
2184 int dialog_select_type(TALLOC_CTX *ctx, int *type)
2187 enum dialog_action action;
2189 struct dialog_section *section;
2190 const char *reg_types[] = {
2197 #define NTYPES ARRAY_SIZE(reg_types)
2198 struct button_spec spec[] = {
2199 {.label = "OK", .action = DIALOG_OK},
2200 {.label = "Cancel", .action = DIALOG_CANCEL},
2203 bool flags[NTYPES] = { true };
2204 struct option_spec opsec[NTYPES + 1];
2207 memset(&opsec, '\0', sizeof(opsec));
2208 for (i = 0; i < NTYPES; ++i) {
2209 opsec[i].label = reg_types[i];
2210 opsec[i].state = &flags[i];
2213 dia = dialog_new(ctx, PAIR_BLACK_CYAN, "New Value", -1, -1);
2215 section = dialog_section_label_new(dia, "Select type for new value:");
2216 dialog_append_section(dia, section);
2217 section = dialog_section_hsep_new(dia, ' ');
2218 dialog_append_section(dia, section);
2219 section = dialog_section_options_new(dia, opsec, 2, true);
2220 dialog_append_section(dia, section);
2221 section = dialog_section_hsep_new(dia, 0);
2222 dialog_append_section(dia, section);
2223 section = dialog_section_buttons_new(dia, spec);
2224 dialog_section_set_justify(section, SECTION_JUSTIFY_CENTER);
2225 dialog_append_section(dia, section);
2230 dialog_modal_loop(dia, &err, &action);
2231 if (action == DIALOG_OK) {
2232 for (i = 0; i < NTYPES; ++i) {
2234 *type = regtype_by_string(reg_types[i]);
2247 struct regedit_search_opts *opts;
2250 static bool search_on_submit(struct dialog *dia, struct dialog_section *section,
2253 struct search_req *search = arg;
2254 struct dialog_section *query;
2256 query = dialog_find_section(dia, "query");
2257 SMB_ASSERT(query != NULL);
2259 if (!search->opts->search_key && !search->opts->search_value) {
2260 dialog_notice(dia, DIA_ALERT, "Error",
2261 "Must search a key and/or a value");
2265 talloc_free(discard_const(search->opts->query));
2266 search->opts->query = dialog_section_text_field_get(search->ctx, query);
2267 SMB_ASSERT(search->opts->query != NULL);
2268 if (search->opts->query[0] == '\0') {
2269 dialog_notice(dia, DIA_ALERT, "Error",
2270 "Query must not be blank.");
2277 int dialog_search_input(TALLOC_CTX *ctx, struct regedit_search_opts *opts)
2280 enum dialog_action action;
2282 struct dialog_section *section, *query;
2283 struct search_req search;
2284 struct button_spec spec[] = {
2285 {.label = "Search", .action = DIALOG_OK},
2286 {.label = "Cancel", .action = DIALOG_CANCEL},
2289 struct option_spec search_opts[] = {
2290 {.label = "Search Keys", .state = &opts->search_key},
2291 {.label = "Search Values", .state = &opts->search_value},
2292 {.label = "Recursive", .state = &opts->search_recursive},
2293 {.label = "Case Sensitive", .state = &opts->search_case},
2297 if (!opts->search_key && !opts->search_value) {
2298 opts->search_key = true;
2303 dia = dialog_new(ctx, PAIR_BLACK_CYAN, "Search", -1, -1);
2304 dialog_set_submit_cb(dia, search_on_submit, &search);
2305 section = dialog_section_label_new(dia, "Query");
2306 dialog_append_section(dia, section);
2307 query = dialog_section_text_field_new(dia, 1, -1);
2308 dialog_section_set_name(query, "query");
2309 dialog_append_section(dia, query);
2310 section = dialog_section_hsep_new(dia, 0);
2311 dialog_append_section(dia, section);
2312 section = dialog_section_options_new(dia, search_opts, 2, false);
2313 dialog_append_section(dia, section);
2314 section = dialog_section_hsep_new(dia, 0);
2315 dialog_append_section(dia, section);
2316 section = dialog_section_buttons_new(dia, spec);
2317 dialog_section_set_justify(section, SECTION_JUSTIFY_CENTER);
2318 dialog_append_section(dia, section);
2322 dialog_section_text_field_set(query, opts->query);
2325 dialog_modal_loop(dia, &err, &action);