/* menu.h

   This is the universal menu system. "Universal" means that the code in this
   module is designed to manage any menu. The menus themselves can then be
   implemented in separate modules with very little effort.

   This module chains to menuback.c to handle the menu background.

   A menu is stored as an array of BOMB_MENU structs. The end of the array is
   indicated by a null 'draw' proc. Run a menu by calling run_bomb_menu(),
   passing the array and specifying which option should be selected first.
   WARNING: passing the index of a non-option will make the program
   unreliable and must be avoided. The writer of the menu system should
   implement an ASSERT() statement to make sure this does not happen.

   Each struct in the array represents either an option or a non-option. If
   the 'option' field is nonzero (conventionally set to 1), then this is an
   option. Otherwise it is a non-option.

   Non-options are displayed, but otherwise do nothing. They can point to
   options that will be modified while the menu is running, and thus they can
   be used to display information. See menuproc.h for examples on how to do
   this. However, non-options cannot be selected. A 'key' function need not
   be specified (set the field to NULL).

   For both options and non-options, the 'draw' proc is responsible for
   drawing the entry on to the bitmap provided. The 'entry' parameter points
   to the specific object that must be drawn, not the whole array. The
   'selected' parameter is nonzero (1) if the entry is selected, or zero if
   not. You should draw the option differently if it is selected. For
   non-options, the 'selected' parameter will always be zero.

   Options can be selected with the Up and Down Arrow Keys. Hence pressing Up
   or Down must be handled by looping through the menu items, wrapping at the
   end or beginning of the array, until we find an option. You may assume
   that a menu will always contain an option, even if it only says 'Return to
   Main Menu' or similar. That means, when designing a menu, you must make
   sure there is at least one option.

   If Esc is pressed, the menu will terminate.

   When an option is selected, any keys pressed apart from Up, Down and Esc
   will be passed to the 'key' proc. The 'key' proc is guaranteed to be
   specified for an option - use ASSERT() to check it's not NULL, and then
   proceed to call the function. The 'k' parameter is as returned by
   readkey(). This proc is responsible for changing the option if Left or
   Right are pressed, or otherwise dealing with the key or ignoring it. The
   proc does not ever have to worry about redrawing the menu; that will
   happen automatically, since the screen is animated.

   If the 'key' proc returns nonzero, the menu will exit. In all other cases
   it should return zero.

   The 'key' proc may safely recurse, calling run_bomb_menu() on a different
   menu. That is the only reason why the bitmap is passed. run_bomb_menu()
   may simply initiate a new timing loop; the timing loop module is desinged
   to handle this kind of recursion. See timeloop.h.

   x and y are typically used to represent the position of the menu item, but
   you may use them to represent something else if you like. d and dp are
   extra variables to be used for any purpose by the 'draw' function. k and
   kp are likewise for the 'key' function.

   It is recommended that you do not store option values themselves in the
   menus, but rather pointers to the option variables. This eliminates the
   need to access specific indices in the menus, an error-prone technique
   that makes the menus harder to modify.

   See menuproc.h for draw() and key() procs for some common types of option
   and non-option. When designing menus, look here first to see if the object
   you need already exists, or if you could chain to one of these when
   designing your own.
*/

#ifndef INCLUDED_MENU_H
#define INCLUDED_MENU_H

struct BOMB_MENU;

/* The function pointer types are typedeffed. If we ever have to change their
   parameter lists, this reduces the amount of work involved and makes the
   process safer.
*/
typedef void (*MENU_DRAW_PROC)(BITMAP *bmp,
                               struct BOMB_MENU *entry, int selected);

typedef int (*MENU_KEY_PROC)(struct BOMB_MENU *entry, int k);


typedef struct BOMB_MENU {

 int option; /* 1 for an option; 0 for a non-option. */

 MENU_DRAW_PROC draw; /* Set this to null to indicate the end of the menu. */
 int x, y;
 int d;
 void *dp, *dp2;

 MENU_KEY_PROC key;
 int k, k2;
 void *kp;

} BOMB_MENU;


/* These must be called before and after running the main menu.
   A wrapper in m_main.c does this; do not call them from main.c.
   You should not call them when recursing into submenus.
   You must also call the shutdown function before running the game,
   and the initialise function afterwards.
*/
void initialise_menu_system(void);
void shut_down_menu_system(void);

void run_bomb_menu(BOMB_MENU *menu, int selection);

#endif /* INCLUDED_MENU_H */
