Просмотр исходного кода

[settings] Add hierarchy navigation in "config" user interface

Allow the user to browse through the settings block hierarchy.

Originally-implemented-by: Glenn Brown <glenn@myri.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 лет назад
Родитель
Сommit
da312ba03b
1 измененных файлов: 260 добавлений и 199 удалений
  1. 260
    199
      src/hci/tui/settings_ui.c

+ 260
- 199
src/hci/tui/settings_ui.c Просмотреть файл

@@ -47,12 +47,12 @@ FILE_LICENCE ( GPL2_OR_LATER );
47 47
 #define SETTINGS_LIST_COL	1
48 48
 #define SETTINGS_LIST_ROWS	16
49 49
 #define INFO_ROW		20
50
-#define ALERT_ROW		20
50
+#define ALERT_ROW		22
51 51
 #define INSTRUCTION_ROW		22
52 52
 #define INSTRUCTION_PAD "     "
53 53
 
54 54
 /** Layout of text within a setting widget */
55
-struct setting_row {
55
+struct setting_row_text {
56 56
 	char start[0];
57 57
 	char pad1[1];
58 58
 	char name[15];
@@ -62,15 +62,17 @@ struct setting_row {
62 62
 	char nul;
63 63
 } __attribute__ (( packed ));
64 64
 
65
-/** A setting widget */
66
-struct setting_widget {
67
-	/** Settings block */
65
+/** A setting row widget */
66
+struct setting_row_widget {
67
+	/** Target configuration settings block
68
+	 *
69
+	 * Valid only for rows that lead to new settings blocks.
70
+	 */
68 71
 	struct settings *settings;
69
-	/** Number of applicable settings */
70
-	unsigned int num_settings;
71
-        /** Index of the first visible setting, for scrolling. */
72
-	unsigned int first_visible;
73
-	/** Configuration setting */
72
+	/** Configuration setting
73
+	 *
74
+	 * Valid only for rows that represent individual settings.
75
+	 */
74 76
 	struct setting *setting;
75 77
 	/** Screen row */
76 78
 	unsigned int row;
@@ -86,123 +88,142 @@ struct setting_widget {
86 88
 	char value[256]; /* enough size for a DHCP string */
87 89
 };
88 90
 
89
-static void load_setting ( struct setting_widget *widget ) __nonnull;
90
-static int save_setting ( struct setting_widget *widget ) __nonnull;
91
-static void init_widget ( struct setting_widget *widget,
92
-                           struct settings *settings ) __nonnull;
93
-static void draw_setting ( struct setting_widget *widget ) __nonnull;
94
-static int edit_setting ( struct setting_widget *widget, int key ) __nonnull;
95
-static void select_setting ( struct setting_widget *widget,
96
-			     unsigned int index ) __nonnull;
97
-static void reveal ( struct setting_widget *widget, unsigned int n) __nonnull;
98
-static void vmsg ( unsigned int row, const char *fmt, va_list args ) __nonnull;
99
-static void msg ( unsigned int row, const char *fmt, ... ) __nonnull;
100
-static void valert ( const char *fmt, va_list args ) __nonnull;
101
-static void alert ( const char *fmt, ... ) __nonnull;
102
-static void draw_info_row ( struct settings *settings,
103
-			    struct setting *setting ) __nonnull;
104
-static int main_loop ( struct settings *settings ) __nonnull;
91
+/** A settings widget */
92
+struct setting_widget {
93
+	/** Settings block */
94
+	struct settings *settings;
95
+	/** Number of rows */
96
+	unsigned int num_rows;
97
+	/** Current row index */
98
+	unsigned int current;
99
+        /** Index of the first visible row, for scrolling. */
100
+	unsigned int first_visible;
101
+	/** Active row */
102
+	struct setting_row_widget row;
103
+};
105 104
 
106 105
 /**
107
- * Load setting widget value from configuration settings
106
+ * Select a setting row
108 107
  *
109 108
  * @v widget		Setting widget
110
- *
109
+ * @v index		Index of setting row
110
+ * @ret count		Number of settings rows
111 111
  */
112
-static void load_setting ( struct setting_widget *widget ) {
113
-
114
-	/* Mark as not editing */
115
-	widget->editing = 0;
112
+static unsigned int select_setting_row ( struct setting_widget *widget,
113
+					 unsigned int index ) {
114
+	struct settings *settings;
115
+	struct settings *origin;
116
+	struct setting *setting;
117
+	unsigned int count = 0;
118
+
119
+	/* Initialise structure */
120
+	memset ( &widget->row, 0, sizeof ( widget->row ) );
121
+	widget->current = index;
122
+	widget->row.row = ( SETTINGS_LIST_ROW + index - widget->first_visible );
123
+	widget->row.col = SETTINGS_LIST_COL;
124
+
125
+	/* Include parent settings block, if applicable */
126
+	if ( widget->settings->parent && ( count++ == index ) ) {
127
+		widget->row.settings = widget->settings->parent;
128
+		snprintf ( widget->row.value, sizeof ( widget->row.value ),
129
+			   "../" );
130
+	}
116 131
 
117
-	/* Read current setting value */
118
-	if ( fetchf_setting ( widget->settings, widget->setting,
119
-			      widget->value, sizeof ( widget->value ) ) < 0 ) {
120
-		widget->value[0] = '\0';
132
+	/* Include any child settings blocks, if applicable */
133
+	list_for_each_entry ( settings, &widget->settings->children, siblings ){
134
+		if ( count++ == index ) {
135
+			widget->row.settings = settings;
136
+			snprintf ( widget->row.value,
137
+				   sizeof ( widget->row.value ), "%s/",
138
+				   settings->name );
139
+		}
121 140
 	}
122 141
 
123
-	/* Check setting's origin */
124
-	widget->originates_here =
125
-		( widget->settings ==
126
-		  fetch_setting_origin ( widget->settings, widget->setting ) );
142
+	/* Include any applicable settings */
143
+	for_each_table_entry ( setting, SETTINGS ) {
144
+		if ( ! setting_applies ( widget->settings, setting ) )
145
+			continue;
146
+		if ( count++ == index ) {
147
+			widget->row.setting = setting;
148
+
149
+			/* Read current setting value */
150
+			fetchf_setting ( widget->settings, widget->row.setting,
151
+					 widget->row.value,
152
+					 sizeof ( widget->row.value ) );
153
+
154
+			/* Check setting's origin */
155
+			origin = fetch_setting_origin ( widget->settings,
156
+							widget->row.setting );
157
+			widget->row.originates_here =
158
+				( origin == widget->settings );
159
+		}
160
+	}
127 161
 
128 162
 	/* Initialise edit box */
129
-	init_editbox ( &widget->editbox, widget->value,
130
-		       sizeof ( widget->value ), NULL, widget->row,
131
-		       ( widget->col + offsetof ( struct setting_row, value )),
132
-		       sizeof ( ( ( struct setting_row * ) NULL )->value ), 0);
133
-}
134
-
135
-/**
136
- * Save setting widget value back to configuration settings
137
- *
138
- * @v widget		Setting widget
139
- */
140
-static int save_setting ( struct setting_widget *widget ) {
141
-	return storef_setting ( widget->settings, widget->setting,
142
-				widget->value );
163
+	init_editbox ( &widget->row.editbox, widget->row.value,
164
+		       sizeof ( widget->row.value ), NULL, widget->row.row,
165
+		       ( widget->row.col +
166
+			 offsetof ( struct setting_row_text, value ) ),
167
+		       sizeof ( ( ( struct setting_row_text * ) NULL )->value ),
168
+		       0 );
169
+
170
+	return count;
143 171
 }
144 172
 
145
-/**
146
- * Initialise the scrolling setting widget, drawing initial display.
147
- *
148
- * @v widget		Setting widget
149
- * @v settings		Settings block
150
- */
151
-static void init_widget ( struct setting_widget *widget,
152
-			  struct settings *settings ) {
153
-	struct setting *setting;
173
+static size_t string_copy ( char *dest, const char *src, size_t len ) {
174
+	size_t src_len;
154 175
 
155
-	memset ( widget, 0, sizeof ( *widget ) );
156
-	widget->settings = settings;
157
-	for_each_table_entry ( setting, SETTINGS ) {
158
-		if ( setting_applies ( settings, setting ) )
159
-			widget->num_settings++;
160
-	}
161
-	widget->first_visible = SETTINGS_LIST_ROWS;
162
-	reveal ( widget, 0 );
176
+	src_len = strlen ( src );
177
+	if ( len > src_len )
178
+		len = src_len;
179
+	memcpy ( dest, src, len );
180
+	return len;
163 181
 }
164 182
 
165 183
 /**
166
- * Draw setting widget
184
+ * Draw setting row
167 185
  *
168 186
  * @v widget		Setting widget
169 187
  */
170
-static void draw_setting ( struct setting_widget *widget ) {
171
-	struct setting_row row;
172
-	unsigned int len;
173
-	unsigned int curs_col;
188
+static void draw_setting_row ( struct setting_widget *widget ) {
189
+	struct setting_row_text text;
190
+	unsigned int curs_offset;
174 191
 	char *value;
175 192
 
176 193
 	/* Fill row with spaces */
177
-	memset ( &row, ' ', sizeof ( row ) );
178
-	row.nul = '\0';
179
-
180
-	/* Construct dot-padded name */
181
-	memset ( row.name, '.', sizeof ( row.name ) );
182
-	len = strlen ( widget->setting->name );
183
-	if ( len > sizeof ( row.name ) )
184
-		len = sizeof ( row.name );
185
-	memcpy ( row.name, widget->setting->name, len );
186
-
187
-	/* Construct space-padded value */
188
-	value = widget->value;
189
-	if ( ! *value )
190
-		value = "<not specified>";
191
-	len = strlen ( value );
192
-	if ( len > sizeof ( row.value ) )
193
-		len = sizeof ( row.value );
194
-	memcpy ( row.value, value, len );
195
-	curs_col = ( widget->col + offsetof ( typeof ( row ), value )
196
-		     + len );
194
+	memset ( &text, ' ', sizeof ( text ) );
195
+	text.nul = '\0';
196
+
197
+	/* Construct row content */
198
+	if ( widget->row.settings ) {
199
+
200
+		/* Construct space-padded name */
201
+		curs_offset = ( offsetof ( typeof ( text ), name ) +
202
+				string_copy ( text.name, widget->row.value,
203
+					      sizeof ( text.name ) ) );
204
+
205
+	} else {
206
+
207
+		/* Construct dot-padded name */
208
+		memset ( text.name, '.', sizeof ( text.name ) );
209
+		string_copy ( text.name, widget->row.setting->name,
210
+			      sizeof ( text.name ) );
211
+
212
+		/* Construct space-padded value */
213
+		value = widget->row.value;
214
+		if ( ! *value )
215
+			value = "<not specified>";
216
+		curs_offset = ( offsetof ( typeof ( text ), value ) +
217
+				string_copy ( text.value, value,
218
+					      sizeof ( text.value ) ) );
219
+	}
197 220
 
198 221
 	/* Print row */
199
-	if ( widget->originates_here )
222
+	if ( widget->row.originates_here || widget->row.settings )
200 223
 		attron ( A_BOLD );
201
-	mvprintw ( widget->row, widget->col, "%s", row.start );
224
+	mvprintw ( widget->row.row, widget->row.col, "%s", text.start );
202 225
 	attroff ( A_BOLD );
203
-	move ( widget->row, curs_col );
204
-	if ( widget->editing )
205
-		draw_editbox ( &widget->editbox );
226
+	move ( widget->row.row, widget->row.col + curs_offset );
206 227
 }
207 228
 
208 229
 /**
@@ -213,34 +234,20 @@ static void draw_setting ( struct setting_widget *widget ) {
213 234
  * @ret key		Key returned to application, or zero
214 235
  */
215 236
 static int edit_setting ( struct setting_widget *widget, int key ) {
216
-	widget->editing = 1;
217
-	return edit_editbox ( &widget->editbox, key );
237
+	assert ( widget->row.setting != NULL );
238
+	widget->row.editing = 1;
239
+	return edit_editbox ( &widget->row.editbox, key );
218 240
 }
219 241
 
220 242
 /**
221
- * Select a setting for display updates, by index.
243
+ * Save setting widget value back to configuration settings
222 244
  *
223 245
  * @v widget		Setting widget
224
- * @v settings		Settings block
225
- * @v index		Index of setting with settings list
226 246
  */
227
-static void select_setting ( struct setting_widget *widget,
228
-			     unsigned int index ) {
229
-	unsigned int skip = offsetof ( struct setting_widget, setting );
230
-
231
-	/* Reset the widget, preserving static state. */
232
-	memset ( ( char * ) widget + skip, 0, sizeof ( *widget ) - skip );
233
-	widget->row = SETTINGS_LIST_ROW + index - widget->first_visible;
234
-	widget->col = SETTINGS_LIST_COL;
235
-	for_each_table_entry ( widget->setting, SETTINGS ) {
236
-		if ( ! setting_applies ( widget->settings, widget->setting ) )
237
-			continue;
238
-		if ( index-- == 0 )
239
-			break;
240
-	}
241
-
242
-	/* Read current setting value */
243
-	load_setting ( widget );
247
+static int save_setting ( struct setting_widget *widget ) {
248
+	assert ( widget->row.setting != NULL );
249
+	return storef_setting ( widget->settings, widget->row.setting,
250
+				widget->row.value );
244 251
 }
245 252
 
246 253
 /**
@@ -314,173 +321,227 @@ static void alert ( const char *fmt, ... ) {
314 321
 
315 322
 /**
316 323
  * Draw title row
324
+ *
325
+ * @v widget		Setting widget
317 326
  */
318
-static void draw_title_row ( void ) {
327
+static void draw_title_row ( struct setting_widget *widget ) {
328
+	const char *name;
329
+
330
+	clearmsg ( TITLE_ROW );
331
+	name = settings_name ( widget->settings );
319 332
 	attron ( A_BOLD );
320
-	msg ( TITLE_ROW, "iPXE option configuration console" );
333
+	msg ( TITLE_ROW, "iPXE option configuration%s%s",
334
+	      ( name[0] ? " - " : "" ), name );
321 335
 	attroff ( A_BOLD );
322 336
 }
323 337
 
324 338
 /**
325 339
  * Draw information row
326 340
  *
327
- * @v settings		Settings block
328
- * @v setting		Current configuration setting
341
+ * @v widget		Setting widget
329 342
  */
330
-static void draw_info_row ( struct settings *settings,
331
-			    struct setting *setting ) {
343
+static void draw_info_row ( struct setting_widget *widget ) {
332 344
 	struct settings *origin;
333 345
 	char buf[32];
334 346
 
347
+	/* Draw nothing unless this row represents a setting */
348
+	clearmsg ( INFO_ROW );
349
+	if ( ! widget->row.setting )
350
+		return;
351
+
335 352
 	/* Determine a suitable setting name */
336
-	origin = fetch_setting_origin ( settings, setting );
353
+	origin = fetch_setting_origin ( widget->settings, widget->row.setting );
337 354
 	if ( ! origin )
338
-		origin = settings;
339
-	setting_name ( origin, setting, buf, sizeof ( buf ) );
355
+		origin = widget->settings;
356
+	setting_name ( origin, widget->row.setting, buf, sizeof ( buf ) );
340 357
 
341
-	clearmsg ( INFO_ROW );
358
+	/* Draw row */
342 359
 	attron ( A_BOLD );
343
-	msg ( INFO_ROW, "%s - %s", buf, setting->description );
360
+	msg ( INFO_ROW, "%s - %s", buf, widget->row.setting->description );
344 361
 	attroff ( A_BOLD );
345 362
 }
346 363
 
347 364
 /**
348 365
  * Draw instruction row
349 366
  *
350
- * @v editing		Editing in progress flag
367
+ * @v widget		Setting widget
351 368
  */
352
-static void draw_instruction_row ( int editing ) {
369
+static void draw_instruction_row ( struct setting_widget *widget ) {
370
+
353 371
 	clearmsg ( INSTRUCTION_ROW );
354
-	if ( editing ) {
372
+	if ( widget->row.editing ) {
355 373
 		msg ( INSTRUCTION_ROW,
356 374
 		      "Enter - accept changes" INSTRUCTION_PAD
357 375
 		      "Ctrl-C - discard changes" );
358 376
 	} else {
359 377
 		msg ( INSTRUCTION_ROW,
360
-		      "Ctrl-D - delete setting" INSTRUCTION_PAD
361
-		      "Ctrl-X - exit configuration utility" );
378
+		      "%sCtrl-X - exit configuration utility",
379
+		      ( widget->row.setting ?
380
+			"Ctrl-D - delete setting" INSTRUCTION_PAD : "" ) );
362 381
 	}
363 382
 }
364 383
 
365 384
 /**
366
- * Reveal a setting by index: Scroll the setting list to reveal the
367
- * specified setting.
385
+ * Reveal setting row
368 386
  *
369
- * @widget	The main loop's display widget.
370
- * @n		The index of the setting to reveal.
387
+ * @v widget		Setting widget
388
+ * @v index		Index of setting row
371 389
  */
372
-static void reveal ( struct setting_widget *widget, unsigned int n)
373
-{
390
+static void reveal_setting_row ( struct setting_widget *widget,
391
+				 unsigned int index ) {
374 392
 	unsigned int i;
375 393
 
376 394
 	/* Simply return if setting N is already on-screen. */
377
-	if ( n - widget->first_visible < SETTINGS_LIST_ROWS )
395
+	if ( index - widget->first_visible < SETTINGS_LIST_ROWS )
378 396
 		return;
379
-	
380
-	/* Jump scroll to make the specified setting visible. */
381
-	while ( widget->first_visible < n )
397
+
398
+	/* Jump scroll to make the specified setting row visible. */
399
+	while ( widget->first_visible < index )
382 400
 		widget->first_visible += SETTINGS_LIST_ROWS;
383
-	while ( widget->first_visible > n )
401
+	while ( widget->first_visible > index )
384 402
 		widget->first_visible -= SETTINGS_LIST_ROWS;
385
-	
386
-	/* Draw elipses before and/or after the settings list to
387
-	   represent any invisible settings. */
403
+
404
+	/* Draw ellipses before and/or after the settings list to
405
+	 * represent any invisible settings.
406
+	 */
388 407
 	mvaddstr ( SETTINGS_LIST_ROW - 1,
389 408
 		   SETTINGS_LIST_COL + 1,
390 409
 		   widget->first_visible > 0 ? "..." : "   " );
391 410
 	mvaddstr ( SETTINGS_LIST_ROW + SETTINGS_LIST_ROWS,
392 411
 		   SETTINGS_LIST_COL + 1,
393 412
 		   ( ( widget->first_visible + SETTINGS_LIST_ROWS )
394
-		     < widget->num_settings ? "..." : "   " ) );
395
-	
413
+		     < widget->num_rows ? "..." : "   " ) );
414
+
396 415
 	/* Draw visible settings. */
397 416
 	for ( i = 0; i < SETTINGS_LIST_ROWS; i++ ) {
398
-		if ( ( widget->first_visible + i ) < widget->num_settings ) {
399
-			select_setting ( widget, widget->first_visible + i );
400
-			draw_setting ( widget );
417
+		if ( ( widget->first_visible + i ) < widget->num_rows ) {
418
+			select_setting_row ( widget,
419
+					     widget->first_visible + i );
420
+			draw_setting_row ( widget );
401 421
 		} else {
402 422
 			clearmsg ( SETTINGS_LIST_ROW + i );
403 423
 		}
404 424
 	}
425
+}
426
+
427
+/**
428
+ * Reveal setting row
429
+ *
430
+ * @v widget		Setting widget
431
+ * @v settings		Settings block
432
+ */
433
+static void init_widget ( struct setting_widget *widget,
434
+			  struct settings *settings ) {
405 435
 
406
-	/* Set the widget to the current row, which will be redrawn
407
-	   appropriately by the main loop. */
408
-	select_setting ( widget, n );
436
+	widget->settings = settings;
437
+	widget->num_rows = select_setting_row ( widget, 0 );
438
+	widget->first_visible = SETTINGS_LIST_ROWS;
439
+	draw_title_row ( widget );
440
+	reveal_setting_row ( widget, 0 );
441
+	select_setting_row ( widget, 0 );
409 442
 }
410 443
 
411 444
 static int main_loop ( struct settings *settings ) {
412 445
 	struct setting_widget widget;
413
-	unsigned int current = 0;
446
+	int redraw = 1;
414 447
 	unsigned int next;
415 448
 	int key;
416 449
 	int rc;
417 450
 
418 451
 	/* Print initial screen content */
419
-	draw_title_row();
420 452
 	color_set ( CPAIR_NORMAL, NULL );
453
+	memset ( &widget, 0, sizeof ( widget ) );
421 454
 	init_widget ( &widget, settings );
422
-	
455
+
423 456
 	while ( 1 ) {
424
-		/* Redraw information and instruction rows */
425
-		draw_info_row ( widget.settings, widget.setting );
426
-		draw_instruction_row ( widget.editing );
427
-
428
-		/* Redraw current setting */
429
-		color_set ( ( widget.editing ? CPAIR_EDIT : CPAIR_SELECT ),
430
-			    NULL );
431
-		draw_setting ( &widget );
432
-		color_set ( CPAIR_NORMAL, NULL );
433
-
434
-		key = getkey ( 0 );
435
-		if ( widget.editing ) {
436
-			key = edit_setting ( &widget, key );
457
+
458
+		/* Redraw rows if necessary */
459
+		if ( redraw ) {
460
+			draw_info_row ( &widget );
461
+			draw_instruction_row ( &widget );
462
+			color_set ( ( widget.row.editing ?
463
+				      CPAIR_EDIT : CPAIR_SELECT ), NULL );
464
+			draw_setting_row ( &widget );
465
+			color_set ( CPAIR_NORMAL, NULL );
466
+			redraw = 0;
467
+		}
468
+
469
+		if ( widget.row.editing ) {
470
+
471
+			/* Sanity check */
472
+			assert ( widget.row.setting != NULL );
473
+
474
+			/* Redraw edit box */
475
+			color_set ( CPAIR_EDIT, NULL );
476
+			draw_editbox ( &widget.row.editbox );
477
+			color_set ( CPAIR_NORMAL, NULL );
478
+
479
+			/* Process keypress */
480
+			key = edit_setting ( &widget, getkey ( 0 ) );
437 481
 			switch ( key ) {
438 482
 			case CR:
439 483
 			case LF:
440
-				if ( ( rc = save_setting ( &widget ) ) != 0 ) {
441
-					alert ( " Could not set %s: %s ",
442
-						widget.setting->name,
443
-						strerror ( rc ) );
444
-				}
484
+				if ( ( rc = save_setting ( &widget ) ) != 0 )
485
+					alert ( " %s ", strerror ( rc ) );
445 486
 				/* Fall through */
446 487
 			case CTRL_C:
447
-				load_setting ( &widget );
488
+				select_setting_row ( &widget, widget.current );
489
+				redraw = 1;
448 490
 				break;
449 491
 			default:
450 492
 				/* Do nothing */
451 493
 				break;
452 494
 			}
495
+
453 496
 		} else {
454
-			next = current;
497
+
498
+			/* Process keypress */
499
+			key = getkey ( 0 );
500
+			next = widget.current;
455 501
 			switch ( key ) {
456 502
 			case KEY_DOWN:
457
-				if ( next < ( widget.num_settings - 1 ) )
458
-					reveal ( &widget, ++next );
503
+				if ( widget.current < ( widget.num_rows - 1 ) )
504
+					next++;
459 505
 				break;
460 506
 			case KEY_UP:
461
-				if ( next > 0 )
462
-					reveal ( &widget, --next ) ;
507
+				if ( widget.current > 0 )
508
+					next--;
463 509
 				break;
464 510
 			case CTRL_D:
465
-				delete_setting ( widget.settings,
466
-						 widget.setting );
467
-				select_setting ( &widget, next );
468
-				draw_setting ( &widget );
511
+				if ( ! widget.row.setting )
512
+					break;
513
+				if ( ( rc = delete_setting ( widget.settings,
514
+						widget.row.setting ) ) != 0 ) {
515
+					alert ( " %s ", strerror ( rc ) );
516
+				}
517
+				select_setting_row ( &widget, widget.current );
518
+				redraw = 1;
469 519
 				break;
470 520
 			case CTRL_X:
471 521
 				return 0;
522
+			case CR:
523
+			case LF:
524
+				if ( widget.row.settings ) {
525
+					init_widget ( &widget,
526
+						      widget.row.settings );
527
+					redraw = 1;
528
+				}
529
+				/* Fall through */
472 530
 			default:
473
-				edit_setting ( &widget, key );
531
+				if ( widget.row.setting ) {
532
+					edit_setting ( &widget, key );
533
+					redraw = 1;
534
+				}
474 535
 				break;
475
-			}	
476
-			if ( next != current ) {
477
-				draw_setting ( &widget );
478
-				select_setting ( &widget, next );
479
-				current = next;
536
+			}
537
+			if ( next != widget.current ) {
538
+				draw_setting_row ( &widget );
539
+				redraw = 1;
540
+				reveal_setting_row ( &widget, next );
541
+				select_setting_row ( &widget, next );
480 542
 			}
481 543
 		}
482 544
 	}
483
-	
484 545
 }
485 546
 
486 547
 int settings_ui ( struct settings *settings ) {

Загрузка…
Отмена
Сохранить