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
, 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);
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
) {
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
)
1767 struct input_req req
;
1768 enum dialog_action action
;
1770 struct dialog_section
*section
;
1771 struct button_spec spec
[] = {
1772 {.label
= "OK", .action
= DIALOG_OK
},
1773 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
1779 req
.out
.out
= output
;
1780 *req
.out
.out_str
= NULL
;
1782 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, title
, -1, -1);
1783 dialog_set_submit_cb(dia
, input_on_submit
, &req
);
1784 section
= dialog_section_label_new_va(dia
, msg
, ap
);
1785 dialog_append_section(dia
, section
);
1786 section
= dialog_section_hsep_new(dia
, ' ');
1787 dialog_append_section(dia
, section
);
1788 section
= dialog_section_text_field_new(dia
, 1, -1);
1789 dialog_section_set_name(section
, "input");
1790 dialog_append_section(dia
, section
);
1791 section
= dialog_section_hsep_new(dia
, 0);
1792 dialog_append_section(dia
, section
);
1793 section
= dialog_section_buttons_new(dia
, spec
);
1794 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1795 dialog_append_section(dia
, section
);
1799 dialog_modal_loop(dia
, &err
, &action
);
1805 int dialog_input(TALLOC_CTX
*ctx
, const char **output
, const char *title
,
1806 const char *msg
, ...)
1812 rv
= dialog_input_internal(ctx
, output
, DLG_IN_STR
, title
, msg
, ap
);
1818 int dialog_input_ulong(TALLOC_CTX
*ctx
, unsigned long *output
,
1819 const char *title
, const char *msg
, ...)
1825 rv
= dialog_input_internal(ctx
, output
, DLG_IN_ULONG
, title
, msg
, ap
);
1831 int dialog_input_long(TALLOC_CTX
*ctx
, long *output
,
1832 const char *title
, const char *msg
, ...)
1838 rv
= dialog_input_internal(ctx
, output
, DLG_IN_LONG
, title
, msg
, ap
);
1844 int dialog_notice(TALLOC_CTX
*ctx
, enum dialog_type type
,
1845 const char *title
, const char *msg
, ...)
1849 enum dialog_action action
;
1851 struct dialog_section
*section
;
1852 struct button_spec spec
[3];
1854 memset(&spec
, '\0', sizeof(spec
));
1855 spec
[0].label
= "OK";
1856 spec
[0].action
= DIALOG_OK
;
1857 if (type
== DIA_CONFIRM
) {
1858 spec
[1].label
= "Cancel";
1859 spec
[1].action
= DIALOG_CANCEL
;
1862 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, title
, -1, -1);
1864 section
= dialog_section_label_new_va(dia
, msg
, ap
);
1866 dialog_append_section(dia
, section
);
1867 section
= dialog_section_hsep_new(dia
, 0);
1868 dialog_append_section(dia
, section
);
1869 section
= dialog_section_buttons_new(dia
, spec
);
1870 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1871 dialog_append_section(dia
, section
);
1875 dialog_modal_loop(dia
, &err
, &action
);
1885 struct registry_key
*key
;
1886 const struct value_item
*vitem
;
1889 static WERROR
fill_value_buffer(struct dialog
*dia
, struct edit_req
*edit
)
1892 struct dialog_section
*data
;
1894 if (edit
->vitem
== NULL
) {
1898 data
= dialog_find_section(dia
, "data");
1899 SMB_ASSERT(data
!= NULL
);
1901 switch (edit
->mode
) {
1904 if (edit
->vitem
->data
.length
>= 4) {
1905 v
= IVAL(edit
->vitem
->data
.data
, 0);
1907 tmp
= talloc_asprintf(dia
, "%u", (unsigned)v
);
1911 dialog_section_text_field_set(data
, tmp
);
1916 case REG_EXPAND_SZ
: {
1919 if (!pull_reg_sz(dia
, &edit
->vitem
->data
, &s
)) {
1922 dialog_section_text_field_set(data
, s
);
1925 case REG_MULTI_SZ
: {
1928 if (!pull_reg_multi_sz(dia
, &edit
->vitem
->data
, &array
)) {
1931 return dialog_section_text_field_set_lines(dia
, data
, array
);
1935 return dialog_section_hexedit_set_buf(data
,
1936 edit
->vitem
->data
.data
,
1937 edit
->vitem
->data
.length
);
1943 static bool value_exists(TALLOC_CTX
*ctx
, const struct registry_key
*key
,
1950 rv
= reg_key_get_value_by_name(ctx
, key
, name
, &type
, &blob
);
1952 return W_ERROR_IS_OK(rv
);
1955 static bool edit_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
1958 struct edit_req
*edit
= arg
;
1962 struct dialog_section
*name_section
, *data
;
1964 name_section
= dialog_find_section(dia
, "name");
1966 name
= dialog_section_text_field_get(dia
, name_section
);
1967 if (*name
== '\0') {
1968 dialog_notice(dia
, DIA_ALERT
, "Error",
1969 "Value name must not be blank.");
1972 if (value_exists(dia
, edit
->key
, name
)) {
1973 dialog_notice(dia
, DIA_ALERT
, "Error",
1974 "Value named \"%s\" already exists.",
1979 SMB_ASSERT(edit
->vitem
);
1980 name
= edit
->vitem
->value_name
;
1984 data
= dialog_find_section(dia
, "data");
1985 SMB_ASSERT(data
!= NULL
);
1988 switch (edit
->mode
) {
1990 unsigned long long v
;
1993 if (!dialog_section_text_field_get_uint(data
, &v
)) {
1994 dialog_notice(dia
, DIA_ALERT
, "Error",
1995 "REG_DWORD value must be an integer.");
1998 if (v
> UINT32_MAX
) {
1999 dialog_notice(dia
, DIA_ALERT
, "Error",
2000 "REG_DWORD value must less than %lu.",
2001 (unsigned long)UINT32_MAX
);
2005 blob
= data_blob_talloc(dia
, NULL
, sizeof(val
));
2006 SIVAL(blob
.data
, 0, val
);
2010 case REG_EXPAND_SZ
: {
2013 buf
= dialog_section_text_field_get(dia
, data
);
2014 if (!buf
|| !push_reg_sz(dia
, &blob
, buf
)) {
2019 case REG_MULTI_SZ
: {
2022 lines
= dialog_section_text_field_get_lines(dia
, data
);
2023 if (!lines
|| !push_reg_multi_sz(dia
, &blob
, lines
)) {
2032 dialog_section_hexedit_get_buf(data
, &buf
, &len
);
2033 blob
= data_blob_talloc(dia
, buf
, len
);
2038 if (W_ERROR_IS_OK(rv
)) {
2039 rv
= reg_val_set(edit
->key
, name
, edit
->type
, blob
);
2042 if (!W_ERROR_IS_OK(rv
)) {
2043 const char *msg
= get_friendly_werror_msg(rv
);
2044 dialog_notice(dia
, DIA_ALERT
, "Error",
2045 "Error saving value:\n%s", msg
);
2054 static enum dialog_action
edit_on_resize(struct dialog
*dia
,
2055 struct dialog_section
*section
)
2057 struct dialog_section
*data
;
2061 data
= dialog_find_section(dia
, "data");
2062 rv
= dialog_input_ulong(dia
, &size
, "Resize", "Enter size of buffer");
2063 if (rv
== DIALOG_OK
) {
2064 dialog_section_hexedit_resize(data
, size
);
2067 return DIALOG_IGNORE
;
2070 int dialog_edit_value(TALLOC_CTX
*ctx
, struct registry_key
*key
,
2071 uint32_t type
, const struct value_item
*vitem
,
2072 bool force_binary
, WERROR
*err
,
2075 enum dialog_action action
;
2077 struct dialog_section
*section
;
2078 struct edit_req edit
;
2079 struct button_spec buttons
[] = {
2080 {.label
= "OK", .action
= DIALOG_OK
},
2081 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2084 struct button_spec buttons_hexedit
[] = {
2085 {.label
= "OK", .action
= DIALOG_OK
},
2086 {.label
= "Resize Buffer", .on_enter
= edit_on_resize
},
2087 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2096 if (force_binary
|| (vitem
&& vitem
->unprintable
)) {
2097 edit
.mode
= REG_BINARY
;
2100 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "Edit Value", -1, -1);
2101 dialog_set_submit_cb(dia
, edit_on_submit
, &edit
);
2103 section
= dialog_section_label_new(dia
, "Type");
2104 dialog_append_section(dia
, section
);
2105 section
= dialog_section_label_new(dia
, "%s",
2107 dialog_append_section(dia
, section
);
2108 section
= dialog_section_hsep_new(dia
, ' ');
2109 dialog_append_section(dia
, section
);
2111 section
= dialog_section_label_new(dia
, "Name");
2112 dialog_append_section(dia
, section
);
2114 section
= dialog_section_label_new(dia
, "%s",
2117 section
= dialog_section_text_field_new(dia
, 1, 50);
2118 dialog_section_set_name(section
, "name");
2120 dialog_append_section(dia
, section
);
2121 section
= dialog_section_hsep_new(dia
, ' ');
2122 dialog_append_section(dia
, section
);
2124 section
= dialog_section_label_new(dia
, "Data");
2125 dialog_append_section(dia
, section
);
2127 switch (edit
.mode
) {
2131 section
= dialog_section_text_field_new(dia
, 1, 50);
2134 section
= dialog_section_text_field_new(dia
, 10, 50);
2138 section
= dialog_section_hexedit_new(dia
, 10);
2142 dialog_section_set_name(section
, "data");
2143 dialog_append_section(dia
, section
);
2145 section
= dialog_section_hsep_new(dia
, 0);
2146 dialog_append_section(dia
, section
);
2147 if (edit
.mode
== REG_BINARY
) {
2148 section
= dialog_section_buttons_new(dia
, buttons_hexedit
);
2150 section
= dialog_section_buttons_new(dia
, buttons
);
2152 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2153 dialog_append_section(dia
, section
);
2157 *err
= fill_value_buffer(dia
, &edit
);
2158 if (!W_ERROR_IS_OK(*err
)) {
2159 return DIALOG_CANCEL
;
2163 dialog_modal_loop(dia
, err
, &action
);
2165 if (action
== DIALOG_OK
&& name
) {
2167 *name
= talloc_strdup(ctx
, vitem
->value_name
);
2168 } else if ((section
= dialog_find_section(dia
, "name"))) {
2169 *name
= dialog_section_text_field_get(ctx
, section
);
2178 int dialog_select_type(TALLOC_CTX
*ctx
, int *type
)
2181 enum dialog_action action
;
2183 struct dialog_section
*section
;
2184 const char *reg_types
[] = {
2191 #define NTYPES ARRAY_SIZE(reg_types)
2192 struct button_spec spec
[] = {
2193 {.label
= "OK", .action
= DIALOG_OK
},
2194 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2197 bool flags
[NTYPES
] = { true };
2198 struct option_spec opsec
[NTYPES
+ 1];
2201 memset(&opsec
, '\0', sizeof(opsec
));
2202 for (i
= 0; i
< NTYPES
; ++i
) {
2203 opsec
[i
].label
= reg_types
[i
];
2204 opsec
[i
].state
= &flags
[i
];
2207 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "New Value", -1, -1);
2209 section
= dialog_section_label_new(dia
, "Select type for new value:");
2210 dialog_append_section(dia
, section
);
2211 section
= dialog_section_hsep_new(dia
, ' ');
2212 dialog_append_section(dia
, section
);
2213 section
= dialog_section_options_new(dia
, opsec
, 2, true);
2214 dialog_append_section(dia
, section
);
2215 section
= dialog_section_hsep_new(dia
, 0);
2216 dialog_append_section(dia
, section
);
2217 section
= dialog_section_buttons_new(dia
, spec
);
2218 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2219 dialog_append_section(dia
, section
);
2224 dialog_modal_loop(dia
, &err
, &action
);
2225 if (action
== DIALOG_OK
) {
2226 for (i
= 0; i
< NTYPES
; ++i
) {
2228 *type
= regtype_by_string(reg_types
[i
]);
2241 struct regedit_search_opts
*opts
;
2244 static bool search_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
2247 struct search_req
*search
= arg
;
2248 struct dialog_section
*query
;
2250 query
= dialog_find_section(dia
, "query");
2251 SMB_ASSERT(query
!= NULL
);
2253 if (!search
->opts
->search_key
&& !search
->opts
->search_value
) {
2254 dialog_notice(dia
, DIA_ALERT
, "Error",
2255 "Must search a key and/or a value");
2259 talloc_free(discard_const(search
->opts
->query
));
2260 search
->opts
->query
= dialog_section_text_field_get(search
->ctx
, query
);
2261 SMB_ASSERT(search
->opts
->query
!= NULL
);
2262 if (search
->opts
->query
[0] == '\0') {
2263 dialog_notice(dia
, DIA_ALERT
, "Error",
2264 "Query must not be blank.");
2271 int dialog_search_input(TALLOC_CTX
*ctx
, struct regedit_search_opts
*opts
)
2274 enum dialog_action action
;
2276 struct dialog_section
*section
, *query
;
2277 struct search_req search
;
2278 struct button_spec spec
[] = {
2279 {.label
= "Search", .action
= DIALOG_OK
},
2280 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2283 struct option_spec search_opts
[] = {
2284 {.label
= "Search Keys", .state
= &opts
->search_key
},
2285 {.label
= "Search Values", .state
= &opts
->search_value
},
2286 {.label
= "Recursive", .state
= &opts
->search_recursive
},
2287 {.label
= "Case Sensitive", .state
= &opts
->search_case
},
2291 if (!opts
->search_key
&& !opts
->search_value
) {
2292 opts
->search_key
= true;
2297 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "Search", -1, -1);
2298 dialog_set_submit_cb(dia
, search_on_submit
, &search
);
2299 section
= dialog_section_label_new(dia
, "Query");
2300 dialog_append_section(dia
, section
);
2301 query
= dialog_section_text_field_new(dia
, 1, -1);
2302 dialog_section_set_name(query
, "query");
2303 dialog_append_section(dia
, query
);
2304 section
= dialog_section_hsep_new(dia
, 0);
2305 dialog_append_section(dia
, section
);
2306 section
= dialog_section_options_new(dia
, search_opts
, 2, false);
2307 dialog_append_section(dia
, section
);
2308 section
= dialog_section_hsep_new(dia
, 0);
2309 dialog_append_section(dia
, section
);
2310 section
= dialog_section_buttons_new(dia
, spec
);
2311 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2312 dialog_append_section(dia
, section
);
2316 dialog_section_text_field_set(query
, opts
->query
);
2319 dialog_modal_loop(dia
, &err
, &action
);