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
;
726 static WERROR
text_field_create(struct dialog
*dia
,
727 struct dialog_section
*section
)
729 struct dialog_section_text_field
*text_field
=
730 talloc_get_type_abort(section
, struct dialog_section_text_field
);
732 text_field
->field
[0] = new_field(section
->nlines
, section
->ncols
,
734 if (text_field
->field
[0] == NULL
) {
737 set_field_back(text_field
->field
[0], A_REVERSE
);
738 set_field_opts(text_field
->field
[0], text_field
->opts
);
740 text_field
->form
= new_form(text_field
->field
);
741 if (text_field
->form
== NULL
) {
745 set_form_win(text_field
->form
, dia
->window
);
746 set_form_sub(text_field
->form
, section
->window
);
747 set_current_field(text_field
->form
, text_field
->field
[0]);
748 post_form(text_field
->form
);
753 static void text_field_destroy(struct dialog_section
*section
)
755 struct dialog_section_text_field
*text_field
=
756 talloc_get_type_abort(section
, struct dialog_section_text_field
);
758 if (text_field
->form
) {
759 unpost_form(text_field
->form
);
760 free_form(text_field
->form
);
761 text_field
->form
= NULL
;
763 if (text_field
->field
[0]) {
764 free_field(text_field
->field
[0]);
765 text_field
->field
[0] = NULL
;
769 static void text_field_on_input(struct dialog
*dia
,
770 struct dialog_section
*section
,
773 struct dialog_section_text_field
*text_field
=
774 talloc_get_type_abort(section
, struct dialog_section_text_field
);
778 form_driver(text_field
->form
, REQ_DEL_PREV
);
781 form_driver(text_field
->form
, REQ_DEL_CHAR
);
784 form_driver(text_field
->form
, c
);
789 static bool text_field_on_up(struct dialog
*dia
,
790 struct dialog_section
*section
)
792 struct dialog_section_text_field
*text_field
=
793 talloc_get_type_abort(section
, struct dialog_section_text_field
);
795 if (section
->nlines
> 1) {
796 form_driver(text_field
->form
, REQ_UP_CHAR
);
802 static bool text_field_on_down(struct dialog
*dia
,
803 struct dialog_section
*section
)
805 struct dialog_section_text_field
*text_field
=
806 talloc_get_type_abort(section
, struct dialog_section_text_field
);
808 if (section
->nlines
> 1) {
809 form_driver(text_field
->form
, REQ_DOWN_CHAR
);
815 static bool text_field_on_left(struct dialog
*dia
,
816 struct dialog_section
*section
)
818 struct dialog_section_text_field
*text_field
=
819 talloc_get_type_abort(section
, struct dialog_section_text_field
);
821 form_driver(text_field
->form
, REQ_LEFT_CHAR
);
826 static bool text_field_on_right(struct dialog
*dia
,
827 struct dialog_section
*section
)
829 struct dialog_section_text_field
*text_field
=
830 talloc_get_type_abort(section
, struct dialog_section_text_field
);
832 form_driver(text_field
->form
, REQ_RIGHT_CHAR
);
837 static enum dialog_action
text_field_on_enter(struct dialog
*dia
,
838 struct dialog_section
*section
)
840 struct dialog_section_text_field
*text_field
=
841 talloc_get_type_abort(section
, struct dialog_section_text_field
);
843 if (section
->nlines
> 1) {
844 form_driver(text_field
->form
, REQ_NEW_LINE
);
845 return DIALOG_IGNORE
;
851 static bool text_field_on_focus(struct dialog
*dia
,
852 struct dialog_section
*section
, bool forward
)
854 struct dialog_section_text_field
*text_field
=
855 talloc_get_type_abort(section
, struct dialog_section_text_field
);
857 pos_form_cursor(text_field
->form
);
862 struct dialog_section_ops text_field_ops
= {
863 .create
= text_field_create
,
864 .destroy
= text_field_destroy
,
865 .on_input
= text_field_on_input
,
866 .on_up
= text_field_on_up
,
867 .on_down
= text_field_on_down
,
868 .on_left
= text_field_on_left
,
869 .on_right
= text_field_on_right
,
870 .on_enter
= text_field_on_enter
,
871 .on_focus
= text_field_on_focus
874 static int text_field_free(struct dialog_section_text_field
*text_field
)
876 dialog_section_destroy(&text_field
->section
);
880 struct dialog_section
*dialog_section_text_field_new(TALLOC_CTX
*ctx
,
881 int height
, int width
)
883 struct dialog_section_text_field
*text_field
;
885 text_field
= talloc_zero(ctx
, struct dialog_section_text_field
);
886 if (text_field
== NULL
) {
889 talloc_set_destructor(text_field
, text_field_free
);
890 dialog_section_init(&text_field
->section
, &text_field_ops
,
892 text_field
->opts
= O_ACTIVE
| O_PUBLIC
| O_EDIT
| O_VISIBLE
| O_NULLOK
;
894 return &text_field
->section
;
897 const char *dialog_section_text_field_get(TALLOC_CTX
*ctx
,
898 struct dialog_section
*section
)
900 struct dialog_section_text_field
*text_field
=
901 talloc_get_type_abort(section
, struct dialog_section_text_field
);
903 form_driver(text_field
->form
, REQ_VALIDATION
);
905 return string_trim(ctx
, field_buffer(text_field
->field
[0], 0));
908 void dialog_section_text_field_set(struct dialog_section
*section
,
911 struct dialog_section_text_field
*text_field
=
912 talloc_get_type_abort(section
, struct dialog_section_text_field
);
914 set_field_buffer(text_field
->field
[0], 0, s
);
917 const char **dialog_section_text_field_get_lines(TALLOC_CTX
*ctx
,
918 struct dialog_section
*section
)
924 struct dialog_section_text_field
*text_field
=
925 talloc_get_type_abort(section
, struct dialog_section_text_field
);
927 form_driver(text_field
->form
, REQ_VALIDATION
);
928 buf
= field_buffer(text_field
->field
[0], 0);
930 dynamic_field_info(text_field
->field
[0], &rows
, &cols
, &max
);
932 arr
= talloc_zero_array(ctx
, const char *, rows
+ 1);
936 for (i
= 0; *buf
; ++i
, buf
+= cols
) {
937 SMB_ASSERT(i
< rows
);
938 arr
[i
] = string_trim_n(arr
, buf
, cols
);
944 WERROR
dialog_section_text_field_set_lines(TALLOC_CTX
*ctx
,
945 struct dialog_section
*section
,
949 size_t padding
, length
, index
;
952 struct dialog_section_text_field
*text_field
=
953 talloc_get_type_abort(section
, struct dialog_section_text_field
);
955 dynamic_field_info(text_field
->field
[0], &rows
, &cols
, &max
);
956 /* try to fit each string on it's own line. each line
957 needs to be padded with whitespace manually, since
958 ncurses fields do not have newlines. */
959 for (index
= 0, arrayp
= array
; *arrayp
!= NULL
; ++arrayp
) {
960 length
= MIN(strlen(*arrayp
), cols
);
961 padding
= cols
- length
;
962 buf
= talloc_realloc(ctx
, buf
, char,
963 talloc_array_length(buf
) +
964 length
+ padding
+ 1);
968 memcpy(&buf
[index
], *arrayp
, length
);
970 memset(&buf
[index
], ' ', padding
);
975 set_field_buffer(text_field
->field
[0], 0, buf
);
981 bool dialog_section_text_field_get_int(struct dialog_section
*section
,
987 struct dialog_section_text_field
*text_field
=
988 talloc_get_type_abort(section
, struct dialog_section_text_field
);
990 form_driver(text_field
->form
, REQ_VALIDATION
);
992 buf
= string_trim(section
, field_buffer(text_field
->field
[0], 0));
996 *out
= strtoll(buf
, &endp
, 0);
998 if (endp
== buf
|| endp
== NULL
|| endp
[0] != '\0') {
1006 bool dialog_section_text_field_get_uint(struct dialog_section
*section
,
1007 unsigned long long *out
)
1012 struct dialog_section_text_field
*text_field
=
1013 talloc_get_type_abort(section
, struct dialog_section_text_field
);
1015 form_driver(text_field
->form
, REQ_VALIDATION
);
1017 buf
= string_trim(section
, field_buffer(text_field
->field
[0], 0));
1021 *out
= strtoull(buf
, &endp
, 0);
1023 if (endp
== buf
|| endp
== NULL
|| endp
[0] != '\0') {
1030 /* hex editor field */
1031 struct dialog_section_hexedit
{
1032 struct dialog_section section
;
1033 struct hexedit
*buf
;
1036 #define HEXEDIT_MIN_SIZE 16
1037 static WERROR
hexedit_create(struct dialog
*dia
,
1038 struct dialog_section
*section
)
1040 struct dialog_section_hexedit
*hexedit
=
1041 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1043 hexedit
->buf
= hexedit_new(dia
, section
->window
, NULL
,
1045 if (hexedit
->buf
== NULL
) {
1049 hexedit_refresh(hexedit
->buf
);
1054 static void hexedit_destroy(struct dialog_section
*section
)
1056 struct dialog_section_hexedit
*hexedit
=
1057 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1060 TALLOC_FREE(hexedit
->buf
);
1064 static void hexedit_on_input(struct dialog
*dia
,
1065 struct dialog_section
*section
,
1068 struct dialog_section_hexedit
*hexedit
=
1069 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1073 // FIXME hexedit_driver(hexedit->buf, c);
1076 hexedit_driver(hexedit
->buf
, c
);
1081 static bool hexedit_on_up(struct dialog
*dia
,
1082 struct dialog_section
*section
)
1084 struct dialog_section_hexedit
*hexedit
=
1085 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1087 hexedit_driver(hexedit
->buf
, HE_CURSOR_UP
);
1092 static bool hexedit_on_down(struct dialog
*dia
,
1093 struct dialog_section
*section
)
1095 struct dialog_section_hexedit
*hexedit
=
1096 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1098 hexedit_driver(hexedit
->buf
, HE_CURSOR_DOWN
);
1103 static bool hexedit_on_left(struct dialog
*dia
,
1104 struct dialog_section
*section
)
1106 struct dialog_section_hexedit
*hexedit
=
1107 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1109 hexedit_driver(hexedit
->buf
, HE_CURSOR_LEFT
);
1114 static bool hexedit_on_right(struct dialog
*dia
,
1115 struct dialog_section
*section
)
1117 struct dialog_section_hexedit
*hexedit
=
1118 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1120 hexedit_driver(hexedit
->buf
, HE_CURSOR_RIGHT
);
1125 static enum dialog_action
hexedit_on_enter(struct dialog
*dia
,
1126 struct dialog_section
*section
)
1128 return DIALOG_IGNORE
;
1131 static bool hexedit_on_focus(struct dialog
*dia
,
1132 struct dialog_section
*section
, bool forward
)
1134 struct dialog_section_hexedit
*hexedit
=
1135 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1137 hexedit_set_cursor(hexedit
->buf
);
1142 struct dialog_section_ops hexedit_ops
= {
1143 .create
= hexedit_create
,
1144 .destroy
= hexedit_destroy
,
1145 .on_input
= hexedit_on_input
,
1146 .on_up
= hexedit_on_up
,
1147 .on_down
= hexedit_on_down
,
1148 .on_left
= hexedit_on_left
,
1149 .on_right
= hexedit_on_right
,
1150 .on_enter
= hexedit_on_enter
,
1151 .on_focus
= hexedit_on_focus
1154 static int hexedit_free(struct dialog_section_hexedit
*hexedit
)
1156 dialog_section_destroy(&hexedit
->section
);
1160 struct dialog_section
*dialog_section_hexedit_new(TALLOC_CTX
*ctx
, int height
)
1162 struct dialog_section_hexedit
*hexedit
;
1164 hexedit
= talloc_zero(ctx
, struct dialog_section_hexedit
);
1165 if (hexedit
== NULL
) {
1168 talloc_set_destructor(hexedit
, hexedit_free
);
1169 dialog_section_init(&hexedit
->section
, &hexedit_ops
,
1170 height
, LINE_WIDTH
);
1172 return &hexedit
->section
;
1175 WERROR
dialog_section_hexedit_set_buf(struct dialog_section
*section
,
1176 const void *data
, size_t size
)
1179 struct dialog_section_hexedit
*hexedit
=
1180 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1182 SMB_ASSERT(hexedit
->buf
!= NULL
);
1184 rv
= hexedit_set_buf(hexedit
->buf
, data
, size
);
1185 if (W_ERROR_IS_OK(rv
)) {
1186 hexedit_refresh(hexedit
->buf
);
1187 hexedit_set_cursor(hexedit
->buf
);
1193 void dialog_section_hexedit_get_buf(struct dialog_section
*section
,
1194 const void **data
, size_t *size
)
1196 struct dialog_section_hexedit
*hexedit
=
1197 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1199 SMB_ASSERT(hexedit
->buf
!= NULL
);
1200 *data
= hexedit_get_buf(hexedit
->buf
);
1201 *size
= hexedit_get_buf_len(hexedit
->buf
);
1205 struct dialog_section_buttons
{
1206 struct dialog_section section
;
1207 struct button_spec
*spec
;
1211 static void buttons_unhighlight(struct dialog_section_buttons
*buttons
)
1217 * Some GCC versions will complain if the macro version of
1218 * wattr_get is used. So we should enforce the use of the
1219 * function instead. See:
1220 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1222 (wattr_get
)(buttons
->section
.window
, &attr
, &pair
, NULL
);
1223 mvwchgat(buttons
->section
.window
, 0, 0, -1, A_NORMAL
, pair
, NULL
);
1224 wnoutrefresh(buttons
->section
.window
);
1227 static void buttons_highlight(struct dialog_section_buttons
*buttons
)
1229 struct button_spec
*spec
= &buttons
->spec
[buttons
->current_button
];
1234 * Some GCC versions will complain if the macro version of
1235 * wattr_get is used. So we should enforce the use of the
1236 * function instead. See:
1237 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1239 (wattr_get
)(buttons
->section
.window
, &attr
, &pair
, NULL
);
1240 mvwchgat(buttons
->section
.window
, 0, 0, -1, A_NORMAL
, pair
, NULL
);
1241 mvwchgat(buttons
->section
.window
, 0, spec
->col
,
1242 strlen(spec
->label
), A_REVERSE
, pair
, NULL
);
1243 wmove(buttons
->section
.window
, 0, spec
->col
+ 2);
1244 wcursyncup(buttons
->section
.window
);
1245 wnoutrefresh(buttons
->section
.window
);
1248 static bool buttons_highlight_next(struct dialog_section_buttons
*buttons
)
1250 if (buttons
->current_button
< talloc_array_length(buttons
->spec
) - 1) {
1251 buttons
->current_button
++;
1252 buttons_highlight(buttons
);
1258 static bool buttons_highlight_previous(struct dialog_section_buttons
*buttons
)
1260 if (buttons
->current_button
> 0) {
1261 buttons
->current_button
--;
1262 buttons_highlight(buttons
);
1268 static WERROR
buttons_create(struct dialog
*dia
,
1269 struct dialog_section
*section
)
1272 struct dialog_section_buttons
*buttons
=
1273 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1275 nbuttons
= talloc_array_length(buttons
->spec
);
1276 for (i
= 0; i
< nbuttons
; ++i
) {
1277 struct button_spec
*spec
= &buttons
->spec
[i
];
1278 mvwaddstr(section
->window
, 0, spec
->col
, spec
->label
);
1281 buttons
->current_button
= 0;
1286 static bool buttons_on_btab(struct dialog
*dia
, struct dialog_section
*section
)
1288 struct dialog_section_buttons
*buttons
=
1289 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1291 return buttons_highlight_previous(buttons
);
1294 static bool buttons_on_tab(struct dialog
*dia
, struct dialog_section
*section
)
1296 struct dialog_section_buttons
*buttons
=
1297 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1299 return buttons_highlight_next(buttons
);
1302 static enum dialog_action
buttons_on_enter(struct dialog
*dia
,
1303 struct dialog_section
*section
)
1305 struct dialog_section_buttons
*buttons
=
1306 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1307 struct button_spec
*spec
= &buttons
->spec
[buttons
->current_button
];
1309 if (spec
->on_enter
) {
1310 return spec
->on_enter(dia
, section
);
1313 return spec
->action
;
1316 static bool buttons_on_focus(struct dialog
*dia
,
1317 struct dialog_section
*section
,
1320 struct dialog_section_buttons
*buttons
=
1321 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1324 buttons
->current_button
= 0;
1326 buttons
->current_button
= talloc_array_length(buttons
->spec
) - 1;
1328 buttons_highlight(buttons
);
1333 static void buttons_on_leave_focus(struct dialog
*dia
,
1334 struct dialog_section
*section
)
1336 struct dialog_section_buttons
*buttons
=
1337 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1338 buttons_unhighlight(buttons
);
1341 struct dialog_section_ops buttons_ops
= {
1342 .create
= buttons_create
,
1343 .on_tab
= buttons_on_tab
,
1344 .on_btab
= buttons_on_btab
,
1345 .on_up
= buttons_on_btab
,
1346 .on_down
= buttons_on_tab
,
1347 .on_left
= buttons_on_btab
,
1348 .on_right
= buttons_on_tab
,
1349 .on_enter
= buttons_on_enter
,
1350 .on_focus
= buttons_on_focus
,
1351 .on_leave_focus
= buttons_on_leave_focus
1354 static int buttons_free(struct dialog_section_buttons
*buttons
)
1356 dialog_section_destroy(&buttons
->section
);
1360 struct dialog_section
*dialog_section_buttons_new(TALLOC_CTX
*ctx
,
1361 const struct button_spec
*spec
)
1363 struct dialog_section_buttons
*buttons
;
1367 buttons
= talloc_zero(ctx
, struct dialog_section_buttons
);
1368 if (buttons
== NULL
) {
1371 talloc_set_destructor(buttons
, buttons_free
);
1373 for (nbuttons
= 0; spec
[nbuttons
].label
; ++nbuttons
) {
1375 buttons
->spec
= talloc_zero_array(buttons
, struct button_spec
, nbuttons
);
1376 if (buttons
->spec
== NULL
) {
1380 for (width
= 0, i
= 0; i
< nbuttons
; ++i
) {
1381 buttons
->spec
[i
] = spec
[i
];
1382 buttons
->spec
[i
].label
= talloc_asprintf(buttons
->spec
,
1385 if (!buttons
->spec
[i
].label
) {
1389 buttons
->spec
[i
].col
= width
;
1390 width
+= strlen(buttons
->spec
[i
].label
);
1391 if (i
!= nbuttons
- 1) {
1396 dialog_section_init(&buttons
->section
, &buttons_ops
, 1, width
);
1398 return &buttons
->section
;
1401 talloc_free(buttons
);
1406 struct dialog_section_options
{
1407 struct dialog_section section
;
1408 struct option_spec
*spec
;
1413 static void options_unhighlight(struct dialog_section_options
*options
)
1420 * Some GCC versions will complain if the macro version of
1421 * wattr_get is used. So we should enforce the use of the
1422 * function instead. See:
1423 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1425 (wattr_get
)(options
->section
.window
, &attr
, &pair
, NULL
);
1426 for (row
= 0; row
< options
->section
.nlines
; ++row
) {
1427 mvwchgat(options
->section
.window
, row
, 0, -1, A_NORMAL
, pair
, NULL
);
1429 wnoutrefresh(options
->section
.window
);
1432 static void options_highlight(struct dialog_section_options
*options
)
1434 struct option_spec
*spec
= &options
->spec
[options
->current_option
];
1440 * Some GCC versions will complain if the macro version of
1441 * wattr_get is used. So we should enforce the use of the
1442 * function instead. See:
1443 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1445 (wattr_get
)(options
->section
.window
, &attr
, &pair
, NULL
);
1446 for (row
= 0; row
< options
->section
.nlines
; ++row
) {
1447 mvwchgat(options
->section
.window
, row
, 0, -1, A_NORMAL
, pair
, NULL
);
1449 mvwchgat(options
->section
.window
, spec
->row
, spec
->col
,
1450 strlen(spec
->label
), A_REVERSE
, pair
, NULL
);
1451 wmove(options
->section
.window
, spec
->row
, spec
->col
+ 4);
1452 wcursyncup(options
->section
.window
);
1453 wnoutrefresh(options
->section
.window
);
1456 static void options_render_state(struct dialog_section_options
*options
)
1460 noptions
= talloc_array_length(options
->spec
);
1461 for (i
= 0; i
< noptions
; ++i
) {
1462 struct option_spec
*spec
= &options
->spec
[i
];
1466 mvwaddch(options
->section
.window
,
1467 spec
->row
, spec
->col
+ 1, c
);
1468 wnoutrefresh(options
->section
.window
);
1472 static bool options_highlight_next(struct dialog_section_options
*options
)
1474 if (options
->current_option
< talloc_array_length(options
->spec
) - 1) {
1475 options
->current_option
++;
1476 options_highlight(options
);
1482 static bool options_highlight_previous(struct dialog_section_options
*options
)
1484 if (options
->current_option
> 0) {
1485 options
->current_option
--;
1486 options_highlight(options
);
1492 static WERROR
options_create(struct dialog
*dia
,
1493 struct dialog_section
*section
)
1496 struct dialog_section_options
*options
=
1497 talloc_get_type_abort(section
, struct dialog_section_options
);
1499 noptions
= talloc_array_length(options
->spec
);
1500 for (i
= 0; i
< noptions
; ++i
) {
1501 struct option_spec
*spec
= &options
->spec
[i
];
1502 mvwaddstr(section
->window
, spec
->row
, spec
->col
,
1506 options
->current_option
= 0;
1507 options_render_state(options
);
1512 static bool options_on_btab(struct dialog
*dia
, struct dialog_section
*section
)
1514 struct dialog_section_options
*options
=
1515 talloc_get_type_abort(section
, struct dialog_section_options
);
1517 return options_highlight_previous(options
);
1520 static bool options_on_tab(struct dialog
*dia
, struct dialog_section
*section
)
1522 struct dialog_section_options
*options
=
1523 talloc_get_type_abort(section
, struct dialog_section_options
);
1525 return options_highlight_next(options
);
1528 static void options_on_input(struct dialog
*dia
, struct dialog_section
*section
, int c
)
1530 struct dialog_section_options
*options
=
1531 talloc_get_type_abort(section
, struct dialog_section_options
);
1534 struct option_spec
*spec
= &options
->spec
[options
->current_option
];
1535 if (options
->single_select
) {
1537 noptions
= talloc_array_length(options
->spec
);
1538 for (i
= 0; i
< noptions
; ++i
) {
1539 *(options
->spec
[i
].state
) = false;
1542 *spec
->state
= !*spec
->state
;
1543 options_unhighlight(options
);
1544 options_render_state(options
);
1545 options_highlight(options
);
1549 static enum dialog_action
options_on_enter(struct dialog
*dia
, struct dialog_section
*section
)
1551 options_on_input(dia
, section
, ' ');
1555 static bool options_on_focus(struct dialog
*dia
,
1556 struct dialog_section
*section
,
1559 struct dialog_section_options
*options
=
1560 talloc_get_type_abort(section
, struct dialog_section_options
);
1563 options
->current_option
= 0;
1565 options
->current_option
= talloc_array_length(options
->spec
) - 1;
1567 options_highlight(options
);
1572 static void options_on_leave_focus(struct dialog
*dia
,
1573 struct dialog_section
*section
)
1575 struct dialog_section_options
*options
=
1576 talloc_get_type_abort(section
, struct dialog_section_options
);
1577 options_unhighlight(options
);
1580 struct dialog_section_ops options_ops
= {
1581 .create
= options_create
,
1582 .on_tab
= options_on_tab
,
1583 .on_btab
= options_on_btab
,
1584 .on_up
= options_on_btab
,
1585 .on_down
= options_on_tab
,
1586 .on_left
= options_on_btab
,
1587 .on_right
= options_on_tab
,
1588 .on_input
= options_on_input
,
1589 .on_enter
= options_on_enter
,
1590 .on_focus
= options_on_focus
,
1591 .on_leave_focus
= options_on_leave_focus
1594 static int options_free(struct dialog_section_options
*options
)
1596 dialog_section_destroy(&options
->section
);
1600 struct dialog_section
*dialog_section_options_new(TALLOC_CTX
*ctx
,
1601 const struct option_spec
*spec
,
1602 int maxcol
, bool single_select
)
1604 struct dialog_section_options
*options
;
1606 int width
, maxwidth
, maxrows
;
1608 options
= talloc_zero(ctx
, struct dialog_section_options
);
1609 if (options
== NULL
) {
1612 talloc_set_destructor(options
, options_free
);
1614 for (noptions
= 0; spec
[noptions
].label
; ++noptions
) {
1616 options
->spec
= talloc_zero_array(options
, struct option_spec
, noptions
);
1617 if (options
->spec
== NULL
) {
1621 maxrows
= noptions
/ maxcol
;
1622 if (noptions
% maxcol
) {
1626 for (width
= 0, maxwidth
= 0, i
= 0; i
< noptions
; ++i
) {
1627 options
->spec
[i
] = spec
[i
];
1628 options
->spec
[i
].label
= talloc_asprintf(options
->spec
,
1631 if (!options
->spec
[i
].label
) {
1635 options
->spec
[i
].col
= maxwidth
;
1636 options
->spec
[i
].row
= i
% maxrows
;
1637 width
= MAX(strlen(options
->spec
[i
].label
), width
);
1638 if (options
->spec
[i
].row
== maxrows
- 1 || i
== noptions
- 1) {
1639 maxwidth
+= width
+ 1;
1644 dialog_section_init(&options
->section
, &options_ops
, maxrows
, maxwidth
- 1);
1645 options
->single_select
= single_select
;
1647 return &options
->section
;
1650 talloc_free(options
);
1655 int dialog_input(TALLOC_CTX
*ctx
, const char **output
, const char *title
,
1656 const char *msg
, ...)
1660 enum dialog_action action
;
1662 struct dialog_section
*section
;
1663 struct button_spec spec
[] = {
1664 {.label
= "OK", .action
= DIALOG_OK
},
1665 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
1669 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, title
, -1, -1);
1671 section
= dialog_section_label_new_va(dia
, msg
, ap
);
1673 dialog_append_section(dia
, section
);
1674 section
= dialog_section_hsep_new(dia
, ' ');
1675 dialog_append_section(dia
, section
);
1676 section
= dialog_section_text_field_new(dia
, 1, -1);
1677 dialog_section_set_name(section
, "input");
1678 dialog_append_section(dia
, section
);
1679 section
= dialog_section_hsep_new(dia
, 0);
1680 dialog_append_section(dia
, section
);
1681 section
= dialog_section_buttons_new(dia
, spec
);
1682 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1683 dialog_append_section(dia
, section
);
1687 dialog_modal_loop(dia
, &err
, &action
);
1690 if (action
== DIALOG_OK
) {
1691 section
= dialog_find_section(dia
, "input");
1692 *output
= dialog_section_text_field_get(ctx
, section
);
1700 int dialog_notice(TALLOC_CTX
*ctx
, enum dialog_type type
,
1701 const char *title
, const char *msg
, ...)
1705 enum dialog_action action
;
1707 struct dialog_section
*section
;
1708 struct button_spec spec
[3];
1710 memset(&spec
, '\0', sizeof(spec
));
1711 spec
[0].label
= "OK";
1712 spec
[0].action
= DIALOG_OK
;
1713 if (type
== DIA_CONFIRM
) {
1714 spec
[1].label
= "Cancel";
1715 spec
[1].action
= DIALOG_CANCEL
;
1718 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, title
, -1, -1);
1720 section
= dialog_section_label_new_va(dia
, msg
, ap
);
1722 dialog_append_section(dia
, section
);
1723 section
= dialog_section_hsep_new(dia
, 0);
1724 dialog_append_section(dia
, section
);
1725 section
= dialog_section_buttons_new(dia
, spec
);
1726 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1727 dialog_append_section(dia
, section
);
1731 dialog_modal_loop(dia
, &err
, &action
);
1741 struct registry_key
*key
;
1742 const struct value_item
*vitem
;
1745 static WERROR
fill_value_buffer(struct dialog
*dia
, struct edit_req
*edit
)
1748 struct dialog_section
*data
;
1750 if (edit
->vitem
== NULL
) {
1754 data
= dialog_find_section(dia
, "data");
1755 SMB_ASSERT(data
!= NULL
);
1757 switch (edit
->mode
) {
1760 if (edit
->vitem
->data
.length
>= 4) {
1761 v
= IVAL(edit
->vitem
->data
.data
, 0);
1763 tmp
= talloc_asprintf(dia
, "%u", (unsigned)v
);
1767 dialog_section_text_field_set(data
, tmp
);
1772 case REG_EXPAND_SZ
: {
1775 if (!pull_reg_sz(dia
, &edit
->vitem
->data
, &s
)) {
1778 dialog_section_text_field_set(data
, s
);
1781 case REG_MULTI_SZ
: {
1784 if (!pull_reg_multi_sz(dia
, &edit
->vitem
->data
, &array
)) {
1787 return dialog_section_text_field_set_lines(dia
, data
, array
);
1791 return dialog_section_hexedit_set_buf(data
,
1792 edit
->vitem
->data
.data
,
1793 edit
->vitem
->data
.length
);
1799 static bool value_exists(TALLOC_CTX
*ctx
, const struct registry_key
*key
,
1806 rv
= reg_key_get_value_by_name(ctx
, key
, name
, &type
, &blob
);
1808 return W_ERROR_IS_OK(rv
);
1811 static bool edit_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
1814 struct edit_req
*edit
= arg
;
1818 struct dialog_section
*name_section
, *data
;
1820 name_section
= dialog_find_section(dia
, "name");
1822 name
= dialog_section_text_field_get(dia
, name_section
);
1823 if (*name
== '\0') {
1824 dialog_notice(dia
, DIA_ALERT
, "Error",
1825 "Value name must not be blank.");
1828 if (value_exists(dia
, edit
->key
, name
)) {
1829 dialog_notice(dia
, DIA_ALERT
, "Error",
1830 "Value named \"%s\" already exists.",
1835 SMB_ASSERT(edit
->vitem
);
1836 name
= edit
->vitem
->value_name
;
1840 data
= dialog_find_section(dia
, "data");
1841 SMB_ASSERT(data
!= NULL
);
1844 switch (edit
->mode
) {
1846 unsigned long long v
;
1849 if (!dialog_section_text_field_get_uint(data
, &v
)) {
1850 dialog_notice(dia
, DIA_ALERT
, "Error",
1851 "REG_DWORD value must be an integer.");
1854 if (v
> UINT32_MAX
) {
1855 dialog_notice(dia
, DIA_ALERT
, "Error",
1856 "REG_DWORD value must less than %lu.",
1857 (unsigned long)UINT32_MAX
);
1861 blob
= data_blob_talloc(dia
, NULL
, sizeof(val
));
1862 SIVAL(blob
.data
, 0, val
);
1866 case REG_EXPAND_SZ
: {
1869 buf
= dialog_section_text_field_get(dia
, data
);
1870 if (!buf
|| !push_reg_sz(dia
, &blob
, buf
)) {
1875 case REG_MULTI_SZ
: {
1878 lines
= dialog_section_text_field_get_lines(dia
, data
);
1879 if (!lines
|| !push_reg_multi_sz(dia
, &blob
, lines
)) {
1888 dialog_section_hexedit_get_buf(data
, &buf
, &len
);
1889 blob
= data_blob_talloc(dia
, buf
, len
);
1894 if (W_ERROR_IS_OK(rv
)) {
1895 rv
= reg_val_set(edit
->key
, name
, edit
->type
, blob
);
1898 if (!W_ERROR_IS_OK(rv
)) {
1899 const char *msg
= get_friendly_werror_msg(rv
);
1900 dialog_notice(dia
, DIA_ALERT
, "Error",
1901 "Error saving value:\n%s", msg
);
1910 int dialog_edit_value(TALLOC_CTX
*ctx
, struct registry_key
*key
,
1911 uint32_t type
, const struct value_item
*vitem
,
1912 bool force_binary
, WERROR
*err
,
1915 enum dialog_action action
;
1917 struct dialog_section
*section
;
1918 struct edit_req edit
;
1919 struct button_spec spec
[] = {
1920 {.label
= "OK", .action
= DIALOG_OK
},
1921 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
1929 if (force_binary
|| (vitem
&& vitem
->unprintable
)) {
1930 edit
.mode
= REG_BINARY
;
1933 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "Edit Value", -1, -1);
1934 dialog_set_submit_cb(dia
, edit_on_submit
, &edit
);
1936 section
= dialog_section_label_new(dia
, "Type");
1937 dialog_append_section(dia
, section
);
1938 section
= dialog_section_label_new(dia
, "%s",
1940 dialog_append_section(dia
, section
);
1941 section
= dialog_section_hsep_new(dia
, ' ');
1942 dialog_append_section(dia
, section
);
1944 section
= dialog_section_label_new(dia
, "Name");
1945 dialog_append_section(dia
, section
);
1947 section
= dialog_section_label_new(dia
, "%s",
1950 section
= dialog_section_text_field_new(dia
, 1, 50);
1951 dialog_section_set_name(section
, "name");
1953 dialog_append_section(dia
, section
);
1954 section
= dialog_section_hsep_new(dia
, ' ');
1955 dialog_append_section(dia
, section
);
1957 section
= dialog_section_label_new(dia
, "Data");
1958 dialog_append_section(dia
, section
);
1960 switch (edit
.mode
) {
1964 section
= dialog_section_text_field_new(dia
, 1, 50);
1967 section
= dialog_section_text_field_new(dia
, 10, 50);
1971 section
= dialog_section_hexedit_new(dia
, 10);
1975 dialog_section_set_name(section
, "data");
1976 dialog_append_section(dia
, section
);
1978 section
= dialog_section_hsep_new(dia
, 0);
1979 dialog_append_section(dia
, section
);
1980 section
= dialog_section_buttons_new(dia
, spec
);
1981 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1982 dialog_append_section(dia
, section
);
1986 *err
= fill_value_buffer(dia
, &edit
);
1987 if (!W_ERROR_IS_OK(*err
)) {
1988 return DIALOG_CANCEL
;
1992 dialog_modal_loop(dia
, err
, &action
);
1994 if (action
== DIALOG_OK
&& name
) {
1996 *name
= talloc_strdup(ctx
, vitem
->value_name
);
1997 } else if ((section
= dialog_find_section(dia
, "name"))) {
1998 *name
= dialog_section_text_field_get(ctx
, section
);
2007 int dialog_select_type(TALLOC_CTX
*ctx
, int *type
)
2010 enum dialog_action action
;
2012 struct dialog_section
*section
;
2013 const char *reg_types
[] = {
2020 #define NTYPES ARRAY_SIZE(reg_types)
2021 struct button_spec spec
[] = {
2022 {.label
= "OK", .action
= DIALOG_OK
},
2023 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2026 bool flags
[NTYPES
] = { true };
2027 struct option_spec opsec
[NTYPES
+ 1];
2030 memset(&opsec
, '\0', sizeof(opsec
));
2031 for (i
= 0; i
< NTYPES
; ++i
) {
2032 opsec
[i
].label
= reg_types
[i
];
2033 opsec
[i
].state
= &flags
[i
];
2036 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "New Value", -1, -1);
2038 section
= dialog_section_label_new(dia
, "Select type for new value:");
2039 dialog_append_section(dia
, section
);
2040 section
= dialog_section_hsep_new(dia
, ' ');
2041 dialog_append_section(dia
, section
);
2042 section
= dialog_section_options_new(dia
, opsec
, 2, true);
2043 dialog_append_section(dia
, section
);
2044 section
= dialog_section_hsep_new(dia
, 0);
2045 dialog_append_section(dia
, section
);
2046 section
= dialog_section_buttons_new(dia
, spec
);
2047 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2048 dialog_append_section(dia
, section
);
2053 dialog_modal_loop(dia
, &err
, &action
);
2054 if (action
== DIALOG_OK
) {
2055 for (i
= 0; i
< NTYPES
; ++i
) {
2057 *type
= regtype_by_string(reg_types
[i
]);
2070 struct regedit_search_opts
*opts
;
2073 static bool search_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
2076 struct search_req
*search
= arg
;
2077 struct dialog_section
*query
;
2079 query
= dialog_find_section(dia
, "query");
2080 SMB_ASSERT(query
!= NULL
);
2082 if (!search
->opts
->search_key
&& !search
->opts
->search_value
) {
2083 dialog_notice(dia
, DIA_ALERT
, "Error",
2084 "Must search a key and/or a value");
2088 talloc_free(discard_const(search
->opts
->query
));
2089 search
->opts
->query
= dialog_section_text_field_get(search
->ctx
, query
);
2090 SMB_ASSERT(search
->opts
->query
!= NULL
);
2091 if (search
->opts
->query
[0] == '\0') {
2092 dialog_notice(dia
, DIA_ALERT
, "Error",
2093 "Query must not be blank.");
2100 int dialog_search_input(TALLOC_CTX
*ctx
, struct regedit_search_opts
*opts
)
2103 enum dialog_action action
;
2105 struct dialog_section
*section
, *query
;
2106 struct search_req search
;
2107 struct button_spec spec
[] = {
2108 {.label
= "Search", .action
= DIALOG_OK
},
2109 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2112 struct option_spec search_opts
[] = {
2113 {.label
= "Search Keys", .state
= &opts
->search_key
},
2114 {.label
= "Search Values", .state
= &opts
->search_value
},
2115 {.label
= "Recursive", .state
= &opts
->search_recursive
},
2116 {.label
= "Case Sensitive", .state
= &opts
->search_case
},
2120 if (!opts
->search_key
&& !opts
->search_value
) {
2121 opts
->search_key
= true;
2126 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "Search", -1, -1);
2127 dialog_set_submit_cb(dia
, search_on_submit
, &search
);
2128 section
= dialog_section_label_new(dia
, "Query");
2129 dialog_append_section(dia
, section
);
2130 query
= dialog_section_text_field_new(dia
, 1, -1);
2131 dialog_section_set_name(query
, "query");
2132 dialog_append_section(dia
, query
);
2133 section
= dialog_section_hsep_new(dia
, 0);
2134 dialog_append_section(dia
, section
);
2135 section
= dialog_section_options_new(dia
, search_opts
, 2, false);
2136 dialog_append_section(dia
, section
);
2137 section
= dialog_section_hsep_new(dia
, 0);
2138 dialog_append_section(dia
, section
);
2139 section
= dialog_section_buttons_new(dia
, spec
);
2140 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2141 dialog_append_section(dia
, section
);
2145 dialog_section_text_field_set(query
, opts
->query
);
2148 dialog_modal_loop(dia
, &err
, &action
);