home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / sys / acorn / tech / 1182 < prev    next >
Encoding:
Internet Message Format  |  1993-01-07  |  19.0 KB

  1. Path: sparky!uunet!wupost!waikato.ac.nz!aukuni.ac.nz!cs18.cs.aukuni.ac.nz!jwil1
  2. Newsgroups: comp.sys.acorn.tech
  3. Subject: (long) Better definition of what menu template should do
  4. Message-ID: <1993Jan7.213310.16932@cs.aukuni.ac.nz>
  5. From: jwil1@cs.aukuni.ac.nz (TMOTA)
  6. Date: Thu, 7 Jan 1993 21:33:10 GMT
  7. Sender: jwil1@cs.aukuni.ac.nz (TMOTA)
  8. Organization: Computer Science Dept. University of Auckland
  9. Lines: 460
  10.  
  11. Ah... I've just found that file I was working on a while back.
  12.  
  13. This is a menu template system that I've designed around a text-file
  14. (i.e. easily editable) format for my own use. The main idea of this
  15. one is to give all the features listed below, while being small and
  16. reasonably efficient to implement, and easy and convenient to use from
  17. within your program. The text file format is very simple so as to
  18. force minimal parsing code on the application. Obviously a Glass file
  19. binary format for this data will reducethe file size and the amount of
  20. loading-support-code needed.
  21.  
  22. Hopefully this will explain all the details of what I want out of a
  23. menu template system a bit better... Obviously the actual syntax of the
  24. file is of little relevance, but it still serves to illustrate the ideas.
  25.  
  26. (sorry, 2400bps users, but it's a bit long)
  27.  
  28. ---
  29.  
  30.                  The Menu Template System
  31.                 by  Jason Williams
  32.  
  33. We already use template files containing definitions for windows in our
  34. applications: They make life much quicker and easier for the programmer,
  35. and allow the user to alter the layout of windows (at least to some extent)
  36. to suit themselves.
  37.  
  38. However, a startling omission from RISC OS is the lack of a similar function
  39. for definition of menu structures. Partially this stems from the dynamic
  40. nature allowed by the menu system, but I feel it is mostly caused by laziness
  41. and mis-design of menus...
  42.  
  43. In most cases, menus can be designed as fixed entities, with an occasional
  44. menu (a font list, for example) being created 'on the fly'. Much of the
  45. data-entry of menu items *should* be placed into dialogue boxes which are
  46. available in a menu, and by clicking a menu item, and by pressing a certain
  47. key-combination. Some other data may be placed as a group of 'tickable' menu
  48. items, in which the programmer currently has to do all the work of only
  49. allowing one item to be ticked at once. Another failing in many applications
  50. is that when they shade (make unselectable) an item which leads to a submenu,
  51. the submenu can no longer be brought up in order to see what is in it.
  52.  
  53. The menu template system is a C code library which solves all of these
  54. problems in one go. It goes further than any attempt I have ever seen to
  55. provide a menu-template system.
  56.  
  57. The template system, as well as providing an automated system by which menu
  58. templates can be loaded, and used to create menu trees, also gives functions
  59. which automatically handle menus in useful ways, and make menu decoding much
  60. simpler for the programmer.
  61.  
  62. The fundamental concepts behind the template system are:
  63.   * Text file (easily read/edited) contains the templates
  64.   * Intermediate interface between the user, the OS and the program, with
  65.     the program using tags to which menu items are attached, and the user
  66.     being free to edit item data. Thus, the program doesn't have to worry
  67.     about what language the menus are displaying, or where in the menu tree
  68.     an item was when it was selected: A unique tag allows the user to move
  69.     any item anywhere, and it will still operate as normal.
  70.   * Extra automated handling to ease the work of the programmer. Correct
  71.     menu shading and tickable-item e.s.g. handling are provided.
  72.  
  73. ---
  74.  
  75. Menu template file syntax
  76. =========================
  77.  
  78. COMMENTS
  79.   Blank lines, and any line whose first non-blank character is a '#' will
  80.   be treated as comments. Everything on a line after a '#' will be ignored,
  81.   excepting if the '#' appears in a string (between a pair of double quotes)
  82.  
  83.  
  84. TAGS
  85. Menus and their items are referred to using tags. For speed and simplicity
  86. these tags are 4 characters long, and are handled by the loading code in
  87. such a way as to allow
  88.   definition in file:  tag1
  89.   comparison in C:     if (thetag == 'tag1')
  90.                switch (thetag)
  91.                {
  92.              case 'tag1':
  93.              case 'tag2':
  94.                }
  95. which really is extremely convenient.
  96. Tags can be defined as less than 4 characters, in which case, they will be
  97. padded out with space characters, so t1 will become the tag 't1  '.
  98.  
  99. Item tags are localised within each menu definition, but *PLEASE* use
  100. globally unique tags for menu items. This will allow you to act on a
  101. selection of any menu item regardless of where it was situated in any menu
  102. tree. The user could then edit your menus to look completely different,
  103. split menus, and generally rearrange anything anywhere anytime, and your
  104. application would continue to run correctly, completely unaffected (except
  105. for the external menu interface for the user).
  106. This will also improve the chances of porting this code to work as an
  107. interface layer for other operating systems so that porting RISC OS WIMP
  108. applications to other WIMPs might be made easier.
  109.  
  110. Menu tags should be different from all other menu tags, but need not be
  111. different from item tags.
  112.  
  113.  
  114. MENU
  115. A menu is a set of n items, with a header containing the menu tag, the
  116. title text, and the number of items in the menu. NOTE that the numitems
  117. value can be larger than the menu needs (for future menu adjustment), but
  118. must not be smaller.
  119. Each entry must be on a single separate line as shown:
  120.  
  121.   menu   = MENU tag:4 "title" numitems
  122.          item
  123.          item
  124.          ...
  125.        ENDMENU
  126.  
  127.  
  128. ITEM
  129. Each item specifies the item tag, item text, and a set of space-separated
  130. flags.
  131.  
  132.   item   = ITEM tag:4 text [flags]
  133.  
  134.  
  135. The text is an arbitrary string contained within double quotes (double quotes
  136. not allowed within the string: tough titty). For a writable icon, this string
  137. is used as the default text.
  138.  
  139.   text   = "any string"
  140.  
  141. The flags are explained in detail below.
  142. Each flag is separated by a space.
  143. A summary of the flags is:
  144.  
  145.   flags    >                                    ; has subwindow
  146.        >menu                                ; has submenu "menu"
  147.        _                                    ; dotted line after this item
  148.        -                                    ;   "
  149.        T01+                                 ; this item is tickable, with
  150.                         ; esg number 1 & is ticked
  151.        K020                                 ; Key equivalent (decimal)
  152.        ?6                                   ; Writable, 6 chars allowed
  153.        S                                    ; Shaded
  154.  
  155. Full flag descriptions:
  156. >
  157.   This specifies that the item should have a sublink arrow and generate a
  158.   sublink message, for the program to provide the appropriate window.
  159.  
  160. >menu
  161.   This specifies that this item will bring up the named submenu.
  162.  
  163. _ or -
  164.   This specifies that the item is followed by a dotted line
  165.   This may also be used on it's own on a line to indicate the same.
  166.   (Everything after the first _ or - will be ignored)
  167.  
  168. T00+
  169.   This specifies that the item is tickable.
  170.   The following decimal number (not optional) specifies the esg number for the
  171.   tick. Values from 0 to 250 are allowed (251-255 are used internally as
  172.   special values, so do not use them). The esg number of 0 is special,
  173.   indicating no esg - the item is unrelated to any other items.
  174.   ESGs are localised to within one (sub)menu definition.
  175.   Optionally, this can be followed by a + which indicates that the item is
  176.   ticked. If no + is present, the item is not ticked.
  177.  
  178. K020
  179.   This specifies the decimal wimp keycode for the key equivalent.
  180.   You should also set the item text to show this key equivalent to the right
  181.   side of the menu, in the standard format.
  182.  
  183. ?6
  184.   This indicates that the item is writable, with a maximum of 6 characters
  185.   allowed in it. NOTE: This doesn't count the terminator (as the WIMP does),
  186.   so 6 means allow up to 6 characters to be entered.
  187.  
  188. S
  189.   This indicates that the item should be shaded by default.
  190.   (NOTE: If this item also has a submenu, the item will be made grey but will
  191.   remain selectable in order to allow users to see the submenu. If such an
  192.   item is shaded, all items below it recursively will be shaded as well, in
  193.   the internal database, though, this 'global' shading is kept separate from
  194.   individual item shading so that unshading a menu item will restore the
  195.   previous single-item shading in the submenu.)
  196.  
  197.  
  198. QUICKKEYS
  199. This extra feature has been added, as it is very esy to integrate, and saves
  200. extra work along similar lines in another portion of your code.
  201. The quickkeys segment of the template file MUST be the last thing in the file
  202. (i.e. no menu definitions may follow it)
  203.  
  204. It simply defines a set of mappings between tags and WIMP key codes. These
  205. are stored by the Menu manager, and when you request a check for a quickkey,
  206. the menu manager scans all the quick-keys in the menu items it owns, as well
  207. as the quick-key list. If any quick-key is matched, it's tag will be returned
  208. to your menu-selection handler. Thus, all possible functions should be given
  209. a unique tag and be connected by it into your menu-selection handler, so that
  210. your program becomes a simple macro processor (in future a scheme may be
  211. added whereby several tags may be attached to a keypress, such that a single
  212. keypress will be able to perform the equivalent of several menu selections
  213. in sequence) 
  214.  
  215.  
  216. Example:
  217.   menu save "Save format" 2                # Save submenu, 2 items
  218.     item sav1 "Armadeus   " > S            # Shaded, has a sub-window
  219.     item sav2 "DataVox    " >              # Has a sub-window
  220.   endmenu
  221.  
  222.   menu optn "Options" 3                    # Options submenu, 3 items
  223.     item opt1 "Type 1" T01                 # Tickable, esg = 1, not ticked
  224.     item opt2 "Type 2" T01+                # Tickable, esg = 1, ticked
  225.     item opt3 "Thingo" T00+                # Tickable, NO esg,  ticked
  226.   endmenu
  227.  
  228.   menu main "DSEdit II" 8                  # Main menu, up to 8 items long
  229.     info "Info     ^I" K009 >              # Key equiv. 9 (ctrl-I), subwindow
  230.       -----------                      # ...with dotted line underneath
  231.     optn "Options    " >optn S             # optn (options) submenu, shaded
  232.     save "Save       " >save               # save (save format) submenu
  233.       -----------                      # ...with dotted line underneath
  234.     quit "Quit       "                     # Nothing special about this item
  235.   endmenu
  236.  
  237.   quickkeys                                # This must be last thing in file
  238.     ok K13                                 # "OK" key is return
  239.     canc K27                               # "Cancel" key is escape
  240.  
  241.  
  242. Will generate this set of menus:
  243.  +---------------+
  244.  |  DSEdit II    |
  245.  +---------------+
  246.  | Info    ^I => | -> to Info window
  247.  | - - - - - - - | +---------+
  248.  | Options    => | | Options | +-------------+
  249.  | Save       => | +---------+ | Save format |
  250.  | - - - - - - - | | Type 1  | +-------------+
  251.  | Quit          | |/Type 2  | | Armadeus => | -> to save-as window
  252.  +---------------+ |/Thingo  | | DataVox  => | -> to save-as window
  253.            +---------+ +-------------+
  254. The options submenu will automatically pop up from the "Options" item if you
  255. move the pointer over the arrow.
  256. The Save format submenu will automatically pop up from the "Save" item...
  257.  
  258. As well as generating the menus, the above template will set up information
  259. needed ny the handers to handle various things such as ticked items, shading,
  260. submenu linking, and quick-keys automatically.
  261.  
  262. ---
  263.  
  264. Supplied Functions
  265. ==================
  266.  
  267.   Menu_Init(void)
  268.     Initialises the menu system. Call this once (only) before you call any
  269.     other menu functions. If not called, effects are unpredictable.
  270.  
  271.   BOOL Menu_LoadTemplates(char *filename)
  272.     Loads all menus from the given template file, allocating exactly the
  273.     needed space. Returns TRUE if it succeeds, FALSE if it fails.
  274.  
  275.   Menu_ReleaseTemplates()
  276.     Deallocates the memory used by ALL the menus.
  277.  
  278.   Menu_Show(menutag menu, BOOL iconbar)
  279.     Creates and opens the menu structure requested. If iconbar == TRUE, then
  280.     the menu is placed at the correct height above the iconbar, else it is
  281.     placed at the current mouse pointer position.
  282.  
  283.   Menu_Reopen()
  284.     Re-opens the last menu created. Internal call called by Menu_Decode when
  285.     an adjust-click is used on a menuitem.
  286.  
  287.   Menu_Decode(wimp_eventstr *event, menutag *menu, menutag *item)
  288.     When you recieve a menu selection (9) event from the WIMP, for a menu
  289.     you opened with a Menu_Open() call, call this function, which will decode
  290.     the event into menu and item tags.
  291.  
  292.     If the item tag returned is menu_INVALID, ignore the event (do nothing)
  293.     -This can occur from invalid selections and most notably from greyed
  294.     items that have been left selectable to allow the user to see submenus.
  295.     The menu decoder will work out if the selection is valid for you.
  296.  
  297.     Upon receipt, use the *item* tag to determine your action. If *absolutely*
  298.     necessary, you can use the menu tag for this determination, but this will
  299.     remove the ability for anyone to move items to arbitrary positions in
  300.     the menu tree (Also, try to use globally unique tags, although this is
  301.     not enforced by the menu code). The menu tag returned is meant to only
  302.     be used if it is necessary to tick/shade the item or read data from a
  303.     writable...
  304.  
  305.   Menu_CheckKey(wimp_eventstr *event, menutag *menu, menutag *item)
  306.     When you recieve a keypress event from the WIMP, call this function to
  307.     check for quick-keys after checking any more important keypresses. If
  308.     it returns values other than menu_INVALID for the menu/item, then a
  309.     quick-key is being requested, and you should pass these tags to the
  310.     same handling code that you call on a menu selection event.
  311.  
  312.   Menu_ShadeItem(menutag menu, menutag item, BOOL shaded)
  313.     Shades/unshades the given menuitem. Two different shading values are used
  314.     by the menu system (really shaded, and just greyed out so that submenus can
  315.     still be seen). The menu system will not return a click on either type
  316.     of shaded icon. Shading/unshading an item in a globally-shaded menu will
  317.     alter the internal database, but will only have a noticable effect when the
  318.     entre menu is globally-un-shaded.
  319.  
  320.   Menu_TickItem(menutag menu, menutag item, BOOL ticked)
  321.     Ticks/unticks the menu item, with the following provisos:
  322.     * Won't alter an untickable item
  323.     * Will only untick an item with esg 0, which indicates it is a 'loner'.
  324.       If the item is part of an esg group, it will be ticked regardless.
  325.     * Will search for other items of the same esg in the submenu, and will
  326.       untick them, guaranteeing that only one of them is ever ticked.
  327.  
  328.   Menu_SetWritable(menutag menu, menutag item, char *newtext)
  329.     Will set the text in a writable menu item to the given text. It will be
  330.     truncated if necessary to fit the template buffer size.
  331.  
  332.   char *Menu_ReadWritable(menutag menu, menutag item)
  333.     Returns a pointer to the text buffer of the writable. This should ONLY
  334.     be treated as a read-only resource. Use the above call if you wish to
  335.     write to this buffer. If you want to use/alter the text, make a copy
  336.     of the string to your own workspace.
  337.  
  338. Attaching your own submenus/tweaking the WIMP menu data
  339. If you want a dynamic menu (e.g. a font list) anywhere in your menus, you
  340. must create it separately yourself, and then attach it to the Menu_()
  341. created menu tree manually. If you want to 'twiddle' any of the base WIMP
  342. menu items (as passed to Wimp_CreateMenu), then you also need to build and
  343. show the menu in two steps.
  344.  
  345. Example of adding a submenu:
  346.   mainmenu = Menu_Build("main");     /* Create the main menu structure       */
  347.   itemptr  = Menu_ReturnAddress("show","font");
  348.                      /* find the "Show => Font" submenu item */
  349.   menuptr  = Create_My_Font_Menu();  /* Create the font submenu              */
  350.   itemptr->sublink = menuptr;        /* Link it in as this item's submenu    */
  351.   Menu_Open(mainmenu, FALSE);
  352.  
  353. Changing other data for an item is a very similar process to the above.
  354.  
  355.   menu_block *Menu_Build(menutag menu)
  356.     Recursively builds the given menu structure, returning a pointer to
  357.     the WIMP menu definition block. You'll have to use Menu-ReturnAddress
  358.     to chain down the menu structure to a leaf-item where you can attach
  359.     your own submenu (e.g. a font menu), or you can attach this menu tree
  360.     as a subtree of your own menu...
  361.  
  362.   Menu_ReturnAddress(menutag menu, menutag item)
  363.     Returns the address of the last place to which this item was 'built'.
  364.     (So be careful to only use this call when the menu has just been built)
  365.     You can then modify the item's WIMP data directly to tweak things, attach
  366.     your own dynamic submenus, etc.
  367.     If the item tag passed in is menu_INVALID, the address of the menu header
  368.     will be returned instead.
  369.  
  370.   Menu_Open(menu_block *menu, BOOL iconbar)
  371.     Opens the WIMP menu defined in the given block under the pointer. If
  372.     iconbar == TRUE, then it is opened at the appropriate height above the
  373.     icon bar.
  374.     
  375. ---
  376.  
  377. Internal Data Structures
  378. ========================
  379.  
  380. /* Actual WIMP menu blocks... */
  381. typedef struct
  382. {
  383.   unsigned int ticked    : 1;
  384.   unsigned int dotted    : 1;
  385.   unsigned int writable  : 1;
  386.   unsigned int reserved1 : 4;
  387.   unsigned int lastitem  : 1;
  388.   unsigned int reserved2 : 24;
  389. } menu_flags
  390.  
  391.  
  392. typedef union
  393. {
  394.   int              value;
  395.   window_handle    window;
  396.   struct menu_item *submenu;
  397. }
  398.  
  399.  
  400. typedef struct
  401. {
  402.   menu_flags   flags;
  403.   menu_sublink sublink;
  404.   icon_flags   iconflags;
  405.   icon_data    data;
  406. } menu_item;
  407.  
  408.  
  409. typedef struct
  410. {
  411.   char title[12];
  412.   int  colours;
  413.   int  width;
  414.   int  height;
  415.   int  gap;
  416.   /* menu_item items[]; */
  417. } menu_block;
  418.  
  419.  
  420. /* New structures for holding augmented menu structures... */
  421.  
  422. /*  ESG numbers: 0 means this is tickable, but not in any ESG (a loner)
  423.  *               250-254 are reserved for future expansion
  424.  *               255 means this is not tickable
  425.  */
  426. #define ESG_LONER  0
  427. #define ESG_NOTICK 255
  428.  
  429. #define menu_INVALID 0;
  430. typedef int menutag;
  431.  
  432. typedef struct
  433. {
  434.   unsigned int shaded    :1;    /* greyed and unselectable          */
  435.   unsigned int greyed    :1;    /* greyed, but still selectable     */
  436.   unsigned int writable  :1;    /* Item is writable                 */
  437.   unsigned int ticked    :1;    /* This item is ticked              */
  438.  
  439.   unsigned int lastitem  :1;    /* This is the last valid menu item */
  440.  
  441.   unsigned int reserved1 :3;
  442.  
  443.   unsigned int tickesg   :8;    /* Tickable esg number (see above)  */
  444.   unsigned int buffsize  :8;    /* Writable maximum text length     */
  445.  
  446.   unsigned int reserved2 :8;
  447. } menuflags;
  448.  
  449.  
  450. typedef struct
  451. {
  452.   menutag   tag;
  453.   menutag   sublink;             /* Either menu tag or SUBWINDOW             */
  454.   char      *text;               /* Pointer to text/writable buffer          */
  455.   menuflags flags;
  456.   menu_item *lastaddress;        /* Ptr to last place WIMP item for this was */
  457. } menuentry;
  458.  
  459.  
  460. typedef struct
  461. {
  462.   menutag    tag;
  463.   char       *title;
  464.   menu_block *lastaddress;       /* Ptr to last place WIMP defn for this was */
  465.   char       numitems;           /* Max. # of items: size of allocated array */
  466.   char       menuwidth;          /* Menu width (in characters)               */
  467.   menuentry  *items;             /* Pointer to array of items                */
  468. } menuheader;
  469. -- 
  470. themasterofthearcanejwil1@cs.aukuni.ac.nzthismessagewassentonrecycledelectrons
  471.