summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2006-12-20 04:04:07 +0100
committerMichael Brown2006-12-20 04:04:07 +0100
commit1e322d4b4cc88111ad3a71f8201899c12e96ce1e (patch)
tree13bcbae93215e884376876ab2f136b629311a73c
parentDon't automatically redraw the edit box; this allows better inheritance. (diff)
downloadipxe-1e322d4b4cc88111ad3a71f8201899c12e96ce1e.tar.gz
ipxe-1e322d4b4cc88111ad3a71f8201899c12e96ce1e.tar.xz
ipxe-1e322d4b4cc88111ad3a71f8201899c12e96ce1e.zip
Add (partly-functional) user interface for editing configuration settings
-rw-r--r--src/Makefile3
-rw-r--r--src/hci/tui/settings_ui.c285
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();
+}