diff options
Diffstat (limited to 'qemu/roms/ipxe/src/hci/tui/settings_ui.c')
-rw-r--r-- | qemu/roms/ipxe/src/hci/tui/settings_ui.c | 562 |
1 files changed, 0 insertions, 562 deletions
diff --git a/qemu/roms/ipxe/src/hci/tui/settings_ui.c b/qemu/roms/ipxe/src/hci/tui/settings_ui.c deleted file mode 100644 index be421cc0a..000000000 --- a/qemu/roms/ipxe/src/hci/tui/settings_ui.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * 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 2 of the - * License, or 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#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> - -/** @file - * - * Option configuration console - * - */ - -/* Screen layout */ -#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 " " - -/** Layout of text within a setting row */ -#define SETTING_ROW_TEXT( cols ) 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 )) - -/** A settings user interface row */ -struct settings_ui_row { - /** Target configuration settings block - * - * Valid only for rows that lead to new settings blocks. - */ - struct settings *settings; - /** Configuration setting origin - * - * Valid only for rows that represent individual settings. - */ - struct settings *origin; - /** Configuration setting - * - * Valid only for rows that represent individual settings. - */ - struct setting setting; - /** Screen row */ - unsigned int row; - /** Edit box widget used for editing setting */ - struct edit_box editbox; - /** Editing in progress flag */ - int editing; - /** Buffer for setting's value */ - char value[256]; /* enough size for a DHCP string */ -}; - -/** A settings user interface */ -struct settings_ui { - /** Settings block */ - struct settings *settings; - /** Jump scroller */ - struct jump_scroller scroll; - /** Current row */ - struct settings_ui_row row; -}; - -/** - * Select a setting - * - * @v ui Settings user interface - * @v index Index of setting row - * @ret count Number of setting rows - */ -static unsigned int select_setting_row ( struct settings_ui *ui, - unsigned int index ) { - 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; -} - -/** - * Copy string without NUL termination - * - * @v dest Destination - * @v src Source - * @v len Maximum length of destination - * @ret len Length of (unterminated) string - */ -static size_t string_copy ( char *dest, const char *src, size_t len ) { - size_t src_len; - - src_len = strlen ( src ); - if ( len > src_len ) - len = src_len; - memcpy ( dest, src, len ); - return len; -} - -/** - * Draw setting row - * - * @v ui Settings UI - */ -static void draw_setting_row ( struct settings_ui *ui ) { - 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 ) ); -} - -/** - * Edit setting ui - * - * @v ui Settings UI - * @v key Key pressed by user - * @ret key Key returned to application, or zero - */ -static int edit_setting ( struct settings_ui *ui, int key ) { - assert ( ui->row.setting.name != NULL ); - ui->row.editing = 1; - return edit_editbox ( &ui->row.editbox, key ); -} - -/** - * Save setting ui value back to configuration settings - * - * @v ui Settings UI - */ -static int save_setting ( struct settings_ui *ui ) { - assert ( ui->row.setting.name != NULL ); - return storef_setting ( ui->settings, &ui->row.setting, ui->row.value ); -} - -/** - * Print message centred on specified row - * - * @v row Row - * @v fmt printf() format string - * @v args printf() argument list - */ -static void vmsg ( unsigned int row, const char *fmt, va_list args ) { - char buf[COLS]; - size_t len; - - len = vsnprintf ( buf, sizeof ( buf ), fmt, args ); - mvprintw ( row, ( ( COLS - len ) / 2 ), "%s", buf ); -} - -/** - * Print message centred on specified row - * - * @v row Row - * @v fmt printf() format string - * @v .. printf() arguments - */ -static void msg ( unsigned int row, const char *fmt, ... ) { - va_list args; - - va_start ( args, fmt ); - vmsg ( row, fmt, args ); - va_end ( args ); -} - -/** - * Clear message on specified row - * - * @v row Row - */ -static void clearmsg ( unsigned int row ) { - move ( row, 0 ); - clrtoeol(); -} - -/** - * Print alert message - * - * @v fmt printf() format string - * @v args printf() argument list - */ -static void valert ( const char *fmt, va_list args ) { - clearmsg ( ALERT_ROW ); - color_set ( CPAIR_ALERT, NULL ); - vmsg ( ALERT_ROW, fmt, args ); - sleep ( 2 ); - color_set ( CPAIR_NORMAL, NULL ); - clearmsg ( ALERT_ROW ); -} - -/** - * Print alert message - * - * @v fmt printf() format string - * @v ... printf() arguments - */ -static void alert ( const char *fmt, ... ) { - va_list args; - - va_start ( args, fmt ); - valert ( fmt, args ); - va_end ( args ); -} - -/** - * Draw title row - * - * @v ui Settings UI - */ -static void draw_title_row ( struct settings_ui *ui ) { - 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 ); -} - -/** - * Draw information row - * - * @v ui Settings UI - */ -static void draw_info_row ( struct settings_ui *ui ) { - 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 ); -} - -/** - * Draw instruction row - * - * @v ui Settings UI - */ -static void draw_instruction_row ( struct settings_ui *ui ) { - - 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 : "" ) ); - } -} - -/** - * Draw the current block of setting rows - * - * @v ui Settings UI - */ -static void draw_setting_rows ( struct settings_ui *ui ) { - 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 ); - } - } -} - -/** - * Select settings block - * - * @v ui Settings UI - * @v settings Settings block - */ -static void select_settings ( struct settings_ui *ui, - struct settings *settings ) { - - 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 ) { - 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 ) { - int rc; - - initscr(); - start_color(); - color_set ( CPAIR_NORMAL, NULL ); - curs_set ( 0 ); - erase(); - - rc = main_loop ( settings ); - - endwin(); - - return rc; -} |