Next: Menu Attributes, Previous: Menu Interaction, Up: Menu Object [Contents][Index]

#### 23.2.4 Other Menu Routines

There are two ways to populate a menu, i.e., add items. The first one is a bit more complex but allows for more flexibility, e.g., later adding and removing items, associating callbacks with individual items etc. For the more simple (and in many cases sufficient) method see the function `fl_set_menu_entries()`.

To set the actual menu for a menu object, use the routine

    void fl_set_menu(FL_OBJECT *obj, const char *menustr, ...);

`menustr` describes the menu in the form used by XPopups (see XPopup). In the simplest case it just contains the texts for the menu items, separated by a bar (`'|'`), e.g., `"First|Second|Third"`. But it’s also possible to employ special tags (see Creating XPopups) that can be used to indicate special attributes (radio, toggle and greyed-out, for example). For this usage the unspecified arguments (the `...` in the function call) can be used t add neceassary information. Whenever the user selects a menu item, a pointer to the menu object it belongs to is returned to the application program.

Please note that if you call `fl_set_menu()` on a menu that already contains items the existing items are replaced by the new ones - the function calls `fl_clear_menu()` internally before the new items are added.

If you explicitely assign a menu item ID to a menu, using the special tag `%x`, it is your responsibility to make sure that this ID isn’t already used by a different menu item in the same menu. Failure to do so may make it impossible to use the menu properly. All functions working on items expect the menu item ID as one of their arguments. Also note that only values that fit into a `char` can be used, so the range is restricted to the interval `[-128, 127]` on most machines with a signed `char` type and to `[0, 255]` on those with an unsigned `char` type. For portability reasons it’s thus to be recommended to restrict the range to `[0, 127]`.

In case you don’t set menu item IDs they are assigned automatically with the first item obtaining the menu item ID 1, the next 2 etc., i.e., it directly reflects the position of the item in the menu.

It is also possible to add menu items to an existing menu using a call of

    int fl_addto_menu(FL_OBJECT *obj, const char *menustr, ...);

where `menustr` is a string of the same form as used in `fl_set_menu()` (you can add one or more new menu items this way).

Also routines exist to delete a particular menu item or change it:

    void fl_delete_menu_item(FL_OBJECT *obj, int miid);
    void fl_replace_menu_item(FL_OBJECT *obj, int miid,
                               const char *menustr, ...);

`miid` is the menu item ID. `menustr` must be a string as used in `fl_set_menu()` with the only difference that only a single menu item can be specified.

Please note: when deleting a menu item all other items keep their menu item IDs. The menu item ID of the deleted menu item isn’t re-used when new items are added later. Instead for each menu an internal counter exists that gets incremented for each menu item added and which value is used for the menu item ID unless one is explicitely assigned to the menu item. The counter oly gets reset to 1 when the menu is cleared used `fl_clear_menu()`.

The menu item ID of a menu item changed by using `fl_replace_menu_item()` does not change unless the library is explicitely asked to via `%x` in `menustr`.

For most applications, the following routine may be easier to use at the expense of somewhat restrictive value a menu item can have as well as a loss of the ability to delete menu items or associate callbacks with menu items.

    int fl_set_menu_entries(FL_OBJECT *obj, FL_PUP_ENTRY *ent);

where `ent` is a pointer to an array of structure of the following type, terminated by an element, where at least the `text` member is a `NULL` pointer:

    typedef struct {
        const char *text;
        FL_PUP_CB callback;
        const char *shortcut;
        int mode;
    } FL_PUP_ENTRY;

The meaning of each member is explained in Section 21.3. For menus, item callback function can be `NULL` if the menu callback handles the interaction results. See demo program `popup.c` for an example use of `fl_set_menu_entries()`.

The function `fl_set_menu_entries()` works by creating and associating a popup menu with the menu object. The popup ID is returned by the function. Whenever the function is called, the old popup associated with the object (if one exists) is freed and a new one is created. Although you can manipulate the menu either through the menu API (but adding and removing menu items is not supported for menus created this way ) or popup API, the application should not free the popup directly and use `fl_clear_menu()` instead.

