iPXE
Data Structures | Defines | Functions
settings_ui.c File Reference

Option configuration console. More...

#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <curses.h>
#include <ipxe/console.h>
#include <ipxe/settings.h>
#include <ipxe/editbox.h>
#include <ipxe/keys.h>
#include <ipxe/ansicol.h>
#include <ipxe/jumpscroll.h>
#include <ipxe/settings_ui.h>
#include <config/branding.h>

Go to the source code of this file.

Data Structures

struct  settings_ui_row
 A settings user interface row. More...
struct  settings_ui
 A settings user interface. More...

Defines

#define TITLE_ROW   1U
#define SETTINGS_LIST_ROW   3U
#define SETTINGS_LIST_COL   1U
#define SETTINGS_LIST_ROWS   ( LINES - 6U - SETTINGS_LIST_ROW )
#define INFO_ROW   ( LINES - 5U )
#define ALERT_ROW   ( LINES - 2U )
#define INSTRUCTION_ROW   ( LINES - 2U )
#define INSTRUCTION_PAD   " "
#define SETTING_ROW_TEXT(cols)
 Layout of text within a setting row.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static unsigned int select_setting_row (struct settings_ui *ui, unsigned int index)
 Select a setting.
static size_t string_copy (char *dest, const char *src, size_t len)
 Copy string without NUL termination.
static void draw_setting_row (struct settings_ui *ui)
 Draw setting row.
static int edit_setting (struct settings_ui *ui, int key)
 Edit setting ui.
static int save_setting (struct settings_ui *ui)
 Save setting ui value back to configuration settings.
static void vmsg (unsigned int row, const char *fmt, va_list args)
 Print message centred on specified row.
static void msg (unsigned int row, const char *fmt,...)
 Print message centred on specified row.
static void clearmsg (unsigned int row)
 Clear message on specified row.
static void valert (const char *fmt, va_list args)
 Print alert message.
static void alert (const char *fmt,...)
 Print alert message.
static void draw_title_row (struct settings_ui *ui)
 Draw title row.
static void draw_info_row (struct settings_ui *ui)
 Draw information row.
static void draw_instruction_row (struct settings_ui *ui)
 Draw instruction row.
static void draw_setting_rows (struct settings_ui *ui)
 Draw the current block of setting rows.
static void select_settings (struct settings_ui *ui, struct settings *settings)
 Select settings block.
static int main_loop (struct settings *settings)
int settings_ui (struct settings *settings)

Detailed Description

Option configuration console.

Definition in file settings_ui.c.


Define Documentation

#define TITLE_ROW   1U

Definition at line 47 of file settings_ui.c.

Referenced by draw_title_row().

#define SETTINGS_LIST_ROW   3U

Definition at line 48 of file settings_ui.c.

Referenced by draw_setting_rows(), and select_setting_row().

#define SETTINGS_LIST_COL   1U

Definition at line 49 of file settings_ui.c.

Referenced by draw_setting_row(), draw_setting_rows(), and select_setting_row().

#define SETTINGS_LIST_ROWS   ( LINES - 6U - SETTINGS_LIST_ROW )

Definition at line 50 of file settings_ui.c.

Referenced by draw_setting_rows(), and select_settings().

#define INFO_ROW   ( LINES - 5U )

Definition at line 51 of file settings_ui.c.

Referenced by draw_info_row().

#define ALERT_ROW   ( LINES - 2U )

Definition at line 52 of file settings_ui.c.

Referenced by valert().

#define INSTRUCTION_ROW   ( LINES - 2U )

Definition at line 53 of file settings_ui.c.

Referenced by draw_instruction_row().

#define INSTRUCTION_PAD   " "

Definition at line 54 of file settings_ui.c.

Referenced by draw_instruction_row().

#define SETTING_ROW_TEXT (   cols)
Value:
struct {                                \
        char start[0];                                                  \
        char pad1[1];                                                   \
        union {                                                         \
                char settings[ cols - 1 - 1 - 1 - 1 ];                  \
                struct {                                                \
                        char name[15];                                  \
                        char pad2[1];                                   \
                        char value[ cols - 1 - 15 - 1 - 1 - 1 - 1 ];    \
                } setting;                                              \
        } u;                                                            \
        char pad3[1];                                                   \
        char nul;                                                       \
} __attribute__ (( packed ))

Layout of text within a setting row.

Definition at line 57 of file settings_ui.c.

Referenced by draw_setting_row(), and select_setting_row().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static unsigned int select_setting_row ( struct settings_ui ui,
unsigned int  index 
) [static]

Select a setting.

