iPXE
menu_ui.c File Reference

Menu interface. More...

#include <string.h>
#include <errno.h>
#include <curses.h>
#include <ipxe/keys.h>
#include <ipxe/timer.h>
#include <ipxe/console.h>
#include <ipxe/ansicol.h>
#include <ipxe/jumpscroll.h>
#include <ipxe/dynui.h>

Go to the source code of this file.

Data Structures

struct  menu_ui
 A menu user interface. More...

Macros

#define TITLE_ROW   1U
#define MENU_ROW   3U
#define MENU_COL   1U
#define MENU_ROWS   ( LINES - 2U - MENU_ROW )
#define MENU_COLS   ( COLS - 2U )
#define MENU_PAD   2U

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static void draw_menu_item (struct menu_ui *ui, unsigned int index)
 Draw a numbered menu item.
static void draw_menu_items (struct menu_ui *ui)
 Draw the current block of menu items.
static int menu_loop (struct menu_ui *ui, struct dynamic_item **selected)
 Menu main loop.
int show_menu (struct dynamic_ui *dynui, unsigned long timeout, unsigned long retimeout, const char *select, struct dynamic_item **selected)
 Show menu.

Detailed Description

Menu interface.

Definition in file menu_ui.c.

Macro Definition Documentation

◆ TITLE_ROW

#define TITLE_ROW   1U

Definition at line 44 of file menu_ui.c.

◆ MENU_ROW

#define MENU_ROW   3U

Definition at line 45 of file menu_ui.c.

Referenced by draw_menu_item(), and draw_menu_items().

◆ MENU_COL

#define MENU_COL   1U

Definition at line 46 of file menu_ui.c.

Referenced by draw_menu_item(), and draw_menu_items().

◆ MENU_ROWS

#define MENU_ROWS   ( LINES - 2U - MENU_ROW )

Definition at line 47 of file menu_ui.c.

Referenced by draw_menu_items(), and show_menu().

◆ MENU_COLS

#define MENU_COLS   ( COLS - 2U )

Definition at line 48 of file menu_ui.c.

Referenced by draw_menu_item(), and show_menu().

◆ MENU_PAD

#define MENU_PAD   2U

Definition at line 49 of file menu_ui.c.

Referenced by draw_menu_item(), and draw_menu_items().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ draw_menu_item()

void draw_menu_item ( struct menu_ui * ui,
unsigned int index )
static

Draw a numbered menu item.

Parameters
uiMenu user interface
indexIndex

Definition at line 69 of file menu_ui.c.

