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"
27 #include "lib/util/smb_strtox.h"
31 static char *string_trim_n(TALLOC_CTX
*ctx
, const char *buf
, size_t n
)
35 str
= talloc_strndup(ctx
, buf
, n
);
38 trim_string(str
, " ", " ");
44 static char *string_trim(TALLOC_CTX
*ctx
, const char *buf
)
48 str
= talloc_strdup(ctx
, buf
);
51 trim_string(str
, " ", " ");
57 static int dialog_free(struct dialog
*dia
)
64 static bool default_validator(struct dialog
*dia
, struct dialog_section
*sect
,
70 struct dialog
*dialog_new(TALLOC_CTX
*ctx
, short color
, const char *title
,
75 dia
= talloc_zero(ctx
, struct dialog
);
80 talloc_set_destructor(dia
, dialog_free
);
82 dia
->title
= talloc_strdup(dia
, title
);
83 if (dia
->title
== NULL
) {
89 dia
->submit
= default_validator
;
100 void dialog_set_submit_cb(struct dialog
*dia
, dialog_submit_cb cb
, void *arg
)
103 dia
->submit_arg
= arg
;
106 static void center_above_window(int *nlines
, int *ncols
, int *y
, int *x
)
108 int centery
, centerx
;
115 if (*nlines
> LINES
) {
122 if (*nlines
/2 < centery
) {
123 *y
= centery
- *nlines
/ 2;
125 if (*ncols
/2 < centerx
) {
126 *x
= centerx
- *ncols
/ 2;
130 void dialog_section_destroy(struct dialog_section
*section
)
132 if (section
->ops
->destroy
) {
133 section
->ops
->destroy(section
);
135 if (section
->window
) {
136 delwin(section
->window
);
137 section
->window
= NULL
;
141 void dialog_section_init(struct dialog_section
*section
,
142 const struct dialog_section_ops
*ops
,
143 int nlines
, int ncols
)
146 section
->nlines
= nlines
;
147 section
->ncols
= ncols
;
150 const char *dialog_section_get_name(struct dialog_section
*section
)
152 return section
->name
;
155 void dialog_section_set_name(struct dialog_section
*section
, const char *name
)
157 TALLOC_FREE(section
->name
);
158 section
->name
= talloc_strdup(section
, name
);
161 void dialog_section_set_justify(struct dialog_section
*section
,
162 enum section_justify justify
)
164 section
->justify
= justify
;
167 /* append a section to the dialog's circular list */
168 void dialog_append_section(struct dialog
*dia
,
169 struct dialog_section
*section
)
171 SMB_ASSERT(section
!= NULL
);
173 if (!dia
->head_section
) {
174 dia
->head_section
= section
;
176 if (dia
->tail_section
) {
177 dia
->tail_section
->next
= section
;
179 section
->prev
= dia
->tail_section
;
180 section
->next
= dia
->head_section
;
181 dia
->head_section
->prev
= section
;
182 dia
->tail_section
= section
;
185 struct dialog_section
*dialog_find_section(struct dialog
*dia
, const char *name
)
187 struct dialog_section
*section
= dia
->head_section
;
190 if (section
->name
&& strequal(section
->name
, name
)) {
193 section
= section
->next
;
194 } while (section
!= dia
->head_section
);
199 static void section_on_input(struct dialog
*dia
, int c
)
201 struct dialog_section
*section
= dia
->current_section
;
203 if (!section
->ops
->on_input
) {
206 section
->ops
->on_input(dia
, section
, c
);
209 static bool section_on_tab(struct dialog
*dia
)
211 struct dialog_section
*section
= dia
->current_section
;
213 if (!section
|| !section
->ops
->on_tab
) {
216 return section
->ops
->on_tab(dia
, section
);
219 static bool section_on_btab(struct dialog
*dia
)
221 struct dialog_section
*section
= dia
->current_section
;
223 if (!section
|| !section
->ops
->on_btab
) {
226 return section
->ops
->on_btab(dia
, section
);
229 static bool section_on_up(struct dialog
*dia
)
231 struct dialog_section
*section
= dia
->current_section
;
233 if (!section
|| !section
->ops
->on_up
) {
236 return section
->ops
->on_up(dia
, section
);
239 static bool section_on_down(struct dialog
*dia
)
241 struct dialog_section
*section
= dia
->current_section
;
243 if (!section
|| !section
->ops
->on_down
) {
246 return section
->ops
->on_down(dia
, section
);
249 static bool section_on_left(struct dialog
*dia
)
251 struct dialog_section
*section
= dia
->current_section
;
253 if (!section
|| !section
->ops
->on_left
) {
256 return section
->ops
->on_left(dia
, section
);
259 static bool section_on_right(struct dialog
*dia
)
261 struct dialog_section
*section
= dia
->current_section
;
263 if (!section
|| !section
->ops
->on_right
) {
266 return section
->ops
->on_right(dia
, section
);
269 static enum dialog_action
section_on_enter(struct dialog
*dia
)
271 struct dialog_section
*section
= dia
->current_section
;
273 if (!section
|| !section
->ops
->on_enter
) {
276 return section
->ops
->on_enter(dia
, section
);
279 static bool section_on_focus(struct dialog
*dia
, bool forward
)
281 struct dialog_section
*section
= dia
->current_section
;
283 if (!section
->ops
->on_focus
) {
286 return section
->ops
->on_focus(dia
, section
, forward
);
289 static void section_on_leave_focus(struct dialog
*dia
)
291 struct dialog_section
*section
= dia
->current_section
;
293 if (section
->ops
->on_leave_focus
) {
294 section
->ops
->on_leave_focus(dia
, section
);
298 static void section_set_next_focus(struct dialog
*dia
)
300 section_on_leave_focus(dia
);
303 dia
->current_section
= dia
->current_section
->next
;
304 } while (!section_on_focus(dia
, true));
307 static void section_set_previous_focus(struct dialog
*dia
)
309 section_on_leave_focus(dia
);
312 dia
->current_section
= dia
->current_section
->prev
;
313 } while (!section_on_focus(dia
, false));
316 WERROR
dialog_create(struct dialog
*dia
)
321 struct dialog_section
*section
;
325 SMB_ASSERT(dia
->head_section
!= NULL
);
327 /* calculate total size based on sections */
328 section
= dia
->head_section
;
330 nlines
+= section
->nlines
;
331 ncols
= MAX(ncols
, section
->ncols
);
332 section
= section
->next
;
333 } while (section
!= dia
->head_section
);
335 /* fill in widths for sections that expand */
336 section
= dia
->head_section
;
338 if (section
->ncols
< 0) {
339 section
->ncols
= ncols
;
341 section
= section
->next
;
342 } while (section
!= dia
->head_section
);
344 /* create window for dialog */
347 dia
->pad
= newpad(nlines
, ncols
);
348 if (dia
->pad
== NULL
) {
349 rv
= WERR_NOT_ENOUGH_MEMORY
;
352 dia
->centered
= false;
353 if (dia
->y
< 0 || dia
->x
< 0) {
354 dia
->centered
= true;
355 center_above_window(&nlines
, &ncols
, &dia
->y
, &dia
->x
);
357 dia
->window
= newwin(nlines
, ncols
, dia
->y
, dia
->x
);
358 if (dia
->window
== NULL
) {
359 rv
= WERR_NOT_ENOUGH_MEMORY
;
362 dia
->panel
= new_panel(dia
->window
);
363 if (dia
->panel
== NULL
) {
364 rv
= WERR_NOT_ENOUGH_MEMORY
;
368 /* setup color and border */
369 getmaxyx(dia
->pad
, nlines
, ncols
);
370 wbkgdset(dia
->pad
, ' ' | COLOR_PAIR(dia
->color
));
372 mvwhline(dia
->pad
, 1, 2, 0, ncols
- 4);
373 mvwhline(dia
->pad
, nlines
- 2, 2, 0, ncols
- 4);
374 mvwvline(dia
->pad
, 2, 1, 0, nlines
- 4);
375 mvwvline(dia
->pad
, 2, ncols
- 2, 0, nlines
- 4);
376 mvwaddch(dia
->pad
, 1, 1, ACS_ULCORNER
);
377 mvwaddch(dia
->pad
, 1, ncols
- 2, ACS_URCORNER
);
378 mvwaddch(dia
->pad
, nlines
- 2, 1, ACS_LLCORNER
);
379 mvwaddch(dia
->pad
, nlines
- 2, ncols
- 2, ACS_LRCORNER
);
380 col
= ncols
/ 2 - MIN(strlen(dia
->title
) + 2, ncols
) / 2;
381 mvwprintw(dia
->pad
, 1, col
, " %s ", dia
->title
);
383 /* create subwindows for each section */
385 section
= dia
->head_section
;
389 switch (section
->justify
) {
390 case SECTION_JUSTIFY_LEFT
:
392 case SECTION_JUSTIFY_CENTER
:
393 col
+= (ncols
- 6)/ 2 - section
->ncols
/ 2;
395 case SECTION_JUSTIFY_RIGHT
:
399 section
->window
= subpad(dia
->pad
, section
->nlines
,
400 section
->ncols
, row
, col
);
401 if (section
->window
== NULL
) {
402 rv
= WERR_NOT_ENOUGH_MEMORY
;
405 SMB_ASSERT(section
->ops
->create
!= NULL
);
406 rv
= section
->ops
->create(dia
, section
);
407 row
+= section
->nlines
;
408 section
= section
->next
;
409 } while (section
!= dia
->head_section
&& W_ERROR_IS_OK(rv
));
411 dia
->current_section
= dia
->head_section
;
412 section_set_next_focus(dia
);
418 void dialog_show(struct dialog
*dia
)
426 getmaxyx(dia
->window
, nlines
, ncols
);
427 getmaxyx(dia
->pad
, pad_y
, pad_x
);
429 if (pad_y
> nlines
) {
430 y
= (pad_y
- nlines
) / 2;
434 x
= (pad_x
- ncols
) / 2;
436 rv
= copywin(dia
->pad
, dia
->window
, y
, x
, 0, 0,
437 nlines
- 1, ncols
- 1, false);
438 SMB_ASSERT(rv
== OK
);
440 getyx(dia
->pad
, pad_y
, pad_x
);
441 wmove(dia
->window
, pad_y
- y
, pad_x
- x
);
442 touchwin(dia
->window
);
443 wnoutrefresh(dia
->window
);
446 void dialog_destroy(struct dialog
*dia
)
448 struct dialog_section
*section
;
450 section
= dia
->head_section
;
452 dialog_section_destroy(section
);
453 section
= section
->next
;
454 } while (section
!= dia
->head_section
);
457 del_panel(dia
->panel
);
466 static int dialog_getch(struct dialog
*dia
)
471 if (c
== KEY_RESIZE
) {
472 int nlines
, ncols
, y
, x
;
473 int pad_nlines
, pad_ncols
;
474 int win_nlines
, win_ncols
;
476 getmaxyx(dia
->window
, win_nlines
, win_ncols
);
477 getmaxyx(dia
->pad
, pad_nlines
, pad_ncols
);
478 getbegyx(dia
->window
, y
, x
);
484 center_above_window(&nlines
, &ncols
, &y
, &x
);
486 if (nlines
+ y
> LINES
) {
487 if (nlines
> LINES
) {
493 if (ncols
+ x
> COLS
) {
501 if (nlines
!= win_nlines
|| ncols
!= win_ncols
) {
502 wresize(dia
->window
, nlines
, ncols
);
503 replace_panel(dia
->panel
, dia
->window
);
505 move_panel(dia
->panel
, y
, x
);
511 bool dialog_handle_input(struct dialog
*dia
, WERROR
*err
,
512 enum dialog_action
*action
)
518 c
= dialog_getch(dia
);
522 if (!section_on_tab(dia
)) {
523 section_set_next_focus(dia
);
527 if (!section_on_btab(dia
)) {
528 section_set_previous_focus(dia
);
532 if (!section_on_up(dia
)) {
533 section_set_previous_focus(dia
);
537 if (!section_on_down(dia
)) {
538 section_set_next_focus(dia
);
542 if (!section_on_left(dia
)) {
543 section_set_previous_focus(dia
);
547 if (!section_on_right(dia
)) {
548 section_set_next_focus(dia
);
553 *action
= section_on_enter(dia
);
560 return !dia
->submit(dia
, dia
->current_section
,
567 section_on_input(dia
, c
);
574 void dialog_modal_loop(struct dialog
*dia
, WERROR
*err
,
575 enum dialog_action
*action
)
581 } while (dialog_handle_input(dia
, err
, action
));
585 struct dialog_section_label
{
586 struct dialog_section section
;
590 static WERROR
label_create(struct dialog
*dia
, struct dialog_section
*section
)
593 struct dialog_section_label
*label
=
594 talloc_get_type_abort(section
, struct dialog_section_label
);
596 for (row
= 0; row
< section
->nlines
; ++row
) {
597 mvwaddstr(section
->window
, row
, 0, label
->text
[row
]);
603 struct dialog_section_ops label_ops
= {
604 .create
= label_create
,
607 static int label_free(struct dialog_section_label
*label
)
609 dialog_section_destroy(&label
->section
);
613 struct dialog_section
*dialog_section_label_new_va(TALLOC_CTX
*ctx
,
614 const char *msg
, va_list ap
)
616 struct dialog_section_label
*label
;
617 char *tmp
, *ptmp
, *line
, *saveptr
;
620 label
= talloc_zero(ctx
, struct dialog_section_label
);
624 talloc_set_destructor(label
, label_free
);
625 tmp
= talloc_vasprintf(label
, msg
, ap
);
630 for (nlines
= 0, ncols
= 0, ptmp
= tmp
;
631 (line
= strtok_r(ptmp
, "\n", &saveptr
)) != NULL
;
634 label
->text
= talloc_realloc(label
, label
->text
,
636 if (label
->text
== NULL
) {
639 ncols
= MAX(ncols
, strlen(line
));
640 label
->text
[nlines
] = talloc_strdup(label
->text
, line
);
641 if (label
->text
[nlines
] == NULL
) {
646 dialog_section_init(&label
->section
, &label_ops
, nlines
, ncols
);
648 return &label
->section
;
655 struct dialog_section
*dialog_section_label_new(TALLOC_CTX
*ctx
,
656 const char *msg
, ...)
659 struct dialog_section
*rv
;
662 rv
= dialog_section_label_new_va(ctx
, msg
, ap
);
668 /* horizontal separator */
669 struct dialog_section_hsep
{
670 struct dialog_section section
;
674 static WERROR
hsep_create(struct dialog
*dia
, struct dialog_section
*section
)
677 struct dialog_section_hsep
*hsep
=
678 talloc_get_type_abort(section
, struct dialog_section_hsep
);
680 whline(section
->window
, hsep
->sep
, section
->ncols
);
682 if (hsep
->sep
== 0 || hsep
->sep
== ACS_HLINE
) {
683 /* change the border characters around this section to
685 getparyx(section
->window
, y
, x
);
686 mvwaddch(dia
->pad
, y
, x
- 1, ACS_HLINE
);
687 mvwaddch(dia
->pad
, y
, x
- 2, ACS_LTEE
);
688 mvwaddch(dia
->pad
, y
, x
+ section
->ncols
, ACS_HLINE
);
689 mvwaddch(dia
->pad
, y
, x
+ section
->ncols
+ 1, ACS_RTEE
);
695 struct dialog_section_ops hsep_ops
= {
696 .create
= hsep_create
699 static int hsep_free(struct dialog_section_hsep
*hsep
)
701 dialog_section_destroy(&hsep
->section
);
705 struct dialog_section
*dialog_section_hsep_new(TALLOC_CTX
*ctx
, int sep
)
707 struct dialog_section_hsep
*hsep
;
709 hsep
= talloc_zero(ctx
, struct dialog_section_hsep
);
711 talloc_set_destructor(hsep
, hsep_free
);
712 dialog_section_init(&hsep
->section
, &hsep_ops
, 1, -1);
716 return &hsep
->section
;
719 /* text input field */
720 struct dialog_section_text_field
{
721 struct dialog_section section
;
728 static int get_cursor_col(struct dialog_section_text_field
*field
)
732 col
= field
->form
->curcol
+ field
->form
->begincol
;
737 static WERROR
text_field_create(struct dialog
*dia
,
738 struct dialog_section
*section
)
740 struct dialog_section_text_field
*text_field
=
741 talloc_get_type_abort(section
, struct dialog_section_text_field
);
743 text_field
->field
[0] = new_field(section
->nlines
, section
->ncols
,
745 if (text_field
->field
[0] == NULL
) {
746 return WERR_NOT_ENOUGH_MEMORY
;
748 set_field_back(text_field
->field
[0], A_REVERSE
);
749 set_field_opts(text_field
->field
[0], text_field
->opts
);
751 text_field
->form
= new_form(text_field
->field
);
752 if (text_field
->form
== NULL
) {
753 return WERR_NOT_ENOUGH_MEMORY
;
756 set_form_win(text_field
->form
, dia
->window
);
757 set_form_sub(text_field
->form
, section
->window
);
758 set_current_field(text_field
->form
, text_field
->field
[0]);
759 post_form(text_field
->form
);
764 static void text_field_destroy(struct dialog_section
*section
)
766 struct dialog_section_text_field
*text_field
=
767 talloc_get_type_abort(section
, struct dialog_section_text_field
);
769 if (text_field
->form
) {
770 unpost_form(text_field
->form
);
771 free_form(text_field
->form
);
772 text_field
->form
= NULL
;
774 if (text_field
->field
[0]) {
775 free_field(text_field
->field
[0]);
776 text_field
->field
[0] = NULL
;
780 static void text_field_on_input(struct dialog
*dia
,
781 struct dialog_section
*section
,
784 struct dialog_section_text_field
*text_field
=
785 talloc_get_type_abort(section
, struct dialog_section_text_field
);
789 if (text_field
->length
) {
790 text_field
->length
--;
792 form_driver(text_field
->form
, REQ_DEL_PREV
);
796 if (text_field
->length
) {
797 text_field
->length
--;
799 form_driver(text_field
->form
, REQ_DEL_CHAR
);
802 text_field
->length
++;
803 form_driver(text_field
->form
, c
);
808 static bool text_field_on_up(struct dialog
*dia
,
809 struct dialog_section
*section
)
811 struct dialog_section_text_field
*text_field
=
812 talloc_get_type_abort(section
, struct dialog_section_text_field
);
814 if (section
->nlines
> 1) {
815 form_driver(text_field
->form
, REQ_UP_CHAR
);
821 static bool text_field_on_down(struct dialog
*dia
,
822 struct dialog_section
*section
)
824 struct dialog_section_text_field
*text_field
=
825 talloc_get_type_abort(section
, struct dialog_section_text_field
);
827 if (section
->nlines
> 1) {
828 form_driver(text_field
->form
, REQ_DOWN_CHAR
);
834 static bool text_field_on_left(struct dialog
*dia
,
835 struct dialog_section
*section
)
837 struct dialog_section_text_field
*text_field
=
838 talloc_get_type_abort(section
, struct dialog_section_text_field
);
840 form_driver(text_field
->form
, REQ_LEFT_CHAR
);
845 static bool text_field_on_right(struct dialog
*dia
,
846 struct dialog_section
*section
)
848 struct dialog_section_text_field
*text_field
=
849 talloc_get_type_abort(section
, struct dialog_section_text_field
);
851 if (section
->nlines
> 1 ||
852 get_cursor_col(text_field
) < text_field
->length
) {
853 form_driver(text_field
->form
, REQ_RIGHT_CHAR
);
859 static enum dialog_action
text_field_on_enter(struct dialog
*dia
,
860 struct dialog_section
*section
)
862 struct dialog_section_text_field
*text_field
=
863 talloc_get_type_abort(section
, struct dialog_section_text_field
);
865 if (section
->nlines
> 1) {
866 text_field
->length
+= text_field
->form
->cols
;
867 form_driver(text_field
->form
, REQ_NEW_LINE
);
868 return DIALOG_IGNORE
;
874 static bool text_field_on_focus(struct dialog
*dia
,
875 struct dialog_section
*section
, bool forward
)
877 struct dialog_section_text_field
*text_field
=
878 talloc_get_type_abort(section
, struct dialog_section_text_field
);
880 pos_form_cursor(text_field
->form
);
885 struct dialog_section_ops text_field_ops
= {
886 .create
= text_field_create
,
887 .destroy
= text_field_destroy
,
888 .on_input
= text_field_on_input
,
889 .on_up
= text_field_on_up
,
890 .on_down
= text_field_on_down
,
891 .on_left
= text_field_on_left
,
892 .on_right
= text_field_on_right
,
893 .on_enter
= text_field_on_enter
,
894 .on_focus
= text_field_on_focus
897 static int text_field_free(struct dialog_section_text_field
*text_field
)
899 dialog_section_destroy(&text_field
->section
);
903 struct dialog_section
*dialog_section_text_field_new(TALLOC_CTX
*ctx
,
904 int height
, int width
)
906 struct dialog_section_text_field
*text_field
;
908 text_field
= talloc_zero(ctx
, struct dialog_section_text_field
);
909 if (text_field
== NULL
) {
912 talloc_set_destructor(text_field
, text_field_free
);
913 dialog_section_init(&text_field
->section
, &text_field_ops
,
915 text_field
->opts
= O_ACTIVE
| O_PUBLIC
| O_EDIT
| O_VISIBLE
| O_NULLOK
;
917 return &text_field
->section
;
920 const char *dialog_section_text_field_get(TALLOC_CTX
*ctx
,
921 struct dialog_section
*section
)
923 struct dialog_section_text_field
*text_field
=
924 talloc_get_type_abort(section
, struct dialog_section_text_field
);
926 form_driver(text_field
->form
, REQ_VALIDATION
);
928 return string_trim(ctx
, field_buffer(text_field
->field
[0], 0));
931 void dialog_section_text_field_set(struct dialog_section
*section
,
934 struct dialog_section_text_field
*text_field
=
935 talloc_get_type_abort(section
, struct dialog_section_text_field
);
937 text_field
->length
= strlen(s
);
938 set_field_buffer(text_field
->field
[0], 0, s
);
941 const char **dialog_section_text_field_get_lines(TALLOC_CTX
*ctx
,
942 struct dialog_section
*section
)
948 struct dialog_section_text_field
*text_field
=
949 talloc_get_type_abort(section
, struct dialog_section_text_field
);
951 form_driver(text_field
->form
, REQ_VALIDATION
);
952 buf
= field_buffer(text_field
->field
[0], 0);
954 dynamic_field_info(text_field
->field
[0], &rows
, &cols
, &max
);
956 arr
= talloc_zero_array(ctx
, const char *, rows
+ 1);
960 for (i
= 0; *buf
; ++i
, buf
+= cols
) {
961 SMB_ASSERT(i
< rows
);
962 arr
[i
] = string_trim_n(arr
, buf
, cols
);
968 WERROR
dialog_section_text_field_set_lines(TALLOC_CTX
*ctx
,
969 struct dialog_section
*section
,
973 size_t padding
, length
, idx
;
976 struct dialog_section_text_field
*text_field
=
977 talloc_get_type_abort(section
, struct dialog_section_text_field
);
979 dynamic_field_info(text_field
->field
[0], &rows
, &cols
, &max
);
980 /* try to fit each string on it's own line. each line
981 needs to be padded with whitespace manually, since
982 ncurses fields do not have newlines. */
983 for (idx
= 0, arrayp
= array
; *arrayp
!= NULL
; ++arrayp
) {
984 length
= MIN(strlen(*arrayp
), cols
);
985 padding
= cols
- length
;
986 buf
= talloc_realloc(ctx
, buf
, char,
987 talloc_array_length(buf
) +
988 length
+ padding
+ 1);
990 return WERR_NOT_ENOUGH_MEMORY
;
992 memcpy(&buf
[idx
], *arrayp
, length
);
994 memset(&buf
[idx
], ' ', padding
);
999 set_field_buffer(text_field
->field
[0], 0, buf
);
1005 bool dialog_section_text_field_get_int(struct dialog_section
*section
,
1011 struct dialog_section_text_field
*text_field
=
1012 talloc_get_type_abort(section
, struct dialog_section_text_field
);
1014 form_driver(text_field
->form
, REQ_VALIDATION
);
1016 buf
= string_trim(section
, field_buffer(text_field
->field
[0], 0));
1020 *out
= strtoll(buf
, &endp
, 0);
1022 if (endp
== buf
|| endp
== NULL
|| endp
[0] != '\0') {
1030 bool dialog_section_text_field_get_uint(struct dialog_section
*section
,
1031 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
= smb_strtoull(buf
, NULL
, 0, &error
, SMB_STR_FULL_STR_CONV
);
1052 /* hex editor field */
1053 struct dialog_section_hexedit
{
1054 struct dialog_section section
;
1055 struct hexedit
*buf
;
1058 #define HEXEDIT_MIN_SIZE 1
1059 static WERROR
hexedit_create(struct dialog
*dia
,
1060 struct dialog_section
*section
)
1062 struct dialog_section_hexedit
*hexedit
=
1063 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1065 hexedit
->buf
= hexedit_new(dia
, section
->window
, NULL
,
1067 if (hexedit
->buf
== NULL
) {
1068 return WERR_NOT_ENOUGH_MEMORY
;
1071 hexedit_refresh(hexedit
->buf
);
1076 static void hexedit_destroy(struct dialog_section
*section
)
1078 struct dialog_section_hexedit
*hexedit
=
1079 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1082 TALLOC_FREE(hexedit
->buf
);
1086 static void hexedit_on_input(struct dialog
*dia
,
1087 struct dialog_section
*section
,
1090 struct dialog_section_hexedit
*hexedit
=
1091 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1095 hexedit_driver(hexedit
->buf
, HE_BACKSPACE
);
1099 hexedit_driver(hexedit
->buf
, HE_DELETE
);
1102 hexedit_driver(hexedit
->buf
, c
);
1107 static bool hexedit_on_up(struct dialog
*dia
,
1108 struct dialog_section
*section
)
1110 struct dialog_section_hexedit
*hexedit
=
1111 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1113 hexedit_driver(hexedit
->buf
, HE_CURSOR_UP
);
1118 static bool hexedit_on_down(struct dialog
*dia
,
1119 struct dialog_section
*section
)
1121 struct dialog_section_hexedit
*hexedit
=
1122 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1124 hexedit_driver(hexedit
->buf
, HE_CURSOR_DOWN
);
1129 static bool hexedit_on_left(struct dialog
*dia
,
1130 struct dialog_section
*section
)
1132 struct dialog_section_hexedit
*hexedit
=
1133 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1135 hexedit_driver(hexedit
->buf
, HE_CURSOR_LEFT
);
1140 static bool hexedit_on_right(struct dialog
*dia
,
1141 struct dialog_section
*section
)
1143 struct dialog_section_hexedit
*hexedit
=
1144 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1146 hexedit_driver(hexedit
->buf
, HE_CURSOR_RIGHT
);
1151 static enum dialog_action
hexedit_on_enter(struct dialog
*dia
,
1152 struct dialog_section
*section
)
1154 return DIALOG_IGNORE
;
1157 static bool hexedit_on_focus(struct dialog
*dia
,
1158 struct dialog_section
*section
, bool forward
)
1160 struct dialog_section_hexedit
*hexedit
=
1161 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1163 hexedit_set_cursor(hexedit
->buf
);
1168 struct dialog_section_ops hexedit_ops
= {
1169 .create
= hexedit_create
,
1170 .destroy
= hexedit_destroy
,
1171 .on_input
= hexedit_on_input
,
1172 .on_up
= hexedit_on_up
,
1173 .on_down
= hexedit_on_down
,
1174 .on_left
= hexedit_on_left
,
1175 .on_right
= hexedit_on_right
,
1176 .on_enter
= hexedit_on_enter
,
1177 .on_focus
= hexedit_on_focus
1180 static int hexedit_free(struct dialog_section_hexedit
*hexedit
)
1182 dialog_section_destroy(&hexedit
->section
);
1186 struct dialog_section
*dialog_section_hexedit_new(TALLOC_CTX
*ctx
, int height
)
1188 struct dialog_section_hexedit
*hexedit
;
1190 hexedit
= talloc_zero(ctx
, struct dialog_section_hexedit
);
1191 if (hexedit
== NULL
) {
1194 talloc_set_destructor(hexedit
, hexedit_free
);
1195 dialog_section_init(&hexedit
->section
, &hexedit_ops
,
1196 height
, LINE_WIDTH
);
1198 return &hexedit
->section
;
1201 WERROR
dialog_section_hexedit_set_buf(struct dialog_section
*section
,
1202 const void *data
, size_t size
)
1205 struct dialog_section_hexedit
*hexedit
=
1206 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1208 SMB_ASSERT(hexedit
->buf
!= NULL
);
1210 rv
= hexedit_set_buf(hexedit
->buf
, data
, size
);
1211 if (W_ERROR_IS_OK(rv
)) {
1212 hexedit_refresh(hexedit
->buf
);
1213 hexedit_set_cursor(hexedit
->buf
);
1219 void dialog_section_hexedit_get_buf(struct dialog_section
*section
,
1220 const void **data
, size_t *size
)
1222 struct dialog_section_hexedit
*hexedit
=
1223 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1225 SMB_ASSERT(hexedit
->buf
!= NULL
);
1226 *data
= hexedit_get_buf(hexedit
->buf
);
1227 *size
= hexedit_get_buf_len(hexedit
->buf
);
1230 WERROR
dialog_section_hexedit_resize(struct dialog_section
*section
,
1234 struct dialog_section_hexedit
*hexedit
=
1235 talloc_get_type_abort(section
, struct dialog_section_hexedit
);
1237 SMB_ASSERT(hexedit
->buf
!= NULL
);
1238 rv
= hexedit_resize_buffer(hexedit
->buf
, size
);
1239 if (W_ERROR_IS_OK(rv
)) {
1240 hexedit_refresh(hexedit
->buf
);
1248 struct dialog_section_buttons
{
1249 struct dialog_section section
;
1250 struct button_spec
*spec
;
1254 static void buttons_unhighlight(struct dialog_section_buttons
*buttons
)
1260 * Some GCC versions will complain if the macro version of
1261 * wattr_get is used. So we should enforce the use of the
1262 * function instead. See:
1263 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1265 (wattr_get
)(buttons
->section
.window
, &attr
, &pair
, NULL
);
1266 mvwchgat(buttons
->section
.window
, 0, 0, -1, A_NORMAL
, pair
, NULL
);
1267 wnoutrefresh(buttons
->section
.window
);
1270 static void buttons_highlight(struct dialog_section_buttons
*buttons
)
1272 struct button_spec
*spec
= &buttons
->spec
[buttons
->current_button
];
1277 * Some GCC versions will complain if the macro version of
1278 * wattr_get is used. So we should enforce the use of the
1279 * function instead. See:
1280 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1282 (wattr_get
)(buttons
->section
.window
, &attr
, &pair
, NULL
);
1283 mvwchgat(buttons
->section
.window
, 0, 0, -1, A_NORMAL
, pair
, NULL
);
1284 mvwchgat(buttons
->section
.window
, 0, spec
->col
,
1285 strlen(spec
->label
), A_REVERSE
, pair
, NULL
);
1286 wmove(buttons
->section
.window
, 0, spec
->col
+ 2);
1287 wcursyncup(buttons
->section
.window
);
1288 wnoutrefresh(buttons
->section
.window
);
1291 static bool buttons_highlight_next(struct dialog_section_buttons
*buttons
)
1293 if (buttons
->current_button
< talloc_array_length(buttons
->spec
) - 1) {
1294 buttons
->current_button
++;
1295 buttons_highlight(buttons
);
1301 static bool buttons_highlight_previous(struct dialog_section_buttons
*buttons
)
1303 if (buttons
->current_button
> 0) {
1304 buttons
->current_button
--;
1305 buttons_highlight(buttons
);
1311 static WERROR
buttons_create(struct dialog
*dia
,
1312 struct dialog_section
*section
)
1315 struct dialog_section_buttons
*buttons
=
1316 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1318 nbuttons
= talloc_array_length(buttons
->spec
);
1319 for (i
= 0; i
< nbuttons
; ++i
) {
1320 struct button_spec
*spec
= &buttons
->spec
[i
];
1321 mvwaddstr(section
->window
, 0, spec
->col
, spec
->label
);
1324 buttons
->current_button
= 0;
1329 static bool buttons_on_btab(struct dialog
*dia
, struct dialog_section
*section
)
1331 struct dialog_section_buttons
*buttons
=
1332 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1334 return buttons_highlight_previous(buttons
);
1337 static bool buttons_on_tab(struct dialog
*dia
, struct dialog_section
*section
)
1339 struct dialog_section_buttons
*buttons
=
1340 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1342 return buttons_highlight_next(buttons
);
1345 static enum dialog_action
buttons_on_enter(struct dialog
*dia
,
1346 struct dialog_section
*section
)
1348 struct dialog_section_buttons
*buttons
=
1349 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1350 struct button_spec
*spec
= &buttons
->spec
[buttons
->current_button
];
1352 if (spec
->on_enter
) {
1353 return spec
->on_enter(dia
, section
);
1356 return spec
->action
;
1359 static bool buttons_on_focus(struct dialog
*dia
,
1360 struct dialog_section
*section
,
1363 struct dialog_section_buttons
*buttons
=
1364 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1367 buttons
->current_button
= 0;
1369 buttons
->current_button
= talloc_array_length(buttons
->spec
) - 1;
1371 buttons_highlight(buttons
);
1376 static void buttons_on_leave_focus(struct dialog
*dia
,
1377 struct dialog_section
*section
)
1379 struct dialog_section_buttons
*buttons
=
1380 talloc_get_type_abort(section
, struct dialog_section_buttons
);
1381 buttons_unhighlight(buttons
);
1384 struct dialog_section_ops buttons_ops
= {
1385 .create
= buttons_create
,
1386 .on_tab
= buttons_on_tab
,
1387 .on_btab
= buttons_on_btab
,
1388 .on_up
= buttons_on_btab
,
1389 .on_down
= buttons_on_tab
,
1390 .on_left
= buttons_on_btab
,
1391 .on_right
= buttons_on_tab
,
1392 .on_enter
= buttons_on_enter
,
1393 .on_focus
= buttons_on_focus
,
1394 .on_leave_focus
= buttons_on_leave_focus
1397 static int buttons_free(struct dialog_section_buttons
*buttons
)
1399 dialog_section_destroy(&buttons
->section
);
1403 struct dialog_section
*dialog_section_buttons_new(TALLOC_CTX
*ctx
,
1404 const struct button_spec
*spec
)
1406 struct dialog_section_buttons
*buttons
;
1410 buttons
= talloc_zero(ctx
, struct dialog_section_buttons
);
1411 if (buttons
== NULL
) {
1414 talloc_set_destructor(buttons
, buttons_free
);
1416 for (nbuttons
= 0; spec
[nbuttons
].label
; ++nbuttons
) {
1418 buttons
->spec
= talloc_zero_array(buttons
, struct button_spec
, nbuttons
);
1419 if (buttons
->spec
== NULL
) {
1423 for (width
= 0, i
= 0; i
< nbuttons
; ++i
) {
1424 buttons
->spec
[i
] = spec
[i
];
1425 buttons
->spec
[i
].label
= talloc_asprintf(buttons
->spec
,
1428 if (!buttons
->spec
[i
].label
) {
1432 buttons
->spec
[i
].col
= width
;
1433 width
+= strlen(buttons
->spec
[i
].label
);
1434 if (i
!= nbuttons
- 1) {
1439 dialog_section_init(&buttons
->section
, &buttons_ops
, 1, width
);
1441 return &buttons
->section
;
1444 talloc_free(buttons
);
1449 struct dialog_section_options
{
1450 struct dialog_section section
;
1451 struct option_spec
*spec
;
1456 static void options_unhighlight(struct dialog_section_options
*options
)
1463 * Some GCC versions will complain if the macro version of
1464 * wattr_get is used. So we should enforce the use of the
1465 * function instead. See:
1466 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1468 (wattr_get
)(options
->section
.window
, &attr
, &pair
, NULL
);
1469 for (row
= 0; row
< options
->section
.nlines
; ++row
) {
1470 mvwchgat(options
->section
.window
, row
, 0, -1, A_NORMAL
, pair
, NULL
);
1472 wnoutrefresh(options
->section
.window
);
1475 static void options_highlight(struct dialog_section_options
*options
)
1477 struct option_spec
*spec
= &options
->spec
[options
->current_option
];
1483 * Some GCC versions will complain if the macro version of
1484 * wattr_get is used. So we should enforce the use of the
1485 * function instead. See:
1486 * http://lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
1488 (wattr_get
)(options
->section
.window
, &attr
, &pair
, NULL
);
1489 for (row
= 0; row
< options
->section
.nlines
; ++row
) {
1490 mvwchgat(options
->section
.window
, row
, 0, -1, A_NORMAL
, pair
, NULL
);
1492 mvwchgat(options
->section
.window
, spec
->row
, spec
->col
,
1493 strlen(spec
->label
), A_REVERSE
, pair
, NULL
);
1494 wmove(options
->section
.window
, spec
->row
, spec
->col
+ 4);
1495 wcursyncup(options
->section
.window
);
1496 wnoutrefresh(options
->section
.window
);
1499 static void options_render_state(struct dialog_section_options
*options
)
1503 noptions
= talloc_array_length(options
->spec
);
1504 for (i
= 0; i
< noptions
; ++i
) {
1505 struct option_spec
*spec
= &options
->spec
[i
];
1509 mvwaddch(options
->section
.window
,
1510 spec
->row
, spec
->col
+ 1, c
);
1511 wnoutrefresh(options
->section
.window
);
1515 static bool options_highlight_next(struct dialog_section_options
*options
)
1517 if (options
->current_option
< talloc_array_length(options
->spec
) - 1) {
1518 options
->current_option
++;
1519 options_highlight(options
);
1525 static bool options_highlight_previous(struct dialog_section_options
*options
)
1527 if (options
->current_option
> 0) {
1528 options
->current_option
--;
1529 options_highlight(options
);
1535 static WERROR
options_create(struct dialog
*dia
,
1536 struct dialog_section
*section
)
1539 struct dialog_section_options
*options
=
1540 talloc_get_type_abort(section
, struct dialog_section_options
);
1542 noptions
= talloc_array_length(options
->spec
);
1543 for (i
= 0; i
< noptions
; ++i
) {
1544 struct option_spec
*spec
= &options
->spec
[i
];
1545 mvwaddstr(section
->window
, spec
->row
, spec
->col
,
1549 options
->current_option
= 0;
1550 options_render_state(options
);
1555 static bool options_on_btab(struct dialog
*dia
, struct dialog_section
*section
)
1557 struct dialog_section_options
*options
=
1558 talloc_get_type_abort(section
, struct dialog_section_options
);
1560 return options_highlight_previous(options
);
1563 static bool options_on_tab(struct dialog
*dia
, struct dialog_section
*section
)
1565 struct dialog_section_options
*options
=
1566 talloc_get_type_abort(section
, struct dialog_section_options
);
1568 return options_highlight_next(options
);
1571 static void options_on_input(struct dialog
*dia
, struct dialog_section
*section
, int c
)
1573 struct dialog_section_options
*options
=
1574 talloc_get_type_abort(section
, struct dialog_section_options
);
1577 struct option_spec
*spec
= &options
->spec
[options
->current_option
];
1578 if (options
->single_select
) {
1580 noptions
= talloc_array_length(options
->spec
);
1581 for (i
= 0; i
< noptions
; ++i
) {
1582 *(options
->spec
[i
].state
) = false;
1585 *spec
->state
= !*spec
->state
;
1586 options_unhighlight(options
);
1587 options_render_state(options
);
1588 options_highlight(options
);
1592 static enum dialog_action
options_on_enter(struct dialog
*dia
, struct dialog_section
*section
)
1594 options_on_input(dia
, section
, ' ');
1598 static bool options_on_focus(struct dialog
*dia
,
1599 struct dialog_section
*section
,
1602 struct dialog_section_options
*options
=
1603 talloc_get_type_abort(section
, struct dialog_section_options
);
1606 options
->current_option
= 0;
1608 options
->current_option
= talloc_array_length(options
->spec
) - 1;
1610 options_highlight(options
);
1615 static void options_on_leave_focus(struct dialog
*dia
,
1616 struct dialog_section
*section
)
1618 struct dialog_section_options
*options
=
1619 talloc_get_type_abort(section
, struct dialog_section_options
);
1620 options_unhighlight(options
);
1623 struct dialog_section_ops options_ops
= {
1624 .create
= options_create
,
1625 .on_tab
= options_on_tab
,
1626 .on_btab
= options_on_btab
,
1627 .on_up
= options_on_btab
,
1628 .on_down
= options_on_tab
,
1629 .on_left
= options_on_btab
,
1630 .on_right
= options_on_tab
,
1631 .on_input
= options_on_input
,
1632 .on_enter
= options_on_enter
,
1633 .on_focus
= options_on_focus
,
1634 .on_leave_focus
= options_on_leave_focus
1637 static int options_free(struct dialog_section_options
*options
)
1639 dialog_section_destroy(&options
->section
);
1643 struct dialog_section
*dialog_section_options_new(TALLOC_CTX
*ctx
,
1644 const struct option_spec
*spec
,
1645 int maxcol
, bool single_select
)
1647 struct dialog_section_options
*options
;
1649 int width
, maxwidth
, maxrows
;
1651 options
= talloc_zero(ctx
, struct dialog_section_options
);
1652 if (options
== NULL
) {
1655 talloc_set_destructor(options
, options_free
);
1657 for (noptions
= 0; spec
[noptions
].label
; ++noptions
) {
1659 options
->spec
= talloc_zero_array(options
, struct option_spec
, noptions
);
1660 if (options
->spec
== NULL
) {
1664 maxrows
= noptions
/ maxcol
;
1665 if (noptions
% maxcol
) {
1669 for (width
= 0, maxwidth
= 0, i
= 0; i
< noptions
; ++i
) {
1670 options
->spec
[i
] = spec
[i
];
1671 options
->spec
[i
].label
= talloc_asprintf(options
->spec
,
1674 if (!options
->spec
[i
].label
) {
1678 options
->spec
[i
].col
= maxwidth
;
1679 options
->spec
[i
].row
= i
% maxrows
;
1680 width
= MAX(strlen(options
->spec
[i
].label
), width
);
1681 if (options
->spec
[i
].row
== maxrows
- 1 || i
== noptions
- 1) {
1682 maxwidth
+= width
+ 1;
1687 dialog_section_init(&options
->section
, &options_ops
, maxrows
, maxwidth
- 1);
1688 options
->single_select
= single_select
;
1690 return &options
->section
;
1693 talloc_free(options
);
1706 enum input_type type
;
1709 unsigned long *out_ulong
;
1711 const char **out_str
;
1715 static bool input_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
1718 struct input_req
*req
= arg
;
1719 struct dialog_section
*data
;
1720 unsigned long long out_ulong
;
1723 data
= dialog_find_section(dia
, "input");
1725 switch (req
->type
) {
1727 if (!dialog_section_text_field_get_int(data
, &out_long
)) {
1728 dialog_notice(dia
, DIA_ALERT
, "Error",
1729 "Input must be a number.");
1732 if (out_long
< LONG_MIN
|| out_long
> LONG_MAX
) {
1733 dialog_notice(dia
, DIA_ALERT
, "Error",
1734 "Number is out of range.");
1737 *req
->out
.out_long
= out_long
;
1740 if (!dialog_section_text_field_get_uint(data
, &out_ulong
)) {
1741 dialog_notice(dia
, DIA_ALERT
, "Error",
1742 "Input must be a number greater than zero.");
1745 if (out_ulong
> ULONG_MAX
) {
1746 dialog_notice(dia
, DIA_ALERT
, "Error",
1747 "Number is out of range.");
1750 *req
->out
.out_ulong
= out_ulong
;
1753 *req
->out
.out_str
= dialog_section_text_field_get(req
->ctx
, data
);
1760 static int dialog_input_internal(TALLOC_CTX
*ctx
, void *output
,
1761 enum input_type type
,
1763 const char *msg
, va_list ap
)
1764 PRINTF_ATTRIBUTE(5,0);
1766 static int dialog_input_internal(TALLOC_CTX
*ctx
, void *output
,
1767 enum input_type type
,
1769 const char *msg
, va_list ap
)
1772 struct input_req req
;
1773 enum dialog_action action
;
1775 struct dialog_section
*section
;
1776 struct button_spec spec
[] = {
1777 {.label
= "OK", .action
= DIALOG_OK
},
1778 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
1784 req
.out
.out
= output
;
1785 *req
.out
.out_str
= NULL
;
1787 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, title
, -1, -1);
1788 dialog_set_submit_cb(dia
, input_on_submit
, &req
);
1789 section
= dialog_section_label_new_va(dia
, msg
, ap
);
1790 dialog_append_section(dia
, section
);
1791 section
= dialog_section_hsep_new(dia
, ' ');
1792 dialog_append_section(dia
, section
);
1793 section
= dialog_section_text_field_new(dia
, 1, -1);
1794 dialog_section_set_name(section
, "input");
1795 dialog_append_section(dia
, section
);
1796 section
= dialog_section_hsep_new(dia
, 0);
1797 dialog_append_section(dia
, section
);
1798 section
= dialog_section_buttons_new(dia
, spec
);
1799 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1800 dialog_append_section(dia
, section
);
1804 dialog_modal_loop(dia
, &err
, &action
);
1810 int dialog_input(TALLOC_CTX
*ctx
, const char **output
, const char *title
,
1811 const char *msg
, ...)
1817 rv
= dialog_input_internal(ctx
, output
, DLG_IN_STR
, title
, msg
, ap
);
1823 int dialog_input_ulong(TALLOC_CTX
*ctx
, unsigned long *output
,
1824 const char *title
, const char *msg
, ...)
1830 rv
= dialog_input_internal(ctx
, output
, DLG_IN_ULONG
, title
, msg
, ap
);
1836 int dialog_input_long(TALLOC_CTX
*ctx
, long *output
,
1837 const char *title
, const char *msg
, ...)
1843 rv
= dialog_input_internal(ctx
, output
, DLG_IN_LONG
, title
, msg
, ap
);
1849 int dialog_notice(TALLOC_CTX
*ctx
, enum dialog_type type
,
1850 const char *title
, const char *msg
, ...)
1854 enum dialog_action action
;
1856 struct dialog_section
*section
;
1857 struct button_spec spec
[3];
1859 memset(&spec
, '\0', sizeof(spec
));
1860 spec
[0].label
= "OK";
1861 spec
[0].action
= DIALOG_OK
;
1862 if (type
== DIA_CONFIRM
) {
1863 spec
[1].label
= "Cancel";
1864 spec
[1].action
= DIALOG_CANCEL
;
1867 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, title
, -1, -1);
1869 section
= dialog_section_label_new_va(dia
, msg
, ap
);
1871 dialog_append_section(dia
, section
);
1872 section
= dialog_section_hsep_new(dia
, 0);
1873 dialog_append_section(dia
, section
);
1874 section
= dialog_section_buttons_new(dia
, spec
);
1875 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
1876 dialog_append_section(dia
, section
);
1880 dialog_modal_loop(dia
, &err
, &action
);
1890 struct registry_key
*key
;
1891 const struct value_item
*vitem
;
1894 static WERROR
fill_value_buffer(struct dialog
*dia
, struct edit_req
*edit
)
1897 struct dialog_section
*data
;
1899 if (edit
->vitem
== NULL
) {
1903 data
= dialog_find_section(dia
, "data");
1904 SMB_ASSERT(data
!= NULL
);
1906 switch (edit
->mode
) {
1909 if (edit
->vitem
->data
.length
>= 4) {
1910 v
= IVAL(edit
->vitem
->data
.data
, 0);
1912 tmp
= talloc_asprintf(dia
, "%u", (unsigned)v
);
1914 return WERR_NOT_ENOUGH_MEMORY
;
1916 dialog_section_text_field_set(data
, tmp
);
1921 case REG_EXPAND_SZ
: {
1924 if (!pull_reg_sz(dia
, &edit
->vitem
->data
, &s
)) {
1925 return WERR_NOT_ENOUGH_MEMORY
;
1927 dialog_section_text_field_set(data
, s
);
1930 case REG_MULTI_SZ
: {
1933 if (!pull_reg_multi_sz(dia
, &edit
->vitem
->data
, &array
)) {
1934 return WERR_NOT_ENOUGH_MEMORY
;
1936 return dialog_section_text_field_set_lines(dia
, data
, array
);
1940 return dialog_section_hexedit_set_buf(data
,
1941 edit
->vitem
->data
.data
,
1942 edit
->vitem
->data
.length
);
1948 static bool value_exists(TALLOC_CTX
*ctx
, const struct registry_key
*key
,
1955 rv
= reg_key_get_value_by_name(ctx
, key
, name
, &type
, &blob
);
1957 return W_ERROR_IS_OK(rv
);
1960 static bool edit_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
1963 struct edit_req
*edit
= arg
;
1967 struct dialog_section
*name_section
, *data
;
1969 name_section
= dialog_find_section(dia
, "name");
1971 name
= dialog_section_text_field_get(dia
, name_section
);
1972 if (*name
== '\0') {
1973 dialog_notice(dia
, DIA_ALERT
, "Error",
1974 "Value name must not be blank.");
1977 if (value_exists(dia
, edit
->key
, name
)) {
1978 dialog_notice(dia
, DIA_ALERT
, "Error",
1979 "Value named \"%s\" already exists.",
1984 SMB_ASSERT(edit
->vitem
);
1985 name
= edit
->vitem
->value_name
;
1989 data
= dialog_find_section(dia
, "data");
1990 SMB_ASSERT(data
!= NULL
);
1993 switch (edit
->mode
) {
1995 unsigned long long v
;
1998 if (!dialog_section_text_field_get_uint(data
, &v
)) {
1999 dialog_notice(dia
, DIA_ALERT
, "Error",
2000 "REG_DWORD value must be an integer.");
2003 if (v
> UINT32_MAX
) {
2004 dialog_notice(dia
, DIA_ALERT
, "Error",
2005 "REG_DWORD value must less than %lu.",
2006 (unsigned long)UINT32_MAX
);
2010 blob
= data_blob_talloc(dia
, NULL
, sizeof(val
));
2011 SIVAL(blob
.data
, 0, val
);
2015 case REG_EXPAND_SZ
: {
2018 buf
= dialog_section_text_field_get(dia
, data
);
2019 if (!buf
|| !push_reg_sz(dia
, &blob
, buf
)) {
2020 rv
= WERR_NOT_ENOUGH_MEMORY
;
2024 case REG_MULTI_SZ
: {
2027 lines
= dialog_section_text_field_get_lines(dia
, data
);
2028 if (!lines
|| !push_reg_multi_sz(dia
, &blob
, lines
)) {
2029 rv
= WERR_NOT_ENOUGH_MEMORY
;
2037 dialog_section_hexedit_get_buf(data
, &buf
, &len
);
2038 blob
= data_blob_talloc(dia
, buf
, len
);
2043 if (W_ERROR_IS_OK(rv
)) {
2044 rv
= reg_val_set(edit
->key
, name
, edit
->type
, blob
);
2047 if (!W_ERROR_IS_OK(rv
)) {
2048 const char *msg
= get_friendly_werror_msg(rv
);
2049 dialog_notice(dia
, DIA_ALERT
, "Error",
2050 "Error saving value:\n%s", msg
);
2059 static enum dialog_action
edit_on_resize(struct dialog
*dia
,
2060 struct dialog_section
*section
)
2062 struct dialog_section
*data
;
2066 data
= dialog_find_section(dia
, "data");
2067 rv
= dialog_input_ulong(dia
, &size
, "Resize", "Enter size of buffer");
2068 if (rv
== DIALOG_OK
) {
2069 dialog_section_hexedit_resize(data
, size
);
2072 return DIALOG_IGNORE
;
2075 int dialog_edit_value(TALLOC_CTX
*ctx
, struct registry_key
*key
,
2076 uint32_t type
, const struct value_item
*vitem
,
2077 bool force_binary
, WERROR
*err
,
2080 enum dialog_action action
;
2082 struct dialog_section
*section
;
2083 struct edit_req edit
;
2084 struct button_spec buttons
[] = {
2085 {.label
= "OK", .action
= DIALOG_OK
},
2086 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2089 struct button_spec buttons_hexedit
[] = {
2090 {.label
= "OK", .action
= DIALOG_OK
},
2091 {.label
= "Resize Buffer", .on_enter
= edit_on_resize
},
2092 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2101 if (force_binary
|| (vitem
&& vitem
->unprintable
)) {
2102 edit
.mode
= REG_BINARY
;
2105 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "Edit Value", -1, -1);
2106 dialog_set_submit_cb(dia
, edit_on_submit
, &edit
);
2108 section
= dialog_section_label_new(dia
, "Type");
2109 dialog_append_section(dia
, section
);
2110 section
= dialog_section_label_new(dia
, "%s",
2112 dialog_append_section(dia
, section
);
2113 section
= dialog_section_hsep_new(dia
, ' ');
2114 dialog_append_section(dia
, section
);
2116 section
= dialog_section_label_new(dia
, "Name");
2117 dialog_append_section(dia
, section
);
2119 section
= dialog_section_label_new(dia
, "%s",
2122 section
= dialog_section_text_field_new(dia
, 1, 50);
2123 dialog_section_set_name(section
, "name");
2125 dialog_append_section(dia
, section
);
2126 section
= dialog_section_hsep_new(dia
, ' ');
2127 dialog_append_section(dia
, section
);
2129 section
= dialog_section_label_new(dia
, "Data");
2130 dialog_append_section(dia
, section
);
2132 switch (edit
.mode
) {
2136 section
= dialog_section_text_field_new(dia
, 1, 50);
2139 section
= dialog_section_text_field_new(dia
, 10, 50);
2143 section
= dialog_section_hexedit_new(dia
, 10);
2147 dialog_section_set_name(section
, "data");
2148 dialog_append_section(dia
, section
);
2150 section
= dialog_section_hsep_new(dia
, 0);
2151 dialog_append_section(dia
, section
);
2152 if (edit
.mode
== REG_BINARY
) {
2153 section
= dialog_section_buttons_new(dia
, buttons_hexedit
);
2155 section
= dialog_section_buttons_new(dia
, buttons
);
2157 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2158 dialog_append_section(dia
, section
);
2162 *err
= fill_value_buffer(dia
, &edit
);
2163 if (!W_ERROR_IS_OK(*err
)) {
2164 return DIALOG_CANCEL
;
2168 dialog_modal_loop(dia
, err
, &action
);
2170 if (action
== DIALOG_OK
&& name
) {
2172 *name
= talloc_strdup(ctx
, vitem
->value_name
);
2173 } else if ((section
= dialog_find_section(dia
, "name"))) {
2174 *name
= dialog_section_text_field_get(ctx
, section
);
2183 int dialog_select_type(TALLOC_CTX
*ctx
, int *type
)
2186 enum dialog_action action
;
2188 struct dialog_section
*section
;
2189 const char *reg_types
[] = {
2196 #define NTYPES ARRAY_SIZE(reg_types)
2197 struct button_spec spec
[] = {
2198 {.label
= "OK", .action
= DIALOG_OK
},
2199 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2202 bool flags
[NTYPES
] = { true };
2203 struct option_spec opsec
[NTYPES
+ 1];
2206 memset(&opsec
, '\0', sizeof(opsec
));
2207 for (i
= 0; i
< NTYPES
; ++i
) {
2208 opsec
[i
].label
= reg_types
[i
];
2209 opsec
[i
].state
= &flags
[i
];
2212 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "New Value", -1, -1);
2214 section
= dialog_section_label_new(dia
, "Select type for new value:");
2215 dialog_append_section(dia
, section
);
2216 section
= dialog_section_hsep_new(dia
, ' ');
2217 dialog_append_section(dia
, section
);
2218 section
= dialog_section_options_new(dia
, opsec
, 2, true);
2219 dialog_append_section(dia
, section
);
2220 section
= dialog_section_hsep_new(dia
, 0);
2221 dialog_append_section(dia
, section
);
2222 section
= dialog_section_buttons_new(dia
, spec
);
2223 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2224 dialog_append_section(dia
, section
);
2229 dialog_modal_loop(dia
, &err
, &action
);
2230 if (action
== DIALOG_OK
) {
2231 for (i
= 0; i
< NTYPES
; ++i
) {
2233 *type
= regtype_by_string(reg_types
[i
]);
2246 struct regedit_search_opts
*opts
;
2249 static bool search_on_submit(struct dialog
*dia
, struct dialog_section
*section
,
2252 struct search_req
*search
= arg
;
2253 struct dialog_section
*query
;
2255 query
= dialog_find_section(dia
, "query");
2256 SMB_ASSERT(query
!= NULL
);
2258 if (!search
->opts
->search_key
&& !search
->opts
->search_value
) {
2259 dialog_notice(dia
, DIA_ALERT
, "Error",
2260 "Must search a key and/or a value");
2264 talloc_free(discard_const(search
->opts
->query
));
2265 search
->opts
->query
= dialog_section_text_field_get(search
->ctx
, query
);
2266 SMB_ASSERT(search
->opts
->query
!= NULL
);
2267 if (search
->opts
->query
[0] == '\0') {
2268 dialog_notice(dia
, DIA_ALERT
, "Error",
2269 "Query must not be blank.");
2276 int dialog_search_input(TALLOC_CTX
*ctx
, struct regedit_search_opts
*opts
)
2279 enum dialog_action action
;
2281 struct dialog_section
*section
, *query
;
2282 struct search_req search
;
2283 struct button_spec spec
[] = {
2284 {.label
= "Search", .action
= DIALOG_OK
},
2285 {.label
= "Cancel", .action
= DIALOG_CANCEL
},
2288 struct option_spec search_opts
[] = {
2289 {.label
= "Search Keys", .state
= &opts
->search_key
},
2290 {.label
= "Search Values", .state
= &opts
->search_value
},
2291 {.label
= "Recursive", .state
= &opts
->search_recursive
},
2292 {.label
= "Case Sensitive", .state
= &opts
->search_case
},
2296 if (!opts
->search_key
&& !opts
->search_value
) {
2297 opts
->search_key
= true;
2302 dia
= dialog_new(ctx
, PAIR_BLACK_CYAN
, "Search", -1, -1);
2303 dialog_set_submit_cb(dia
, search_on_submit
, &search
);
2304 section
= dialog_section_label_new(dia
, "Query");
2305 dialog_append_section(dia
, section
);
2306 query
= dialog_section_text_field_new(dia
, 1, -1);
2307 dialog_section_set_name(query
, "query");
2308 dialog_append_section(dia
, query
);
2309 section
= dialog_section_hsep_new(dia
, 0);
2310 dialog_append_section(dia
, section
);
2311 section
= dialog_section_options_new(dia
, search_opts
, 2, false);
2312 dialog_append_section(dia
, section
);
2313 section
= dialog_section_hsep_new(dia
, 0);
2314 dialog_append_section(dia
, section
);
2315 section
= dialog_section_buttons_new(dia
, spec
);
2316 dialog_section_set_justify(section
, SECTION_JUSTIFY_CENTER
);
2317 dialog_append_section(dia
, section
);
2321 dialog_section_text_field_set(query
, opts
->query
);
2324 dialog_modal_loop(dia
, &err
, &action
);