Parameters:
uiSettings user interface
indexIndex of setting row
Return values:
countNumber of setting rows

Definition at line 116 of file settings_ui.c.

References settings::children, COLS, count, settings_ui_row::editbox, fetchf_setting(), jump_scroller::first, for_each_table_entry, init_editbox(), list_for_each_entry, memset(), settings::name, NULL, offsetof, settings_ui_row::origin, settings::parent, settings_ui_row::row, settings_ui::row, settings_ui::scroll, settings_ui_row::setting, setting_applies(), setting_cmp(), SETTING_ROW_TEXT, SETTINGS, settings_ui_row::settings, settings_ui::settings, SETTINGS_LIST_COL, SETTINGS_LIST_ROW, snprintf(), u, and settings_ui_row::value.

Referenced by draw_setting_rows(), main_loop(), and select_settings().

                                                              {
        SETTING_ROW_TEXT ( COLS ) *text;
        struct settings *settings;
        struct setting *setting;
        struct setting *previous = NULL;
        unsigned int count = 0;

        /* Initialise structure */
        memset ( &ui->row, 0, sizeof ( ui->row ) );
        ui->row.row = ( SETTINGS_LIST_ROW + index - ui->scroll.first );

        /* Include parent settings block, if applicable */
        if ( ui->settings->parent && ( count++ == index ) ) {
                ui->row.settings = ui->settings->parent;
                snprintf ( ui->row.value, sizeof ( ui->row.value ),
                           "../" );
        }

        /* Include any child settings blocks, if applicable */
        list_for_each_entry ( settings, &ui->settings->children, siblings ) {
                if ( count++ == index ) {
                        ui->row.settings = settings;
                        snprintf ( ui->row.value, sizeof ( ui->row.value ),
                                   "%s/", settings->name );
                }
        }

        /* Include any applicable settings */
        for_each_table_entry ( setting, SETTINGS ) {

                /* Skip inapplicable settings */
                if ( ! setting_applies ( ui->settings, setting ) )
                        continue;

                /* Skip duplicate settings */
                if ( previous && ( setting_cmp ( setting, previous ) == 0 ) )
                        continue;
                previous = setting;

                /* Read current setting value and origin */
                if ( count++ == index ) {
                        fetchf_setting ( ui->settings, setting, &ui->row.origin,
                                         &ui->row.setting, ui->row.value,
                                         sizeof ( ui->row.value ) );
                }
        }

        /* Initialise edit box */
        init_editbox ( &ui->row.editbox, ui->row.value,
                       sizeof ( ui->row.value ), NULL, ui->row.row,
                       ( SETTINGS_LIST_COL +
                         offsetof ( typeof ( *text ), u.setting.value ) ),
                       sizeof ( text->u.setting.value ), 0 );

        return count;
}
static size_t string_copy ( char *  dest,
const char *  src,
size_t  len 
) [static]

Copy string without NUL termination.

Parameters:
destDestination
srcSource
lenMaximum length of destination
Return values:
lenLength of (unterminated) string

Definition at line 182 of file settings_ui.c.

References len, memcpy(), and strlen().

Referenced by draw_setting_row().

                                                                      {
        size_t src_len;

        src_len = strlen ( src );
        if ( len > src_len )
                len = src_len;
        memcpy ( dest, src, len );
        return len;
}
static void draw_setting_row ( struct settings_ui ui) [static]

Draw setting row.

Parameters:
uiSettings UI

Definition at line 197 of file settings_ui.c.

References A_BOLD, attroff(), attron(), COLS, memset(), move(), mvprintw, setting::name, NULL, offsetof, settings_ui_row::origin, settings_ui_row::row, settings_ui::row, settings_ui_row::setting, SETTING_ROW_TEXT, settings_ui_row::settings, settings_ui::settings, SETTINGS_LIST_COL, string_copy(), u, settings_ui_row::value, and value.