69 {
70 struct dynamic_item *item;
71 unsigned int row_offset;
72 char buf[ MENU_COLS + 1 /* NUL */ ];
73 char timeout_buf[6]; /* "(xxx)" + NUL */
74 size_t timeout_len;
75 size_t max_len;
76 size_t len;
77
78 /* Move to start of row */
79 row_offset = ( index - ui->scroll.first );
80 move ( ( MENU_ROW + row_offset ), MENU_COL );
81
82 /* Get menu item */
83 item = dynui_item ( ui->dynui, index );
84 if ( item ) {
85
86 /* Draw separators in a different colour */
87 if ( ! item->name )
89
90 /* Highlight if this is the selected item */
91 if ( index == ui->scroll.current ) {
93 attron ( A_BOLD );
94 }
95
96 /* Construct row */
97 memset ( buf, ' ', ( sizeof ( buf ) - 1 ) );
98 buf[ sizeof ( buf ) -1 ] = '\0';
99 len = strlen ( item->text );
100 max_len = ( sizeof ( buf ) - 1 /* NUL */ - ( 2 * MENU_PAD ) );
101 if ( len > max_len )
102 len = max_len;
103 memcpy ( ( buf + MENU_PAD ), item->text, len );
104
105 /* Add timeout if applicable */
106 timeout_len =
107 snprintf ( timeout_buf, sizeof ( timeout_buf ), "(%ld)",
108 ( ( ui->timeout + TICKS_PER_SEC - 1 ) /
109 TICKS_PER_SEC ) );
110 if ( ( index == ui->scroll.current ) && ( ui->timeout != 0 ) ) {
111 memcpy ( ( buf + MENU_COLS - MENU_PAD - timeout_len ),
112 timeout_buf, timeout_len );
113 }
114
115 /* Print row */
116 printw ( "%s", buf );
117
118 /* Reset attributes */
120 attroff ( A_BOLD );
121
122 } else {
123 /* Clear row if there is no corresponding menu item */
124 clrtoeol();
125 }
126
127 /* Move cursor back to start of row */
128 move ( ( MENU_ROW + row_offset ), MENU_COL );
129}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
long index
Definition bigint.h:65
#define printw(fmt,...)
Definition curses.h:717
static int move(int y, int x)
Definition curses.h:594
#define A_BOLD
Definition curses.h:139
#define color_set(cpno, opts)
Definition curses.h:241
static int clrtoeol(void)
Definition curses.h:554
static int attroff(int attrs)
Definition curses.h:509
static int attron(int attrs)
Definition curses.h:513
ring len
Length.
Definition dwmac.h:226
struct dynamic_item * dynui_item(struct dynamic_ui *dynui, unsigned int index)
Find dynamic user interface item by index.
Definition dynui.c:193
#define CPAIR_SELECT
Highlighted text.
Definition ansicol.h:44
#define CPAIR_NORMAL
Normal text.
Definition ansicol.h:41
#define CPAIR_SEPARATOR
Unselectable text (e.g.
Definition ansicol.h:47
#define TICKS_PER_SEC
Number of ticks per second.
Definition timer.h:16
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define MENU_COL
Definition menu_ui.c:46
#define MENU_COLS
Definition menu_ui.c:48
#define MENU_ROW
Definition menu_ui.c:45
#define MENU_PAD
Definition menu_ui.c:49
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
A dynamic user interface item.
Definition dynui.h:30
const char * text
Text.
Definition dynui.h:36
const char * name
Name.
Definition dynui.h:34
unsigned int first
First visible item.
Definition jumpscroll.h:24
unsigned int current
Currently selected item.
Definition jumpscroll.h:22
struct jump_scroller scroll
Jump scroller.
Definition menu_ui.c:56
struct dynamic_ui * dynui
Dynamic user interface.
Definition menu_ui.c:54
unsigned long timeout
Remaining timeout (0=indefinite)
Definition menu_ui.c:58
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References A_BOLD, attroff(), attron(), clrtoeol(), color_set, CPAIR_NORMAL, CPAIR_SELECT, CPAIR_SEPARATOR, jump_scroller::current, menu_ui::dynui, dynui_item(), jump_scroller::first, index, len, memcpy(), memset(), MENU_COL, MENU_COLS, MENU_PAD, MENU_ROW, move(), dynamic_item::name, NULL, printw, menu_ui::scroll, snprintf(), strlen(), dynamic_item::text, TICKS_PER_SEC, and menu_ui::timeout.

Referenced by draw_menu_items(), menu_loop(), and show_menu().

◆ draw_menu_items()

void draw_menu_items ( struct menu_ui * ui)
static

Draw the current block of menu items.

Parameters
uiMenu user interface

Definition at line 136 of file menu_ui.c.

136 {
137 unsigned int i;
138
139 /* Draw ellipses before and/or after the list as necessary */
141 mvaddstr ( ( MENU_ROW - 1 ), ( MENU_COL + MENU_PAD ),
142 ( jump_scroll_is_first ( &ui->scroll ) ? " " : "..." ) );
144 ( jump_scroll_is_last ( &ui->scroll ) ? " " : "..." ) );
146
147 /* Draw visible items */
148 for ( i = 0 ; i < MENU_ROWS ; i++ )
149 draw_menu_item ( ui, ( ui->scroll.first + i ) );
150}
static int mvaddstr(int y, int x, const char *str)
Definition curses.h:618
static int jump_scroll_is_first(struct jump_scroller *scroll)
Check if jump scroller is currently on first page.
Definition jumpscroll.h:62
static int jump_scroll_is_last(struct jump_scroller *scroll)
Check if jump scroller is currently on last page.
Definition jumpscroll.h:73
static void draw_menu_item(struct menu_ui *ui, unsigned int index)
Draw a numbered menu item.
Definition menu_ui.c:69
#define MENU_ROWS
Definition menu_ui.c:47

References color_set, CPAIR_NORMAL, CPAIR_SEPARATOR, draw_menu_item(), jump_scroller::first, jump_scroll_is_first(), jump_scroll_is_last(), MENU_COL, MENU_PAD, MENU_ROW, MENU_ROWS, mvaddstr(), NULL, and menu_ui::scroll.

Referenced by menu_loop(), and show_menu().

◆ menu_loop()

int menu_loop ( struct menu_ui * ui,
struct dynamic_item ** selected )
static

