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
) {
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
) {
361 dia
->panel
= new_panel(dia
->window
);
362 if (dia
->panel
== NULL
) {
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
) {
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
) {
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
) {
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
, index
;
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 (index
= 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);
991 memcpy(&buf
[index
], *arrayp
, length
);
993 memset(&buf
[index
], ' ', 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 16
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
) {
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 // FIXME hexedit_driver(hexedit->buf, c);
1099 hexedit_driver(hexedit
->buf
, c
);
1104 static bool hexedit_on_up(struct dialog
*dia
,
1105 struct dialog_section
*section
)
1107 struct dialog_section_hexedit
*hexedit
=
1108 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1110 hexedit_driver(hexedit
->buf
, HE_CURSOR_UP
);
1115 static bool hexedit_on_down(struct dialog
*dia
,
1116 struct dialog_section
*section
)
1118 struct dialog_section_hexedit
*hexedit
=
1119 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1121 hexedit_driver(hexedit
->buf
, HE_CURSOR_DOWN
);
1126 static bool hexedit_on_left(struct dialog
*dia
,
1127 struct dialog_section
*section
)
1129 struct dialog_section_hexedit
*hexedit
=
1130 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1132 hexedit_driver(hexedit
->buf
, HE_CURSOR_LEFT
);
1137 static bool hexedit_on_right(struct dialog
*dia
,
1138 struct dialog_section
*section
)
1140 struct dialog_section_hexedit
*hexedit
=
1141 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1143 hexedit_driver(hexedit
->buf
, HE_CURSOR_RIGHT
);
1148 static enum dialog_action
hexedit_on_enter(struct dialog
*dia
,
1149 struct dialog_section
*section
)
1151 return DIALOG_IGNORE
;
1154 static bool hexedit_on_focus(struct dialog
*dia
,
1155 struct dialog_section
*section
, bool forward
)
1157 struct dialog_section_hexedit
*hexedit
=
1158 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1160 hexedit_set_cursor(hexedit
->buf
);
1165 struct dialog_section_ops hexedit_ops
= {
1166 .create
= hexedit_create
,
1167 .destroy
= hexedit_destroy
,
1168 .on_input
= hexedit_on_input
,
1169 .on_up
= hexedit_on_up
,
1170 .on_down
= hexedit_on_down
,
1171 .on_left
= hexedit_on_left
,
1172 .on_right
= hexedit_on_right
,
1173 .on_enter
= hexedit_on_enter
,
1174 .on_focus
= hexedit_on_focus
1177 static int hexedit_free(struct dialog_section_hexedit
*hexedit
)
1179 dialog_section_destroy(&hexedit
->section
);
1183 struct dialog_section
*dialog_section_hexedit_new(TALLOC_CTX
*ctx
, int height
)
1185 struct dialog_section_hexedit
*hexedit
;
1187 hexedit
= talloc_zero(ctx
, struct dialog_section_hexedit
);
1188 if (hexedit
== NULL
) {
1191 talloc_set_destructor(hexedit
, hexedit_free
);
1192 dialog_section_init(&hexedit
->section
, &hexedit_ops
,
1193 height
, LINE_WIDTH
);
1195 return &hexedit
->section
;
1198 WERROR
dialog_section_hexedit_set_buf(struct dialog_section
*section
,
1199 const void *data
, size_t size
)
1202 struct dialog_section_hexedit
*hexedit
=
1203 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1205 SMB_ASSERT(hexedit
->buf
!= NULL
);
1207 rv
= hexedit_set_buf(hexedit
->buf
, data
, size
);
1208 if (W_ERROR_IS_OK(rv
)) {
1209 hexedit_refresh(hexedit
->buf
);
1210 hexedit_set_cursor(hexedit
->buf
);
1216 void dialog_section_hexedit_get_buf(struct dialog_section
*section
,
1217 const void **data
, size_t *size
)
1219 struct dialog_section_hexedit
*hexedit
=
1220 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1222 SMB_ASSERT(hexedit
->buf
!= NULL
);
1223 *data
= hexedit_get_buf(hexedit
->buf
);
1224 *size
= hexedit_get_buf_len(hexedit
->buf
);
1228 struct dialog_section_buttons
{
1229 struct dialog_section section
;
1230 struct button_spec
*spec
;
1234 static void buttons_unhighlight(struct dialog_section_buttons
*buttons
)
1240 * Some GCC versions will complain if the macro version of
1241 * wattr_get is used. So we should enforce the use of the
1242 * function instead. See:
1243 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1245 (wattr_get
)(buttons
->section
.window
, &attr
, &pair
, NULL
);
1246 mvwchgat(buttons
->section
.window
, 0, 0, -1, A_NORMAL
, pair
, NULL
);
1247 wnoutrefresh(buttons
->section
.window
);
1250 static void buttons_highlight(struct dialog_section_buttons
*buttons
)
1252 struct button_spec
*spec
= &buttons
->spec
[buttons
->current_button
];
1257 * Some GCC versions will complain if the macro version of
1258 * wattr_get is used. So we should enforce the use of the
1259 * function instead. See:
1260 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1262 (wattr_get
)(buttons
->section
.window
, &attr
, &pair
, NULL
);
1263 mvwchgat(buttons
->section
.window
, 0, 0, -1, A_NORMAL
, pair
, NULL
);
1264 mvwchgat(buttons
->section
.window
, 0, spec
->col
,
1265 strlen(spec
->label
), A_REVERSE
, pair
, NULL
);
1266 wmove(buttons
->section
.window
, 0, spec
->col
+ 2);
1267 wcursyncup(buttons
->section
.window
);
1268 wnoutrefresh(buttons
->section
.window
);
1271 static bool buttons_highlight_next(struct dialog_section_buttons
*buttons
)
1273 if (buttons
->current_button
< talloc_array_length(buttons
->spec
) - 1) {
1274 buttons
->current_button
++;
1275 buttons_highlight(buttons
);
1281 static bool buttons_highlight_previous(struct dialog_section_buttons
*buttons
)
1283 if (buttons
->current_button
> 0) {
1284 buttons
->current_button
--;
1285 buttons_highlight(buttons
);
1291 static WERROR
buttons_create(struct dialog
*dia
,
1292 struct dialog_section
*section
)
1295 struct dialog_section_buttons
*buttons
=
1296 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1298 nbuttons
= talloc_array_length(buttons
->spec
);
1299 for (i
= 0; i
< nbuttons
; ++i
) {
1300 struct button_spec
*spec
= &buttons
->spec
[i
];
1301 mvwaddstr(section
->window
, 0, spec
->col
, spec
->label
);
1304 buttons
->current_button
= 0;
1309 static bool buttons_on_btab(struct dialog
*dia
, struct dialog_section
*section
)
1311 struct dialog_section_buttons
*buttons
=
1312 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1314 return buttons_highlight_previous(buttons
);
1317 static bool buttons_on_tab(struct dialog
*dia
, struct dialog_section
*section
)
1319 struct dialog_section_buttons
*buttons
=
1320 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1322 return buttons_highlight_next(buttons
);
1325 static enum dialog_action
buttons_on_enter(struct dialog
*dia
,
1326 struct dialog_section
*section
)
1328 struct dialog_section_buttons
*buttons
=
1329 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1330 struct button_spec
*spec
= &buttons
->spec
[buttons
->current_button
];
1332 if (spec
->on_enter
) {
1333 return spec
->on_enter(dia
, section
);
1336 return spec
->action
;
1339 static bool buttons_on_focus(struct dialog
*dia
,
1340 struct dialog_section
*section
,
1343 struct dialog_section_buttons
*buttons
=
1344 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1347 buttons
->current_button
= 0;
1349 buttons
->current_button
= talloc_array_length(buttons
->spec
) - 1;
1351 buttons_highlight(buttons
);
1356 static void buttons_on_leave_focus(struct dialog
*dia
,
1357 struct dialog_section
*section
)
1359 struct dialog_section_buttons
*buttons
=
1360 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1361 buttons_unhighlight(buttons
);
1364 struct dialog_section_ops buttons_ops
= {
1365 .create
= buttons_create
,
1366 .on_tab
= buttons_on_tab
,
1367 .on_btab
= buttons_on_btab
,
1368 .on_up
= buttons_on_btab
,
1369 .on_down
= buttons_on_tab
,
1370 .on_left
= buttons_on_btab
,
1371 .on_right
= buttons_on_tab
,
1372 .on_enter
= buttons_on_enter
,
1373 .on_focus
= buttons_on_focus
,
1374 .on_leave_focus
= buttons_on_leave_focus
1377 static int buttons_free(struct dialog_section_buttons
*buttons
)
1379 dialog_section_destroy(&buttons
->section
);
1383 struct dialog_section
*dialog_section_buttons_new(TALLOC_CTX
*ctx
,
1384 const struct button_spec
*spec
)
1386 struct dialog_section_buttons
*buttons
;
1390 buttons
= talloc_zero(ctx
, struct dialog_section_buttons
);
1391 if (buttons
== NULL
) {
1394 talloc_set_destructor(buttons
, buttons_free
);
1396 for (nbuttons
= 0; spec
[nbuttons
].label
; ++nbuttons
) {
1398 buttons
->spec
= talloc_zero_array(buttons
, struct button_spec
, nbuttons
);
1399 if (buttons
->spec
== NULL
) {
1403 for (width
= 0, i
= 0; i
< nbuttons
; ++i
) {
1404 buttons
->spec
[i
] = spec
[i
];
1405 buttons
->spec
[i
].label
= talloc_asprintf(buttons
->spec
,
1408 if (!buttons
->spec
[i
].label
) {
1412 buttons
->spec
[i
].col
= width
;
1413 width
+= strlen(buttons
->spec
[i
].label
);
1414 if (i
!= nbuttons
- 1) {
1419 dialog_section_init(&buttons
->section
, &buttons_ops
, 1, width
);
1421 return &buttons
->section
;
1424 talloc_free(buttons
);
1429 struct dialog_section_options
{
1430 struct dialog_section section
;
1431 struct option_spec
*spec
;
1436 static void options_unhighlight(struct dialog_section_options
*options
)
1443 * Some GCC versions will complain if the macro version of
1444 * wattr_get is used. So we should enforce the use of the
1445 * function instead. See:
1446 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1448 (wattr_get
)(options
->section
.window
, &attr
, &pair
, NULL
);
1449 for (row
= 0; row
< options
->section
.nlines
; ++row
) {
1450 mvwchgat(options
->section
.window
, row
, 0, -1, A_NORMAL
, pair
, NULL
);
1452 wnoutrefresh(options
->section
.window
);
1455 static void options_highlight(struct dialog_section_options
*options
)
1457 struct option_spec
*spec
= &options
->spec
[options
->current_option
];
1463 * Some GCC versions will complain if the macro version of
1464 * wattr_get is used. So we should enforce the use of the
1465 * function instead. See:
1466 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1468 (wattr_get
)(options
->section
.window
, &attr
, &pair
, NULL
);
1469 for (row
= 0; row
< options
->section
.nlines
; ++row
) {
1470 mvwchgat(options
->section
.window
, row
, 0, -1, A_NORMAL
, pair
, NULL
);
1472 mvwchgat(options
->section
.window
, spec
->row
, spec
->col
,
1473 strlen(spec
->label
), A_REVERSE
, pair
, NULL
);
1474 wmove(options
->section
.window
, spec
->row
, spec
->col
+ 4);
1475 wcursyncup(options
->section
.window
);
1476 wnoutrefresh(options
->section
.window
);
1479 static void options_render_state(struct dialog_section_options
*options
)
1483 noptions
= talloc_array_length(options
->spec
);
1484 for (i
= 0; i
< noptions
; ++i
) {
1485 struct option_spec
*spec
= &options
->spec
[i
];
1489 mvwaddch(options
->section
.window
,
1490 spec
->row
, spec
->col
+ 1, c
);
1491 wnoutrefresh(options
->section
.window
);
1495 static bool options_highlight_next(struct dialog_section_options
*options
)
1497 if (options
->current_option
< talloc_array_length(options
->spec
) - 1) {
1498 options
->current_option
++;
1499 options_highlight(options
);
1505 static bool options_highlight_previous(struct dialog_section_options
*options
)
1507 if (options
->current_option
> 0) {
1508 options
->current_option
--;
1509 options_highlight(options
);
1515 static WERROR
options_create(struct dialog
*dia
,
1516 struct dialog_section
*section
)
1519 struct dialog_section_options
*options
=
1520 talloc_get_type_abort(section
, struct dialog_section_options
);
1522 noptions
= talloc_array_length(options
->spec
);
1523 for (i
= 0; i
< noptions
; ++i
) {
1524 struct option_spec
*spec
= &options
->spec
[i
];
1525 mvwaddstr(section
->window
, spec
->row
, spec
->col
,
1529 options
->current_option
= 0;
1530 options_render_state(options
);
1535 static bool options_on_btab(struct dialog
*dia
, struct dialog_section
*section
)
1537 struct dialog_section_options
*options
=
1538 talloc_get_type_abort(section
, struct dialog_section_options
);
1540 return options_highlight_previous(options
);
1543 static bool options_on_tab(struct dialog
*dia
, struct dialog_section
*section
)
1545 struct dialog_section_options
*options
=
1546 talloc_get_type_abort(section
, struct dialog_section_options
);
1548 return options_highlight_next(options
);
1551 static void options_on_input(struct dialog
*dia
, struct dialog_section
*section
, int c
)
1553 struct dialog_section_options
*options
=
1554 talloc_get_type_abort(section
, struct dialog_section_options
);
1557 struct option_spec
*spec
= &options
->spec
[options
->current_option
];
1558 if (options
->single_select
) {
1560 noptions
= talloc_array_length(options
->spec
);
1561 for (i
= 0; i
< noptions
; ++i
) {
1562 *(options
->spec
[i
].state
) = false;
1565 *spec
->state
= !*spec
->state
;
1566 options_unhighlight(options
);
1567 options_render_state(options
);
1568 options_highlight(options
);
1572 static enum dialog_action
options_on_enter(struct dialog
*dia
, struct dialog_section
*section
)
1574 options_on_input(dia
, section
, ' ');
1578 static bool options_on_focus(struct dialog
*dia
,
1579 struct dialog_section
*section
,
1582 struct dialog_section_options
*options
=
1583 talloc_get_type_abort(section
, struct dialog_section_options
);
1586 options
->current_option
= 0;
1588 options
->current_option
= talloc_array_length(options
->spec
) - 1;
1590 options_highlight(options
);
1595 static void options_on_leave_focus(struct dialog
*dia
,
1596 struct dialog_section
*section
)
1598 struct dialog_section_options
*options
=
1599 talloc_get_type_abort(section
, struct dialog_section_options
);
1600 options_unhighlight(options
);
1603 struct dialog_section_ops options_ops
= {
1604 .create
= options_create
,
1605 .on_tab
= options_on_tab
,
1606 .on_btab
= options_on_btab
,
1607 .on_up
= options_on_btab
,
1608 .on_down
= options_on_tab
,
1609 .on_left
= options_on_btab
,
1610 .on_right
= options_on_tab
,
1611 .on_input
= options_on_input
,
1612 .on_enter
= options_on_enter
,
1613 .on_focus
= options_on_focus
,
1614 .on_leave_focus
= options_on_leave_focus
1617 static int options_free(struct dialog_section_options
*options
)
1619 dialog_section_destroy(&options
->section
);
1623 struct dialog_section
*dialog_section_options_new(TALLOC_CTX
*ctx
,
1624 const struct option_spec
*spec
,
1625 int maxcol
, bool single_select
)
1627 struct dialog_section_options
*options
;
1629 int width
, maxwidth
, maxrows
;
1631 options
= talloc_zero(ctx
, struct dialog_section_options
);
1632 if (options
== NULL
) {
1635 talloc_set_destructor(options
, options_free
);
1637 for (noptions
= 0; spec
[noptions
].label
; ++noptions
) {
1639 options
->spec
= talloc_zero_array(options
, struct option_spec
, noptions
);
1640 if (options
->spec
== NULL
) {
1644 maxrows
= noptions
/ maxcol
;
1645 if (noptions
% maxcol
) {
1649 for (width
= 0, maxwidth
= 0, i
= 0; i
< noptions
; ++i
) {
1650 options
->spec
[i
] = spec
[i
];
1651 options
->spec
[i
].label
= talloc_asprintf(options
->spec
,
1654 if (!options
->spec
[i
].label
) {
1658 options
->spec
[i
].col
= maxwidth
;
1659 options
->spec
[i
].row
= i
% maxrows
;
1660 width
= MAX(strlen(options
->spec
[i
].label
), width
);
1661 if (options
->spec
[i
].row
== maxrows
- 1 || i
== noptions
- 1) {
1662 maxwidth
+= width
+ 1;
1667 dialog_section_init(&options
->section
, &options_ops
, maxrows
, maxwidth
- 1);
1668 options
->single_select
= single_select
;
1670 return &options
->section
;
1673 talloc_free(options
);
1686 enum input_type type
;
1689 unsigned long *out_ulong
;
1691 const char **out_str
;
1695 static bool input_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
1698 struct input_req
*req
= arg
;
1699 struct dialog_section
*data
;
1700 unsigned long long out_ulong
;
1703 data
= dialog_find_section(dia
, "input");
1705 switch (req
->type
) {
1707 if (!dialog_section_text_field_get_int(data
, &out_long
)) {
1708 dialog_notice(dia
, DIA_ALERT
, "Error",
1709 "Input must be a number.");
1712 if (out_long
< LONG_MIN
|| out_long
> LONG_MAX
) {
1713 dialog_notice(dia
, DIA_ALERT
, "Error",
1714 "Number is out of range.");
1717 *req
->out
.out_long
= out_long
;
1720 if (!dialog_section_text_field_get_uint(data
, &out_ulong
)) {
1721 dialog_notice(dia
, DIA_ALERT
, "Error",
1722 "Input must be a number greater than zero.");
1725 if (out_ulong
> ULONG_MAX
) {
1726 dialog_notice(dia
, DIA_ALERT
, "Error",
1727 "Number is out of range.");
1730 *req
->out
.out_ulong
= out_ulong
;
1733 *req
->out
.out_str
= dialog_section_text_field_get(req
->ctx
, data
);
1740 static int dialog_input_internal(TALLOC_CTX
*ctx
, void *output
,
1741 enum input_type type
,
1743 const char *msg
, va_list ap
)
1746 struct input_req req
;
1747 enum dialog_action action
;
1749 struct dialog_section
*section
;
1750 struct button_spec spec
[] = {
1751 {.label
= "OK", .action
= DIALOG_OK
},
1752 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
1758 req
.out
.out
= output
;
1759 *req
.out
.out_str
= NULL
;
1761 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, title
, -1, -1);
1762 dialog_set_submit_cb(dia
, input_on_submit
, &req
);
1763 section
= dialog_section_label_new_va(dia
, msg
, ap
);
1764 dialog_append_section(dia
, section
);
1765 section
= dialog_section_hsep_new(dia
, ' ');
1766 dialog_append_section(dia
, section
);
1767 section
= dialog_section_text_field_new(dia
, 1, -1);
1768 dialog_section_set_name(section
, "input");
1769 dialog_append_section(dia
, section
);
1770 section
= dialog_section_hsep_new(dia
, 0);
1771 dialog_append_section(dia
, section
);
1772 section
= dialog_section_buttons_new(dia
, spec
);
1773 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1774 dialog_append_section(dia
, section
);
1778 dialog_modal_loop(dia
, &err
, &action
);
1784 int dialog_input(TALLOC_CTX
*ctx
, const char **output
, const char *title
,
1785 const char *msg
, ...)
1791 rv
= dialog_input_internal(ctx
, output
, DLG_IN_STR
, title
, msg
, ap
);
1797 int dialog_input_ulong(TALLOC_CTX
*ctx
, unsigned long *output
,
1798 const char *title
, const char *msg
, ...)
1804 rv
= dialog_input_internal(ctx
, output
, DLG_IN_ULONG
, title
, msg
, ap
);
1810 int dialog_input_long(TALLOC_CTX
*ctx
, long *output
,
1811 const char *title
, const char *msg
, ...)
1817 rv
= dialog_input_internal(ctx
, output
, DLG_IN_LONG
, title
, msg
, ap
);
1823 int dialog_notice(TALLOC_CTX
*ctx
, enum dialog_type type
,
1824 const char *title
, const char *msg
, ...)
1828 enum dialog_action action
;
1830 struct dialog_section
*section
;
1831 struct button_spec spec
[3];
1833 memset(&spec
, '\0', sizeof(spec
));
1834 spec
[0].label
= "OK";
1835 spec
[0].action
= DIALOG_OK
;
1836 if (type
== DIA_CONFIRM
) {
1837 spec
[1].label
= "Cancel";
1838 spec
[1].action
= DIALOG_CANCEL
;
1841 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, title
, -1, -1);
1843 section
= dialog_section_label_new_va(dia
, msg
, ap
);
1845 dialog_append_section(dia
, section
);
1846 section
= dialog_section_hsep_new(dia
, 0);
1847 dialog_append_section(dia
, section
);
1848 section
= dialog_section_buttons_new(dia
, spec
);
1849 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1850 dialog_append_section(dia
, section
);
1854 dialog_modal_loop(dia
, &err
, &action
);
1864 struct registry_key
*key
;
1865 const struct value_item
*vitem
;
1868 static WERROR
fill_value_buffer(struct dialog
*dia
, struct edit_req
*edit
)
1871 struct dialog_section
*data
;
1873 if (edit
->vitem
== NULL
) {
1877 data
= dialog_find_section(dia
, "data");
1878 SMB_ASSERT(data
!= NULL
);
1880 switch (edit
->mode
) {
1883 if (edit
->vitem
->data
.length
>= 4) {
1884 v
= IVAL(edit
->vitem
->data
.data
, 0);
1886 tmp
= talloc_asprintf(dia
, "%u", (unsigned)v
);
1890 dialog_section_text_field_set(data
, tmp
);
1895 case REG_EXPAND_SZ
: {
1898 if (!pull_reg_sz(dia
, &edit
->vitem
->data
, &s
)) {
1901 dialog_section_text_field_set(data
, s
);
1904 case REG_MULTI_SZ
: {
1907 if (!pull_reg_multi_sz(dia
, &edit
->vitem
->data
, &array
)) {
1910 return dialog_section_text_field_set_lines(dia
, data
, array
);
1914 return dialog_section_hexedit_set_buf(data
,
1915 edit
->vitem
->data
.data
,
1916 edit
->vitem
->data
.length
);
1922 static bool value_exists(TALLOC_CTX
*ctx
, const struct registry_key
*key
,
1929 rv
= reg_key_get_value_by_name(ctx
, key
, name
, &type
, &blob
);
1931 return W_ERROR_IS_OK(rv
);
1934 static bool edit_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
1937 struct edit_req
*edit
= arg
;
1941 struct dialog_section
*name_section
, *data
;
1943 name_section
= dialog_find_section(dia
, "name");
1945 name
= dialog_section_text_field_get(dia
, name_section
);
1946 if (*name
== '\0') {
1947 dialog_notice(dia
, DIA_ALERT
, "Error",
1948 "Value name must not be blank.");
1951 if (value_exists(dia
, edit
->key
, name
)) {
1952 dialog_notice(dia
, DIA_ALERT
, "Error",
1953 "Value named \"%s\" already exists.",
1958 SMB_ASSERT(edit
->vitem
);
1959 name
= edit
->vitem
->value_name
;
1963 data
= dialog_find_section(dia
, "data");
1964 SMB_ASSERT(data
!= NULL
);
1967 switch (edit
->mode
) {
1969 unsigned long long v
;
1972 if (!dialog_section_text_field_get_uint(data
, &v
)) {
1973 dialog_notice(dia
, DIA_ALERT
, "Error",
1974 "REG_DWORD value must be an integer.");
1977 if (v
> UINT32_MAX
) {
1978 dialog_notice(dia
, DIA_ALERT
, "Error",
1979 "REG_DWORD value must less than %lu.",
1980 (unsigned long)UINT32_MAX
);
1984 blob
= data_blob_talloc(dia
, NULL
, sizeof(val
));
1985 SIVAL(blob
.data
, 0, val
);
1989 case REG_EXPAND_SZ
: {
1992 buf
= dialog_section_text_field_get(dia
, data
);
1993 if (!buf
|| !push_reg_sz(dia
, &blob
, buf
)) {
1998 case REG_MULTI_SZ
: {
2001 lines
= dialog_section_text_field_get_lines(dia
, data
);
2002 if (!lines
|| !push_reg_multi_sz(dia
, &blob
, lines
)) {
2011 dialog_section_hexedit_get_buf(data
, &buf
, &len
);
2012 blob
= data_blob_talloc(dia
, buf
, len
);
2017 if (W_ERROR_IS_OK(rv
)) {
2018 rv
= reg_val_set(edit
->key
, name
, edit
->type
, blob
);
2021 if (!W_ERROR_IS_OK(rv
)) {
2022 const char *msg
= get_friendly_werror_msg(rv
);
2023 dialog_notice(dia
, DIA_ALERT
, "Error",
2024 "Error saving value:\n%s", msg
);
2033 int dialog_edit_value(TALLOC_CTX
*ctx
, struct registry_key
*key
,
2034 uint32_t type
, const struct value_item
*vitem
,
2035 bool force_binary
, WERROR
*err
,
2038 enum dialog_action action
;
2040 struct dialog_section
*section
;
2041 struct edit_req edit
;
2042 struct button_spec spec
[] = {
2043 {.label
= "OK", .action
= DIALOG_OK
},
2044 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2052 if (force_binary
|| (vitem
&& vitem
->unprintable
)) {
2053 edit
.mode
= REG_BINARY
;
2056 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "Edit Value", -1, -1);
2057 dialog_set_submit_cb(dia
, edit_on_submit
, &edit
);
2059 section
= dialog_section_label_new(dia
, "Type");
2060 dialog_append_section(dia
, section
);
2061 section
= dialog_section_label_new(dia
, "%s",
2063 dialog_append_section(dia
, section
);
2064 section
= dialog_section_hsep_new(dia
, ' ');
2065 dialog_append_section(dia
, section
);
2067 section
= dialog_section_label_new(dia
, "Name");
2068 dialog_append_section(dia
, section
);
2070 section
= dialog_section_label_new(dia
, "%s",
2073 section
= dialog_section_text_field_new(dia
, 1, 50);
2074 dialog_section_set_name(section
, "name");
2076 dialog_append_section(dia
, section
);
2077 section
= dialog_section_hsep_new(dia
, ' ');
2078 dialog_append_section(dia
, section
);
2080 section
= dialog_section_label_new(dia
, "Data");
2081 dialog_append_section(dia
, section
);
2083 switch (edit
.mode
) {
2087 section
= dialog_section_text_field_new(dia
, 1, 50);
2090 section
= dialog_section_text_field_new(dia
, 10, 50);
2094 section
= dialog_section_hexedit_new(dia
, 10);
2098 dialog_section_set_name(section
, "data");
2099 dialog_append_section(dia
, section
);
2101 section
= dialog_section_hsep_new(dia
, 0);
2102 dialog_append_section(dia
, section
);
2103 section
= dialog_section_buttons_new(dia
, spec
);
2104 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2105 dialog_append_section(dia
, section
);
2109 *err
= fill_value_buffer(dia
, &edit
);
2110 if (!W_ERROR_IS_OK(*err
)) {
2111 return DIALOG_CANCEL
;
2115 dialog_modal_loop(dia
, err
, &action
);
2117 if (action
== DIALOG_OK
&& name
) {
2119 *name
= talloc_strdup(ctx
, vitem
->value_name
);
2120 } else if ((section
= dialog_find_section(dia
, "name"))) {
2121 *name
= dialog_section_text_field_get(ctx
, section
);
2130 int dialog_select_type(TALLOC_CTX
*ctx
, int *type
)
2133 enum dialog_action action
;
2135 struct dialog_section
*section
;
2136 const char *reg_types
[] = {
2143 #define NTYPES ARRAY_SIZE(reg_types)
2144 struct button_spec spec
[] = {
2145 {.label
= "OK", .action
= DIALOG_OK
},
2146 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2149 bool flags
[NTYPES
] = { true };
2150 struct option_spec opsec
[NTYPES
+ 1];
2153 memset(&opsec
, '\0', sizeof(opsec
));
2154 for (i
= 0; i
< NTYPES
; ++i
) {
2155 opsec
[i
].label
= reg_types
[i
];
2156 opsec
[i
].state
= &flags
[i
];
2159 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "New Value", -1, -1);
2161 section
= dialog_section_label_new(dia
, "Select type for new value:");
2162 dialog_append_section(dia
, section
);
2163 section
= dialog_section_hsep_new(dia
, ' ');
2164 dialog_append_section(dia
, section
);
2165 section
= dialog_section_options_new(dia
, opsec
, 2, true);
2166 dialog_append_section(dia
, section
);
2167 section
= dialog_section_hsep_new(dia
, 0);
2168 dialog_append_section(dia
, section
);
2169 section
= dialog_section_buttons_new(dia
, spec
);
2170 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2171 dialog_append_section(dia
, section
);
2176 dialog_modal_loop(dia
, &err
, &action
);
2177 if (action
== DIALOG_OK
) {
2178 for (i
= 0; i
< NTYPES
; ++i
) {
2180 *type
= regtype_by_string(reg_types
[i
]);
2193 struct regedit_search_opts
*opts
;
2196 static bool search_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
2199 struct search_req
*search
= arg
;
2200 struct dialog_section
*query
;
2202 query
= dialog_find_section(dia
, "query");
2203 SMB_ASSERT(query
!= NULL
);
2205 if (!search
->opts
->search_key
&& !search
->opts
->search_value
) {
2206 dialog_notice(dia
, DIA_ALERT
, "Error",
2207 "Must search a key and/or a value");
2211 talloc_free(discard_const(search
->opts
->query
));
2212 search
->opts
->query
= dialog_section_text_field_get(search
->ctx
, query
);
2213 SMB_ASSERT(search
->opts
->query
!= NULL
);
2214 if (search
->opts
->query
[0] == '\0') {
2215 dialog_notice(dia
, DIA_ALERT
, "Error",
2216 "Query must not be blank.");
2223 int dialog_search_input(TALLOC_CTX
*ctx
, struct regedit_search_opts
*opts
)
2226 enum dialog_action action
;
2228 struct dialog_section
*section
, *query
;
2229 struct search_req search
;
2230 struct button_spec spec
[] = {
2231 {.label
= "Search", .action
= DIALOG_OK
},
2232 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2235 struct option_spec search_opts
[] = {
2236 {.label
= "Search Keys", .state
= &opts
->search_key
},
2237 {.label
= "Search Values", .state
= &opts
->search_value
},
2238 {.label
= "Recursive", .state
= &opts
->search_recursive
},
2239 {.label
= "Case Sensitive", .state
= &opts
->search_case
},
2243 if (!opts
->search_key
&& !opts
->search_value
) {
2244 opts
->search_key
= true;
2249 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "Search", -1, -1);
2250 dialog_set_submit_cb(dia
, search_on_submit
, &search
);
2251 section
= dialog_section_label_new(dia
, "Query");
2252 dialog_append_section(dia
, section
);
2253 query
= dialog_section_text_field_new(dia
, 1, -1);
2254 dialog_section_set_name(query
, "query");
2255 dialog_append_section(dia
, query
);
2256 section
= dialog_section_hsep_new(dia
, 0);
2257 dialog_append_section(dia
, section
);
2258 section
= dialog_section_options_new(dia
, search_opts
, 2, false);
2259 dialog_append_section(dia
, section
);
2260 section
= dialog_section_hsep_new(dia
, 0);
2261 dialog_append_section(dia
, section
);
2262 section
= dialog_section_buttons_new(dia
, spec
);
2263 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2264 dialog_append_section(dia
, section
);
2268 dialog_section_text_field_set(query
, opts
->query
);
2271 dialog_modal_loop(dia
, &err
, &action
);