iPXE
settings_ui.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_SECBOOT ( PERMITTED );
26 
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <curses.h>
33 #include <ipxe/console.h>
34 #include <ipxe/settings.h>
35 #include <ipxe/editbox.h>
36 #include <ipxe/keys.h>
37 #include <ipxe/ansicol.h>
38 #include <ipxe/jumpscroll.h>
39 #include <ipxe/message.h>
40 #include <ipxe/settings_ui.h>
41 #include <config/branding.h>
42 
43 /** @file
44  *
45  * Option configuration console
46  *
47  */
48 
49 /* Screen layout */
50 #define TITLE_ROW 1U
51 #define SETTINGS_LIST_ROW 3U
52 #define SETTINGS_LIST_COL 1U
53 #define SETTINGS_LIST_ROWS ( LINES - 6U - SETTINGS_LIST_ROW )
54 #define INFO_ROW ( LINES - 5U )
55 #define ALERT_ROW ( LINES - 2U )
56 #define INSTRUCTION_ROW ( LINES - 2U )
57 #define INSTRUCTION_PAD " "
58 
59 /** Layout of text within a setting row */
60 #define SETTING_ROW_TEXT( cols ) struct { \
61  char start[0]; \
62  char pad1[1]; \
63  union { \
64  struct { \
65  char name[ cols - 1 - 1 - 1 - 1 - 1 ]; \
66  char pad2[1]; \
67  } __attribute__ (( packed )) settings; \
68  struct { \
69  char name[15]; \
70  char pad2[1]; \
71  char value[ cols - 1 - 15 - 1 - 1 - 1 - 1 ]; \
72  } __attribute__ (( packed )) setting; \
73  } u; \
74  char pad3[1]; \
75  char nul; \
76 } __attribute__ (( packed ))
77 
78 /** A settings user interface row */
80  /** Target configuration settings block
81  *
82  * Valid only for rows that lead to new settings blocks.
83  */
84  struct settings *settings;
85  /** Configuration setting origin
86  *
87  * Valid only for rows that represent individual settings.
88  */
89  struct settings *origin;
90  /** Configuration setting
91  *
92  * Valid only for rows that represent individual settings.
93  */
94  struct setting setting;
95  /** Screen row */
96  unsigned int row;
97  /** Edit box widget used for editing setting */
98  struct edit_box editbox;
99  /** Editing in progress flag */
100  int editing;
101  /** Dynamically allocated buffer for setting's value */
102  char *buf;
103 };
104 
105 /** A settings user interface */
106 struct settings_ui {
107  /** Settings block */
109  /** Jump scroller */
111  /** Current row */
113 };
114 
115 /**
116  * Select a setting
117  *
118  * @v ui Settings user interface
119  * @v index Index of setting row
120  * @ret count Number of setting rows
121  */
122 static unsigned int select_setting_row ( struct settings_ui *ui,
123  unsigned int index ) {
124  SETTING_ROW_TEXT ( COLS ) *text;
125  struct settings *settings;
126  struct setting *setting;
127  struct setting *previous = NULL;
128  unsigned int count = 0;
129 
130  /* Free any previous setting value */
131  free ( ui->row.buf );
132  ui->row.buf = NULL;
133 
134  /* Initialise structure */
135  memset ( &ui->row, 0, sizeof ( ui->row ) );
136  ui->row.row = ( SETTINGS_LIST_ROW + index - ui->scroll.first );
137 
138  /* Include parent settings block, if applicable */
139  if ( ui->settings->parent && ( count++ == index ) )
140  ui->row.settings = ui->settings->parent;
141 
142  /* Include any child settings blocks, if applicable */
143  list_for_each_entry ( settings, &ui->settings->children, siblings ) {
144  if ( count++ == index )
145  ui->row.settings = settings;
146  }
147 
148  /* Include any applicable settings */
150 
151  /* Skip inapplicable settings */
152  if ( ! setting_applies ( ui->settings, setting ) )
153  continue;
154 
155  /* Skip duplicate settings */
156  if ( previous && ( setting_cmp ( setting, previous ) == 0 ) )
157  continue;
158  previous = setting;
159 
160  /* Read current setting value and origin */
161  if ( count++ == index ) {
163  &ui->row.origin,
164  &ui->row.setting, &ui->row.buf );
165  }
166  }
167 
168  /* Initialise edit box */
169  memset ( &ui->row.editbox, 0, sizeof ( ui->row.editbox ) );
170  init_editbox ( &ui->row.editbox, ui->row.row,
172  offsetof ( typeof ( *text ), u.setting.value ) ),
173  sizeof ( text->u.setting.value ), 0, &ui->row.buf );
174 
175  return count;
176 }
177 
178 /**
179  * Copy string without NUL termination
180  *
181  * @v dest Destination
182  * @v src Source
183  * @v len Maximum length of destination
184  * @ret len Length of (unterminated) string
185  */
186 static size_t string_copy ( char *dest, const char *src, size_t len ) {
187  size_t src_len;
188 
189  src_len = strlen ( src );
190  if ( len > src_len )
191  len = src_len;
192  memcpy ( dest, src, len );
193  return len;
194 }
195 
196 /**
197  * Draw setting row
198  *
199  * @v ui Settings UI
200  */
201 static void draw_setting_row ( struct settings_ui *ui ) {
202  SETTING_ROW_TEXT ( COLS ) text;
203  unsigned int curs_offset;
204  const char *value;
205 
206  /* Fill row with spaces */
207  memset ( &text, ' ', sizeof ( text ) );
208  text.nul = '\0';
209 
210  /* Construct row content */
211  if ( ui->row.settings ) {
212 
213  /* Construct space-padded name */
214  value = ( ( ui->row.settings == ui->settings->parent ) ?
215  ".." : ui->row.settings->name );
216  curs_offset = string_copy ( text.u.settings.name, value,
217  sizeof ( text.u.settings.name ) );
218  text.u.settings.name[curs_offset] = '/';
219  curs_offset += offsetof ( typeof ( text ), u.settings );
220 
221  } else {
222 
223  /* Construct dot-padded name */
224  memset ( text.u.setting.name, '.',
225  sizeof ( text.u.setting.name ) );
226  string_copy ( text.u.setting.name, ui->row.setting.name,
227  sizeof ( text.u.setting.name ) );
228 
229  /* Construct space-padded value */
230  value = ui->row.buf;
231  if ( ! ( value && value[0] ) )
232  value = "<not specified>";
233  curs_offset = string_copy ( text.u.setting.value, value,
234  sizeof ( text.u.setting.value ) );
235  curs_offset += offsetof ( typeof ( text ), u.setting.value );
236  }
237 
238  /* Print row */
239  if ( ( ui->row.origin == ui->settings ) || ( ui->row.settings != NULL ))
240  attron ( A_BOLD );
241  mvprintw ( ui->row.row, SETTINGS_LIST_COL, "%s", text.start );
242  attroff ( A_BOLD );
243  move ( ui->row.row, ( SETTINGS_LIST_COL + curs_offset ) );
244 }
245 
246 /**
247  * Edit setting ui
248  *
249  * @v ui Settings UI
250  * @v key Key pressed by user
251  * @ret key Key returned to application, or zero
252  */
253 static int edit_setting ( struct settings_ui *ui, int key ) {
254  assert ( ui->row.setting.name != NULL );
255  ui->row.editing = 1;
256  return edit_widget ( &ui->row.editbox.widget, key );
257 }
258 
259 /**
260  * Save setting ui value back to configuration settings
261  *
262  * @v ui Settings UI
263  */
264 static int save_setting ( struct settings_ui *ui ) {
265  assert ( ui->row.setting.name != NULL );
266  return storef_setting ( ui->settings, &ui->row.setting, ui->row.buf );
267 }
268 
269 /**
270  * Draw title row
271  *
272  * @v ui Settings UI
273  */
274 static void draw_title_row ( struct settings_ui *ui ) {
275  const char *name;
276 
277  clearmsg ( TITLE_ROW );
278  name = settings_name ( ui->settings );
279  attron ( A_BOLD );
280  msg ( TITLE_ROW, PRODUCT_SHORT_NAME " configuration settings%s%s",
281  ( name[0] ? " - " : "" ), name );
282  attroff ( A_BOLD );
283 }
284 
285 /**
286  * Draw information row
287  *
288  * @v ui Settings UI
289  */
290 static void draw_info_row ( struct settings_ui *ui ) {
291  char buf[32];
292 
293  /* Draw nothing unless this row represents a setting */
294  clearmsg ( INFO_ROW );
295  clearmsg ( INFO_ROW + 1 );
296  if ( ! ui->row.setting.name )
297  return;
298 
299  /* Determine a suitable setting name */
300  setting_name ( ( ui->row.origin ?
301  ui->row.origin : ui->settings ),
302  &ui->row.setting, buf, sizeof ( buf ) );
303 
304  /* Draw row */
305  attron ( A_BOLD );
306  msg ( INFO_ROW, "%s - %s", buf, ui->row.setting.description );
307  attroff ( A_BOLD );
308  color_set ( CPAIR_URL, NULL );
309  msg ( ( INFO_ROW + 1 ), PRODUCT_SETTING_URI, ui->row.setting.name );
311 }
312 
313 /**
314  * Draw instruction row
315  *
316  * @v ui Settings UI
317  */
318 static void draw_instruction_row ( struct settings_ui *ui ) {
319 
321  if ( ui->row.editing ) {
323  "Enter - accept changes" INSTRUCTION_PAD
324  "Ctrl-C - discard changes" );
325  } else {
327  "%sCtrl-X - exit configuration utility",
328  ( ( ui->row.origin == ui->settings ) ?
329  "Ctrl-D - delete setting" INSTRUCTION_PAD : "" ) );
330  }
331 }
332 
333 /**
334  * Draw the current block of setting rows
335  *
336  * @v ui Settings UI
337  */
338 static void draw_setting_rows ( struct settings_ui *ui ) {
339  unsigned int i;
340 
341  /* Draw ellipses before and/or after the list as necessary */
343  mvaddstr ( ( SETTINGS_LIST_ROW - 1 ), ( SETTINGS_LIST_COL + 1 ),
344  jump_scroll_is_first ( &ui->scroll ) ? " " : "..." );
346  ( SETTINGS_LIST_COL + 1 ),
347  jump_scroll_is_last ( &ui->scroll ) ? " " : "..." );
349 
350  /* Draw visible settings. */
351  for ( i = 0 ; i < SETTINGS_LIST_ROWS ; i++ ) {
352  if ( ( ui->scroll.first + i ) < ui->scroll.count ) {
353  select_setting_row ( ui, ( ui->scroll.first + i ) );
354  draw_setting_row ( ui );
355  } else {
356  clearmsg ( SETTINGS_LIST_ROW + i );
357  }
358  }
359 }
360 
361 /**
362  * Select settings block
363  *
364  * @v ui Settings UI
365  * @v settings Settings block
366  */
367 static void select_settings ( struct settings_ui *ui,
368  struct settings *settings ) {
369 
371  ui->scroll.count = select_setting_row ( ui, 0 );
373  ui->scroll.current = 0;
374  ui->scroll.first = 0;
375  draw_title_row ( ui );
376  draw_setting_rows ( ui );
377  select_setting_row ( ui, 0 );
378 }
379 
380 static int main_loop ( struct settings *settings ) {
381  struct settings_ui ui;
382  unsigned int previous;
383  unsigned int move;
384  int redraw = 1;
385  int key;
386  int rc;
387 
388  /* Print initial screen content */
390  memset ( &ui, 0, sizeof ( ui ) );
391  select_settings ( &ui, settings );
392 
393  while ( 1 ) {
394 
395  /* Redraw rows if necessary */
396  if ( redraw ) {
397  draw_info_row ( &ui );
398  draw_instruction_row ( &ui );
399  color_set ( ( ui.row.editing ?
401  draw_setting_row ( &ui );
403  curs_set ( ui.row.editing );
404  redraw = 0;
405  }
406 
407  /* Edit setting, if we are currently editing */
408  if ( ui.row.editing ) {
409 
410  /* Sanity check */
411  assert ( ui.row.setting.name != NULL );
412 
413  /* Redraw edit box */
414  draw_widget ( &ui.row.editbox.widget );
415 
416  /* Process keypress */
417  key = edit_setting ( &ui, getkey ( 0 ) );
418  switch ( key ) {
419  case CR:
420  case LF:
421  if ( ( rc = save_setting ( &ui ) ) != 0 ) {
422  alert ( ALERT_ROW, " %s ",
423  strerror ( rc ) );
424  }
425  /* Fall through */
426  case CTRL_C:
427  select_setting_row ( &ui, ui.scroll.current );
428  redraw = 1;
429  break;
430  default:
431  /* Do nothing */
432  break;
433  }
434 
435  continue;
436  }
437 
438  /* Otherwise, navigate through settings */
439  key = getkey ( 0 );
440  move = jump_scroll_key ( &ui.scroll, key );
441  if ( move ) {
442  previous = ui.scroll.current;
443  jump_scroll_move ( &ui.scroll, move );
444  if ( ui.scroll.current != previous ) {
445  draw_setting_row ( &ui );
446  redraw = 1;
447  if ( jump_scroll ( &ui.scroll ) )
448  draw_setting_rows ( &ui );
449  select_setting_row ( &ui, ui.scroll.current );
450  }
451  continue;
452  }
453 
454  /* Handle non-navigation keys */
455  switch ( key ) {
456  case CTRL_D:
457  if ( ! ui.row.setting.name )
458  break;
459  if ( ( rc = delete_setting ( ui.settings,
460  &ui.row.setting ) ) != 0 ){
461  alert ( ALERT_ROW, " %s ", strerror ( rc ) );
462  }
463  select_setting_row ( &ui, ui.scroll.current );
464  redraw = 1;
465  break;
466  case CTRL_X:
467  select_setting_row ( &ui, -1U );
468  return 0;
469  case CR:
470  case LF:
471  if ( ui.row.settings ) {
472  select_settings ( &ui, ui.row.settings );
473  redraw = 1;
474  }
475  /* Fall through */
476  default:
477  if ( ui.row.setting.name ) {
478  edit_setting ( &ui, key );
479  redraw = 1;
480  }
481  break;
482  }
483  }
484 }
485 
486 int settings_ui ( struct settings *settings ) {
487  int rc;
488 
489  initscr();
490  start_color();
492  curs_set ( 0 );
493  erase();
494 
495  rc = main_loop ( settings );
496 
497  endwin();
498 
499  return rc;
500 }
int getkey(unsigned long timeout)
Get single keypress.
Definition: getkey.c:72
MuCurses header file.
int editing
Editing in progress flag.
Definition: settings_ui.c:100
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1986
Editable text box widget.
static void draw_widget(struct widget *widget)
Draw text widget.
Definition: widget.h:87
#define PRODUCT_SHORT_NAME
Definition: branding.h:29
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition: message.c:62
int erase(void)
Completely clear the screen.
Definition: clear.c:98
int settings_ui(struct settings *settings)
Definition: settings_ui.c:486
static void draw_setting_row(struct settings_ui *ui)
Draw setting row.
Definition: settings_ui.c:201
int fetchf_setting_copy(struct settings *settings, const struct setting *setting, struct settings **origin, struct setting *fetched, char **value)
Fetch copy of formatted value of setting.
Definition: settings.c:1277
struct settings * parent
Parent settings block.
Definition: settings.h:139
static int attroff(int attrs)
Definition: curses.h:509
#define CPAIR_EDIT
Editable text.
Definition: ansicol.h:50
A settings user interface.
Definition: settings_ui.c:106
static int main_loop(struct settings *settings)
Definition: settings_ui.c:380
struct settings_ui_row row
Current row.
Definition: settings_ui.c:112
void clearmsg(unsigned int row)
Clear message on specified row.
Definition: message.c:75
static int delete_setting(struct settings *settings, const struct setting *setting)
Delete setting.
Definition: settings.h:534
#define start_color()
Definition: curses.h:397
int endwin(void)
Finalise console environment.
Definition: wininit.c:32
long index
Definition: bigint.h:65
A settings user interface row.
Definition: settings_ui.c:79
#define mvprintw(y, x, fmt,...)
Definition: curses.h:649
const char * settings_name(struct settings *settings)
Return settings block name.
Definition: settings.c:346
#define SETTINGS_LIST_ROW
Definition: settings_ui.c:51
void alert(unsigned int row, const char *fmt,...)
Show alert message.
Definition: message.c:104
static void draw_instruction_row(struct settings_ui *ui)
Draw instruction row.
Definition: settings_ui.c:318
Branding configuration.
union @18 u
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:25
const char * description
Description.
Definition: settings.h:31
static unsigned int select_setting_row(struct settings_ui *ui, unsigned int index)
Select a setting.
Definition: settings_ui.c:122
A jump scroller.
Definition: jumpscroll.h:16
Message printing.
#define CPAIR_NORMAL
Normal text.
Definition: ansicol.h:41
struct settings * origin
Configuration setting origin.
Definition: settings_ui.c:89
const char * name
Name.
Definition: settings.h:29
#define SETTINGS
Configuration setting table.
Definition: settings.h:54
#define CTRL_X
Definition: keys.h:42
static int save_setting(struct settings_ui *ui)
Save setting ui value back to configuration settings.
Definition: settings_ui.c:264
void * memcpy(void *dest, const void *src, size_t len) __nonnull
struct settings * settings_target(struct settings *settings)
Redirect to target settings block.
Definition: settings.c:550
static void draw_setting_rows(struct settings_ui *ui)
Draw the current block of setting rows.
Definition: settings_ui.c:338
WINDOW * initscr(void)
Initialise console environment.
Definition: wininit.c:18
static void draw_info_row(struct settings_ui *ui)
Draw information row.
Definition: settings_ui.c:290
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define PRODUCT_SETTING_URI
Definition: branding.h:171
static const void * src
Definition: string.h:48
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:432
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
unsigned int first
First visible item.
Definition: jumpscroll.h:24
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned int count
Total number of items.
Definition: jumpscroll.h:20
int jump_scroll(struct jump_scroller *scroll)
Jump scroll to new page (if applicable)
Definition: jumpscroll.c:141
ring len
Length.
Definition: dwmac.h:231
#define COLS
Definition: vga.h:27
#define CTRL_C
Definition: keys.h:21
static unsigned int count
Number of entries.
Definition: dwmac.h:225
#define CPAIR_URL
URL text.
Definition: ansicol.h:56
struct settings * settings
Target configuration settings block.
Definition: settings_ui.c:84
An editable text box widget.
Definition: editbox.h:18
User interaction.
FILE_SECBOOT(PERMITTED)
#define ALERT_ROW
Definition: settings_ui.c:55
#define TITLE_ROW
Definition: settings_ui.c:50
Configuration settings.
int storef_setting(struct settings *settings, const struct setting *setting, const char *value)
Store formatted value of setting.
Definition: settings.c:1320
struct settings * settings
Settings block.
Definition: settings_ui.c:108
Option configuration console.
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
static void select_settings(struct settings_ui *ui, struct settings *settings)
Select settings block.
Definition: settings_ui.c:367
int setting_applies(struct settings *settings, const struct setting *setting)
Check applicability of setting.
Definition: settings.c:571
unsigned int jump_scroll_move(struct jump_scroller *scroll, unsigned int move)
Move scroller.
Definition: jumpscroll.c:93
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:386
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
A settings block.
Definition: settings.h:133
#define INSTRUCTION_ROW
Definition: settings_ui.c:56
#define CPAIR_SEPARATOR
Unselectable text (e.g.
Definition: ansicol.h:47
const char * name
Name.
Definition: settings.h:137
#define INFO_ROW
Definition: settings_ui.c:54
#define INSTRUCTION_PAD
Definition: settings_ui.c:57
#define LF
Definition: keys.h:48
A setting.
Definition: settings.h:24
char * buf
Dynamically allocated buffer for setting's value.
Definition: settings_ui.c:102
static void init_editbox(struct edit_box *box, unsigned int row, unsigned int col, unsigned int width, unsigned int flags, char **buf)
Initialise text box widget.
Definition: editbox.h:40
static int jump_scroll_is_last(struct jump_scroller *scroll)
Check if jump scroller is currently on last page.
Definition: jumpscroll.h:73
int curs_set(int visibility)
Set cursor visibility.
Definition: mucurses.c:154
Key definitions.
unsigned int row
Screen row.
Definition: settings_ui.c:96
struct setting setting
Configuration setting.
Definition: settings_ui.c:94
struct jump_scroller scroll
Jump scroller.
Definition: settings_ui.c:110
static int jump_scroll_is_first(struct jump_scroller *scroll)
Check if jump scroller is currently on first page.
Definition: jumpscroll.h:62
struct edit_box editbox
Edit box widget used for editing setting.
Definition: settings_ui.c:98
static int move(int y, int x)
Definition: curses.h:594
#define CPAIR_SELECT
Highlighted text.
Definition: ansicol.h:44
#define SETTINGS_LIST_COL
Definition: settings_ui.c:52
Jump scrolling.
#define CR
Definition: keys.h:49
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:151
unsigned int rows
Maximum number of visible rows.
Definition: jumpscroll.h:18
struct list_head children
Child settings blocks.
Definition: settings.h:143
#define color_set(cpno, opts)
Definition: curses.h:241
static void draw_title_row(struct settings_ui *ui)
Draw title row.
Definition: settings_ui.c:274
struct widget widget
Text widget.
Definition: editbox.h:20
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition: acpi.c:48
#define CTRL_D
Definition: keys.h:22
#define A_BOLD
Definition: curses.h:139
static size_t string_copy(char *dest, const char *src, size_t len)
Copy string without NUL termination.
Definition: settings_ui.c:186
static int edit_setting(struct settings_ui *ui, int key)
Edit setting ui.
Definition: settings_ui.c:253
unsigned int current
Currently selected item.
Definition: jumpscroll.h:22
#define SETTINGS_LIST_ROWS
Definition: settings_ui.c:53
int setting_name(struct settings *settings, const struct setting *setting, char *buf, size_t len)
Return full setting name.
Definition: settings.c:1607
int setting_cmp(const struct setting *a, const struct setting *b)
Compare two settings.
Definition: settings.c:1121
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
unsigned int jump_scroll_key(struct jump_scroller *scroll, int key)
Jump scrolling.
Definition: jumpscroll.c:43
static int edit_widget(struct widget *widget, int key)
Edit text widget.
Definition: widget.h:104
static int mvaddstr(int y, int x, const char *str)
Definition: curses.h:618
#define SETTING_ROW_TEXT(cols)
Layout of text within a setting row.
Definition: settings_ui.c:60
union @391 key
Sense key.
Definition: scsi.h:18
ANSI colours.
static int attron(int attrs)
Definition: curses.h:513
void * memset(void *dest, int character, size_t len) __nonnull