Referenced by draw_setting_rows(), and main_loop().

                                                        {
        SETTING_ROW_TEXT ( COLS ) text;
        unsigned int curs_offset;
        char *value;

        /* Fill row with spaces */
        memset ( &text, ' ', sizeof ( text ) );
        text.nul = '\0';

        /* Construct row content */
        if ( ui->row.settings ) {

                /* Construct space-padded name */
                curs_offset = ( offsetof ( typeof ( text ), u.settings ) +
                                string_copy ( text.u.settings,
                                              ui->row.value,
                                              sizeof ( text.u.settings ) ) );

        } else {

                /* Construct dot-padded name */
                memset ( text.u.setting.name, '.',
                         sizeof ( text.u.setting.name ) );
                string_copy ( text.u.setting.name, ui->row.setting.name,
                              sizeof ( text.u.setting.name ) );

                /* Construct space-padded value */
                value = ui->row.value;
                if ( ! *value )
                        value = "<not specified>";
                curs_offset = ( offsetof ( typeof ( text ), u.setting.value ) +
                                string_copy ( text.u.setting.value, value,
                                              sizeof ( text.u.setting.value )));
        }

        /* Print row */
        if ( ( ui->row.origin == ui->settings ) || ( ui->row.settings != NULL ))
                attron ( A_BOLD );
        mvprintw ( ui->row.row, SETTINGS_LIST_COL, "%s", text.start );
        attroff ( A_BOLD );
        move ( ui->row.row, ( SETTINGS_LIST_COL + curs_offset ) );
}
static int edit_setting ( struct settings_ui ui,
int  key 
) [static]

Edit setting ui.

Parameters:
uiSettings UI
keyKey pressed by user
Return values:
keyKey returned to application, or zero

Definition at line 247 of file settings_ui.c.

References assert, edit_editbox(), settings_ui_row::editbox, settings_ui_row::editing, setting::name, NULL, settings_ui::row, and settings_ui_row::setting.

Referenced by main_loop().

                                                            {
        assert ( ui->row.setting.name != NULL );
        ui->row.editing = 1;
        return edit_editbox ( &ui->row.editbox, key );
}
static int save_setting ( struct settings_ui ui) [static]

Save setting ui value back to configuration settings.

Parameters:
uiSettings UI

Definition at line 258 of file settings_ui.c.

References assert, setting::name, NULL, settings_ui::row, settings_ui_row::setting, settings_ui::settings, storef_setting(), and settings_ui_row::value.

Referenced by main_loop().

                                                   {
        assert ( ui->row.setting.name != NULL );
        return storef_setting ( ui->settings, &ui->row.setting, ui->row.value );
}
static void vmsg ( unsigned int  row,
const char *  fmt,
va_list  args 
) [static]

Print message centred on specified row.

Parameters:
rowRow
fmtprintf() format string
argsprintf() argument list

Definition at line 270 of file settings_ui.c.

References COLS, len, mvprintw, and vsnprintf().

Referenced by msg(), and valert().

                                                                     {
        char buf[COLS];
        size_t len;

        len = vsnprintf ( buf, sizeof ( buf ), fmt, args );
        mvprintw ( row, ( ( COLS - len ) / 2 ), "%s", buf );
}
static void msg ( unsigned int  row,
const char *  fmt,
  ... 
) [static]
static void clearmsg ( unsigned int  row) [static]

Clear message on specified row.

Parameters:
rowRow

Definition at line 298 of file settings_ui.c.

References clrtoeol(), and move().

Referenced by draw_info_row(), draw_instruction_row(), draw_setting_rows(), draw_title_row(), and valert().

                                          {
        move ( row, 0 );
        clrtoeol();
}
static void valert ( const char *  fmt,
va_list  args 
) [static]

Print alert message.

Parameters:
fmtprintf() format string
argsprintf() argument list

Definition at line 309 of file settings_ui.c.

References ALERT_ROW, clearmsg(), color_set, CPAIR_ALERT, CPAIR_NORMAL, NULL, sleep(), and vmsg().

Referenced by alert().

static void alert ( const char *  fmt,
  ... 
) [static]

Print alert message.

Parameters:
fmtprintf() format string
...printf() arguments

Definition at line 324 of file settings_ui.c.

References va_end, va_start, and valert().

Referenced by main_loop(), and tls_new_alert().

                                           {
        va_list args;

        va_start ( args, fmt );
        valert ( fmt, args );
        va_end ( args );
}
static void draw_title_row ( struct settings_ui ui) [static]

Draw title row.

Parameters:
uiSettings UI

Definition at line 337 of file settings_ui.c.

References A_BOLD, attroff(), attron(), clearmsg(), msg(), name, PRODUCT_SHORT_NAME, settings_ui::settings, settings_name(), and TITLE_ROW.

Referenced by select_settings().

                                                      {
        const char *name;

        clearmsg ( TITLE_ROW );
        name = settings_name ( ui->settings );
        attron ( A_BOLD );
        msg ( TITLE_ROW, PRODUCT_SHORT_NAME " configuration settings%s%s",
              ( name[0] ? " - " : "" ), name );
        attroff ( A_BOLD );
}
static void draw_info_row ( struct settings_ui ui) [static]

Draw information row.

Parameters:
uiSettings UI

Definition at line 353 of file settings_ui.c.

