July 16, 2019

SOML oven documentation - modifying menus

The program "oven" is now invoked from the linux command line and displays the text GUI that is used to run the oven. This is plain old C code. It makes use of two libraries that are worth mentioning. One is cfitsio -- which is only used by the "ovend" program. The other is ncurses, which is central to the oven GUI.

The menu system itself is tricky. It is set up using a metalanguage and a code generator, which needs to be understood and explained before anything can be done as far as adding information to the menus.

What I would like to do is to add the name of the oven being monitored to the top of at least the first "Main Menu" window. This would be either oven0v0 for the big oven or oven1v0 for the meter cube. When the meter cubed is selected (typically by starting the oven gui via "oven -M" it would be nice to display something like:

oven1v0 (Meter cube)
It would also be useful perhaps to display "oven2v2 (!! Unknown !!) or something of the sort if some haywire non-existant oven was chosen.

A first look at the code

If we look at main() in oven.c, we see that it calls oven_gui() in the same file. This performs a bunch of initialization, the calls:
	init_menus ();
	do_menus ( period, offset );
Both of these routines are in domenus.c. The first one, init_menus() calls menus () which is in menusm/menus.c -- it returns a pointer to a MENUS object which will then be used by do_menus().

The menus tables

At this point it is worth looking at the Makefile and the build setup. We have several directories to be aware of:
menus - menu definition files (source files, so to speak)
menusc - C source, one per file above with corresponding name
menusm - holds menus.c and a big generated file "menus.vc"
menust - generated templates -- no longer of interest

A tool exists (makemenus.c) that is used to generate code based on the "source" files in the menus directory. It is run by the Makefile in the menust directory.

The main menu is governed by menus/aa which looks like this:

Oven Main Menu
Exit                          %ex      $
Configuration and Status      %cs      $
Error Log                     %er      $
Database                      %db      $
Part of what gets generated for this (in menusm/menus.vc) looks like this:
	#include "menus.i"
	ip->text_start = 0;
    ip->text_end   = 13;
    ip->text = "Oven Main Menu";
So, there is the title we wish to modify!

A pair of files get repeatedly included as a sort of code generation macro scheme. The file "menus.m" is included to start each menu. The file menus.i is included to start each menu item.
They look like this:

	/* menus.m */
	if (msp->nmenus >= MAX_MENUS)
	    return ((MENUS *)1);
	if ((mp = (MENU *)calloc (1, sizeof(MENU))) == (MENU *)0)
	    return ((MENUS *)0);
	msp->menu[msp->nmenus++] = mp;

	/* menus.i */
	if (mp->nitems >= MAX_ITEMS)
        return ((MENUS *)2);
    if ((ip = (ITEM *)calloc (1, sizeof(ITEM))) == (ITEM *)0)
        return ((MENUS *)0);
    mp->item[mp->nitems++] = ip;
There are 3 different objects, as follows:
	MENUS   *msp;
    MENU    *mp;
    ITEM    *ip;
Only one "msp" is allocated. It holds a list of "mp" items (one per menu), and each "mp" holds a lits of "ip" items. No linked lists or pointers, just arrays and dynamic allocation.

So the call to menus() returns a pointer to the top level (one and only) MENUS object. This gets returned to the call in init_menus() in oven.c. It puts the pointer into globalp->msp.

What we might do

Each MENU object (mp) has an "id" string, which will be "aa" for the main menu. We can look for this to recognize when mp is pointing to the main menu.

My idea is this. Add code to init_menus() in oven.c to find the first text thing in the first menu and replace it! Perform verification that the first menu id is "aa" and the the first item is text and starts with "Oven".

Simple enough.