00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stdio.h>
00022 #include <stdarg.h>
00023 #include <unistd.h>
00024 #include <string.h>
00025 #include <curses.h>
00026 #include <console.h>
00027 #include <gpxe/settings.h>
00028 #include <gpxe/editbox.h>
00029 #include <gpxe/keys.h>
00030 #include <gpxe/settings_ui.h>
00031
00032
00033
00034
00035
00036
00037
00038
00039 #define CPAIR_NORMAL 1
00040 #define CPAIR_SELECT 2
00041 #define CPAIR_EDIT 3
00042 #define CPAIR_ALERT 4
00043
00044
00045 #define TITLE_ROW 1
00046 #define SETTINGS_LIST_ROW 3
00047 #define SETTINGS_LIST_COL 1
00048 #define INFO_ROW 20
00049 #define ALERT_ROW 20
00050 #define INSTRUCTION_ROW 22
00051 #define INSTRUCTION_PAD " "
00052
00053
00054 struct setting_row {
00055 char start[0];
00056 char pad1[1];
00057 char name[15];
00058 char pad2[1];
00059 char value[60];
00060 char pad3[1];
00061 char nul;
00062 } __attribute__ (( packed ));
00063
00064
00065 struct setting_widget {
00066
00067 struct settings *settings;
00068
00069 struct setting *setting;
00070
00071 unsigned int row;
00072
00073 unsigned int col;
00074
00075 struct edit_box editbox;
00076
00077 int editing;
00078
00079 char value[256];
00080 };
00081
00082
00083 #define NUM_SETTINGS table_num_entries ( SETTINGS )
00084
00085 static void load_setting ( struct setting_widget *widget ) __nonnull;
00086 static int save_setting ( struct setting_widget *widget ) __nonnull;
00087 static void init_setting ( struct setting_widget *widget,
00088 struct settings *settings,
00089 struct setting *setting,
00090 unsigned int row, unsigned int col ) __nonnull;
00091 static void draw_setting ( struct setting_widget *widget ) __nonnull;
00092 static int edit_setting ( struct setting_widget *widget, int key ) __nonnull;
00093 static void init_setting_index ( struct setting_widget *widget,
00094 struct settings *settings,
00095 unsigned int index ) __nonnull;
00096 static void vmsg ( unsigned int row, const char *fmt, va_list args ) __nonnull;
00097 static void msg ( unsigned int row, const char *fmt, ... ) __nonnull;
00098 static void valert ( const char *fmt, va_list args ) __nonnull;
00099 static void alert ( const char *fmt, ... ) __nonnull;
00100 static void draw_info_row ( struct setting *setting ) __nonnull;
00101 static int main_loop ( struct settings *settings ) __nonnull;
00102
00103
00104
00105
00106
00107
00108
00109 static void load_setting ( struct setting_widget *widget ) {
00110
00111
00112 widget->editing = 0;
00113
00114
00115 if ( fetchf_setting ( widget->settings, widget->setting,
00116 widget->value, sizeof ( widget->value ) ) < 0 ) {
00117 widget->value[0] = '\0';
00118 }
00119
00120
00121 init_editbox ( &widget->editbox, widget->value,
00122 sizeof ( widget->value ), NULL, widget->row,
00123 ( widget->col + offsetof ( struct setting_row, value )),
00124 sizeof ( ( ( struct setting_row * ) NULL )->value ), 0);
00125 }
00126
00127
00128
00129
00130
00131
00132 static int save_setting ( struct setting_widget *widget ) {
00133 return storef_setting ( widget->settings, widget->setting,
00134 widget->value );
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 static void init_setting ( struct setting_widget *widget,
00147 struct settings *settings,
00148 struct setting *setting,
00149 unsigned int row, unsigned int col ) {
00150
00151
00152 memset ( widget, 0, sizeof ( *widget ) );
00153 widget->settings = settings;
00154 widget->setting = setting;
00155 widget->row = row;
00156 widget->col = col;
00157
00158
00159 load_setting ( widget );
00160 }
00161
00162
00163
00164
00165
00166
00167 static void draw_setting ( struct setting_widget *widget ) {
00168 struct setting_row row;
00169 unsigned int len;
00170 unsigned int curs_col;
00171 char *value;
00172
00173
00174 memset ( &row, ' ', sizeof ( row ) );
00175 row.nul = '\0';
00176
00177
00178 memset ( row.name, '.', sizeof ( row.name ) );
00179 len = strlen ( widget->setting->name );
00180 if ( len > sizeof ( row.name ) )
00181 len = sizeof ( row.name );
00182 memcpy ( row.name, widget->setting->name, len );
00183
00184
00185 value = widget->value;
00186 if ( ! *value )
00187 value = "<not specified>";
00188 len = strlen ( value );
00189 if ( len > sizeof ( row.value ) )
00190 len = sizeof ( row.value );
00191 memcpy ( row.value, value, len );
00192 curs_col = ( widget->col + offsetof ( typeof ( row ), value )
00193 + len );
00194
00195
00196 mvprintw ( widget->row, widget->col, "%s", row.start );
00197 move ( widget->row, curs_col );
00198 if ( widget->editing )
00199 draw_editbox ( &widget->editbox );
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 static int edit_setting ( struct setting_widget *widget, int key ) {
00210 widget->editing = 1;
00211 return edit_editbox ( &widget->editbox, key );
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221 static void init_setting_index ( struct setting_widget *widget,
00222 struct settings *settings,
00223 unsigned int index ) {
00224 struct setting *all_settings = table_start ( SETTINGS );
00225
00226 init_setting ( widget, settings, &all_settings[index],
00227 ( SETTINGS_LIST_ROW + index ), SETTINGS_LIST_COL );
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237 static void vmsg ( unsigned int row, const char *fmt, va_list args ) {
00238 char buf[COLS];
00239 size_t len;
00240
00241 len = vsnprintf ( buf, sizeof ( buf ), fmt, args );
00242 mvprintw ( row, ( ( COLS - len ) / 2 ), "%s", buf );
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252 static void msg ( unsigned int row, const char *fmt, ... ) {
00253 va_list args;
00254
00255 va_start ( args, fmt );
00256 vmsg ( row, fmt, args );
00257 va_end ( args );
00258 }
00259
00260
00261
00262
00263
00264
00265 static void clearmsg ( unsigned int row ) {
00266 move ( row, 0 );
00267 clrtoeol();
00268 }
00269
00270
00271
00272
00273
00274
00275
00276 static void valert ( const char *fmt, va_list args ) {
00277 clearmsg ( ALERT_ROW );
00278 color_set ( CPAIR_ALERT, NULL );
00279 vmsg ( ALERT_ROW, fmt, args );
00280 sleep ( 2 );
00281 color_set ( CPAIR_NORMAL, NULL );
00282 clearmsg ( ALERT_ROW );
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 static void alert ( const char *fmt, ... ) {
00292 va_list args;
00293
00294 va_start ( args, fmt );
00295 valert ( fmt, args );
00296 va_end ( args );
00297 }
00298
00299
00300
00301
00302 static void draw_title_row ( void ) {
00303 attron ( A_BOLD );
00304 msg ( TITLE_ROW, "gPXE option configuration console" );
00305 attroff ( A_BOLD );
00306 }
00307
00308
00309
00310
00311
00312
00313 static void draw_info_row ( struct setting *setting ) {
00314 clearmsg ( INFO_ROW );
00315 attron ( A_BOLD );
00316 msg ( INFO_ROW, "%s - %s", setting->name, setting->description );
00317 attroff ( A_BOLD );
00318 }
00319
00320
00321
00322
00323
00324
00325 static void draw_instruction_row ( int editing ) {
00326 clearmsg ( INSTRUCTION_ROW );
00327 if ( editing ) {
00328 msg ( INSTRUCTION_ROW,
00329 "Enter - accept changes" INSTRUCTION_PAD
00330 "Ctrl-C - discard changes" );
00331 } else {
00332 msg ( INSTRUCTION_ROW,
00333 "Ctrl-X - exit configuration utility" );
00334 }
00335 }
00336
00337 static int main_loop ( struct settings *settings ) {
00338 struct setting_widget widget;
00339 unsigned int current = 0;
00340 unsigned int next;
00341 int i;
00342 int key;
00343 int rc;
00344
00345
00346 draw_title_row();
00347 color_set ( CPAIR_NORMAL, NULL );
00348 for ( i = ( NUM_SETTINGS - 1 ) ; i >= 0 ; i-- ) {
00349 init_setting_index ( &widget, settings, i );
00350 draw_setting ( &widget );
00351 }
00352
00353 while ( 1 ) {
00354
00355 draw_info_row ( widget.setting );
00356 draw_instruction_row ( widget.editing );
00357
00358
00359 color_set ( ( widget.editing ? CPAIR_EDIT : CPAIR_SELECT ),
00360 NULL );
00361 draw_setting ( &widget );
00362 color_set ( CPAIR_NORMAL, NULL );
00363
00364 key = getkey();
00365 if ( widget.editing ) {
00366 key = edit_setting ( &widget, key );
00367 switch ( key ) {
00368 case CR:
00369 case LF:
00370 if ( ( rc = save_setting ( &widget ) ) != 0 ) {
00371 alert ( " Could not set %s: %s ",
00372 widget.setting->name,
00373 strerror ( rc ) );
00374 }
00375
00376 case CTRL_C:
00377 load_setting ( &widget );
00378 break;
00379 default:
00380
00381 break;
00382 }
00383 } else {
00384 next = current;
00385 switch ( key ) {
00386 case KEY_DOWN:
00387 if ( next < ( NUM_SETTINGS - 1 ) )
00388 next++;
00389 break;
00390 case KEY_UP:
00391 if ( next > 0 )
00392 next--;
00393 break;
00394 case CTRL_X:
00395 return 0;
00396 default:
00397 edit_setting ( &widget, key );
00398 break;
00399 }
00400 if ( next != current ) {
00401 draw_setting ( &widget );
00402 init_setting_index ( &widget, settings, next );
00403 current = next;
00404 }
00405 }
00406 }
00407
00408 }
00409
00410 int settings_ui ( struct settings *settings ) {
00411 int rc;
00412
00413 initscr();
00414 start_color();
00415 init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE );
00416 init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED );
00417 init_pair ( CPAIR_EDIT, COLOR_BLACK, COLOR_CYAN );
00418 init_pair ( CPAIR_ALERT, COLOR_WHITE, COLOR_RED );
00419 color_set ( CPAIR_NORMAL, NULL );
00420 erase();
00421
00422 rc = main_loop ( settings );
00423
00424 endwin();
00425
00426 return rc;
00427 }