|  | @@ -45,25 +45,30 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 45 | 45 |  #define CPAIR_URL	5
 | 
		
	
		
			
			| 46 | 46 |  
 | 
		
	
		
			
			| 47 | 47 |  /* Screen layout */
 | 
		
	
		
			
			| 48 |  | -#define TITLE_ROW		1
 | 
		
	
		
			
			| 49 |  | -#define SETTINGS_LIST_ROW	3
 | 
		
	
		
			
			| 50 |  | -#define SETTINGS_LIST_COL	1
 | 
		
	
		
			
			| 51 |  | -#define SETTINGS_LIST_ROWS	15
 | 
		
	
		
			
			| 52 |  | -#define INFO_ROW		19
 | 
		
	
		
			
			| 53 |  | -#define ALERT_ROW		22
 | 
		
	
		
			
			| 54 |  | -#define INSTRUCTION_ROW		22
 | 
		
	
		
			
			|  | 48 | +#define TITLE_ROW		1U
 | 
		
	
		
			
			|  | 49 | +#define SETTINGS_LIST_ROW	3U
 | 
		
	
		
			
			|  | 50 | +#define SETTINGS_LIST_COL	1U
 | 
		
	
		
			
			|  | 51 | +#define SETTINGS_LIST_ROWS	( LINES - 6U - SETTINGS_LIST_ROW )
 | 
		
	
		
			
			|  | 52 | +#define INFO_ROW		( LINES - 5U )
 | 
		
	
		
			
			|  | 53 | +#define ALERT_ROW		( LINES - 2U )
 | 
		
	
		
			
			|  | 54 | +#define INSTRUCTION_ROW		( LINES - 2U )
 | 
		
	
		
			
			| 55 | 55 |  #define INSTRUCTION_PAD "     "
 | 
		
	
		
			
			| 56 | 56 |  
 | 
		
	
		
			
			| 57 | 57 |  /** Layout of text within a setting widget */
 | 
		
	
		
			
			| 58 |  | -struct setting_row_text {
 | 
		
	
		
			
			| 59 |  | -	char start[0];
 | 
		
	
		
			
			| 60 |  | -	char pad1[1];
 | 
		
	
		
			
			| 61 |  | -	char name[15];
 | 
		
	
		
			
			| 62 |  | -	char pad2[1];
 | 
		
	
		
			
			| 63 |  | -	char value[60];
 | 
		
	
		
			
			| 64 |  | -	char pad3[1];
 | 
		
	
		
			
			| 65 |  | -	char nul;
 | 
		
	
		
			
			| 66 |  | -} __attribute__ (( packed ));
 | 
		
	
		
			
			|  | 58 | +#define SETTING_ROW_TEXT( cols ) struct {				\
 | 
		
	
		
			
			|  | 59 | +	char start[0];							\
 | 
		
	
		
			
			|  | 60 | +	char pad1[1];							\
 | 
		
	
		
			
			|  | 61 | +	union {								\
 | 
		
	
		
			
			|  | 62 | +		char settings[ cols - 1 - 1 - 1 - 1 ];			\
 | 
		
	
		
			
			|  | 63 | +		struct {						\
 | 
		
	
		
			
			|  | 64 | +			char name[15];					\
 | 
		
	
		
			
			|  | 65 | +			char pad2[1];					\
 | 
		
	
		
			
			|  | 66 | +			char value[ cols - 1 - 15 - 1 - 1 - 1 - 1 ];	\
 | 
		
	
		
			
			|  | 67 | +		} setting;						\
 | 
		
	
		
			
			|  | 68 | +	} u;								\
 | 
		
	
		
			
			|  | 69 | +	char pad3[1];							\
 | 
		
	
		
			
			|  | 70 | +	char nul;							\
 | 
		
	
		
			
			|  | 71 | +} __attribute__ (( packed ))
 | 
		
	
		
			
			| 67 | 72 |  
 | 
		
	
		
			
			| 68 | 73 |  /** A setting row widget */
 | 
		
	
		
			
			| 69 | 74 |  struct setting_row_widget {
 | 
		
	
	
		
			
			|  | @@ -117,6 +122,7 @@ struct setting_widget {
 | 
		
	
		
			
			| 117 | 122 |   */
 | 
		
	
		
			
			| 118 | 123 |  static unsigned int select_setting_row ( struct setting_widget *widget,
 | 
		
	
		
			
			| 119 | 124 |  					 unsigned int index ) {
 | 
		
	
		
			
			|  | 125 | +	SETTING_ROW_TEXT ( COLS ) *text;
 | 
		
	
		
			
			| 120 | 126 |  	struct settings *settings;
 | 
		
	
		
			
			| 121 | 127 |  	struct setting *setting;
 | 
		
	
		
			
			| 122 | 128 |  	struct setting *previous = NULL;
 | 
		
	
	
		
			
			|  | @@ -171,13 +177,20 @@ static unsigned int select_setting_row ( struct setting_widget *widget,
 | 
		
	
		
			
			| 171 | 177 |  	init_editbox ( &widget->row.editbox, widget->row.value,
 | 
		
	
		
			
			| 172 | 178 |  		       sizeof ( widget->row.value ), NULL, widget->row.row,
 | 
		
	
		
			
			| 173 | 179 |  		       ( widget->row.col +
 | 
		
	
		
			
			| 174 |  | -			 offsetof ( struct setting_row_text, value ) ),
 | 
		
	
		
			
			| 175 |  | -		       sizeof ( ( ( struct setting_row_text * ) NULL )->value ),
 | 
		
	
		
			
			| 176 |  | -		       0 );
 | 
		
	
		
			
			|  | 180 | +			 offsetof ( typeof ( *text ), u.setting.value ) ),
 | 
		
	
		
			
			|  | 181 | +		       sizeof ( text->u.setting.value ), 0 );
 | 
		
	
		
			
			| 177 | 182 |  
 | 
		
	
		
			
			| 178 | 183 |  	return count;
 | 
		
	
		
			
			| 179 | 184 |  }
 | 
		
	
		
			
			| 180 | 185 |  
 | 
		
	
		
			
			|  | 186 | +/**
 | 
		
	
		
			
			|  | 187 | + * Copy string without NUL termination
 | 
		
	
		
			
			|  | 188 | + *
 | 
		
	
		
			
			|  | 189 | + * @v dest		Destination
 | 
		
	
		
			
			|  | 190 | + * @v src		Source
 | 
		
	
		
			
			|  | 191 | + * @v len		Maximum length of destination
 | 
		
	
		
			
			|  | 192 | + * @ret len		Length of (unterminated) string
 | 
		
	
		
			
			|  | 193 | + */
 | 
		
	
		
			
			| 181 | 194 |  static size_t string_copy ( char *dest, const char *src, size_t len ) {
 | 
		
	
		
			
			| 182 | 195 |  	size_t src_len;
 | 
		
	
		
			
			| 183 | 196 |  
 | 
		
	
	
		
			
			|  | @@ -194,7 +207,7 @@ static size_t string_copy ( char *dest, const char *src, size_t len ) {
 | 
		
	
		
			
			| 194 | 207 |   * @v widget		Setting widget
 | 
		
	
		
			
			| 195 | 208 |   */
 | 
		
	
		
			
			| 196 | 209 |  static void draw_setting_row ( struct setting_widget *widget ) {
 | 
		
	
		
			
			| 197 |  | -	struct setting_row_text text;
 | 
		
	
		
			
			|  | 210 | +	SETTING_ROW_TEXT ( COLS ) text;
 | 
		
	
		
			
			| 198 | 211 |  	unsigned int curs_offset;
 | 
		
	
		
			
			| 199 | 212 |  	char *value;
 | 
		
	
		
			
			| 200 | 213 |  
 | 
		
	
	
		
			
			|  | @@ -206,24 +219,26 @@ static void draw_setting_row ( struct setting_widget *widget ) {
 | 
		
	
		
			
			| 206 | 219 |  	if ( widget->row.settings ) {
 | 
		
	
		
			
			| 207 | 220 |  
 | 
		
	
		
			
			| 208 | 221 |  		/* Construct space-padded name */
 | 
		
	
		
			
			| 209 |  | -		curs_offset = ( offsetof ( typeof ( text ), name ) +
 | 
		
	
		
			
			| 210 |  | -				string_copy ( text.name, widget->row.value,
 | 
		
	
		
			
			| 211 |  | -					      sizeof ( text.name ) ) );
 | 
		
	
		
			
			|  | 222 | +		curs_offset = ( offsetof ( typeof ( text ), u.settings ) +
 | 
		
	
		
			
			|  | 223 | +				string_copy ( text.u.settings,
 | 
		
	
		
			
			|  | 224 | +					      widget->row.value,
 | 
		
	
		
			
			|  | 225 | +					      sizeof ( text.u.settings ) ) );
 | 
		
	
		
			
			| 212 | 226 |  
 | 
		
	
		
			
			| 213 | 227 |  	} else {
 | 
		
	
		
			
			| 214 | 228 |  
 | 
		
	
		
			
			| 215 | 229 |  		/* Construct dot-padded name */
 | 
		
	
		
			
			| 216 |  | -		memset ( text.name, '.', sizeof ( text.name ) );
 | 
		
	
		
			
			| 217 |  | -		string_copy ( text.name, widget->row.setting.name,
 | 
		
	
		
			
			| 218 |  | -			      sizeof ( text.name ) );
 | 
		
	
		
			
			|  | 230 | +		memset ( text.u.setting.name, '.',
 | 
		
	
		
			
			|  | 231 | +			 sizeof ( text.u.setting.name ) );
 | 
		
	
		
			
			|  | 232 | +		string_copy ( text.u.setting.name, widget->row.setting.name,
 | 
		
	
		
			
			|  | 233 | +			      sizeof ( text.u.setting.name ) );
 | 
		
	
		
			
			| 219 | 234 |  
 | 
		
	
		
			
			| 220 | 235 |  		/* Construct space-padded value */
 | 
		
	
		
			
			| 221 | 236 |  		value = widget->row.value;
 | 
		
	
		
			
			| 222 | 237 |  		if ( ! *value )
 | 
		
	
		
			
			| 223 | 238 |  			value = "<not specified>";
 | 
		
	
		
			
			| 224 |  | -		curs_offset = ( offsetof ( typeof ( text ), value ) +
 | 
		
	
		
			
			| 225 |  | -				string_copy ( text.value, value,
 | 
		
	
		
			
			| 226 |  | -					      sizeof ( text.value ) ) );
 | 
		
	
		
			
			|  | 239 | +		curs_offset = ( offsetof ( typeof ( text ), u.setting.value ) +
 | 
		
	
		
			
			|  | 240 | +				string_copy ( text.u.setting.value, value,
 | 
		
	
		
			
			|  | 241 | +					      sizeof ( text.u.setting.value )));
 | 
		
	
		
			
			| 227 | 242 |  	}
 | 
		
	
		
			
			| 228 | 243 |  
 | 
		
	
		
			
			| 229 | 244 |  	/* Print row */
 |