Browse Source

Add (partly-functional) user interface for editing configuration settings

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
1e322d4b4c
2 changed files with 287 additions and 1 deletions
  1. 2
    1
      src/Makefile
  2. 285
    0
      src/hci/tui/settings_ui.c

+ 2
- 1
src/Makefile View File

@@ -144,7 +144,8 @@ SRCDIRS		+= drivers/bitbash
144 144
 SRCDIRS		+= interface/pxe
145 145
 SRCDIRS		+= tests
146 146
 SRCDIRS		+= crypto
147
-SRCDIRS		+= hci hci/commands hci/mucurses
147
+SRCDIRS		+= hci hci/commands hci/tui
148
+SRCDIRS		+= hci/mucurses hci/mucurses/widgets
148 149
 
149 150
 # NON_AUTO_SRCS lists files that are excluded from the normal
150 151
 # automatic build system.

+ 285
- 0
src/hci/tui/settings_ui.c View File

@@ -0,0 +1,285 @@
1
+/*
2
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <string.h>
20
+#include <curses.h>
21
+#include <console.h>
22
+#include <gpxe/settings.h>
23
+#include <gpxe/editbox.h>
24
+
25
+/** @file
26
+ *
27
+ * Configuration settings UI
28
+ *
29
+ */
30
+
31
+#include <gpxe/nvo.h>
32
+extern struct nvo_block *ugly_nvo_hack;
33
+
34
+/* Colour pairs */
35
+#define CPAIR_NORMAL	1
36
+#define CPAIR_SELECT	2
37
+#define CPAIR_EDIT	3
38
+
39
+/* Screen layout */
40
+#define SETTINGS_LIST_ROW	3
41
+#define SETTINGS_LIST_COL	1
42
+
43
+/** Layout of text within a setting widget */
44
+struct setting_row {
45
+	char start[0];
46
+	char pad1[1];
47
+	char name[15];
48
+	char pad2[1];
49
+	char value[60];
50
+	char pad3[1];
51
+	char nul;
52
+} __attribute__ (( packed ));
53
+
54
+/** A setting widget */
55
+struct setting_widget {
56
+	/** Configuration context */
57
+	struct config_context *context;
58
+	/** Configuration setting */
59
+	struct config_setting *setting;
60
+	/** Screen row */
61
+	unsigned int row;
62
+	/** Screen column */
63
+	unsigned int col;
64
+	/** Edit box widget used for editing setting */
65
+	struct edit_box editbox;
66
+	/** Editing active flag */
67
+	int editing;
68
+	/** Buffer for setting's value */
69
+	char value[256]; /* enough size for a DHCP string */
70
+};
71
+
72
+/** Registered configuration settings */
73
+static struct config_setting
74
+config_settings[0] __table_start ( config_settings );
75
+static struct config_setting
76
+config_settings_end[0] __table_end ( config_settings );
77
+#define NUM_SETTINGS ( ( unsigned ) ( config_settings_end - config_settings ) )
78
+
79
+/**
80
+ * Load setting widget value from configuration context
81
+ *
82
+ * @v widget		Setting widget
83
+ *
84
+ */
85
+static void load_setting ( struct setting_widget *widget ) {
86
+
87
+	/* Mark as not editing */
88
+	widget->editing = 0;
89
+
90
+	/* Read current setting value */
91
+	if ( widget->setting->type->show ( widget->context, widget->setting,
92
+					   widget->value,
93
+					   sizeof ( widget->value ) ) != 0 ) {
94
+		widget->value[0] = '\0';
95
+	}	
96
+
97
+	/* Initialise edit box */
98
+	init_editbox ( &widget->editbox, widget->value,
99
+		       sizeof ( widget->value ), NULL, widget->row,
100
+		       ( widget->col + offsetof ( struct setting_row, value )),
101
+		       sizeof ( ( ( struct setting_row * ) NULL )->value ) );
102
+}
103
+
104
+/**
105
+ * Save setting widget value back to configuration context
106
+ *
107
+ * @v widget		Setting widget
108
+ */
109
+static int save_setting ( struct setting_widget *widget ) {
110
+	widget->editing = 0;
111
+	return widget->setting->type->set ( widget->context, widget->setting,
112
+					    widget->value );
113
+}
114
+
115
+/**
116
+ * Initialise setting widget
117
+ *
118
+ * @v widget		Setting widget
119
+ * @v context		Configuration context
120
+ * @v setting		Configuration setting
121
+ * @v row		Screen row
122
+ * @v col		Screen column
123
+ */
124
+static void init_setting ( struct setting_widget *widget,
125
+			   struct config_context *context,
126
+			   struct config_setting *setting,
127
+			   unsigned int row, unsigned int col ) {
128
+
129
+	/* Initialise widget structure */
130
+	memset ( widget, 0, sizeof ( *widget ) );
131
+	widget->context = context;
132
+	widget->setting = setting;
133
+	widget->row = row;
134
+	widget->col = col;
135
+
136
+	/* Read current setting value */
137
+	load_setting ( widget );
138
+}
139
+
140
+/**
141
+ * Draw setting widget
142
+ *
143
+ * @v widget		Setting widget
144
+ */
145
+static void draw_setting ( struct setting_widget *widget ) {
146
+	struct setting_row row;
147
+	unsigned int len;
148
+	unsigned int curs_col;
149
+	char *value;
150
+
151
+	/* Fill row with spaces */
152
+	memset ( &row, ' ', sizeof ( row ) );
153
+	row.nul = '\0';
154
+
155
+	/* Construct dot-padded name */
156
+	memset ( row.name, '.', sizeof ( row.name ) );
157
+	len = strlen ( widget->setting->name );
158
+	if ( len > sizeof ( row.name ) )
159
+		len = sizeof ( row.name );
160
+	memcpy ( row.name, widget->setting->name, len );
161
+
162
+	/* Construct space-padded value */
163
+	value = widget->value;
164
+	if ( ! *value )
165
+		value = "<not specified>";
166
+	len = strlen ( value );
167
+	if ( len > sizeof ( row.value ) )
168
+		len = sizeof ( row.value );
169
+	memcpy ( row.value, value, len );
170
+	curs_col = ( widget->col + offsetof ( typeof ( row ), value )
171
+		     + len );
172
+
173
+	/* Print row */
174
+	mvprintw ( widget->row, widget->col, "%s", row.start );
175
+	move ( widget->row, curs_col );
176
+	if ( widget->editing )
177
+		draw_editbox ( &widget->editbox );
178
+}
179
+
180
+/**
181
+ * Edit setting widget
182
+ *
183
+ * @v widget		Setting widget
184
+ * @v key		Key pressed by user
185
+ * @ret key		Key returned to application, or zero
186
+ */
187
+static int edit_setting ( struct setting_widget *widget, int key ) {
188
+	widget->editing = 1;
189
+	return edit_editbox ( &widget->editbox, key );
190
+}
191
+
192
+/**
193
+ * Initialise setting widget by index
194
+ *
195
+ * @v widget		Setting widget
196
+ * @v context		Configuration context
197
+ * @v index		Index of setting with settings list
198
+ */
199
+static void init_setting_index ( struct setting_widget *widget,
200
+				 struct config_context *context,
201
+				 unsigned int index ) {
202
+	init_setting ( widget, context, &config_settings[index],
203
+		       ( SETTINGS_LIST_ROW + index ), SETTINGS_LIST_COL );
204
+}
205
+
206
+static void main_loop ( struct config_context *context ) {
207
+	struct setting_widget widget;
208
+	unsigned int current = 0;
209
+	unsigned int next;
210
+	int i;
211
+	int key;
212
+	int rc;
213
+
214
+	/* Print initial screen content */
215
+	color_set ( CPAIR_NORMAL, NULL );
216
+	for ( i = ( NUM_SETTINGS - 1 ) ; i >= 0 ; i-- ) {
217
+		init_setting_index ( &widget, context, i );
218
+		draw_setting ( &widget );
219
+	}
220
+
221
+	while ( 1 ) {
222
+		/* Redraw current setting */
223
+		color_set ( ( widget.editing ? CPAIR_EDIT : CPAIR_SELECT ),
224
+			    NULL );
225
+		draw_setting ( &widget );
226
+		color_set ( CPAIR_NORMAL, NULL );
227
+
228
+		key = getchar();
229
+		if ( widget.editing ) {
230
+			key = edit_setting ( &widget, key );
231
+			switch ( key ) {
232
+			case 0x0a: /* Enter */
233
+				if ( ( rc = save_setting ( &widget ) ) != 0 ) {
234
+					
235
+				}
236
+				break;
237
+			case 0x03: /* Ctrl-C */
238
+				load_setting ( &widget );
239
+				break;
240
+			default:
241
+				/* Do nothing */
242
+				break;
243
+			}
244
+		} else {
245
+			next = current;
246
+			switch ( key ) {
247
+			case '+':
248
+				if ( next < ( NUM_SETTINGS - 1 ) )
249
+					next++;
250
+				break;
251
+			case '-':
252
+				if ( next > 0 )
253
+					next--;
254
+				break;
255
+			default:
256
+				edit_setting ( &widget, key );
257
+				break;
258
+			}	
259
+			if ( next != current ) {
260
+				draw_setting ( &widget );
261
+				init_setting_index ( &widget, context, next );
262
+				current = next;
263
+			}
264
+		}
265
+	}
266
+	
267
+}
268
+
269
+void uitest ( void ) {
270
+	struct config_context dummy_context;
271
+
272
+	dummy_context.options = ugly_nvo_hack->options;
273
+
274
+	initscr();
275
+	start_color();
276
+	init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE );
277
+	init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED );
278
+	init_pair ( CPAIR_EDIT, COLOR_BLACK, COLOR_GREEN );
279
+	color_set ( CPAIR_NORMAL, NULL );
280
+	erase();
281
+	
282
+	main_loop ( &dummy_context );
283
+
284
+	endwin();
285
+}

Loading…
Cancel
Save