2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
19 FILE_LICENCE ( GPL2_OR_LATER
);
27 #include <gpxe/settings.h>
28 #include <gpxe/editbox.h>
29 #include <gpxe/keys.h>
30 #include <gpxe/settings_ui.h>
34 * Option configuration console
39 #define CPAIR_NORMAL 1
40 #define CPAIR_SELECT 2
46 #define SETTINGS_LIST_ROW 3
47 #define SETTINGS_LIST_COL 1
50 #define INSTRUCTION_ROW 22
51 #define INSTRUCTION_PAD " "
53 /** Layout of text within a setting widget */
62 } __attribute__ (( packed
));
64 /** A setting widget */
65 struct setting_widget
{
67 struct settings
*settings
;
68 /** Configuration setting */
69 struct setting
*setting
;
74 /** Edit box widget used for editing setting */
75 struct edit_box editbox
;
76 /** Editing in progress flag */
78 /** Buffer for setting's value */
79 char value
[256]; /* enough size for a DHCP string */
82 /** Number of registered configuration settings */
83 #define NUM_SETTINGS table_num_entries ( SETTINGS )
85 static void load_setting ( struct setting_widget
*widget
) __nonnull
;
86 static int save_setting ( struct setting_widget
*widget
) __nonnull
;
87 static void init_setting ( struct setting_widget
*widget
,
88 struct settings
*settings
,
89 struct setting
*setting
,
90 unsigned int row
, unsigned int col
) __nonnull
;
91 static void draw_setting ( struct setting_widget
*widget
) __nonnull
;
92 static int edit_setting ( struct setting_widget
*widget
, int key
) __nonnull
;
93 static void init_setting_index ( struct setting_widget
*widget
,
94 struct settings
*settings
,
95 unsigned int index
) __nonnull
;
96 static void vmsg ( unsigned int row
, const char *fmt
, va_list args
) __nonnull
;
97 static void msg ( unsigned int row
, const char *fmt
, ... ) __nonnull
;
98 static void valert ( const char *fmt
, va_list args
) __nonnull
;
99 static void alert ( const char *fmt
, ... ) __nonnull
;
100 static void draw_info_row ( struct setting
*setting
) __nonnull
;
101 static int main_loop ( struct settings
*settings
) __nonnull
;
104 * Load setting widget value from configuration settings
106 * @v widget Setting widget
109 static void load_setting ( struct setting_widget
*widget
) {
111 /* Mark as not editing */
114 /* Read current setting value */
115 if ( fetchf_setting ( widget
->settings
, widget
->setting
,
116 widget
->value
, sizeof ( widget
->value
) ) < 0 ) {
117 widget
->value
[0] = '\0';
120 /* Initialise edit box */
121 init_editbox ( &widget
->editbox
, widget
->value
,
122 sizeof ( widget
->value
), NULL
, widget
->row
,
123 ( widget
->col
+ offsetof ( struct setting_row
, value
)),
124 sizeof ( ( ( struct setting_row
* ) NULL
)->value
), 0);
128 * Save setting widget value back to configuration settings
130 * @v widget Setting widget
132 static int save_setting ( struct setting_widget
*widget
) {
133 return storef_setting ( widget
->settings
, widget
->setting
,
138 * Initialise setting widget
140 * @v widget Setting widget
141 * @v settings Settings block
142 * @v setting Configuration setting
144 * @v col Screen column
146 static void init_setting ( struct setting_widget
*widget
,
147 struct settings
*settings
,
148 struct setting
*setting
,
149 unsigned int row
, unsigned int col
) {
151 /* Initialise widget structure */
152 memset ( widget
, 0, sizeof ( *widget
) );
153 widget
->settings
= settings
;
154 widget
->setting
= setting
;
158 /* Read current setting value */
159 load_setting ( widget
);
163 * Draw setting widget
165 * @v widget Setting widget
167 static void draw_setting ( struct setting_widget
*widget
) {
168 struct setting_row row
;
170 unsigned int curs_col
;
173 /* Fill row with spaces */
174 memset ( &row
, ' ', sizeof ( row
) );
177 /* Construct dot-padded name */
178 memset ( row
.name
, '.', sizeof ( row
.name
) );
179 len
= strlen ( widget
->setting
->name
);
180 if ( len
> sizeof ( row
.name
) )
181 len
= sizeof ( row
.name
);
182 memcpy ( row
.name
, widget
->setting
->name
, len
);
184 /* Construct space-padded value */
185 value
= widget
->value
;
187 value
= "<not specified>";
188 len
= strlen ( value
);
189 if ( len
> sizeof ( row
.value
) )
190 len
= sizeof ( row
.value
);
191 memcpy ( row
.value
, value
, len
);
192 curs_col
= ( widget
->col
+ offsetof ( typeof ( row
), value
)
196 mvprintw ( widget
->row
, widget
->col
, "%s", row
.start
);
197 move ( widget
->row
, curs_col
);
198 if ( widget
->editing
)
199 draw_editbox ( &widget
->editbox
);
203 * Edit setting widget
205 * @v widget Setting widget
206 * @v key Key pressed by user
207 * @ret key Key returned to application, or zero
209 static int edit_setting ( struct setting_widget
*widget
, int key
) {
211 return edit_editbox ( &widget
->editbox
, key
);
215 * Initialise setting widget by index
217 * @v widget Setting widget
218 * @v settings Settings block
219 * @v index Index of setting with settings list
221 static void init_setting_index ( struct setting_widget
*widget
,
222 struct settings
*settings
,
223 unsigned int index
) {
224 struct setting
*all_settings
= table_start ( SETTINGS
);
226 init_setting ( widget
, settings
, &all_settings
[index
],
227 ( SETTINGS_LIST_ROW
+ index
), SETTINGS_LIST_COL
);
231 * Print message centred on specified row
234 * @v fmt printf() format string
235 * @v args printf() argument list
237 static void vmsg ( unsigned int row
, const char *fmt
, va_list args
) {
241 len
= vsnprintf ( buf
, sizeof ( buf
), fmt
, args
);
242 mvprintw ( row
, ( ( COLS
- len
) / 2 ), "%s", buf
);
246 * Print message centred on specified row
249 * @v fmt printf() format string
250 * @v .. printf() arguments
252 static void msg ( unsigned int row
, const char *fmt
, ... ) {
255 va_start ( args
, fmt
);
256 vmsg ( row
, fmt
, args
);
261 * Clear message on specified row
265 static void clearmsg ( unsigned int row
) {
271 * Print alert message
273 * @v fmt printf() format string
274 * @v args printf() argument list
276 static void valert ( const char *fmt
, va_list args
) {
277 clearmsg ( ALERT_ROW
);
278 color_set ( CPAIR_ALERT
, NULL
);
279 vmsg ( ALERT_ROW
, fmt
, args
);
281 color_set ( CPAIR_NORMAL
, NULL
);
282 clearmsg ( ALERT_ROW
);
286 * Print alert message
288 * @v fmt printf() format string
289 * @v ... printf() arguments
291 static void alert ( const char *fmt
, ... ) {
294 va_start ( args
, fmt
);
295 valert ( fmt
, args
);
302 static void draw_title_row ( void ) {
304 msg ( TITLE_ROW
, "gPXE option configuration console" );
309 * Draw information row
311 * @v setting Current configuration setting
313 static void draw_info_row ( struct setting
*setting
) {
314 clearmsg ( INFO_ROW
);
316 msg ( INFO_ROW
, "%s - %s", setting
->name
, setting
->description
);
321 * Draw instruction row
323 * @v editing Editing in progress flag
325 static void draw_instruction_row ( int editing
) {
326 clearmsg ( INSTRUCTION_ROW
);
328 msg ( INSTRUCTION_ROW
,
329 "Enter - accept changes" INSTRUCTION_PAD
330 "Ctrl-C - discard changes" );
332 msg ( INSTRUCTION_ROW
,
333 "Ctrl-X - exit configuration utility" );
337 static int main_loop ( struct settings
*settings
) {
338 struct setting_widget widget
;
339 unsigned int current
= 0;
345 /* Print initial screen content */
347 color_set ( CPAIR_NORMAL
, NULL
);
348 for ( i
= ( NUM_SETTINGS
- 1 ) ; i
>= 0 ; i
-- ) {
349 init_setting_index ( &widget
, settings
, i
);
350 draw_setting ( &widget
);
354 /* Redraw information and instruction rows */
355 draw_info_row ( widget
.setting
);
356 draw_instruction_row ( widget
.editing
);
358 /* Redraw current setting */
359 color_set ( ( widget
.editing
? CPAIR_EDIT
: CPAIR_SELECT
),
361 draw_setting ( &widget
);
362 color_set ( CPAIR_NORMAL
, NULL
);
365 if ( widget
.editing
) {
366 key
= edit_setting ( &widget
, key
);
370 if ( ( rc
= save_setting ( &widget
) ) != 0 ) {
371 alert ( " Could not set %s: %s ",
372 widget
.setting
->name
,
377 load_setting ( &widget
);
387 if ( next
< ( NUM_SETTINGS
- 1 ) )
397 edit_setting ( &widget
, key
);
400 if ( next
!= current
) {
401 draw_setting ( &widget
);
402 init_setting_index ( &widget
, settings
, next
);
410 int settings_ui ( struct settings
*settings
) {
415 init_pair ( CPAIR_NORMAL
, COLOR_WHITE
, COLOR_BLUE
);
416 init_pair ( CPAIR_SELECT
, COLOR_WHITE
, COLOR_RED
);
417 init_pair ( CPAIR_EDIT
, COLOR_BLACK
, COLOR_CYAN
);
418 init_pair ( CPAIR_ALERT
, COLOR_WHITE
, COLOR_RED
);
419 color_set ( CPAIR_NORMAL
, NULL
);
422 rc
= main_loop ( settings
);