Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[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>
- Loading branch information
Showing
2 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#ifndef _IPXE_MENU_H | ||
#define _IPXE_MENU_H | ||
|
||
/** @file | ||
* | ||
* Menu selection | ||
* | ||
*/ | ||
|
||
FILE_LICENCE ( GPL2_OR_LATER ); | ||
|
||
#include <ipxe/list.h> | ||
|
||
/** A menu */ | ||
struct menu { | ||
/** List of menus */ | ||
struct list_head list; | ||
/** Name */ | ||
const char *name; | ||
/** Title */ | ||
const char *title; | ||
/** Menu items */ | ||
struct list_head items; | ||
}; | ||
|
||
/** A menu item */ | ||
struct menu_item { | ||
/** List of menu items */ | ||
struct list_head list; | ||
/** Label */ | ||
const char *label; | ||
/** Text */ | ||
const char *text; | ||
/** Shortcut key */ | ||
int shortcut; | ||
/** Is default item */ | ||
int is_default; | ||
}; | ||
|
||
extern struct menu * create_menu ( const char *name, const char *title ); | ||
extern struct menu_item * add_menu_item ( struct menu *menu, const char *label, | ||
const char *text, int shortcut, | ||
int is_default ); | ||
extern void destroy_menu ( struct menu *menu ); | ||
extern struct menu * find_menu ( const char *name ); | ||
|
||
#endif /* _IPXE_MENU_H */ |