/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for 
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #                                      
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    Menu.h
    Author:  Copyright  1993, 1994, 1995 Jason Williams
             Thanks to Shaun Blackmore, Tim Browse, and others for various
             bits and pieces, menu template ideas, etc, which were mostly
             not used for this simple implementation, but may be used in
             the future.
    Version: 1.03 (Dec 1994)
    Purpose: Equivalent of RISC OS Lib's "menus" functions - Give a simple
             method for creating and showing menus.

    Notes:   These are simple menu create and show functions along very
             similar lines to RISC OS Lib's 'menu' functions. However, there
             are major differences -
               + menu items are ALWAYS indexed starting from 0.
               + menu pointers point to real Wimp menu structures, no
                 messing about
               + Menu_Show is provided to show the menus for you, including
                 placing a menu in the correct position over the icon bar.
*/


#ifndef __dl_menu_h
#define __dl_menu_h

#ifdef __cplusplus
extern "C" {
#endif


#ifndef __dl_core_h
#include "Core.h"
#endif

#ifndef __dl_wimp_h
#include "Wimp.h"
#endif

#ifndef __dl_event_h
#include "Event.h"
#endif


extern menu_ptr Menu_New(char *title, char *description);
  /*
   *  Creates a new menu. "title" should be no more than 12 characters long
   *  (including the terminator). "description" is a RISC OS Lib style
   *  menu_new() string (Desktop C manual, page 240, but note their syntax
   *  AND their example are both WRONG!), i.e.
   *      opt   :- " "  no special options (i.e. leading spaces are skipped)
   *               "!"  ticked
   *               "~"  shaded
   *               ">"  has submenu/subwindow
   *               "-"  dotted
   *      name  :- any character except "," and "|"
   *      entry :- {opt}* name
   *      sep   :- ","  to separate normal items
   *               "|"  to separate items and place a dotted line between them
   *      descr :- entry {sep entry}*
   *
   *      EXAMPLES:
   *        "!Ticked,~Disabled,>Sub-menu,!~Ticked and disabled, Normal"
   *        ">Info, Create| Quit"         ; info with sublink arrow
   *                                      ; then create, dotted line, quit.
   *
   *  NOTES:
   *    If this call fails (out of malloc memory) then it will call
   *    Error_OutOfMemory() and then return NULL.
   */


extern menu_ptr Menu_Extend(menu_ptr menu, char *description);
  /*
   *  Extends (if possible) the menu by appending the items in "description"
   *  onto the menu structure "menu". If the memory reallocation fails, it
   *  returns the pointer to the old, UNCHANGED menu structure.
   *  "description" is the same as for Menu_New().
   */


extern void Menu_Show(menu_ptr menu, int x, int y);
  /*
   *  Shows the given menu on screen, at the given x and y position.
   *  Set (y = -1) to place the menu at the correct position above the
   *  icon bar.
   */


extern void Menu_ShowLast(void);
  /*
   *  Re-opens the last menu opened (call when a menu item is chosen using
   *  the adjust mouse button to keep the menu open).
   *  Note that if no menu has been opened, or if the last menu opened
   *  has been "dispose"d, this will have bad (dire) results.
   */


extern void Menu_PopUp(menu_ptr menu,window_handle window,icon_handle icon);
  /*
   *  Shows a menu just beside the given icon, as in the Acorn style guide
   *  for popups (who cares if it's a pain in the ass moving the pointer
   *  all the way over there instead of having the menu pop up in a useful
   *  place, right? ;-)
   */

extern void Menu_PopUpAuto(menu_ptr menu);
  /*  PopUpAuto is a variant which determines the icon to use from the
   *  last Wimp event processed (uses Event_ stuff). Useful in a default
   *  handler. If no icon info can be found from the last event, nothing
   *  happens.
   */



extern void Menu_AddSubMenu(menu_ptr menu, int entry, menu_ptr submenu);
  /*
   *  Adds a menu to an existing menu as a submenu at a particular item.
   */


extern void Menu_MakeIndirected(menu_ptr menu, int entry,
                                char *buffer, int size);
  /*
   *  Converts a menu item into an indirected item, setting it to use the
   *  given buffer (thus setting it to use different text)
   *  SeeAlso: Menu_SetText; Menu_ReviseWidth
   */

extern void Menu_MakeWritable(menu_ptr menu, int entry,
                               char *buffer, int size, char *valid);
  /*
   *  Makes a menu item writable. You supply the buffer into which the
   *  menu item data will be written, as well as the size of this buffer
   *  (including terminator), plus the validation string (as in Wimp icons)
   */

extern void Menu_SetFlags(menu_ptr menu, int entry, int ticked, int shaded);
  /*
   *  Alters the state of a menu item. Setting ticked/shaded to 0 will
   *  turn off the tick/make the item selectable. Setting them to 1 will
   *  turn on a tick/make the item unselectable. Values other than 0 and 1
   *  are undefined, so ensure the values you use are 0 and 1.
   */


extern void Menu_GetFlags(menu_ptr menu, int entry, int *ticked, int *shaded);
  /*
   *  Reads the state of a menu item. If ticked/shaded are non-null
   *  pointers then the ints will be updated to reflect the current
   *  state of the menu entry.
   */


extern void Menu_SetText(menu_ptr menu, int entry, char *text);
  /*
   *  Sets the text for a menu entry.  
   *  SeeAlso: Menu_MakeIndirected; Menu_ReviseWidth
   */


extern char *Menu_GetText(menu_ptr menu, int entry);
  /*
   *  Finds the address of the text of a menu entry.
   *  NOTE that this is the actual menu item text buffer, so treat it with
   *  care!
   */


extern int Menu_CalcHeight(menu_ptr menu);
  /*
   *  Calculates the height of a menu in OS coords. For internal use.
   */


#define Menu_SysHandle(menu) (menu)
  /*
   *  Returns a pointer to the 'underlying' Wimp menu definition. In DeskLib
   *  this IS the menu definition.
   */


#define Menu_SDispose(menu) free(menu)
  /*
   *  Frees up the memory used by a menu. Note that this is a simple Dispose
   *  which does not recursively dispose of attached submenus, and does not
   *  dispose of memory used by long (indirected) item text.
   */


extern void Menu_FullDispose(menu_ptr menu);
  /*
   *  Frees up the memory used by a menu. Note that this also
   *  does not recursively dispose of attached submenus.
   *  It does, however, dispose of all indirected menu data
   */


extern void Menu_RemoveItem(menu_ptr menu, int entry);
  /*
   *
   *  Removes a menu item from a menu, shuffling items following it up the
   *  menu. If there is only one item in the menu, nothing happens.
   */



extern void Menu_Warn(menu_ptr menu, int entry, BOOL yesno,
                      event_handler handler, void *reference);
  /*
   *  Sets up the given menu item as needing a message when the user follows
   *  the submenu arrow. If yesno is TRUE, attaches the given handler to
   *  menuwarnings, else releases the handler. Uses EventMsg.
   */


extern void Menu_ReviseWidth(menu_ptr menu);
/*
 *  Revises a menu's width, by scanning through all the items.
 *  The title width is also taken into consideration.
 *  It is assumed that there is AT LEAST ONE item in the menu.
 *
 *  Use it after using Menu_SetText(), or when updating the
 *  contents of an indirected text menu item, ie when having
 *  used Menu_MakeIndirected().
 */


#define	Menu_FirstItem(menu) ((menu_item *) (((menu_ptr) (menu) + 1)))
/*
Very useful macro for messing around with menu_block's.

menu_item *Menu_FirstItem( menu_ptr *menu);
*/



#define Menu_FontMenu_NOTICK      0             /* don't tick anything */
#define Menu_FontMenu_TICKSYSFONT ((char *)1)   /* tick the system font entry */

extern menu_ptr Menu_FontMenu(BOOL sysfont, char *tick);
  /*
   *  Returns a pointer to a font menu, or 0 if it couldn't make one.
   *  Set sysfont to TRUE to add 'System font' at the top of the menu.
   *  Set tick to a font name to tick it, or Menu_FontMenu_<x> for
   *  something else.
   *  Use Menu_FontMenu3 if you don't want the RISC OS 2 compatability
   *  code dragged in. Under RISC OS 2, you get a plain list of fonts
   *  without submenus. If the user has RISC OS 2, it's their own fault,
   *  but at least it'll work.
   */

extern menu_ptr Menu_FontMenu3(BOOL sysfont, char *tick);

extern char *Menu_FontMenuDecode(int *selection);
  /* return pointers to font name given selection of entries within menu
   * or 0 if an error occured 
   * Use MenuFontMenuDecode3 to avoid RISCOS2 compatability code being included
   */

extern char *Menu_FontMenuDecode3(int *selection);




#ifdef _DeskLib_SDLS
  extern menu_ptr   *Menu__Ref_fontmenu( void);
  extern wimp_point *Menu__Ref_currentpos( void);
  extern menu_ptr   *Menu__Ref_currentopen( void);
#endif

#if defined( _DeskLib_SDLS) && !defined( _DeskLib_Menu)

  #define menu_fontmenu    (*Menu__Ref_fontmenu())
  #define menu_currentpos  (*Menu__Ref_currentpos())
  #define menu_currentopen (*Menu__Ref_currentopen())

#else

  extern menu_ptr   menu_fontmenu;
/*
only for comparison with menu_currentopen. This is defined in an
assembler file, so won't work well in the dynamic-linking DeskLib.
*/

  extern wimp_point menu_currentpos; 
/*
holds the x,y position where the last menu was opened. If no menu has
been opened, or the last menu has been disposed, then this values will
be invalid - use with care.
*/

  extern menu_ptr   menu_currentopen; 
/* pointer to the last menu opened. If no menu has been opened, or the
last menu has been disposed, then this values will be invalid - use with
care.
*/
#endif


#ifdef __cplusplus
}
#endif


#endif
