summaryrefslogtreecommitdiffstats
path: root/src/core/menu.c
diff options
context:
space:
mode:
authorMichael Brown2012-03-27 18:27:27 +0200
committerMichael Brown2012-03-29 14:44:48 +0200
commit0d2fba2887a78b8bc4cd0d7fc6946d001075d92f (patch)
tree544a87c6d6a994c1bfd4824df7b9b1e0281b5b24 /src/core/menu.c
parent[bios] Recognise Page Up and Page Down keys (diff)
downloadipxe-0d2fba2887a78b8bc4cd0d7fc6946d001075d92f.tar.gz
ipxe-0d2fba2887a78b8bc4cd0d7fc6946d001075d92f.tar.xz
ipxe-0d2fba2887a78b8bc4cd0d7fc6946d001075d92f.zip
[menu] Add the abstract concept of a menu
Inspired-by: Robin Smidsrød <robin@smidsrod.no> Tested-by: Robin Smidsrød <robin@smidsrod.no> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core/menu.c')
-rw-r--r--src/core/menu.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/core/menu.c b/src/core/menu.c
new file mode 100644
index 00000000..1d1678f3
--- /dev/null
+++ b/src/core/menu.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Menu selection
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ipxe/list.h>
+#include <ipxe/menu.h>
+
+/** List of all menus */
+static LIST_HEAD ( menus );
+
+/**
+ * Create menu
+ *
+ * @v name Menu name, or NULL
+ * @v title Menu title, or NULL
+ * @ret menu Menu, or NULL on failure
+ */
+struct menu * create_menu ( const char *name, const char *title ) {
+ size_t name_len;
+ size_t title_len;
+ size_t len;
+ struct menu *menu;
+ char *name_copy;
+ char *title_copy;
+
+ /* Destroy any existing menu of this name */
+ menu = find_menu ( name );
+ if ( menu )
+ destroy_menu ( menu );
+
+ /* Use empty title if none given */
+ if ( ! title )
+ title = "";
+
+ /* Allocate menu */
+ name_len = ( name ? ( strlen ( name ) + 1 /* NUL */ ) : 0 );
+ title_len = ( strlen ( title ) + 1 /* NUL */ );
+ len = ( sizeof ( *menu ) + name_len + title_len );
+ menu = zalloc ( len );
+ if ( ! menu )
+ return NULL;
+ name_copy = ( ( void * ) ( menu + 1 ) );
+ title_copy = ( name_copy + name_len );
+
+ /* Initialise menu */
+ if ( name ) {
+ strcpy ( name_copy, name );
+ menu->name = name_copy;
+ }
+ strcpy ( title_copy, title );
+ menu->title = title_copy;
+ INIT_LIST_HEAD ( &menu->items );
+
+ /* Add to list of menus */
+ list_add_tail ( &menu->list, &menus );
+
+ DBGC ( menu, "MENU %s created with title \"%s\"\n",
+ menu->name, menu->title );
+
+ return menu;
+}
+
+/**
+ * Add menu item
+ *
+ * @v menu Menu
+ * @v label Label, or NULL
+ * @v text Text, or NULL
+ * @v shortcut Shortcut key
+ * @v is_default Item is the default item
+ * @ret item Menu item, or NULL on failure
+ */
+struct menu_item * add_menu_item ( struct menu *menu, const char *label,
+ const char *text, int shortcut,
+ int is_default ) {
+ size_t label_len;
+ size_t text_len;
+ size_t len;
+ struct menu_item *item;
+ char *label_copy;
+ char *text_copy;
+
+ /* Use empty text if none given */
+ if ( ! text )
+ text = "";
+
+ /* Allocate item */
+ label_len = ( label ? ( strlen ( label ) + 1 /* NUL */ ) : 0 );
+ text_len = ( strlen ( text ) + 1 /* NUL */ );
+ len = ( sizeof ( *item ) + label_len + text_len );
+ item = zalloc ( len );
+ if ( ! item )
+ return NULL;
+ label_copy = ( ( void * ) ( item + 1 ) );
+ text_copy = ( label_copy + label_len );
+
+ /* Initialise item */
+ if ( label ) {
+ strcpy ( label_copy, label );
+ item->label = label_copy;
+ }
+ strcpy ( text_copy, text );
+ item->text = text_copy;
+ item->shortcut = shortcut;
+ item->is_default = is_default;
+
+ /* Add to list of items */
+ list_add_tail ( &item->list, &menu->items );
+
+ return item;
+}
+
+/**
+ * Destroy menu
+ *
+ * @v menu Menu
+ */
+void destroy_menu ( struct menu *menu ) {
+ struct menu_item *item;
+ struct menu_item *tmp;
+
+ /* Remove from list of menus */
+ list_del ( &menu->list );
+
+ /* Free items */
+ list_for_each_entry_safe ( item, tmp, &menu->items, list ) {
+ list_del ( &item->list );
+ free ( item );
+ }
+
+ /* Free menu */
+ free ( menu );
+}
+
+/**
+ * Find menu
+ *
+ * @v name Menu name, or NULL
+ * @ret menu Menu, or NULL if not found
+ */
+struct menu * find_menu ( const char *name ) {
+ struct menu *menu;
+
+ list_for_each_entry ( menu, &menus, list ) {
+ if ( ( menu->name == name ) ||
+ ( strcmp ( menu->name, name ) == 0 ) ) {
+ return menu;
+ }
+ }
+
+ return NULL;
+}