Menu main loop.

Parameters
uiMenu user interface
Return values
selectedSelected item
rcReturn status code

Definition at line 159 of file menu_ui.c.

159 {
160 struct dynamic_item *item;
161 unsigned long timeout;
162 unsigned int previous;
163 unsigned int move;
164 int key;
165 int chosen = 0;
166 int rc = 0;
167
168 do {
169 /* Record current selection */
170 previous = ui->scroll.current;
171
172 /* Calculate timeout as remainder of current second */
173 timeout = ( ui->timeout % TICKS_PER_SEC );
174 if ( ( timeout == 0 ) && ( ui->timeout != 0 ) )
176 ui->timeout -= timeout;
177
178 /* Get key */
180 key = getkey ( timeout );
181 if ( key < 0 ) {
182 /* Choose default if we finally time out */
183 if ( ui->timeout == 0 )
184 chosen = 1;
185 } else {
186 /* Reset timeout after activity */
187 ui->timeout = ui->retimeout;
188
189 /* Handle scroll keys */
190 move = jump_scroll_key ( &ui->scroll, key );
191
192 /* Handle other keys */
193 switch ( key ) {
194 case ESC:
195 case CTRL_C:
196 rc = -ECANCELED;
197 break;
198 case CR:
199 case LF:
200 chosen = 1;
201 break;
202 default:
203 item = dynui_shortcut ( ui->dynui, key );
204 if ( item ) {
205 ui->scroll.current = item->index;
206 if ( item->name ) {
207 chosen = 1;
208 } else {
210 }
211 }
212 break;
213 }
214 }
215
216 /* Move selection, if applicable */
217 while ( move ) {
218 move = jump_scroll_move ( &ui->scroll, move );
219 item = dynui_item ( ui->dynui, ui->scroll.current );
220 if ( item->name )
221 break;
222 }
223
224 /* Redraw selection if necessary */
225 if ( ( ui->scroll.current != previous ) || ( timeout != 0 ) ) {
226 draw_menu_item ( ui, previous );
227 if ( jump_scroll ( &ui->scroll ) )
228 draw_menu_items ( ui );
229 draw_menu_item ( ui, ui->scroll.current );
230 }
231
232 /* Record selection */
233 item = dynui_item ( ui->dynui, ui->scroll.current );
234 assert ( item != NULL );
235 assert ( item->name != NULL );
236 *selected = item;
237
238 } while ( ( rc == 0 ) && ! chosen );
239
240 return rc;
241}
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
#define ESC
Escape character.
Definition ansiesc.h:93
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
void timeout(int)
struct dynamic_item * dynui_shortcut(struct dynamic_ui *dynui, int key)
Find dynamic user interface item by shortcut key.
Definition dynui.c:212
int getkey(unsigned long timeout)
Get single keypress.
Definition getkey.c:72
#define ECANCELED
Operation canceled.
Definition errno.h:344
unsigned int jump_scroll_move(struct jump_scroller *scroll, unsigned int move)
Move scroller.
Definition jumpscroll.c:93
unsigned int jump_scroll_key(struct jump_scroller *scroll, int key)
Jump scrolling.
Definition jumpscroll.c:43
int jump_scroll(struct jump_scroller *scroll)
Jump scroll to new page (if applicable)
Definition jumpscroll.c:141
#define SCROLL_NONE
Do not scroll.
Definition jumpscroll.h:48
#define SCROLL_DOWN
Scroll down by one line.
Definition jumpscroll.h:54
#define LF
Definition keys.h:48
#define CTRL_C
Definition keys.h:21
#define CR
Definition keys.h:49
static void draw_menu_items(struct menu_ui *ui)
Draw the current block of menu items.
Definition menu_ui.c:136
unsigned int index
Index.
Definition dynui.h:38
unsigned long retimeout
Post-activity timeout (0=indefinite)
Definition menu_ui.c:60

References assert, CR, CTRL_C, jump_scroller::current, draw_menu_item(), draw_menu_items(), menu_ui::dynui, dynui_item(), dynui_shortcut(), ECANCELED, ESC, getkey(), dynamic_item::index, jump_scroll(), jump_scroll_key(), jump_scroll_move(), key, LF, move(), dynamic_item::name, NULL, rc, menu_ui::retimeout, menu_ui::scroll, SCROLL_DOWN, SCROLL_NONE, TICKS_PER_SEC, menu_ui::timeout, and timeout().