References A_BOLD, attroff(), attron(), clearmsg(), color_set, CPAIR_NORMAL, CPAIR_URL, setting::description, INFO_ROW, msg(), setting::name, NULL, settings_ui_row::origin, PRODUCT_SETTING_URI, settings_ui::row, settings_ui_row::setting, setting_name(), and settings_ui::settings.

Referenced by main_loop().

                                                     {
        char buf[32];

        /* Draw nothing unless this row represents a setting */
        clearmsg ( INFO_ROW );
        clearmsg ( INFO_ROW + 1 );
        if ( ! ui->row.setting.name )
                return;

        /* Determine a suitable setting name */
        setting_name ( ( ui->row.origin ?
                         ui->row.origin : ui->settings ),
                       &ui->row.setting, buf, sizeof ( buf ) );

        /* Draw row */
        attron ( A_BOLD );
        msg ( INFO_ROW, "%s - %s", buf, ui->row.setting.description );
        attroff ( A_BOLD );
        color_set ( CPAIR_URL, NULL );
        msg ( ( INFO_ROW + 1 ), PRODUCT_SETTING_URI, ui->row.setting.name );
        color_set ( CPAIR_NORMAL, NULL );
}
static void draw_instruction_row ( struct settings_ui ui) [static]

Draw instruction row.

Parameters:
uiSettings UI

Definition at line 381 of file settings_ui.c.

References clearmsg(), settings_ui_row::editing, INSTRUCTION_PAD, INSTRUCTION_ROW, msg(), settings_ui_row::origin, settings_ui::row, and settings_ui::settings.

Referenced by main_loop().

                                                            {

        clearmsg ( INSTRUCTION_ROW );
        if ( ui->row.editing ) {
                msg ( INSTRUCTION_ROW,
                      "Enter - accept changes" INSTRUCTION_PAD
                      "Ctrl-C - discard changes" );
        } else {
                msg ( INSTRUCTION_ROW,
                      "%sCtrl-X - exit configuration utility",
                      ( ( ui->row.origin == ui->settings ) ?
                        "Ctrl-D - delete setting" INSTRUCTION_PAD : "" ) );
        }
}
static void draw_setting_rows ( struct settings_ui ui) [static]

Draw the current block of setting rows.

Parameters:
uiSettings UI

Definition at line 401 of file settings_ui.c.

References clearmsg(), color_set, jump_scroller::count, CPAIR_NORMAL, CPAIR_SEPARATOR, draw_setting_row(), jump_scroller::first, jump_scroll_is_first(), jump_scroll_is_last(), mvaddstr(), NULL, settings_ui::scroll, select_setting_row(), SETTINGS_LIST_COL, SETTINGS_LIST_ROW, and SETTINGS_LIST_ROWS.

Referenced by main_loop(), and select_settings().

                                                         {
        unsigned int i;

        /* Draw ellipses before and/or after the list as necessary */
        color_set ( CPAIR_SEPARATOR, NULL );
        mvaddstr ( ( SETTINGS_LIST_ROW - 1 ), ( SETTINGS_LIST_COL + 1 ),
                   jump_scroll_is_first ( &ui->scroll ) ? "   " : "..." );
        mvaddstr ( ( SETTINGS_LIST_ROW + SETTINGS_LIST_ROWS ),
                   ( SETTINGS_LIST_COL + 1 ),
                   jump_scroll_is_last ( &ui->scroll ) ? "   " : "..." );
        color_set ( CPAIR_NORMAL, NULL );

        /* Draw visible settings. */
        for ( i = 0 ; i < SETTINGS_LIST_ROWS ; i++ ) {
                if ( ( ui->scroll.first + i ) < ui->scroll.count ) {
                        select_setting_row ( ui, ( ui->scroll.first + i ) );
                        draw_setting_row ( ui );
                } else {
                        clearmsg ( SETTINGS_LIST_ROW + i );
                }
        }
}
static void select_settings ( struct settings_ui ui,
struct settings settings 
) [static]

Select settings block.

Parameters:
uiSettings UI
settingsSettings block

Definition at line 430 of file settings_ui.c.

References jump_scroller::count, jump_scroller::current, draw_setting_rows(), draw_title_row(), jump_scroller::first, jump_scroller::rows, settings_ui::scroll, select_setting_row(), settings_ui::settings, SETTINGS_LIST_ROWS, and settings_target().

Referenced by main_loop().

                                                          {

        ui->settings = settings_target ( settings );
        ui->scroll.count = select_setting_row ( ui, 0 );
        ui->scroll.rows = SETTINGS_LIST_ROWS;
        ui->scroll.current = 0;
        ui->scroll.first = 0;
        draw_title_row ( ui );
        draw_setting_rows ( ui );
        select_setting_row ( ui, 0 );
}
static int main_loop ( struct settings settings) [static]

