2012-07-27 14:37:22 +04:00
/*
* Samba Unix / Linux SMB client library
* Registry Editor
* Copyright ( C ) Christopher Davis 2012
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2012-08-11 08:56:58 +04:00
# include "regedit.h"
2012-07-27 14:37:22 +04:00
# include "regedit_dialog.h"
2012-08-07 06:11:13 +04:00
# include "regedit_valuelist.h"
2012-08-09 07:44:58 +04:00
# include "regedit_hexedit.h"
2012-08-07 06:11:13 +04:00
# include "util_reg.h"
# include "lib/registry/registry.h"
2012-07-27 14:37:22 +04:00
# include <stdarg.h>
2012-08-07 06:11:13 +04:00
# include <form.h>
2012-07-27 14:37:22 +04:00
2012-08-09 04:49:06 +04:00
static char * string_trim_n ( TALLOC_CTX * ctx , const char * buf , size_t n )
{
char * str ;
str = talloc_strndup ( ctx , buf , n ) ;
if ( str ) {
trim_string ( str , " " , " " ) ;
}
return str ;
}
static char * string_trim ( TALLOC_CTX * ctx , const char * buf )
{
char * str ;
str = talloc_strdup ( ctx , buf ) ;
if ( str ) {
trim_string ( str , " " , " " ) ;
}
return str ;
}
2012-07-27 14:37:22 +04:00
static int dialog_free ( struct dialog * dia )
{
2014-07-26 10:26:27 +04:00
dialog_destroy ( dia ) ;
2012-07-27 14:37:22 +04:00
return 0 ;
}
2014-07-26 10:26:27 +04:00
static bool default_validator ( struct dialog * dia , struct dialog_section * sect ,
void * arg )
{
return true ;
}
struct dialog * dialog_new ( TALLOC_CTX * ctx , short color , const char * title ,
int y , int x )
2012-07-27 14:37:22 +04:00
{
struct dialog * dia ;
dia = talloc_zero ( ctx , struct dialog ) ;
if ( dia = = NULL ) {
return NULL ;
}
talloc_set_destructor ( dia , dialog_free ) ;
2014-07-26 10:26:27 +04:00
dia - > title = talloc_strdup ( dia , title ) ;
if ( dia - > title = = NULL ) {
2012-07-27 14:37:22 +04:00
goto fail ;
}
2014-07-26 10:26:27 +04:00
dia - > x = x ;
dia - > y = y ;
dia - > color = color ;
dia - > submit = default_validator ;
2012-07-27 14:37:22 +04:00
return dia ;
fail :
talloc_free ( dia ) ;
return NULL ;
}
2014-07-26 10:26:27 +04:00
void dialog_set_submit_cb ( struct dialog * dia , dialog_submit_cb cb , void * arg )
{
dia - > submit = cb ;
dia - > submit_arg = arg ;
}
static void center_above_window ( int * nlines , int * ncols , int * y , int * x )
2012-07-27 14:37:22 +04:00
{
2012-07-28 05:39:54 +04:00
int centery , centerx ;
2012-07-27 14:37:22 +04:00
2012-08-11 08:56:58 +04:00
centery = LINES / 2 ;
centerx = COLS / 2 ;
2012-07-28 05:39:54 +04:00
* y = 0 ;
* x = 0 ;
2012-08-11 08:56:58 +04:00
if ( * nlines > LINES ) {
* nlines = LINES ;
2012-07-28 05:39:54 +04:00
}
2012-08-11 08:56:58 +04:00
if ( * ncols > COLS ) {
* ncols = COLS ;
2012-07-28 05:39:54 +04:00
}
2012-08-11 08:56:58 +04:00
if ( * nlines / 2 < centery ) {
2012-08-11 07:05:20 +04:00
* y = centery - * nlines / 2 ;
2012-07-28 05:39:54 +04:00
}
2012-08-11 08:56:58 +04:00
if ( * ncols / 2 < centerx ) {
2012-08-11 07:05:20 +04:00
* x = centerx - * ncols / 2 ;
2012-07-28 05:39:54 +04:00
}
}
2014-07-26 10:26:27 +04:00
void dialog_section_destroy ( struct dialog_section * section )
2012-08-11 08:56:58 +04:00
{
2014-07-26 10:26:27 +04:00
if ( section - > ops - > destroy ) {
section - > ops - > destroy ( section ) ;
}
if ( section - > window ) {
delwin ( section - > window ) ;
section - > window = NULL ;
}
}
2012-08-11 08:56:58 +04:00
2014-07-26 10:26:27 +04:00
void dialog_section_init ( struct dialog_section * section ,
const struct dialog_section_ops * ops ,
int nlines , int ncols )
{
section - > ops = ops ;
section - > nlines = nlines ;
section - > ncols = ncols ;
}
2012-08-11 08:56:58 +04:00
2014-07-26 10:26:27 +04:00
const char * dialog_section_get_name ( struct dialog_section * section )
{
return section - > name ;
}
2012-08-11 08:56:58 +04:00
2014-07-26 10:26:27 +04:00
void dialog_section_set_name ( struct dialog_section * section , const char * name )
{
TALLOC_FREE ( section - > name ) ;
section - > name = talloc_strdup ( section , name ) ;
}
void dialog_section_set_justify ( struct dialog_section * section ,
enum section_justify justify )
{
section - > justify = justify ;
}
/* append a section to the dialog's circular list */
void dialog_append_section ( struct dialog * dia ,
struct dialog_section * section )
{
SMB_ASSERT ( section ! = NULL ) ;
if ( ! dia - > head_section ) {
dia - > head_section = section ;
}
if ( dia - > tail_section ) {
dia - > tail_section - > next = section ;
}
section - > prev = dia - > tail_section ;
section - > next = dia - > head_section ;
dia - > head_section - > prev = section ;
dia - > tail_section = section ;
}
struct dialog_section * dialog_find_section ( struct dialog * dia , const char * name )
{
struct dialog_section * section = dia - > head_section ;
do {
if ( section - > name & & strequal ( section - > name , name ) ) {
return section ;
2012-08-11 08:56:58 +04:00
}
2014-07-26 10:26:27 +04:00
section = section - > next ;
} while ( section ! = dia - > head_section ) ;
return NULL ;
}
static void section_on_input ( struct dialog * dia , int c )
{
struct dialog_section * section = dia - > current_section ;
if ( ! section - > ops - > on_input ) {
return ;
2012-08-11 08:56:58 +04:00
}
2014-07-26 10:26:27 +04:00
section - > ops - > on_input ( dia , section , c ) ;
}
2012-08-11 08:56:58 +04:00
2014-07-26 10:26:27 +04:00
static bool section_on_tab ( struct dialog * dia )
{
struct dialog_section * section = dia - > current_section ;
if ( ! section | | ! section - > ops - > on_tab ) {
return false ;
}
return section - > ops - > on_tab ( dia , section ) ;
2012-08-11 08:56:58 +04:00
}
2014-07-26 10:26:27 +04:00
static bool section_on_btab ( struct dialog * dia )
2012-07-28 05:39:54 +04:00
{
2014-07-26 10:26:27 +04:00
struct dialog_section * section = dia - > current_section ;
if ( ! section | | ! section - > ops - > on_btab ) {
return false ;
}
return section - > ops - > on_btab ( dia , section ) ;
}
2012-07-28 05:39:54 +04:00
2014-07-26 10:26:27 +04:00
static bool section_on_up ( struct dialog * dia )
{
struct dialog_section * section = dia - > current_section ;
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
if ( ! section | | ! section - > ops - > on_up ) {
return false ;
2012-08-11 08:56:58 +04:00
}
2014-07-26 10:26:27 +04:00
return section - > ops - > on_up ( dia , section ) ;
}
2012-08-11 08:56:58 +04:00
2014-07-26 10:26:27 +04:00
static bool section_on_down ( struct dialog * dia )
{
struct dialog_section * section = dia - > current_section ;
if ( ! section | | ! section - > ops - > on_down ) {
return false ;
}
return section - > ops - > on_down ( dia , section ) ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
static bool section_on_left ( struct dialog * dia )
2012-07-27 14:37:22 +04:00
{
2014-07-26 10:26:27 +04:00
struct dialog_section * section = dia - > current_section ;
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
if ( ! section | | ! section - > ops - > on_left ) {
return false ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
return section - > ops - > on_left ( dia , section ) ;
}
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
static bool section_on_right ( struct dialog * dia )
{
struct dialog_section * section = dia - > current_section ;
if ( ! section | | ! section - > ops - > on_right ) {
return false ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
return section - > ops - > on_right ( dia , section ) ;
}
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
static enum dialog_action section_on_enter ( struct dialog * dia )
{
struct dialog_section * section = dia - > current_section ;
if ( ! section | | ! section - > ops - > on_enter ) {
return DIALOG_OK ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
return section - > ops - > on_enter ( dia , section ) ;
}
static bool section_on_focus ( struct dialog * dia , bool forward )
{
struct dialog_section * section = dia - > current_section ;
if ( ! section - > ops - > on_focus ) {
return false ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
return section - > ops - > on_focus ( dia , section , forward ) ;
}
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
static void section_on_leave_focus ( struct dialog * dia )
{
struct dialog_section * section = dia - > current_section ;
if ( section - > ops - > on_leave_focus ) {
section - > ops - > on_leave_focus ( dia , section ) ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
}
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
static void section_set_next_focus ( struct dialog * dia )
{
section_on_leave_focus ( dia ) ;
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
do {
dia - > current_section = dia - > current_section - > next ;
} while ( ! section_on_focus ( dia , true ) ) ;
}
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
static void section_set_previous_focus ( struct dialog * dia )
{
section_on_leave_focus ( dia ) ;
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
do {
dia - > current_section = dia - > current_section - > prev ;
} while ( ! section_on_focus ( dia , false ) ) ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
WERROR dialog_create ( struct dialog * dia )
2012-07-27 14:37:22 +04:00
{
2014-07-26 10:26:27 +04:00
WERROR rv = WERR_OK ;
int row , col ;
int nlines , ncols ;
struct dialog_section * section ;
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
nlines = 0 ;
ncols = 0 ;
SMB_ASSERT ( dia - > head_section ! = NULL ) ;
/* calculate total size based on sections */
section = dia - > head_section ;
do {
nlines + = section - > nlines ;
ncols = MAX ( ncols , section - > ncols ) ;
section = section - > next ;
} while ( section ! = dia - > head_section ) ;
/* fill in widths for sections that expand */
section = dia - > head_section ;
do {
if ( section - > ncols < 0 ) {
section - > ncols = ncols ;
}
section = section - > next ;
} while ( section ! = dia - > head_section ) ;
/* create window for dialog */
nlines + = 4 ;
ncols + = 6 ;
2014-07-29 10:04:10 +04:00
dia - > pad = newpad ( nlines , ncols ) ;
if ( dia - > pad = = NULL ) {
rv = WERR_NOMEM ;
goto fail ;
}
2014-07-26 10:26:27 +04:00
dia - > centered = false ;
if ( dia - > y < 0 | | dia - > x < 0 ) {
2012-08-11 08:56:58 +04:00
dia - > centered = true ;
2014-07-26 10:26:27 +04:00
center_above_window ( & nlines , & ncols , & dia - > y , & dia - > x ) ;
}
dia - > window = newwin ( nlines , ncols , dia - > y , dia - > x ) ;
if ( dia - > window = = NULL ) {
rv = WERR_NOMEM ;
goto fail ;
}
dia - > panel = new_panel ( dia - > window ) ;
if ( dia - > panel = = NULL ) {
rv = WERR_NOMEM ;
goto fail ;
2012-08-11 08:56:58 +04:00
}
2012-07-27 14:37:22 +04:00
2014-07-26 10:26:27 +04:00
/* setup color and border */
2014-07-29 10:04:10 +04:00
getmaxyx ( dia - > pad , nlines , ncols ) ;
wbkgdset ( dia - > pad , ' ' | COLOR_PAIR ( dia - > color ) ) ;
wclear ( dia - > pad ) ;
mvwhline ( dia - > pad , 1 , 2 , 0 , ncols - 4 ) ;
mvwhline ( dia - > pad , nlines - 2 , 2 , 0 , ncols - 4 ) ;
mvwvline ( dia - > pad , 2 , 1 , 0 , nlines - 4 ) ;
mvwvline ( dia - > pad , 2 , ncols - 2 , 0 , nlines - 4 ) ;
mvwaddch ( dia - > pad , 1 , 1 , ACS_ULCORNER ) ;
mvwaddch ( dia - > pad , 1 , ncols - 2 , ACS_URCORNER ) ;
mvwaddch ( dia - > pad , nlines - 2 , 1 , ACS_LLCORNER ) ;
mvwaddch ( dia - > pad , nlines - 2 , ncols - 2 , ACS_LRCORNER ) ;
2014-07-26 10:26:27 +04:00
col = ncols / 2 - MIN ( strlen ( dia - > title ) + 2 , ncols ) / 2 ;
2014-07-29 10:04:10 +04:00
mvwprintw ( dia - > pad , 1 , col , " %s " , dia - > title ) ;
2014-07-26 10:26:27 +04:00
/* create subwindows for each section */
row = 2 ;
section = dia - > head_section ;
do {
col = 3 ;
switch ( section - > justify ) {
case SECTION_JUSTIFY_LEFT :
break ;
case SECTION_JUSTIFY_CENTER :
col + = ( ncols - 6 ) / 2 - section - > ncols / 2 ;
break ;
case SECTION_JUSTIFY_RIGHT :
break ;
}
2014-07-29 10:04:10 +04:00
section - > window = subpad ( dia - > pad , section - > nlines ,
2014-07-26 10:26:27 +04:00
section - > ncols , row , col ) ;
if ( section - > window = = NULL ) {
rv = WERR_NOMEM ;
goto fail ;
}
SMB_ASSERT ( section - > ops - > create ! = NULL ) ;
rv = section - > ops - > create ( dia , section ) ;
row + = section - > nlines ;
section = section - > next ;
} while ( section ! = dia - > head_section & & W_ERROR_IS_OK ( rv ) ) ;
dia - > current_section = dia - > head_section ;
section_set_next_focus ( dia ) ;
fail :
return rv ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
void dialog_show ( struct dialog * dia )
2012-08-17 14:06:20 +04:00
{
2014-07-29 10:04:10 +04:00
int nlines , ncols ;
int pad_y , pad_x ;
int y , x ;
int rv ;
touchwin ( dia - > pad ) ;
getmaxyx ( dia - > window , nlines , ncols ) ;
getmaxyx ( dia - > pad , pad_y , pad_x ) ;
y = 0 ;
if ( pad_y > nlines ) {
y = ( pad_y - nlines ) / 2 ;
}
x = 0 ;
if ( pad_x > ncols ) {
x = ( pad_x - ncols ) / 2 ;
}
rv = copywin ( dia - > pad , dia - > window , y , x , 0 , 0 ,
nlines - 1 , ncols - 1 , false ) ;
SMB_ASSERT ( rv = = OK ) ;
2012-08-17 14:06:20 +04:00
2014-07-29 10:04:10 +04:00
getyx ( dia - > pad , pad_y , pad_x ) ;
wmove ( dia - > window , pad_y - y , pad_x - x ) ;
2014-07-26 10:26:27 +04:00
touchwin ( dia - > window ) ;
wnoutrefresh ( dia - > window ) ;
2012-08-17 14:06:20 +04:00
}
2014-07-26 10:26:27 +04:00
void dialog_destroy ( struct dialog * dia )
2012-08-17 14:06:20 +04:00
{
2014-07-26 10:26:27 +04:00
struct dialog_section * section ;
2012-08-17 14:06:20 +04:00
2014-07-26 10:26:27 +04:00
section = dia - > head_section ;
do {
dialog_section_destroy ( section ) ;
section = section - > next ;
} while ( section ! = dia - > head_section ) ;
if ( dia - > panel ) {
del_panel ( dia - > panel ) ;
dia - > panel = NULL ;
}
if ( dia - > window ) {
delwin ( dia - > window ) ;
dia - > window = NULL ;
}
2012-08-17 14:06:20 +04:00
}
2014-07-26 10:26:27 +04:00
static int dialog_getch ( struct dialog * dia )
2012-07-27 14:37:22 +04:00
{
2014-07-26 10:26:27 +04:00
int c ;
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
c = regedit_getch ( ) ;
if ( c = = KEY_RESIZE ) {
int nlines , ncols , y , x ;
2014-07-29 10:04:10 +04:00
int pad_nlines , pad_ncols ;
int win_nlines , win_ncols ;
2014-07-26 10:26:27 +04:00
2014-07-29 10:04:10 +04:00
getmaxyx ( dia - > window , win_nlines , win_ncols ) ;
getmaxyx ( dia - > pad , pad_nlines , pad_ncols ) ;
2014-07-26 10:26:27 +04:00
getbegyx ( dia - > window , y , x ) ;
2014-07-29 10:04:10 +04:00
nlines = pad_nlines ;
ncols = pad_ncols ;
2014-07-26 10:26:27 +04:00
if ( dia - > centered ) {
center_above_window ( & nlines , & ncols , & y , & x ) ;
2012-08-17 14:06:20 +04:00
} else {
2014-07-26 10:26:27 +04:00
if ( nlines + y > LINES ) {
if ( nlines > LINES ) {
y = 0 ;
} else {
y = LINES - nlines ;
}
}
if ( ncols + x > COLS ) {
if ( ncols > COLS ) {
x = 0 ;
} else {
x = COLS - ncols ;
}
}
2012-08-17 14:06:20 +04:00
}
2014-07-29 10:04:10 +04:00
if ( nlines ! = win_nlines | | ncols ! = win_ncols ) {
wresize ( dia - > window , nlines , ncols ) ;
replace_panel ( dia - > panel , dia - > window ) ;
}
2014-07-26 10:26:27 +04:00
move_panel ( dia - > panel , y , x ) ;
2012-08-07 06:11:13 +04:00
}
2014-07-26 10:26:27 +04:00
return c ;
2012-08-07 06:11:13 +04:00
}
2014-07-26 10:26:27 +04:00
bool dialog_handle_input ( struct dialog * dia , WERROR * err ,
enum dialog_action * action )
2012-08-09 04:49:06 +04:00
{
2014-07-26 10:26:27 +04:00
int c ;
* err = WERR_OK ;
c = dialog_getch ( dia ) ;
2012-08-09 04:49:06 +04:00
switch ( c ) {
2014-07-26 10:26:27 +04:00
case ' \t ' :
if ( ! section_on_tab ( dia ) ) {
section_set_next_focus ( dia ) ;
}
break ;
case KEY_BTAB :
if ( ! section_on_btab ( dia ) ) {
section_set_previous_focus ( dia ) ;
}
2012-08-09 04:49:06 +04:00
break ;
case KEY_UP :
2014-07-26 10:26:27 +04:00
if ( ! section_on_up ( dia ) ) {
section_set_previous_focus ( dia ) ;
}
2012-08-09 04:49:06 +04:00
break ;
case KEY_DOWN :
2014-07-26 10:26:27 +04:00
if ( ! section_on_down ( dia ) ) {
section_set_next_focus ( dia ) ;
}
2012-08-09 04:49:06 +04:00
break ;
case KEY_LEFT :
2014-07-26 10:26:27 +04:00
if ( ! section_on_left ( dia ) ) {
section_set_previous_focus ( dia ) ;
}
2012-08-09 04:49:06 +04:00
break ;
case KEY_RIGHT :
2014-07-26 10:26:27 +04:00
if ( ! section_on_right ( dia ) ) {
section_set_next_focus ( dia ) ;
}
break ;
case ' \n ' :
case KEY_ENTER :
* action = section_on_enter ( dia ) ;
switch ( * action ) {
case DIALOG_IGNORE :
break ;
case DIALOG_CANCEL :
return false ;
case DIALOG_OK :
return ! dia - > submit ( dia , dia - > current_section ,
dia - > submit_arg ) ;
}
2012-08-09 04:49:06 +04:00
break ;
2014-07-26 10:26:27 +04:00
case 27 : /* ESC */
return false ;
2012-08-09 04:49:06 +04:00
default :
2014-07-26 10:26:27 +04:00
section_on_input ( dia , c ) ;
2012-08-09 04:49:06 +04:00
break ;
}
2014-07-26 10:26:27 +04:00
return true ;
2012-08-09 04:49:06 +04:00
}
2014-07-26 10:26:27 +04:00
void dialog_modal_loop ( struct dialog * dia , WERROR * err ,
enum dialog_action * action )
2012-08-07 06:11:13 +04:00
{
2014-07-26 10:26:27 +04:00
do {
2014-07-29 10:04:10 +04:00
dialog_show ( dia ) ;
2012-08-07 06:11:13 +04:00
update_panels ( ) ;
doupdate ( ) ;
2014-07-26 10:26:27 +04:00
} while ( dialog_handle_input ( dia , err , action ) ) ;
}
/* text label */
struct dialog_section_label {
struct dialog_section section ;
char * * text ;
} ;
static WERROR label_create ( struct dialog * dia , struct dialog_section * section )
{
int row ;
struct dialog_section_label * label =
talloc_get_type_abort ( section , struct dialog_section_label ) ;
for ( row = 0 ; row < section - > nlines ; + + row ) {
mvwaddstr ( section - > window , row , 0 , label - > text [ row ] ) ;
2012-08-07 06:11:13 +04:00
}
2014-07-26 10:26:27 +04:00
return WERR_OK ;
}
struct dialog_section_ops label_ops = {
. create = label_create ,
} ;
static int label_free ( struct dialog_section_label * label )
{
dialog_section_destroy ( & label - > section ) ;
return 0 ;
}
struct dialog_section * dialog_section_label_new_va ( TALLOC_CTX * ctx ,
const char * msg , va_list ap )
{
struct dialog_section_label * label ;
char * tmp , * ptmp , * line , * saveptr ;
int nlines , ncols ;
label = talloc_zero ( ctx , struct dialog_section_label ) ;
if ( label = = NULL ) {
return NULL ;
}
talloc_set_destructor ( label , label_free ) ;
tmp = talloc_vasprintf ( label , msg , ap ) ;
if ( tmp = = NULL ) {
goto fail ;
}
for ( nlines = 0 , ncols = 0 , ptmp = tmp ;
( line = strtok_r ( ptmp , " \n " , & saveptr ) ) ! = NULL ;
+ + nlines ) {
ptmp = NULL ;
label - > text = talloc_realloc ( label , label - > text ,
char * , nlines + 1 ) ;
if ( label - > text = = NULL ) {
goto fail ;
}
ncols = MAX ( ncols , strlen ( line ) ) ;
label - > text [ nlines ] = talloc_strdup ( label - > text , line ) ;
if ( label - > text [ nlines ] = = NULL ) {
goto fail ;
}
}
talloc_free ( tmp ) ;
dialog_section_init ( & label - > section , & label_ops , nlines , ncols ) ;
return & label - > section ;
fail :
talloc_free ( label ) ;
return NULL ;
}
struct dialog_section * dialog_section_label_new ( TALLOC_CTX * ctx ,
const char * msg , . . . )
{
va_list ap ;
struct dialog_section * rv ;
va_start ( ap , msg ) ;
rv = dialog_section_label_new_va ( ctx , msg , ap ) ;
va_end ( ap ) ;
return rv ;
}
/* horizontal separator */
struct dialog_section_hsep {
struct dialog_section section ;
int sep ;
} ;
static WERROR hsep_create ( struct dialog * dia , struct dialog_section * section )
{
int y , x ;
struct dialog_section_hsep * hsep =
talloc_get_type_abort ( section , struct dialog_section_hsep ) ;
whline ( section - > window , hsep - > sep , section - > ncols ) ;
if ( hsep - > sep = = 0 | | hsep - > sep = = ACS_HLINE ) {
/* change the border characters around this section to
tee chars */
getparyx ( section - > window , y , x ) ;
2014-07-29 10:04:10 +04:00
mvwaddch ( dia - > pad , y , x - 1 , ACS_HLINE ) ;
mvwaddch ( dia - > pad , y , x - 2 , ACS_LTEE ) ;
mvwaddch ( dia - > pad , y , x + section - > ncols , ACS_HLINE ) ;
mvwaddch ( dia - > pad , y , x + section - > ncols + 1 , ACS_RTEE ) ;
2014-07-26 10:26:27 +04:00
}
return WERR_OK ;
}
struct dialog_section_ops hsep_ops = {
. create = hsep_create
} ;
static int hsep_free ( struct dialog_section_hsep * hsep )
{
dialog_section_destroy ( & hsep - > section ) ;
return 0 ;
}
struct dialog_section * dialog_section_hsep_new ( TALLOC_CTX * ctx , int sep )
{
struct dialog_section_hsep * hsep ;
hsep = talloc_zero ( ctx , struct dialog_section_hsep ) ;
if ( hsep ) {
talloc_set_destructor ( hsep , hsep_free ) ;
dialog_section_init ( & hsep - > section , & hsep_ops , 1 , - 1 ) ;
hsep - > sep = sep ;
}
return & hsep - > section ;
}
/* text input field */
struct dialog_section_text_field {
struct dialog_section section ;
unsigned opts ;
FIELD * field [ 2 ] ;
FORM * form ;
2014-08-09 09:25:50 +04:00
int length ;
2014-07-26 10:26:27 +04:00
} ;
2014-08-09 09:25:50 +04:00
static int get_cursor_col ( struct dialog_section_text_field * field )
{
int col ;
col = field - > form - > curcol + field - > form - > begincol ;
return col ;
}
2014-07-26 10:26:27 +04:00
static WERROR text_field_create ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
text_field - > field [ 0 ] = new_field ( section - > nlines , section - > ncols ,
0 , 0 , 0 , 0 ) ;
if ( text_field - > field [ 0 ] = = NULL ) {
return WERR_NOMEM ;
}
set_field_back ( text_field - > field [ 0 ] , A_REVERSE ) ;
set_field_opts ( text_field - > field [ 0 ] , text_field - > opts ) ;
text_field - > form = new_form ( text_field - > field ) ;
if ( text_field - > form = = NULL ) {
return WERR_NOMEM ;
}
set_form_win ( text_field - > form , dia - > window ) ;
set_form_sub ( text_field - > form , section - > window ) ;
set_current_field ( text_field - > form , text_field - > field [ 0 ] ) ;
post_form ( text_field - > form ) ;
return WERR_OK ;
}
static void text_field_destroy ( struct dialog_section * section )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
if ( text_field - > form ) {
unpost_form ( text_field - > form ) ;
free_form ( text_field - > form ) ;
text_field - > form = NULL ;
}
if ( text_field - > field [ 0 ] ) {
free_field ( text_field - > field [ 0 ] ) ;
text_field - > field [ 0 ] = NULL ;
}
}
static void text_field_on_input ( struct dialog * dia ,
struct dialog_section * section ,
int c )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
switch ( c ) {
case KEY_BACKSPACE :
2014-08-09 09:25:50 +04:00
if ( text_field - > length ) {
text_field - > length - - ;
}
2014-07-26 10:26:27 +04:00
form_driver ( text_field - > form , REQ_DEL_PREV ) ;
break ;
2014-08-09 09:25:50 +04:00
case ' \x7f ' :
2014-08-09 06:58:03 +04:00
case KEY_DC :
2014-08-09 09:25:50 +04:00
if ( text_field - > length ) {
text_field - > length - - ;
}
2014-08-09 06:58:03 +04:00
form_driver ( text_field - > form , REQ_DEL_CHAR ) ;
break ;
2014-07-26 10:26:27 +04:00
default :
2014-08-09 09:25:50 +04:00
text_field - > length + + ;
2014-07-26 10:26:27 +04:00
form_driver ( text_field - > form , c ) ;
break ;
}
}
static bool text_field_on_up ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
if ( section - > nlines > 1 ) {
form_driver ( text_field - > form , REQ_UP_CHAR ) ;
return true ;
}
return false ;
}
static bool text_field_on_down ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
if ( section - > nlines > 1 ) {
form_driver ( text_field - > form , REQ_DOWN_CHAR ) ;
return true ;
}
return false ;
}
static bool text_field_on_left ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
form_driver ( text_field - > form , REQ_LEFT_CHAR ) ;
return true ;
}
static bool text_field_on_right ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
2014-08-09 09:25:50 +04:00
if ( section - > nlines > 1 | |
get_cursor_col ( text_field ) < text_field - > length ) {
form_driver ( text_field - > form , REQ_RIGHT_CHAR ) ;
}
2014-07-26 10:26:27 +04:00
return true ;
}
static enum dialog_action text_field_on_enter ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
if ( section - > nlines > 1 ) {
2014-08-09 09:25:50 +04:00
text_field - > length + = text_field - > form - > cols ;
2014-07-26 10:26:27 +04:00
form_driver ( text_field - > form , REQ_NEW_LINE ) ;
return DIALOG_IGNORE ;
}
return DIALOG_OK ;
}
static bool text_field_on_focus ( struct dialog * dia ,
struct dialog_section * section , bool forward )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
pos_form_cursor ( text_field - > form ) ;
return true ;
}
struct dialog_section_ops text_field_ops = {
. create = text_field_create ,
. destroy = text_field_destroy ,
. on_input = text_field_on_input ,
. on_up = text_field_on_up ,
. on_down = text_field_on_down ,
. on_left = text_field_on_left ,
. on_right = text_field_on_right ,
. on_enter = text_field_on_enter ,
. on_focus = text_field_on_focus
} ;
static int text_field_free ( struct dialog_section_text_field * text_field )
{
dialog_section_destroy ( & text_field - > section ) ;
return 0 ;
}
struct dialog_section * dialog_section_text_field_new ( TALLOC_CTX * ctx ,
int height , int width )
{
struct dialog_section_text_field * text_field ;
text_field = talloc_zero ( ctx , struct dialog_section_text_field ) ;
if ( text_field = = NULL ) {
return NULL ;
}
talloc_set_destructor ( text_field , text_field_free ) ;
dialog_section_init ( & text_field - > section , & text_field_ops ,
height , width ) ;
text_field - > opts = O_ACTIVE | O_PUBLIC | O_EDIT | O_VISIBLE | O_NULLOK ;
return & text_field - > section ;
}
const char * dialog_section_text_field_get ( TALLOC_CTX * ctx ,
struct dialog_section * section )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
form_driver ( text_field - > form , REQ_VALIDATION ) ;
return string_trim ( ctx , field_buffer ( text_field - > field [ 0 ] , 0 ) ) ;
}
void dialog_section_text_field_set ( struct dialog_section * section ,
const char * s )
{
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
2014-08-09 09:25:50 +04:00
text_field - > length = strlen ( s ) ;
2014-07-26 10:26:27 +04:00
set_field_buffer ( text_field - > field [ 0 ] , 0 , s ) ;
}
const char * * dialog_section_text_field_get_lines ( TALLOC_CTX * ctx ,
struct dialog_section * section )
{
int rows , cols , max ;
const char * * arr ;
size_t i ;
const char * buf ;
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
form_driver ( text_field - > form , REQ_VALIDATION ) ;
buf = field_buffer ( text_field - > field [ 0 ] , 0 ) ;
dynamic_field_info ( text_field - > field [ 0 ] , & rows , & cols , & max ) ;
arr = talloc_zero_array ( ctx , const char * , rows + 1 ) ;
if ( arr = = NULL ) {
return NULL ;
}
for ( i = 0 ; * buf ; + + i , buf + = cols ) {
SMB_ASSERT ( i < rows ) ;
arr [ i ] = string_trim_n ( arr , buf , cols ) ;
}
return arr ;
}
WERROR dialog_section_text_field_set_lines ( TALLOC_CTX * ctx ,
struct dialog_section * section ,
const char * * array )
{
int rows , cols , max ;
2014-11-13 11:12:56 +03:00
size_t padding , length , idx ;
2014-07-26 10:26:27 +04:00
const char * * arrayp ;
char * buf = NULL ;
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
dynamic_field_info ( text_field - > field [ 0 ] , & rows , & cols , & max ) ;
/* try to fit each string on it's own line. each line
needs to be padded with whitespace manually , since
ncurses fields do not have newlines . */
2014-11-13 11:12:56 +03:00
for ( idx = 0 , arrayp = array ; * arrayp ! = NULL ; + + arrayp ) {
2014-07-26 10:26:27 +04:00
length = MIN ( strlen ( * arrayp ) , cols ) ;
padding = cols - length ;
buf = talloc_realloc ( ctx , buf , char ,
talloc_array_length ( buf ) +
length + padding + 1 ) ;
if ( buf = = NULL ) {
return WERR_NOMEM ;
}
2014-11-13 11:12:56 +03:00
memcpy ( & buf [ idx ] , * arrayp , length ) ;
idx + = length ;
memset ( & buf [ idx ] , ' ' , padding ) ;
idx + = padding ;
buf [ idx ] = ' \0 ' ;
2014-07-26 10:26:27 +04:00
}
set_field_buffer ( text_field - > field [ 0 ] , 0 , buf ) ;
talloc_free ( buf ) ;
return WERR_OK ;
}
bool dialog_section_text_field_get_int ( struct dialog_section * section ,
long long * out )
{
bool rv ;
const char * buf ;
char * endp ;
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
form_driver ( text_field - > form , REQ_VALIDATION ) ;
buf = string_trim ( section , field_buffer ( text_field - > field [ 0 ] , 0 ) ) ;
if ( buf = = NULL ) {
return false ;
}
* out = strtoll ( buf , & endp , 0 ) ;
rv = true ;
if ( endp = = buf | | endp = = NULL | | endp [ 0 ] ! = ' \0 ' ) {
rv = false ;
}
return rv ;
}
bool dialog_section_text_field_get_uint ( struct dialog_section * section ,
unsigned long long * out )
{
bool rv ;
const char * buf ;
char * endp ;
struct dialog_section_text_field * text_field =
talloc_get_type_abort ( section , struct dialog_section_text_field ) ;
form_driver ( text_field - > form , REQ_VALIDATION ) ;
buf = string_trim ( section , field_buffer ( text_field - > field [ 0 ] , 0 ) ) ;
if ( buf = = NULL ) {
return false ;
}
* out = strtoull ( buf , & endp , 0 ) ;
rv = true ;
if ( endp = = buf | | endp = = NULL | | endp [ 0 ] ! = ' \0 ' ) {
rv = false ;
}
return rv ;
}
/* hex editor field */
struct dialog_section_hexedit {
struct dialog_section section ;
struct hexedit * buf ;
} ;
2014-08-10 00:39:59 +04:00
# define HEXEDIT_MIN_SIZE 1
2014-07-26 10:26:27 +04:00
static WERROR hexedit_create ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
2014-07-29 10:23:32 +04:00
hexedit - > buf = hexedit_new ( dia , section - > window , NULL ,
HEXEDIT_MIN_SIZE ) ;
2014-07-26 10:26:27 +04:00
if ( hexedit - > buf = = NULL ) {
return WERR_NOMEM ;
}
hexedit_refresh ( hexedit - > buf ) ;
return WERR_OK ;
}
static void hexedit_destroy ( struct dialog_section * section )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
if ( hexedit - > buf ) {
TALLOC_FREE ( hexedit - > buf ) ;
}
}
static void hexedit_on_input ( struct dialog * dia ,
struct dialog_section * section ,
int c )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
switch ( c ) {
case KEY_BACKSPACE :
2014-08-10 04:11:00 +04:00
hexedit_driver ( hexedit - > buf , HE_BACKSPACE ) ;
break ;
case ' \x7f ' :
case KEY_DC :
hexedit_driver ( hexedit - > buf , HE_DELETE ) ;
2014-07-26 10:26:27 +04:00
break ;
default :
hexedit_driver ( hexedit - > buf , c ) ;
break ;
}
}
static bool hexedit_on_up ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
hexedit_driver ( hexedit - > buf , HE_CURSOR_UP ) ;
return true ;
}
static bool hexedit_on_down ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
hexedit_driver ( hexedit - > buf , HE_CURSOR_DOWN ) ;
return true ;
}
static bool hexedit_on_left ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
hexedit_driver ( hexedit - > buf , HE_CURSOR_LEFT ) ;
return true ;
}
static bool hexedit_on_right ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
hexedit_driver ( hexedit - > buf , HE_CURSOR_RIGHT ) ;
return true ;
}
static enum dialog_action hexedit_on_enter ( struct dialog * dia ,
struct dialog_section * section )
{
return DIALOG_IGNORE ;
}
static bool hexedit_on_focus ( struct dialog * dia ,
struct dialog_section * section , bool forward )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
hexedit_set_cursor ( hexedit - > buf ) ;
return true ;
}
struct dialog_section_ops hexedit_ops = {
. create = hexedit_create ,
. destroy = hexedit_destroy ,
. on_input = hexedit_on_input ,
. on_up = hexedit_on_up ,
. on_down = hexedit_on_down ,
. on_left = hexedit_on_left ,
. on_right = hexedit_on_right ,
. on_enter = hexedit_on_enter ,
. on_focus = hexedit_on_focus
} ;
static int hexedit_free ( struct dialog_section_hexedit * hexedit )
{
dialog_section_destroy ( & hexedit - > section ) ;
return 0 ;
}
struct dialog_section * dialog_section_hexedit_new ( TALLOC_CTX * ctx , int height )
{
struct dialog_section_hexedit * hexedit ;
hexedit = talloc_zero ( ctx , struct dialog_section_hexedit ) ;
if ( hexedit = = NULL ) {
return NULL ;
}
talloc_set_destructor ( hexedit , hexedit_free ) ;
dialog_section_init ( & hexedit - > section , & hexedit_ops ,
height , LINE_WIDTH ) ;
return & hexedit - > section ;
}
WERROR dialog_section_hexedit_set_buf ( struct dialog_section * section ,
const void * data , size_t size )
{
WERROR rv ;
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
SMB_ASSERT ( hexedit - > buf ! = NULL ) ;
rv = hexedit_set_buf ( hexedit - > buf , data , size ) ;
if ( W_ERROR_IS_OK ( rv ) ) {
hexedit_refresh ( hexedit - > buf ) ;
hexedit_set_cursor ( hexedit - > buf ) ;
}
return rv ;
}
void dialog_section_hexedit_get_buf ( struct dialog_section * section ,
const void * * data , size_t * size )
{
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
SMB_ASSERT ( hexedit - > buf ! = NULL ) ;
* data = hexedit_get_buf ( hexedit - > buf ) ;
* size = hexedit_get_buf_len ( hexedit - > buf ) ;
}
2014-08-09 10:55:25 +04:00
WERROR dialog_section_hexedit_resize ( struct dialog_section * section ,
size_t size )
{
WERROR rv ;
struct dialog_section_hexedit * hexedit =
talloc_get_type_abort ( section , struct dialog_section_hexedit ) ;
SMB_ASSERT ( hexedit - > buf ! = NULL ) ;
rv = hexedit_resize_buffer ( hexedit - > buf , size ) ;
if ( W_ERROR_IS_OK ( rv ) ) {
hexedit_refresh ( hexedit - > buf ) ;
}
return rv ;
}
2014-07-26 10:26:27 +04:00
/* button box */
struct dialog_section_buttons {
struct dialog_section section ;
struct button_spec * spec ;
int current_button ;
} ;
static void buttons_unhighlight ( struct dialog_section_buttons * buttons )
{
short pair ;
attr_t attr ;
/*
* Some GCC versions will complain if the macro version of
* wattr_get is used . So we should enforce the use of the
* function instead . See :
* http : //lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
*/
( wattr_get ) ( buttons - > section . window , & attr , & pair , NULL ) ;
mvwchgat ( buttons - > section . window , 0 , 0 , - 1 , A_NORMAL , pair , NULL ) ;
wnoutrefresh ( buttons - > section . window ) ;
}
static void buttons_highlight ( struct dialog_section_buttons * buttons )
{
2014-08-07 07:15:38 +04:00
struct button_spec * spec = & buttons - > spec [ buttons - > current_button ] ;
2014-07-26 10:26:27 +04:00
short pair ;
attr_t attr ;
/*
* Some GCC versions will complain if the macro version of
* wattr_get is used . So we should enforce the use of the
* function instead . See :
* http : //lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
*/
( wattr_get ) ( buttons - > section . window , & attr , & pair , NULL ) ;
mvwchgat ( buttons - > section . window , 0 , 0 , - 1 , A_NORMAL , pair , NULL ) ;
2014-08-07 07:15:38 +04:00
mvwchgat ( buttons - > section . window , 0 , spec - > col ,
strlen ( spec - > label ) , A_REVERSE , pair , NULL ) ;
wmove ( buttons - > section . window , 0 , spec - > col + 2 ) ;
2014-07-26 10:26:27 +04:00
wcursyncup ( buttons - > section . window ) ;
wnoutrefresh ( buttons - > section . window ) ;
}
static bool buttons_highlight_next ( struct dialog_section_buttons * buttons )
{
if ( buttons - > current_button < talloc_array_length ( buttons - > spec ) - 1 ) {
buttons - > current_button + + ;
buttons_highlight ( buttons ) ;
return true ;
}
return false ;
}
static bool buttons_highlight_previous ( struct dialog_section_buttons * buttons )
{
if ( buttons - > current_button > 0 ) {
buttons - > current_button - - ;
buttons_highlight ( buttons ) ;
return true ;
}
return false ;
}
static WERROR buttons_create ( struct dialog * dia ,
struct dialog_section * section )
{
size_t i , nbuttons ;
struct dialog_section_buttons * buttons =
talloc_get_type_abort ( section , struct dialog_section_buttons ) ;
nbuttons = talloc_array_length ( buttons - > spec ) ;
for ( i = 0 ; i < nbuttons ; + + i ) {
2014-08-07 07:15:38 +04:00
struct button_spec * spec = & buttons - > spec [ i ] ;
mvwaddstr ( section - > window , 0 , spec - > col , spec - > label ) ;
2014-07-26 10:26:27 +04:00
}
buttons - > current_button = 0 ;
return WERR_OK ;
}
static bool buttons_on_btab ( struct dialog * dia , struct dialog_section * section )
{
struct dialog_section_buttons * buttons =
talloc_get_type_abort ( section , struct dialog_section_buttons ) ;
return buttons_highlight_previous ( buttons ) ;
}
static bool buttons_on_tab ( struct dialog * dia , struct dialog_section * section )
{
struct dialog_section_buttons * buttons =
talloc_get_type_abort ( section , struct dialog_section_buttons ) ;
return buttons_highlight_next ( buttons ) ;
}
static enum dialog_action buttons_on_enter ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_buttons * buttons =
talloc_get_type_abort ( section , struct dialog_section_buttons ) ;
struct button_spec * spec = & buttons - > spec [ buttons - > current_button ] ;
if ( spec - > on_enter ) {
return spec - > on_enter ( dia , section ) ;
}
return spec - > action ;
}
static bool buttons_on_focus ( struct dialog * dia ,
struct dialog_section * section ,
bool forward )
{
struct dialog_section_buttons * buttons =
talloc_get_type_abort ( section , struct dialog_section_buttons ) ;
if ( forward ) {
buttons - > current_button = 0 ;
} else {
buttons - > current_button = talloc_array_length ( buttons - > spec ) - 1 ;
}
buttons_highlight ( buttons ) ;
return true ;
}
static void buttons_on_leave_focus ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_buttons * buttons =
talloc_get_type_abort ( section , struct dialog_section_buttons ) ;
buttons_unhighlight ( buttons ) ;
}
struct dialog_section_ops buttons_ops = {
. create = buttons_create ,
. on_tab = buttons_on_tab ,
. on_btab = buttons_on_btab ,
. on_up = buttons_on_btab ,
. on_down = buttons_on_tab ,
. on_left = buttons_on_btab ,
. on_right = buttons_on_tab ,
. on_enter = buttons_on_enter ,
. on_focus = buttons_on_focus ,
. on_leave_focus = buttons_on_leave_focus
} ;
static int buttons_free ( struct dialog_section_buttons * buttons )
{
dialog_section_destroy ( & buttons - > section ) ;
return 0 ;
}
struct dialog_section * dialog_section_buttons_new ( TALLOC_CTX * ctx ,
const struct button_spec * spec )
{
struct dialog_section_buttons * buttons ;
size_t i , nbuttons ;
int width ;
buttons = talloc_zero ( ctx , struct dialog_section_buttons ) ;
if ( buttons = = NULL ) {
return NULL ;
}
talloc_set_destructor ( buttons , buttons_free ) ;
for ( nbuttons = 0 ; spec [ nbuttons ] . label ; + + nbuttons ) {
}
buttons - > spec = talloc_zero_array ( buttons , struct button_spec , nbuttons ) ;
if ( buttons - > spec = = NULL ) {
goto fail ;
}
for ( width = 0 , i = 0 ; i < nbuttons ; + + i ) {
buttons - > spec [ i ] = spec [ i ] ;
buttons - > spec [ i ] . label = talloc_asprintf ( buttons - > spec ,
" [ %s ] " ,
spec [ i ] . label ) ;
if ( ! buttons - > spec [ i ] . label ) {
goto fail ;
}
buttons - > spec [ i ] . col = width ;
width + = strlen ( buttons - > spec [ i ] . label ) ;
if ( i ! = nbuttons - 1 ) {
+ + width ;
}
}
dialog_section_init ( & buttons - > section , & buttons_ops , 1 , width ) ;
return & buttons - > section ;
fail :
talloc_free ( buttons ) ;
return NULL ;
}
/* options */
struct dialog_section_options {
struct dialog_section section ;
struct option_spec * spec ;
int current_option ;
bool single_select ;
} ;
static void options_unhighlight ( struct dialog_section_options * options )
{
short pair ;
attr_t attr ;
size_t row ;
/*
* Some GCC versions will complain if the macro version of
* wattr_get is used . So we should enforce the use of the
* function instead . See :
* http : //lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
*/
( wattr_get ) ( options - > section . window , & attr , & pair , NULL ) ;
for ( row = 0 ; row < options - > section . nlines ; + + row ) {
mvwchgat ( options - > section . window , row , 0 , - 1 , A_NORMAL , pair , NULL ) ;
}
wnoutrefresh ( options - > section . window ) ;
}
static void options_highlight ( struct dialog_section_options * options )
{
2014-08-07 07:15:38 +04:00
struct option_spec * spec = & options - > spec [ options - > current_option ] ;
2014-07-26 10:26:27 +04:00
short pair ;
attr_t attr ;
size_t row ;
/*
* Some GCC versions will complain if the macro version of
* wattr_get is used . So we should enforce the use of the
* function instead . See :
* http : //lists.gnu.org/archive/html/bug-ncurses/2013-12/msg00017.html
*/
( wattr_get ) ( options - > section . window , & attr , & pair , NULL ) ;
for ( row = 0 ; row < options - > section . nlines ; + + row ) {
mvwchgat ( options - > section . window , row , 0 , - 1 , A_NORMAL , pair , NULL ) ;
}
2014-08-07 07:15:38 +04:00
mvwchgat ( options - > section . window , spec - > row , spec - > col ,
strlen ( spec - > label ) , A_REVERSE , pair , NULL ) ;
wmove ( options - > section . window , spec - > row , spec - > col + 4 ) ;
2014-07-26 10:26:27 +04:00
wcursyncup ( options - > section . window ) ;
wnoutrefresh ( options - > section . window ) ;
}
static void options_render_state ( struct dialog_section_options * options )
{
size_t i , noptions ;
noptions = talloc_array_length ( options - > spec ) ;
for ( i = 0 ; i < noptions ; + + i ) {
2014-08-07 07:15:38 +04:00
struct option_spec * spec = & options - > spec [ i ] ;
2014-07-26 10:26:27 +04:00
char c = ' ' ;
2014-08-07 07:15:38 +04:00
if ( * spec - > state )
2014-07-26 10:26:27 +04:00
c = ' x ' ;
mvwaddch ( options - > section . window ,
2014-08-07 07:15:38 +04:00
spec - > row , spec - > col + 1 , c ) ;
2014-07-26 10:26:27 +04:00
wnoutrefresh ( options - > section . window ) ;
}
}
static bool options_highlight_next ( struct dialog_section_options * options )
{
if ( options - > current_option < talloc_array_length ( options - > spec ) - 1 ) {
options - > current_option + + ;
options_highlight ( options ) ;
return true ;
}
return false ;
}
static bool options_highlight_previous ( struct dialog_section_options * options )
{
if ( options - > current_option > 0 ) {
options - > current_option - - ;
options_highlight ( options ) ;
return true ;
}
return false ;
}
static WERROR options_create ( struct dialog * dia ,
2014-08-07 07:15:38 +04:00
struct dialog_section * section )
2014-07-26 10:26:27 +04:00
{
size_t i , noptions ;
struct dialog_section_options * options =
talloc_get_type_abort ( section , struct dialog_section_options ) ;
noptions = talloc_array_length ( options - > spec ) ;
for ( i = 0 ; i < noptions ; + + i ) {
2014-08-07 07:15:38 +04:00
struct option_spec * spec = & options - > spec [ i ] ;
mvwaddstr ( section - > window , spec - > row , spec - > col ,
spec - > label ) ;
2014-07-26 10:26:27 +04:00
}
options - > current_option = 0 ;
options_render_state ( options ) ;
return WERR_OK ;
}
static bool options_on_btab ( struct dialog * dia , struct dialog_section * section )
{
struct dialog_section_options * options =
talloc_get_type_abort ( section , struct dialog_section_options ) ;
return options_highlight_previous ( options ) ;
}
static bool options_on_tab ( struct dialog * dia , struct dialog_section * section )
{
struct dialog_section_options * options =
talloc_get_type_abort ( section , struct dialog_section_options ) ;
return options_highlight_next ( options ) ;
}
static void options_on_input ( struct dialog * dia , struct dialog_section * section , int c )
{
struct dialog_section_options * options =
talloc_get_type_abort ( section , struct dialog_section_options ) ;
if ( c = = ' ' ) {
2014-08-07 07:15:38 +04:00
struct option_spec * spec = & options - > spec [ options - > current_option ] ;
2014-07-26 10:26:27 +04:00
if ( options - > single_select ) {
size_t i , noptions ;
noptions = talloc_array_length ( options - > spec ) ;
for ( i = 0 ; i < noptions ; + + i ) {
* ( options - > spec [ i ] . state ) = false ;
}
}
2014-08-07 07:15:38 +04:00
* spec - > state = ! * spec - > state ;
2014-07-26 10:26:27 +04:00
options_unhighlight ( options ) ;
options_render_state ( options ) ;
options_highlight ( options ) ;
}
}
static enum dialog_action options_on_enter ( struct dialog * dia , struct dialog_section * section )
{
options_on_input ( dia , section , ' ' ) ;
return DIALOG_OK ;
}
static bool options_on_focus ( struct dialog * dia ,
struct dialog_section * section ,
bool forward )
{
struct dialog_section_options * options =
talloc_get_type_abort ( section , struct dialog_section_options ) ;
if ( forward ) {
options - > current_option = 0 ;
} else {
options - > current_option = talloc_array_length ( options - > spec ) - 1 ;
}
options_highlight ( options ) ;
return true ;
}
static void options_on_leave_focus ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section_options * options =
talloc_get_type_abort ( section , struct dialog_section_options ) ;
options_unhighlight ( options ) ;
}
struct dialog_section_ops options_ops = {
. create = options_create ,
. on_tab = options_on_tab ,
. on_btab = options_on_btab ,
. on_up = options_on_btab ,
. on_down = options_on_tab ,
. on_left = options_on_btab ,
. on_right = options_on_tab ,
. on_input = options_on_input ,
. on_enter = options_on_enter ,
. on_focus = options_on_focus ,
. on_leave_focus = options_on_leave_focus
} ;
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
static int options_free ( struct dialog_section_options * options )
{
dialog_section_destroy ( & options - > section ) ;
return 0 ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
struct dialog_section * dialog_section_options_new ( TALLOC_CTX * ctx ,
const struct option_spec * spec ,
int maxcol , bool single_select )
2012-08-09 02:36:01 +04:00
{
2014-07-26 10:26:27 +04:00
struct dialog_section_options * options ;
size_t i , noptions ;
int width , maxwidth , maxrows ;
2012-08-09 04:49:06 +04:00
2014-07-26 10:26:27 +04:00
options = talloc_zero ( ctx , struct dialog_section_options ) ;
if ( options = = NULL ) {
2012-08-09 04:49:06 +04:00
return NULL ;
}
2014-07-26 10:26:27 +04:00
talloc_set_destructor ( options , options_free ) ;
2012-08-09 04:49:06 +04:00
2014-07-26 10:26:27 +04:00
for ( noptions = 0 ; spec [ noptions ] . label ; + + noptions ) {
2012-08-09 04:49:06 +04:00
}
2014-07-26 10:26:27 +04:00
options - > spec = talloc_zero_array ( options , struct option_spec , noptions ) ;
if ( options - > spec = = NULL ) {
goto fail ;
2012-08-09 04:49:06 +04:00
}
2014-07-26 10:26:27 +04:00
maxrows = noptions / maxcol ;
if ( noptions % maxcol ) {
+ + maxrows ;
}
2012-08-09 04:49:06 +04:00
2014-07-26 10:26:27 +04:00
for ( width = 0 , maxwidth = 0 , i = 0 ; i < noptions ; + + i ) {
options - > spec [ i ] = spec [ i ] ;
options - > spec [ i ] . label = talloc_asprintf ( options - > spec ,
" [ ] %s " ,
spec [ i ] . label ) ;
if ( ! options - > spec [ i ] . label ) {
goto fail ;
}
options - > spec [ i ] . col = maxwidth ;
options - > spec [ i ] . row = i % maxrows ;
width = MAX ( strlen ( options - > spec [ i ] . label ) , width ) ;
if ( options - > spec [ i ] . row = = maxrows - 1 | | i = = noptions - 1 ) {
maxwidth + = width + 1 ;
width = 0 ;
}
}
dialog_section_init ( & options - > section , & options_ops , maxrows , maxwidth - 1 ) ;
options - > single_select = single_select ;
return & options - > section ;
fail :
talloc_free ( options ) ;
return NULL ;
2012-08-09 04:49:06 +04:00
}
2014-07-26 10:26:27 +04:00
2014-08-09 10:36:48 +04:00
enum input_type {
DLG_IN_LONG ,
DLG_IN_ULONG ,
DLG_IN_STR ,
} ;
struct input_req {
TALLOC_CTX * ctx ;
enum input_type type ;
union {
void * out ;
unsigned long * out_ulong ;
long * out_long ;
const char * * out_str ;
} out ;
} ;
static bool input_on_submit ( struct dialog * dia , struct dialog_section * section ,
void * arg )
{
struct input_req * req = arg ;
struct dialog_section * data ;
unsigned long long out_ulong ;
long long out_long ;
data = dialog_find_section ( dia , " input " ) ;
switch ( req - > type ) {
case DLG_IN_LONG :
if ( ! dialog_section_text_field_get_int ( data , & out_long ) ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Input must be a number. " ) ;
return false ;
}
if ( out_long < LONG_MIN | | out_long > LONG_MAX ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Number is out of range. " ) ;
return false ;
}
* req - > out . out_long = out_long ;
break ;
case DLG_IN_ULONG :
if ( ! dialog_section_text_field_get_uint ( data , & out_ulong ) ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Input must be a number greater than zero. " ) ;
return false ;
}
if ( out_ulong > ULONG_MAX ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Number is out of range. " ) ;
return false ;
}
* req - > out . out_ulong = out_ulong ;
break ;
case DLG_IN_STR :
* req - > out . out_str = dialog_section_text_field_get ( req - > ctx , data ) ;
break ;
}
return true ;
}
static int dialog_input_internal ( TALLOC_CTX * ctx , void * output ,
enum input_type type ,
const char * title ,
const char * msg , va_list ap )
2012-08-09 04:49:06 +04:00
{
2014-07-26 10:26:27 +04:00
WERROR err ;
2014-08-09 10:36:48 +04:00
struct input_req req ;
2014-07-26 10:26:27 +04:00
enum dialog_action action ;
2012-08-09 04:49:06 +04:00
struct dialog * dia ;
2014-07-26 10:26:27 +04:00
struct dialog_section * section ;
struct button_spec spec [ ] = {
{ . label = " OK " , . action = DIALOG_OK } ,
{ . label = " Cancel " , . action = DIALOG_CANCEL } ,
{ 0 }
2012-08-09 02:36:01 +04:00
} ;
2014-08-09 10:36:48 +04:00
req . ctx = ctx ;
req . type = type ;
req . out . out = output ;
* req . out . out_str = NULL ;
2014-07-26 10:26:27 +04:00
dia = dialog_new ( ctx , PAIR_BLACK_CYAN , title , - 1 , - 1 ) ;
2014-08-09 10:36:48 +04:00
dialog_set_submit_cb ( dia , input_on_submit , & req ) ;
2014-07-26 10:26:27 +04:00
section = dialog_section_label_new_va ( dia , msg , ap ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_hsep_new ( dia , ' ' ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_text_field_new ( dia , 1 , - 1 ) ;
dialog_section_set_name ( section , " input " ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_hsep_new ( dia , 0 ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_buttons_new ( dia , spec ) ;
dialog_section_set_justify ( section , SECTION_JUSTIFY_CENTER ) ;
dialog_append_section ( dia , section ) ;
dialog_create ( dia ) ;
dialog_show ( dia ) ;
dialog_modal_loop ( dia , & err , & action ) ;
2012-08-09 04:49:06 +04:00
talloc_free ( dia ) ;
2014-07-26 10:26:27 +04:00
return action ;
2012-08-09 04:49:06 +04:00
}
2014-08-09 10:36:48 +04:00
int dialog_input ( TALLOC_CTX * ctx , const char * * output , const char * title ,
const char * msg , . . . )
{
va_list ap ;
int rv ;
va_start ( ap , msg ) ;
rv = dialog_input_internal ( ctx , output , DLG_IN_STR , title , msg , ap ) ;
va_end ( ap ) ;
return rv ;
}
int dialog_input_ulong ( TALLOC_CTX * ctx , unsigned long * output ,
const char * title , const char * msg , . . . )
{
va_list ap ;
int rv ;
va_start ( ap , msg ) ;
rv = dialog_input_internal ( ctx , output , DLG_IN_ULONG , title , msg , ap ) ;
va_end ( ap ) ;
return rv ;
}
int dialog_input_long ( TALLOC_CTX * ctx , long * output ,
const char * title , const char * msg , . . . )
{
va_list ap ;
int rv ;
va_start ( ap , msg ) ;
rv = dialog_input_internal ( ctx , output , DLG_IN_LONG , title , msg , ap ) ;
va_end ( ap ) ;
return rv ;
}
2012-08-09 04:49:06 +04:00
int dialog_notice ( TALLOC_CTX * ctx , enum dialog_type type ,
2012-08-11 08:56:58 +04:00
const char * title , const char * msg , . . . )
2012-08-09 04:49:06 +04:00
{
va_list ap ;
2014-07-26 10:26:27 +04:00
WERROR err ;
enum dialog_action action ;
2012-08-09 04:49:06 +04:00
struct dialog * dia ;
2014-07-26 10:26:27 +04:00
struct dialog_section * section ;
struct button_spec spec [ 3 ] ;
2012-08-09 02:36:01 +04:00
2014-07-26 10:26:27 +04:00
memset ( & spec , ' \0 ' , sizeof ( spec ) ) ;
spec [ 0 ] . label = " OK " ;
spec [ 0 ] . action = DIALOG_OK ;
if ( type = = DIA_CONFIRM ) {
spec [ 1 ] . label = " Cancel " ;
spec [ 1 ] . action = DIALOG_CANCEL ;
2012-08-09 02:36:01 +04:00
}
2012-08-09 04:49:06 +04:00
2014-07-26 10:26:27 +04:00
dia = dialog_new ( ctx , PAIR_BLACK_CYAN , title , - 1 , - 1 ) ;
2012-08-09 04:49:06 +04:00
va_start ( ap , msg ) ;
2014-07-26 10:26:27 +04:00
section = dialog_section_label_new_va ( dia , msg , ap ) ;
2012-08-09 04:49:06 +04:00
va_end ( ap ) ;
2014-07-26 10:26:27 +04:00
dialog_append_section ( dia , section ) ;
section = dialog_section_hsep_new ( dia , 0 ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_buttons_new ( dia , spec ) ;
dialog_section_set_justify ( section , SECTION_JUSTIFY_CENTER ) ;
dialog_append_section ( dia , section ) ;
dialog_create ( dia ) ;
dialog_show ( dia ) ;
dialog_modal_loop ( dia , & err , & action ) ;
talloc_free ( dia ) ;
2012-08-09 02:36:01 +04:00
2014-07-26 10:26:27 +04:00
return action ;
2012-08-09 02:36:01 +04:00
}
2012-08-13 09:39:21 +04:00
2014-07-26 10:26:27 +04:00
struct edit_req {
uint32_t type ;
2012-08-20 07:02:51 +04:00
uint32_t mode ;
2014-07-26 10:26:27 +04:00
struct registry_key * key ;
const struct value_item * vitem ;
2012-08-08 06:19:28 +04:00
} ;
2014-07-26 10:26:27 +04:00
static WERROR fill_value_buffer ( struct dialog * dia , struct edit_req * edit )
2012-08-08 10:41:50 +04:00
{
2014-07-26 10:26:27 +04:00
char * tmp ;
struct dialog_section * data ;
2012-08-13 09:39:21 +04:00
2014-07-26 10:26:27 +04:00
if ( edit - > vitem = = NULL ) {
return WERR_OK ;
2012-08-08 10:41:50 +04:00
}
2014-07-26 10:26:27 +04:00
data = dialog_find_section ( dia , " data " ) ;
SMB_ASSERT ( data ! = NULL ) ;
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
switch ( edit - > mode ) {
2012-08-07 06:11:13 +04:00
case REG_DWORD : {
uint32_t v = 0 ;
2014-07-26 10:26:27 +04:00
if ( edit - > vitem - > data . length > = 4 ) {
v = IVAL ( edit - > vitem - > data . data , 0 ) ;
2012-07-27 14:37:22 +04:00
}
2014-07-26 10:26:27 +04:00
tmp = talloc_asprintf ( dia , " %u " , ( unsigned ) v ) ;
2012-08-08 06:19:28 +04:00
if ( tmp = = NULL ) {
return WERR_NOMEM ;
}
2014-07-26 10:26:27 +04:00
dialog_section_text_field_set ( data , tmp ) ;
2012-08-07 06:11:13 +04:00
talloc_free ( tmp ) ;
2012-07-27 14:37:22 +04:00
break ;
}
2012-08-07 06:11:13 +04:00
case REG_SZ :
case REG_EXPAND_SZ : {
const char * s ;
2014-07-26 10:26:27 +04:00
if ( ! pull_reg_sz ( dia , & edit - > vitem - > data , & s ) ) {
2012-08-08 06:19:28 +04:00
return WERR_NOMEM ;
2012-08-07 06:11:13 +04:00
}
2014-07-26 10:26:27 +04:00
dialog_section_text_field_set ( data , s ) ;
2012-08-07 06:11:13 +04:00
break ;
}
2012-08-08 06:19:28 +04:00
case REG_MULTI_SZ : {
2014-07-26 10:26:27 +04:00
const char * * array ;
2012-08-08 06:19:28 +04:00
2014-07-26 10:26:27 +04:00
if ( ! pull_reg_multi_sz ( dia , & edit - > vitem - > data , & array ) ) {
2012-08-08 06:19:28 +04:00
return WERR_NOMEM ;
}
2014-07-26 10:26:27 +04:00
return dialog_section_text_field_set_lines ( dia , data , array ) ;
2012-08-08 06:19:28 +04:00
}
2012-08-09 07:44:58 +04:00
case REG_BINARY :
2014-07-26 10:26:27 +04:00
default :
return dialog_section_hexedit_set_buf ( data ,
edit - > vitem - > data . data ,
edit - > vitem - > data . length ) ;
2012-08-07 06:11:13 +04:00
}
2012-08-08 06:19:28 +04:00
return WERR_OK ;
2012-08-07 06:11:13 +04:00
}
2012-08-09 02:36:01 +04:00
static bool value_exists ( TALLOC_CTX * ctx , const struct registry_key * key ,
const char * name )
{
uint32_t type ;
DATA_BLOB blob ;
WERROR rv ;
rv = reg_key_get_value_by_name ( ctx , key , name , & type , & blob ) ;
return W_ERROR_IS_OK ( rv ) ;
}
2014-07-26 10:26:27 +04:00
static bool edit_on_submit ( struct dialog * dia , struct dialog_section * section ,
void * arg )
2012-08-08 10:41:50 +04:00
{
2014-07-26 10:26:27 +04:00
struct edit_req * edit = arg ;
2012-08-08 10:41:50 +04:00
WERROR rv ;
DATA_BLOB blob ;
2014-07-26 10:26:27 +04:00
const char * name ;
struct dialog_section * name_section , * data ;
name_section = dialog_find_section ( dia , " name " ) ;
if ( name_section ) {
name = dialog_section_text_field_get ( dia , name_section ) ;
if ( * name = = ' \0 ' ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Value name must not be blank. " ) ;
return false ;
}
if ( value_exists ( dia , edit - > key , name ) ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Value named \" %s \" already exists. " ,
name ) ;
return false ;
}
} else {
SMB_ASSERT ( edit - > vitem ) ;
name = edit - > vitem - > value_name ;
2012-08-09 02:36:01 +04:00
}
2014-07-26 10:26:27 +04:00
SMB_ASSERT ( name ) ;
2012-08-08 10:41:50 +04:00
2014-07-26 10:26:27 +04:00
data = dialog_find_section ( dia , " data " ) ;
SMB_ASSERT ( data ! = NULL ) ;
rv = WERR_OK ;
2012-08-20 07:02:51 +04:00
switch ( edit - > mode ) {
2012-08-08 10:41:50 +04:00
case REG_DWORD : {
2014-07-26 10:26:27 +04:00
unsigned long long v ;
2012-08-08 10:41:50 +04:00
uint32_t val ;
2014-07-26 10:26:27 +04:00
if ( ! dialog_section_text_field_get_uint ( data , & v ) ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" REG_DWORD value must be an integer. " ) ;
return false ;
2012-08-08 10:41:50 +04:00
}
2014-07-26 10:26:27 +04:00
if ( v > UINT32_MAX ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" REG_DWORD value must less than %lu. " ,
( unsigned long ) UINT32_MAX ) ;
return false ;
}
val = ( uint32_t ) v ;
blob = data_blob_talloc ( dia , NULL , sizeof ( val ) ) ;
2012-08-08 10:41:50 +04:00
SIVAL ( blob . data , 0 , val ) ;
break ;
}
case REG_SZ :
case REG_EXPAND_SZ : {
2014-07-26 10:26:27 +04:00
const char * buf ;
2012-08-09 07:44:58 +04:00
2014-07-26 10:26:27 +04:00
buf = dialog_section_text_field_get ( dia , data ) ;
if ( ! buf | | ! push_reg_sz ( dia , & blob , buf ) ) {
2012-08-08 10:41:50 +04:00
rv = WERR_NOMEM ;
}
break ;
}
case REG_MULTI_SZ : {
2014-07-26 10:26:27 +04:00
const char * * lines ;
2012-08-08 10:41:50 +04:00
2014-07-26 10:26:27 +04:00
lines = dialog_section_text_field_get_lines ( dia , data ) ;
if ( ! lines | | ! push_reg_multi_sz ( dia , & blob , lines ) ) {
2012-08-08 10:41:50 +04:00
rv = WERR_NOMEM ;
}
break ;
}
2014-07-26 10:26:27 +04:00
case REG_BINARY : {
const void * buf ;
size_t len ;
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
dialog_section_hexedit_get_buf ( data , & buf , & len ) ;
blob = data_blob_talloc ( dia , buf , len ) ;
2012-08-08 06:19:28 +04:00
break ;
}
}
2014-07-26 10:26:27 +04:00
if ( W_ERROR_IS_OK ( rv ) ) {
rv = reg_val_set ( edit - > key , name , edit - > type , blob ) ;
2012-08-09 07:44:58 +04:00
}
2014-07-26 10:26:27 +04:00
if ( ! W_ERROR_IS_OK ( rv ) ) {
const char * msg = get_friendly_werror_msg ( rv ) ;
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Error saving value: \n %s " , msg ) ;
2012-08-08 06:19:28 +04:00
2014-07-26 10:26:27 +04:00
return false ;
2012-08-08 06:19:28 +04:00
}
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
return true ;
2012-08-07 06:11:13 +04:00
2012-08-13 09:39:21 +04:00
}
2014-08-09 10:55:25 +04:00
static enum dialog_action edit_on_resize ( struct dialog * dia ,
struct dialog_section * section )
{
struct dialog_section * data ;
unsigned long size ;
int rv ;
data = dialog_find_section ( dia , " data " ) ;
rv = dialog_input_ulong ( dia , & size , " Resize " , " Enter size of buffer " ) ;
if ( rv = = DIALOG_OK ) {
dialog_section_hexedit_resize ( data , size ) ;
}
return DIALOG_IGNORE ;
}
2014-07-27 06:49:33 +04:00
int dialog_edit_value ( TALLOC_CTX * ctx , struct registry_key * key ,
uint32_t type , const struct value_item * vitem ,
bool force_binary , WERROR * err ,
const char * * name )
2012-08-13 09:39:21 +04:00
{
2014-07-26 10:26:27 +04:00
enum dialog_action action ;
struct dialog * dia ;
struct dialog_section * section ;
struct edit_req edit ;
2014-08-09 10:55:25 +04:00
struct button_spec buttons [ ] = {
2014-07-26 10:26:27 +04:00
{ . label = " OK " , . action = DIALOG_OK } ,
{ . label = " Cancel " , . action = DIALOG_CANCEL } ,
{ 0 }
} ;
2014-08-09 10:55:25 +04:00
struct button_spec buttons_hexedit [ ] = {
{ . label = " OK " , . action = DIALOG_OK } ,
{ . label = " Resize Buffer " , . on_enter = edit_on_resize } ,
{ . label = " Cancel " , . action = DIALOG_CANCEL } ,
{ 0 }
} ;
2012-08-13 09:39:21 +04:00
2014-07-26 10:26:27 +04:00
edit . key = key ;
edit . vitem = vitem ;
edit . type = type ;
edit . mode = type ;
if ( force_binary | | ( vitem & & vitem - > unprintable ) ) {
edit . mode = REG_BINARY ;
2012-08-13 09:39:21 +04:00
}
2014-07-26 10:26:27 +04:00
dia = dialog_new ( ctx , PAIR_BLACK_CYAN , " Edit Value " , - 1 , - 1 ) ;
dialog_set_submit_cb ( dia , edit_on_submit , & edit ) ;
2012-08-09 07:44:58 +04:00
2014-07-26 10:26:27 +04:00
section = dialog_section_label_new ( dia , " Type " ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_label_new ( dia , " %s " ,
str_regtype ( type ) ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_hsep_new ( dia , ' ' ) ;
dialog_append_section ( dia , section ) ;
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
section = dialog_section_label_new ( dia , " Name " ) ;
dialog_append_section ( dia , section ) ;
2012-08-07 06:11:13 +04:00
if ( vitem ) {
2014-07-26 10:26:27 +04:00
section = dialog_section_label_new ( dia , " %s " ,
vitem - > value_name ) ;
2012-08-19 11:18:22 +04:00
} else {
2014-07-26 10:26:27 +04:00
section = dialog_section_text_field_new ( dia , 1 , 50 ) ;
dialog_section_set_name ( section , " name " ) ;
2012-08-13 09:39:21 +04:00
}
2014-07-26 10:26:27 +04:00
dialog_append_section ( dia , section ) ;
section = dialog_section_hsep_new ( dia , ' ' ) ;
dialog_append_section ( dia , section ) ;
2012-08-13 09:39:21 +04:00
2014-07-26 10:26:27 +04:00
section = dialog_section_label_new ( dia , " Data " ) ;
dialog_append_section ( dia , section ) ;
2012-08-20 07:02:51 +04:00
2014-07-26 10:26:27 +04:00
switch ( edit . mode ) {
case REG_DWORD :
case REG_SZ :
case REG_EXPAND_SZ :
section = dialog_section_text_field_new ( dia , 1 , 50 ) ;
break ;
case REG_MULTI_SZ :
section = dialog_section_text_field_new ( dia , 10 , 50 ) ;
break ;
case REG_BINARY :
default :
section = dialog_section_hexedit_new ( dia , 10 ) ;
break ;
2012-08-13 09:39:21 +04:00
}
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
dialog_section_set_name ( section , " data " ) ;
dialog_append_section ( dia , section ) ;
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
section = dialog_section_hsep_new ( dia , 0 ) ;
dialog_append_section ( dia , section ) ;
2014-08-09 10:55:25 +04:00
if ( edit . mode = = REG_BINARY ) {
section = dialog_section_buttons_new ( dia , buttons_hexedit ) ;
} else {
section = dialog_section_buttons_new ( dia , buttons ) ;
}
2014-07-26 10:26:27 +04:00
dialog_section_set_justify ( section , SECTION_JUSTIFY_CENTER ) ;
dialog_append_section ( dia , section ) ;
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
dialog_create ( dia ) ;
2012-08-19 11:18:22 +04:00
2014-07-27 06:49:33 +04:00
* err = fill_value_buffer ( dia , & edit ) ;
if ( ! W_ERROR_IS_OK ( * err ) ) {
return DIALOG_CANCEL ;
2014-07-26 10:26:27 +04:00
}
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
dialog_show ( dia ) ;
2014-07-27 06:49:33 +04:00
dialog_modal_loop ( dia , err , & action ) ;
if ( action = = DIALOG_OK & & name ) {
if ( vitem ) {
* name = talloc_strdup ( ctx , vitem - > value_name ) ;
} else if ( ( section = dialog_find_section ( dia , " name " ) ) ) {
* name = dialog_section_text_field_get ( ctx , section ) ;
}
}
2012-08-07 06:11:13 +04:00
2014-07-26 10:26:27 +04:00
talloc_free ( dia ) ;
2012-08-08 10:41:50 +04:00
2014-07-27 06:49:33 +04:00
return action ;
2012-07-27 14:37:22 +04:00
}
2012-08-08 23:09:03 +04:00
2012-08-11 08:56:58 +04:00
int dialog_select_type ( TALLOC_CTX * ctx , int * type )
2012-08-08 23:09:03 +04:00
{
2014-07-26 10:26:27 +04:00
WERROR err ;
enum dialog_action action ;
2012-08-08 23:09:03 +04:00
struct dialog * dia ;
2014-07-26 10:26:27 +04:00
struct dialog_section * section ;
2012-08-08 23:09:03 +04:00
const char * reg_types [ ] = {
2014-07-26 10:26:27 +04:00
" REG_BINARY " ,
2012-08-08 23:09:03 +04:00
" REG_DWORD " ,
" REG_EXPAND_SZ " ,
" REG_MULTI_SZ " ,
2014-07-26 10:26:27 +04:00
" REG_SZ "
2012-08-08 23:09:03 +04:00
} ;
2014-07-26 10:26:27 +04:00
# define NTYPES ARRAY_SIZE(reg_types)
struct button_spec spec [ ] = {
{ . label = " OK " , . action = DIALOG_OK } ,
{ . label = " Cancel " , . action = DIALOG_CANCEL } ,
{ 0 }
} ;
bool flags [ NTYPES ] = { true } ;
struct option_spec opsec [ NTYPES + 1 ] ;
unsigned i ;
2012-08-08 23:09:03 +04:00
2014-07-26 10:26:27 +04:00
memset ( & opsec , ' \0 ' , sizeof ( opsec ) ) ;
2012-08-08 23:09:03 +04:00
for ( i = 0 ; i < NTYPES ; + + i ) {
2014-07-26 10:26:27 +04:00
opsec [ i ] . label = reg_types [ i ] ;
opsec [ i ] . state = & flags [ i ] ;
}
dia = dialog_new ( ctx , PAIR_BLACK_CYAN , " New Value " , - 1 , - 1 ) ;
section = dialog_section_label_new ( dia , " Select type for new value: " ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_hsep_new ( dia , ' ' ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_options_new ( dia , opsec , 2 , true ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_hsep_new ( dia , 0 ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_buttons_new ( dia , spec ) ;
dialog_section_set_justify ( section , SECTION_JUSTIFY_CENTER ) ;
dialog_append_section ( dia , section ) ;
dialog_create ( dia ) ;
dialog_show ( dia ) ;
dialog_modal_loop ( dia , & err , & action ) ;
if ( action = = DIALOG_OK ) {
for ( i = 0 ; i < NTYPES ; + + i ) {
if ( flags [ i ] ) {
* type = regtype_by_string ( reg_types [ i ] ) ;
break ;
}
2012-08-08 23:09:03 +04:00
}
}
talloc_free ( dia ) ;
2014-07-26 10:26:27 +04:00
return action ;
2012-08-08 23:09:03 +04:00
}
2014-06-03 08:50:01 +04:00
2014-07-31 09:04:50 +04:00
struct search_req {
TALLOC_CTX * ctx ;
struct regedit_search_opts * opts ;
} ;
static bool search_on_submit ( struct dialog * dia , struct dialog_section * section ,
void * arg )
{
struct search_req * search = arg ;
struct dialog_section * query ;
query = dialog_find_section ( dia , " query " ) ;
SMB_ASSERT ( query ! = NULL ) ;
if ( ! search - > opts - > search_key & & ! search - > opts - > search_value ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Must search a key and/or a value " ) ;
return false ;
}
talloc_free ( discard_const ( search - > opts - > query ) ) ;
search - > opts - > query = dialog_section_text_field_get ( search - > ctx , query ) ;
SMB_ASSERT ( search - > opts - > query ! = NULL ) ;
if ( search - > opts - > query [ 0 ] = = ' \0 ' ) {
dialog_notice ( dia , DIA_ALERT , " Error " ,
" Query must not be blank. " ) ;
return false ;
}
return true ;
}
2014-06-03 08:50:01 +04:00
int dialog_search_input ( TALLOC_CTX * ctx , struct regedit_search_opts * opts )
{
2014-07-31 09:04:50 +04:00
WERROR err ;
enum dialog_action action ;
struct dialog * dia ;
struct dialog_section * section , * query ;
struct search_req search ;
struct button_spec spec [ ] = {
{ . label = " Search " , . action = DIALOG_OK } ,
{ . label = " Cancel " , . action = DIALOG_CANCEL } ,
{ 0 }
} ;
struct option_spec search_opts [ ] = {
{ . label = " Search Keys " , . state = & opts - > search_key } ,
{ . label = " Search Values " , . state = & opts - > search_value } ,
{ . label = " Recursive " , . state = & opts - > search_recursive } ,
{ . label = " Case Sensitive " , . state = & opts - > search_case } ,
{ 0 }
} ;
if ( ! opts - > search_key & & ! opts - > search_value ) {
opts - > search_key = true ;
}
search . ctx = ctx ;
search . opts = opts ;
dia = dialog_new ( ctx , PAIR_BLACK_CYAN , " Search " , - 1 , - 1 ) ;
dialog_set_submit_cb ( dia , search_on_submit , & search ) ;
section = dialog_section_label_new ( dia , " Query " ) ;
dialog_append_section ( dia , section ) ;
query = dialog_section_text_field_new ( dia , 1 , - 1 ) ;
dialog_section_set_name ( query , " query " ) ;
dialog_append_section ( dia , query ) ;
section = dialog_section_hsep_new ( dia , 0 ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_options_new ( dia , search_opts , 2 , false ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_hsep_new ( dia , 0 ) ;
dialog_append_section ( dia , section ) ;
section = dialog_section_buttons_new ( dia , spec ) ;
dialog_section_set_justify ( section , SECTION_JUSTIFY_CENTER ) ;
dialog_append_section ( dia , section ) ;
2014-06-03 08:50:01 +04:00
2014-07-31 09:04:50 +04:00
dialog_create ( dia ) ;
if ( opts - > query ) {
dialog_section_text_field_set ( query , opts - > query ) ;
}
2014-06-03 08:50:01 +04:00
2014-07-31 09:04:50 +04:00
dialog_modal_loop ( dia , & err , & action ) ;
talloc_free ( dia ) ;
2014-06-03 08:50:01 +04:00
2014-07-31 09:04:50 +04:00
return action ;
2014-06-03 08:50:01 +04:00
}