Referenced by show_menu().

◆ show_menu()

int show_menu ( struct dynamic_ui * dynui,
unsigned long timeout,
unsigned long retimeout,
const char * select,
struct dynamic_item ** selected )

Show menu.

Parameters
dynuiDynamic user interface
timeoutInitial timeout period, in ticks (0=indefinite)
retimeoutPost-activity timeout period, in ticks (0=indefinite)
Return values
selectedSelected item
rcReturn status code

Definition at line 252 of file menu_ui.c.

254 {
255 struct dynamic_item *item;
256 struct menu_ui ui;
257 char buf[ MENU_COLS + 1 /* NUL */ ];
258 int named_count = 0;
259 int rc;
260
261 /* Initialise UI */
262 memset ( &ui, 0, sizeof ( ui ) );
263 ui.dynui = dynui;
264 ui.scroll.rows = MENU_ROWS;
265 ui.timeout = timeout;
266 ui.retimeout = retimeout;
267
268 list_for_each_entry ( item, &dynui->items, list ) {
269 if ( item->name ) {
270 if ( ! named_count )
271 ui.scroll.current = ui.scroll.count;
272 named_count++;
273 if ( select ) {
274 if ( strcmp ( select, item->name ) == 0 )
275 ui.scroll.current = ui.scroll.count;
276 } else {
277 if ( item->flags & DYNUI_DEFAULT )
278 ui.scroll.current = ui.scroll.count;
279 }
280 }
281 ui.scroll.count++;
282 }
283 if ( ! named_count ) {
284 /* Menus with no named items cannot be selected from,
285 * and will seriously confuse the navigation logic.
286 * Refuse to display any such menus.
287 */
288 return -ENOENT;
289 }
290
291 /* Initialise screen */
292 initscr();
293 start_color();
295 curs_set ( 0 );
296 erase();
297
298 /* Draw initial content */
299 attron ( A_BOLD );
300 snprintf ( buf, sizeof ( buf ), "%s", ui.dynui->title );
301 mvprintw ( TITLE_ROW, ( ( COLS - strlen ( buf ) ) / 2 ), "%s", buf );
302 attroff ( A_BOLD );
303 jump_scroll ( &ui.scroll );
304 draw_menu_items ( &ui );
305 draw_menu_item ( &ui, ui.scroll.current );
306
307 /* Enter main loop */
308 rc = menu_loop ( &ui, selected );
309 assert ( *selected );
310
311 /* Clear screen */
312 endwin();
313
314 return rc;
315}
int erase(void)
Completely clear the screen.
Definition clear.c:98
#define mvprintw(y, x, fmt,...)
Definition curses.h:649
#define start_color()
Definition curses.h:397
#define DYNUI_DEFAULT
Dynamic user interface item is default selection.
Definition dynui.h:46
#define TITLE_ROW
Form title row.
Definition form_ui.c:44
#define ENOENT
No such file or directory.
Definition errno.h:515
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
static int menu_loop(struct menu_ui *ui, struct dynamic_item **selected)
Menu main loop.
Definition menu_ui.c:159
int curs_set(int visibility)
Set cursor visibility.
Definition mucurses.c:154
int select(fd_set *readfds, int wait)
Check file descriptors for readiness.
Definition posix_io.c:229
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
unsigned int flags
Flags.
Definition dynui.h:40
struct list_head items
Dynamic user interface items.
Definition dynui.h:24
A menu user interface.
Definition menu_ui.c:52
#define COLS
Definition vga.h:27
WINDOW * initscr(void)
Initialise console environment.
Definition wininit.c:18
int endwin(void)
Finalise console environment.
Definition wininit.c:32

References A_BOLD, assert, attroff(), attron(), color_set, COLS, jump_scroller::count, CPAIR_NORMAL, jump_scroller::current, curs_set(), draw_menu_item(), draw_menu_items(), menu_ui::dynui, DYNUI_DEFAULT, endwin(), ENOENT, erase(), dynamic_item::flags, initscr(), dynamic_ui::items, jump_scroll(), list_for_each_entry, memset(), MENU_COLS, menu_loop(), MENU_ROWS, mvprintw, dynamic_item::name, NULL, rc, menu_ui::retimeout, jump_scroller::rows, menu_ui::scroll, select(), snprintf(), start_color, strcmp(), strlen(), menu_ui::timeout, timeout(), dynamic_ui::title, and TITLE_ROW.

Referenced by choose_exec().