|  | @@ -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 ) {
 |