To clear the whole menu use

    void fl_clear_menu(FL_OBJECT *obj);

To find the menu item selected by the user use

    int fl_get_menu(FL_OBJECT *obj);

The the function returns the menu item ID. In the simplest possible case this is just the position of the menu item (starting at 1). This stops to be true when either IDs have been explicitely assigned to items or items have been deleted. In that case the following rules apply:

1. A menu item ID may have been assigned to a menu item using `%xn` in the string for the text of the menu item.
2. Menu items can get associated with a callback function that is executed when the menu item is selected. The callback function is of type `FL_PUP_CB` and receives the menu item ID of the selected menu. If such a callback is set for a menu item the return value of `fl_get_menu()` is the return value of this function instead of the menu item ID that would have been returned otherwise.

To obtain the text of any item, use the following routine

    const char *fl_get_menu_item_text(FL_OBJECT *obj, int miid);

where `miid` is the menu item ID. If `n` isn’t a valid menu iem ID item `NULL` is returned.

To obtain the text of the selected enu item use

    const char *fl_get_menu_text(FL_OBJECT *obj);

To obtain the total number of menu items, use the function

    int fl_get_menu_maxitems(FL_OBJECT *obj);

One can change the appearance of different menu items. In particular, it is sometimes desirable to make grey-out menu items and make them unselectable or to put boxes with and without checkmarks in front of them. This can be done using the routine:

    void fl_set_menu_item_mode(FL_OBJECT *obj, int miid, unsigned mode);

`miid` is the menu index ID of the memu item you want to change. `mode` represents the special properties you want to apply to the chosen item. You can specify more than one at a time by adding or bitwise OR-ing these values together. For this parameter, the following symbolic constants exist:

`FL_PUP_NONE`

  No special display characteristic, the default.

`FL_PUP_BOX`

  "Binary" entry, i.e., an entry that stands for a choice that can be switched on and off. Displayed with an unchecked box to the left.

`FL_PUP_RADIO`

  "Radio" item belonging to a group, so that gets automatically switched off when another item of the group is selected. Displayed with a diamoned-shaped box at the left.

`FL_PUP_GREY`

  To be OR-ed with one of the above to make that item appear greyed-out and disable it (i.e., not selectable anymore).

`FL_PUP_CHECK`

  To be OR-ed with one of `FL_PUP_BOX` and `FL_PUP_RADIO` to make the box to the left appear checked or pushed.

There is also a routine that can be used to obtain the current mode of an item after interaction, mostly useful for toggle or radio items:

    unsigned int fl_get_menu_item_mode(FL_OBJECT *obj, int miid);

While a callback associated with a menu entry can be set when it is created it can also set later on or be changed. For this use the function

    FL_PUP_CB fl_set_menu_item_callback(FL_OBJECT *ob,
                                        int numb, FL_PUP_CB cb);

where `numb` is the menu entries ID and `cb` is the callback function of type `FL_PUP_CB` (or `NULL` to disable a callback). The return value is a pointer to the previously used callback function (or `NULL`).

It is often useful to define keyboard shortcuts for particular menu items. For example, it would be nice to have `<Alt>s` behave like selecting "Save" from a menu. This can be done using the following routine:

    void fl_set_menu_item_shortcut(FL_OBJECT *obj, int miid,
                                   const char *str);

`miid` is the menu item ID of the menu item under consideration. `str` contains the shortcut for the item. (Actually, it can contain more shortcuts for the same item.) See Shortcuts, for more information about shortcuts.

Finally there is the routine:

    void fl_show_menu_symbol(FL_OBJECT *obj, int yes_no);

With this routine you can indicate whether to show a menu symbol at the right of the menu label. By default no symbol is shown.

Next: Menu Attributes, Previous: Menu Interaction, Up: Menu Object [Contents][Index]