diff options
author | Michael Brown | 2006-12-20 04:04:07 +0100 |
---|---|---|
committer | Michael Brown | 2006-12-20 04:04:07 +0100 |
commit | 1e322d4b4cc88111ad3a71f8201899c12e96ce1e (patch) | |
tree | 13bcbae93215e884376876ab2f136b629311a73c | |
parent | Don't automatically redraw the edit box; this allows better inheritance. (diff) | |
download | ipxe-1e322d4b4cc88111ad3a71f8201899c12e96ce1e.tar.gz ipxe-1e322d4b4cc88111ad3a71f8201899c12e96ce1e.tar.xz ipxe-1e322d4b4cc88111ad3a71f8201899c12e96ce1e.zip |
Add (partly-functional) user interface for editing configuration settings
-rw-r--r-- | src/Makefile | 3 | ||||
-rw-r--r-- | src/hci/tui/settings_ui.c | 285 |
2 files changed, 287 insertions, 1 deletions
diff --git a/src/Makefile b/src/Makefile index fae083ff..9c98909d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -144,7 +144,8 @@ SRCDIRS += drivers/bitbash SRCDIRS += interface/pxe SRCDIRS += tests SRCDIRS += crypto -SRCDIRS += hci hci/commands hci/mucurses +SRCDIRS += hci hci/commands hci/tui +SRCDIRS += hci/mucurses hci/mucurses/widgets # NON_AUTO_SRCS lists files that are excluded from the normal # automatic build system. diff --git a/src/hci/tui/settings_ui.c b/src/hci/tui/settings_ui.c new file mode 100644 index 00000000..8ba5d768 --- /dev/null +++ b/src/hci/tui/settings_ui.c @@ -0,0 +1,285 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <string.h> +#include <curses.h> +#include <console.h> +#include <gpxe/settings.h> +#include <gpxe/editbox.h> + +/** @file + * + * Configuration settings UI + * + */ + +#include <gpxe/nvo.h> +extern struct nvo_block *ugly_nvo_hack; + +/* Colour pairs */ +#define CPAIR_NORMAL 1 +#define CPAIR_SELECT 2 +#define CPAIR_EDIT 3 + +/* Screen layout */ +#define SETTINGS_LIST_ROW 3 +#define SETTINGS_LIST_COL 1 + +/** Layout of text within a setting widget */ +struct setting_row { + char start[0]; + char pad1[1]; + char name[15]; + char pad2[1]; + char value[60]; + char pad3[1]; + char nul; +} __attribute__ (( packed )); + +/** A setting widget */ +struct setting_widget { + /** Configuration context */ + struct config_context *context; + /** Configuration setting */ + struct config_setting *setting; + /** Screen row */ + unsigned int row; + /** Screen column */ + unsigned int col; + /** Edit box widget used for editing setting */ + struct edit_box editbox; + /** Editing active flag */ + int editing; + /** Buffer for setting's value */ + char value[256]; /* enough size for a DHCP string */ +}; + +/** Registered configuration settings */ +static struct config_setting +config_settings[0] __table_start ( config_settings ); +static struct config_setting +config_settings_end[0] __table_end ( config_settings ); +#define NUM_SETTINGS ( ( unsigned ) ( config_settings_end - config_settings ) ) + +/** + * Load setting widget value from configuration context + * + * @v widget Setting widget + * + */ +static void load_setting ( struct setting_widget *widget ) { + + /* Mark as not editing */ + widget->editing = 0; + + /* Read current setting value */ + if ( widget->setting->type->show ( widget->context, widget->setting, + widget->value, + sizeof ( widget->value ) ) != 0 ) { + widget->value[0] = '\0'; + } + + /* Initialise edit box */ + init_editbox ( &widget->editbox, widget->value, + sizeof ( widget->value ), NULL, widget->row, + ( widget->col + offsetof ( struct setting_row, value )), + sizeof ( ( ( struct setting_row * ) NULL )->value ) ); +} + +/** + * Save setting widget value back to configuration context + * + * @v widget Setting widget + */ +static int save_setting ( struct setting_widget *widget ) { + widget->editing = 0; + return widget->setting->type->set ( widget->context, widget->setting, + widget->value ); +} + +/** + * Initialise setting widget + * + * @v widget Setting widget + * @v context Configuration context + * @v setting Configuration setting + * @v row Screen row + * @v col Screen column + */ +static void init_setting ( struct setting_widget *widget, + struct config_context *context, + struct config_setting *setting, + unsigned int row, unsigned int col ) { + + /* Initialise widget structure */ + memset ( widget, 0, sizeof ( *widget ) ); + widget->context = context; + widget->setting = setting; + widget->row = row; + widget->col = col; + + /* Read current setting value */ + load_setting ( widget ); +} + +/** + * Draw setting widget + * + * @v widget Setting widget + */ +static void draw_setting ( struct setting_widget *widget ) { + struct setting_row row; + unsigned int len; + unsigned int curs_col; + char *value; + + /* Fill row with spaces */ + memset ( &row, ' ', sizeof ( row ) ); + row.nul = '\0'; + + /* Construct dot-padded name */ + memset ( row.name, '.', sizeof ( row.name ) ); + len = strlen ( widget->setting->name ); + if ( len > sizeof ( row.name ) ) + len = sizeof ( row.name ); + memcpy ( row.name, widget->setting->name, len ); + + /* Construct space-padded value */ + value = widget->value; + if ( ! *value ) + value = "<not specified>"; + len = strlen ( value ); + if ( len > sizeof ( row.value ) ) + len = sizeof ( row.value ); + memcpy ( row.value, value, len ); + curs_col = ( widget->col + offsetof ( typeof ( row ), value ) + + len ); + + /* Print row */ + mvprintw ( widget->row, widget->col, "%s", row.start ); + move ( widget->row, curs_col ); + if ( widget->editing ) + draw_editbox ( &widget->editbox ); +} + +/** + * Edit setting widget + * + * @v widget Setting widget + * @v key Key pressed by user + * @ret key Key returned to application, or zero + */ +static int edit_setting ( struct setting_widget *widget, int key ) { + widget->editing = 1; + return edit_editbox ( &widget->editbox, key ); +} + +/** + * Initialise setting widget by index + * + * @v widget Setting widget + * @v context Configuration context + * @v index Index of setting with settings list + */ +static void init_setting_index ( struct setting_widget *widget, + struct config_context *context, + unsigned int index ) { + init_setting ( widget, context, &config_settings[index], + ( SETTINGS_LIST_ROW + index ), SETTINGS_LIST_COL ); +} + +static void main_loop ( struct config_context *context ) { + struct setting_widget widget; + unsigned int current = 0; + unsigned int next; + int i; + int key; + int rc; + + /* Print initial screen content */ + color_set ( CPAIR_NORMAL, NULL ); + for ( i = ( NUM_SETTINGS - 1 ) ; i >= 0 ; i-- ) { + init_setting_index ( &widget, context, i ); + draw_setting ( &widget ); + } + + while ( 1 ) { + /* Redraw current setting */ + color_set ( ( widget.editing ? CPAIR_EDIT : CPAIR_SELECT ), + NULL ); + draw_setting ( &widget ); + color_set ( CPAIR_NORMAL, NULL ); + + key = getchar(); + if ( widget.editing ) { + key = edit_setting ( &widget, key ); + switch ( key ) { + case 0x0a: /* Enter */ + if ( ( rc = save_setting ( &widget ) ) != 0 ) { + + } + break; + case 0x03: /* Ctrl-C */ + load_setting ( &widget ); + break; + default: + /* Do nothing */ + break; + } + } else { + next = current; + switch ( key ) { + case '+': + if ( next < ( NUM_SETTINGS - 1 ) ) + next++; + break; + case '-': + if ( next > 0 ) + next--; + break; + default: + edit_setting ( &widget, key ); + break; + } + if ( next != current ) { + draw_setting ( &widget ); + init_setting_index ( &widget, context, next ); + current = next; + } + } + } + +} + +void uitest ( void ) { + struct config_context dummy_context; + + dummy_context.options = ugly_nvo_hack->options; + + initscr(); + start_color(); + init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE ); + init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED ); + init_pair ( CPAIR_EDIT, COLOR_BLACK, COLOR_GREEN ); + color_set ( CPAIR_NORMAL, NULL ); + erase(); + + main_loop ( &dummy_context ); + + endwin(); +} |