[dynui] Generalise mechanisms for looking up user interface items

Generalise the ability to look up a dynamic user interface item by
index or by shortcut key, to allow for reuse of this code for
interactive forms.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
diff --git a/src/core/dynui.c b/src/core/dynui.c
index 6e053b9..33218f5 100644
--- a/src/core/dynui.c
+++ b/src/core/dynui.c
@@ -131,6 +131,7 @@
 	}
 	strcpy ( text_copy, text );
 	item->text = text_copy;
+	item->index = dynui->count++;
 	item->shortcut = shortcut;
 	item->is_default = is_default;
 
@@ -180,3 +181,40 @@
 
 	return NULL;
 }
+
+/**
+ * Find dynamic user interface item by index
+ *
+ * @v dynui		Dynamic user interface
+ * @v index		Index
+ * @ret item		User interface item, or NULL if not found
+ */
+struct dynamic_item * dynui_item ( struct dynamic_ui *dynui,
+				   unsigned int index ) {
+	struct dynamic_item *item;
+
+	list_for_each_entry ( item, &dynui->items, list ) {
+		if ( index-- == 0 )
+			return item;
+	}
+
+	return NULL;
+}
+
+/**
+ * Find dynamic user interface item by shortcut key
+ *
+ * @v dynui		Dynamic user interface
+ * @v key		Shortcut key
+ * @ret item		User interface item, or NULL if not found
+ */
+struct dynamic_item * dynui_shortcut ( struct dynamic_ui *dynui, int key ) {
+	struct dynamic_item *item;
+
+	list_for_each_entry ( item, &dynui->items, list ) {
+		if ( key && ( key == item->shortcut ) )
+			return item;
+	}
+
+	return NULL;
+}
diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c
index ab4e602..00cdab8 100644
--- a/src/hci/tui/menu_ui.c
+++ b/src/hci/tui/menu_ui.c
@@ -58,25 +58,6 @@
 };
 
 /**
- * Return a numbered menu item
- *
- * @v dynui		Dynamic user interface
- * @v index		Index
- * @ret item		Menu item, or NULL
- */
-static struct dynamic_item * menu_item ( struct dynamic_ui *dynui,
-					 unsigned int index ) {
-	struct dynamic_item *item;
-
-	list_for_each_entry ( item, &dynui->items, list ) {
-		if ( index-- == 0 )
-			return item;
-	}
-
-	return NULL;
-}
-
-/**
  * Draw a numbered menu item
  *
  * @v ui		Menu user interface
@@ -96,7 +77,7 @@
 	move ( ( MENU_ROW + row_offset ), MENU_COL );
 
 	/* Get menu item */
-	item = menu_item ( ui->dynui, index );
+	item = dynui_item ( ui->dynui, index );
 	if ( item ) {
 
 		/* Draw separators in a different colour */
@@ -178,7 +159,6 @@
 	unsigned int previous;
 	unsigned int move;
 	int key;
-	int i;
 	int chosen = 0;
 	int rc = 0;
 
@@ -217,15 +197,9 @@
 				chosen = 1;
 				break;
 			default:
-				i = 0;
-				list_for_each_entry ( item, &ui->dynui->items,
-						      list ) {
-					if ( ! ( item->shortcut &&
-						 ( item->shortcut == key ) ) ) {
-						i++;
-						continue;
-					}
-					ui->scroll.current = i;
+				item = dynui_shortcut ( ui->dynui, key );
+				if ( item ) {
+					ui->scroll.current = item->index;
 					if ( item->name ) {
 						chosen = 1;
 					} else {
@@ -239,7 +213,7 @@
 		/* Move selection, if applicable */
 		while ( move ) {
 			move = jump_scroll_move ( &ui->scroll, move );
-			item = menu_item ( ui->dynui, ui->scroll.current );
+			item = dynui_item ( ui->dynui, ui->scroll.current );
 			if ( item->name )
 				break;
 		}
@@ -253,7 +227,7 @@
 		}
 
 		/* Record selection */
-		item = menu_item ( ui->dynui, ui->scroll.current );
+		item = dynui_item ( ui->dynui, ui->scroll.current );
 		assert ( item != NULL );
 		assert ( item->name != NULL );
 		*selected = item;
diff --git a/src/include/ipxe/dynui.h b/src/include/ipxe/dynui.h
index 25124a3..f38d448 100644
--- a/src/include/ipxe/dynui.h
+++ b/src/include/ipxe/dynui.h
@@ -21,6 +21,8 @@
 	const char *title;
 	/** Dynamic user interface items */
 	struct list_head items;
+	/** Number of user interface items */
+	unsigned int count;
 };
 
 /** A dynamic user interface item */
@@ -31,6 +33,8 @@
 	const char *name;
 	/** Text */
 	const char *text;
+	/** Index */
+	unsigned int index;
 	/** Shortcut key */
 	int shortcut;
 	/** Is default item */
@@ -44,6 +48,10 @@
 					      int is_default );
 extern void destroy_dynui ( struct dynamic_ui *dynui );
 extern struct dynamic_ui * find_dynui ( const char *name );
+extern struct dynamic_item * dynui_item ( struct dynamic_ui *dynui,
+					  unsigned int index );
+extern struct dynamic_item * dynui_shortcut ( struct dynamic_ui *dynui,
+					      int key );
 extern int show_menu ( struct dynamic_ui *dynui, unsigned long timeout,
 		       const char *select, struct dynamic_item **selected );