Definition at line 443 of file settings_ui.c.

References alert(), assert, color_set, CPAIR_EDIT, CPAIR_NORMAL, CPAIR_SELECT, CR, CTRL_C, CTRL_D, CTRL_X, jump_scroller::current, curs_set(), delete_setting(), draw_editbox(), draw_info_row(), draw_instruction_row(), draw_setting_row(), draw_setting_rows(), edit_setting(), settings_ui_row::editbox, settings_ui_row::editing, getkey(), jump_scroll(), jump_scroll_key(), jump_scroll_move(), key, LF, memset(), move(), setting::name, NULL, rc, settings_ui::row, save_setting(), settings_ui::scroll, select_setting_row(), select_settings(), settings_ui_row::setting, settings_ui_row::settings, settings_ui::settings, and strerror().

Referenced by settings_ui().

                                                   {
        struct settings_ui ui;
        unsigned int previous;
        int redraw = 1;
        int move;
        int key;
        int rc;

        /* Print initial screen content */
        color_set ( CPAIR_NORMAL, NULL );
        memset ( &ui, 0, sizeof ( ui ) );
        select_settings ( &ui, settings );

        while ( 1 ) {

                /* Redraw rows if necessary */
                if ( redraw ) {
                        draw_info_row ( &ui );
                        draw_instruction_row ( &ui );
                        color_set ( ( ui.row.editing ?
                                      CPAIR_EDIT : CPAIR_SELECT ), NULL );
                        draw_setting_row ( &ui );
                        color_set ( CPAIR_NORMAL, NULL );
                        curs_set ( ui.row.editing );
                        redraw = 0;
                }

                /* Edit setting, if we are currently editing */
                if ( ui.row.editing ) {

                        /* Sanity check */
                        assert ( ui.row.setting.name != NULL );

                        /* Redraw edit box */
                        color_set ( CPAIR_EDIT, NULL );
                        draw_editbox ( &ui.row.editbox );
                        color_set ( CPAIR_NORMAL, NULL );

                        /* Process keypress */
                        key = edit_setting ( &ui, getkey ( 0 ) );
                        switch ( key ) {
                        case CR:
                        case LF:
                                if ( ( rc = save_setting ( &ui ) ) != 0 )
                                        alert ( " %s ", strerror ( rc ) );
                                /* Fall through */
                        case CTRL_C:
                                select_setting_row ( &ui, ui.scroll.current );
                                redraw = 1;
                                break;
                        default:
                                /* Do nothing */
                                break;
                        }

                        continue;
                }

                /* Otherwise, navigate through settings */
                key = getkey ( 0 );
                move = jump_scroll_key ( &ui.scroll, key );
                if ( move ) {
                        previous = ui.scroll.current;
                        jump_scroll_move ( &ui.scroll, move );
                        if ( ui.scroll.current != previous ) {
                                draw_setting_row ( &ui );
                                redraw = 1;
                                if ( jump_scroll ( &ui.scroll ) )
                                        draw_setting_rows ( &ui );
                                select_setting_row ( &ui, ui.scroll.current );
                        }
                        continue;
                }

                /* Handle non-navigation keys */
                switch ( key ) {
                case CTRL_D:
                        if ( ! ui.row.setting.name )
                                break;
                        if ( ( rc = delete_setting ( ui.settings,
                                                     &ui.row.setting ) ) != 0 ){
                                alert ( " %s ", strerror ( rc ) );
                        }
                        select_setting_row ( &ui, ui.scroll.current );
                        redraw = 1;
                        break;
                case CTRL_X:
                        return 0;
                case CR:
                case LF:
                        if ( ui.row.settings ) {
                                select_settings ( &ui, ui.row.settings );
                                redraw = 1;
                        }
                        /* Fall through */
                default:
                        if ( ui.row.setting.name ) {
                                edit_setting ( &ui, key );
                                redraw = 1;
                        }
                        break;
                }
        }
}
int settings_ui ( struct settings settings)

Definition at line 548 of file settings_ui.c.

References color_set, CPAIR_NORMAL, curs_set(), endwin(), erase(), initscr(), main_loop(), NULL, rc, and start_color.

                                              {
        int rc;

        initscr();
        start_color();
        color_set ( CPAIR_NORMAL, NULL );
        curs_set ( 0 );
        erase();
        
        rc = main_loop ( settings );

        endwin();

        return rc;
}