class ref name: menuloop
class name: menuloop
category-group: quickdirt
layer: 0
header file: z_menuloop.h
libraries: libz00.lib

synopsis.
the menuloop object is a simple class that provides an "on-screen" menu, in a terminal or command window, and an internal loop that executes functions that correspond to the user's menu selection. In other words, the menuloop class is designed to provide command-line programs a basis to execute commands associated with a menu. The intent is to interact with a user at the console in a standardized manner. The class requires instantiating an array of "ml_action"s (a structure), and then assigning function pointers for each action. This is a simple callback-style methodology (quick and dirty).

This class object is quite old. if written today, many things would be done differently. you might find it a bit too cumbersome and unwieldy.

member functions (primary)

menuloop_o()
SIGNATURE: menuloop_o ()
SYNOPSIS: default constructor. creates an empty menuloop_o instance
 

menuloop_o(menuloop_o)
SIGNATURE: menuloop_o (const menuloop_o &)
SYNOPSIS: copy constructor. creates a menuloop_o instance.
WARNING: currently copies are not supported! don't use!
 

operator = (menuloop_o)
SIGNATURE: const menuloop_o &operator = (const menuloop_o &)
SYNOPSIS: assignment operator. creates an empty menuloop_o instance
WARNING: currently copies are not supported! don't use!
 

destructor
SIGNATURE: ~menuloop_o
SYNOPSIS: destructor (does nothing)
 

init_actions()
SIGNATURE: int menuloop_o::init_actions (struct ml_action *ptr, count_t n)
SYNOPSIS: sets all pointers to null. provide an array of 'ml_action' (via argument "ptr") and the number of elements in "ptr" (via "n").
RETURNS: 0
 

set()
SIGNATURE: int menuloop_o::set (struct ml_action *ptr, count_t my_n)
SYNOPSIS: pass "ptr" to the menuloop_o instance, along with its size
DESCRIPTION: after setting up a 'ml_action' struct array, use this function to find the array to the object.
 

reset()
SIGNATURE: int reset ()
SYNOPSIS:
disconnects the 'ml_action' struct array from the menuloop object. this effectively sets the menuloop object to an at-construction state.
 

run()
SIGNATURE: int run ()
SYNOPSIS:
runs a perpetual loop:
displays the menu;
gets the user's selection;
performs the action.
generally the first menu item is used to exit the loop.
 

usage.
there are 2 items your program must supply this object: a label to be displayed in the menu, and a function handle (eg pointer) corresponding to that label. You need to allocate an array of "struct ml_action"s, then load the variables in this structure:

struct ml_action
{
    int (* fun ());     // pointer to function
    char *str;          // the name of the menu item
    struct ml_action *child;
}
The next step is to create a menuloop object and give it the array. Finally, you would just call the run() member function. This function goes into an "infinite loop" - actually, until the user selects menu choice 0 (exit).

Here is a quick example-recipe: [1] declare the application's functions that are to be used with the menuloop_o class:

    int app_reset ();
    int app_sync ();
    int app_test ();
    int app_backup ();
[2] instantiate an array of "ml_action" structures (in this case an array of 5) and load the first 4:
struct ml_action app_callbacks[5];
app_callbacks[0].fun = app_reset;
app_callbacks[0].str = "reset the system";
app_callbacks[0].child = NULL;
app_callbacks[1].fun = app_sync;
app_callbacks[1].str = "synchronize the data";
app_callbacks[1].child = NULL;
app_callbacks[2].fun = app_test;
app_callbacks[2].str = "perform internal test";
app_callbacks[2].child = NULL;
app_callbacks[3].fun = app_backup;
app_callbacks[3].str = "backup the current data";
app_callbacks[3].child = NULL;
app_callbacks[4].str = NULL;
app_callbacks[4].child = NULL;
There are 2 unfortunate quirks you must do while initializing this array: (a) set the pointer "child" to NULL (unless using nested menus), and (b) setting the final, unused array element's "str" value to NULL.

[3] finally, create a [singleton] menuloop_o variable, pass the array of "ml_action"s to it, and run it:

void main()
{
    menuloop_o x;
    x.set (app_callbacks, 4);
    x.run ();
}

note.
This class is quite old in the Z Directory (date unknown). Its age is telling by the usage of function pointers and using an array of structs as an input variable. Nevertheless, it works fine. It can be used in conjunction with {lalyer 1} testdriver object, in the member function interactive().

examples.
menuloop requires setting up an array of record structures - "struct ml_action":

    int action_this();
    int action_that();
    struct ml_action stuff[2];
    //..
    int main ()
    {
        menuloop_o ml;
        stuff[0].fun = action_this;
        stuff[0].str = "perform this act";
        stuff[1].fun = action_that;
        stuff[1].str = "perform that act";
        ml.run();
    }

limitations.
There is some policy implemented that may be objectionable: the first item in the menu's list (number "0") is to exit, eg leave out of the menuloop's inner loop, and menu item #1 (the second item) lets the user toggle displaying the menu on or off. When off, it may be disconcerting - only the prompt is displayed. Also, the prompt is hardcoded to "Enter choice:". Hopefully these issues will be addressed in future releases.