CMDCACHE(3L)

NAME
cmdcache, useritems - cache a command in the Application cache

SYNOPSIS
#include <dmd.h>
#include <menu.h>
#include <object.h>

Titem1 useritems;

int cmdcache (s, m, b, u, e)
char *s;
Tmenu *m;
Bitmap *b;
void (*u)( );
void (*e)( );

DESCRIPTION
The cmdcache function allows the caching of an application as a command to expand the basic set of global menu commands accessed from button 3, such as New, Reshape, etc.. Although the basic set of commands mostly deals with window operations, a cached command can have other functionalities. The criteria to decide if an application should be cached as a command or as an application is as follows:

    The application runs without a window.

    The application is compact and specialized, and its user interface must be done through the mouse.

    The scope of the application is global to the whole terminal.

An example of a cached command is the terminal resident Exit command.

The application format is just a vehicle to download the code of the command into the terminal; therefore, it should use a template similar to the one used in the EXAMPLE section, which has main() that calls the cmdcache function with the right parameters and exits immediately.

The cmdcache function will use the null terminated ASCII string s as the tag name (see cache(3L) for a definition of a tag name), and also as the menu name of the command. The menu name will be displayed on the More menu for user selection. Note that a command can only be accessed from the More menu, and booting it through dmdld will not work.

The bitmap b, if not null, will be displayed as an icon on the left on the menu name of the command. It is recommended that cached commands have an icon to differentiate them from cached applications, since the More menu lists all of them nondiscriminatively.

The cached command can have a submenu of its own if the argument m is defined. The submenu m has to be generated dynamically, and the menu generator must use the globally defined useritems (see tmenuhit(3R) for details of a dynamic menu generation). The structure for useritems is Titem1, which is used for all global commands and is defined as follows:

    typedef struct Titem1 {
    	char *text;
    	struct {
    		unsigned short uval;
    		unsigned short grey;
    	} ufield;
    	struct Tmenu *next;
    	Bitmap *icon;
    	void (*dfn)();
    } Titem1;
The field next does not apply for items in a cached command's submenu (i.e., the terminal does not support fourth-level global submenus). Since submenu off the item is not supported, the field dfn is also not relevant. All other fields can be updated by the command's menu generator.

The argument function u is called by the terminal during the generation of the dynamic More menu. (The More menu keeps changing because applications and commands can constantly cache in and decache out.) When the terminal processes a cached command, it copies the static information of the command into useritems: the argument s goes into the item field text, the argument b into item field icon, the argument m into item field next. Then the terminal will call the function of type void pointed by u, if present, with two arguments: The first one is a pointer to the command object under consideration (this argument is reserved) , and the other is a pointer to the item structure being initialized (i.e., useritems). The function pointed by u may dynamically update the item's ufield.grey, and also re-initialize any fields of the item structure (e.g., if the current conditions dictate that all items in the command's submenu are invalid, the command may decide not to have a submenu, so the function pointed by u may change the field next to null).

Note
    The fields ufield.uval and dfn are used by the terminal for housekeeping: they differentiate between selections of cached applications, cached commands in the More menu and items in third-level submenus of those applications and commands. Even though it is possible to modify them, it is strongly not recommended unless the programmer understands the terminal's internals.

If the argument u is not specified, the cmdcache supplies a default function which initializes the grey field of the item to null (no greying).

The argument function e of type void is called when the command or an item from its submenu m is selected. The function e accepts two arguments: The first one is -1 if the command does not have a submenu, or the index of the selected item (i.e., useritems.ufield.uval) if the command has a submenu. The second argument is the pointer to the cached command object, but it is reserved. The function e is executed in the context of the terminal's control process like other global menu commands; therefore, some global variables relating to the downloaded application template and window parameters such as P, display, Drect, etc., do not have any meaning.

If the argument function e is not specified, no action is taken if the item is selected. Also if the command has a submenu, selecting the command menu name in the More menu instead of an item in the command's submenu will result to a null operation.

  Return Value
If the command is successfully cached, the function cmdcache returns a 1. Otherwise, a 0 is returned.

A failure may be due to the following reasons. Another command or application of the same name is already in the cache, or the terminal runs out of memory when initiating the caching operation.

EXAMPLE
The following application caches a command which lets the user pick a window and displays the name of the application running in that window. The command supports two options: the full option displays the full name, and the clipped option displays the full name clipped from any path name prefix. The uargv field of the selected process p holds the argv used by that process.

Note that if the chosen application is cached, the displayed clipped name is the tag name it is cached under.

    #include <dmd.h>
    #include <menu.h>
    #include <object.h>
    struct Tmenu obmenu;
    Word qmarkdata[] = {
    	0x3C00,
    	0x7E00,
    	0xE700,
    	0xC300,
    	0x0300,
    	0x0700,
    	0x0E00,
    	0x1C00,
    	0x1800,
    	0x1800,
    	0x0000,
    	0x1800,
    	0x1800
    };
    Bitmap qmark = {
    	(Word *)qmarkdata,
    	1,
    	0, 0, 8, 13,
    	0
    };
    main ()
    {
    	Titem1 *genesis(); /* command's submenu generator */
    	void showname(); /* command's executing code */
    	obmenu.item = (Titem *)0;	/* dynamic submenu */
    	obmenu.generator = (Titem *(*)())genesis;
    	obmenu.menumap = TM_TEXT|TM_UFIELD|TM_NEXT|
    			 TM_ICON|TM_DFN;
    	cmdcache ("name", &obmenu, &qmark, 0l, showname);
    }
    Titem1 *
    genesis (i, m)
    int i;
    Tmenu *m;
    {
    	register Titem1 *item = &useritems;
    	/* MUST use "useritems" */
    	switch (i) {
    		case 0:		/* first item */
    			item->text = "full";
    			break;
    		case 1:
    			item->text = "clipped";
    			break;
    		default:	/* last item */
    			item->text = (char *)0;
    			return (item);
    	}
    	item->ufield.uval = i;
    	/* WARNING: "useritems" is a global variable
    	** used by all cached commands that have a
    	** submenu, so we cannot assume that fields
    	** that are not initialized by genesis() are
    	** cleared since other
    	** commands may initialize
    	** them when they are running.
    	**
    	** To be sure, just clear any unused fields.
    	*/
    	item->ufield.grey = 0;
    	item->icon = (Bitmap *)0;
    	return (item);	/* returns "useritems" */
    }
    void
    showname (val)
    int val;
    {
    	register Proc *p;
    	register char *s;
    	Proc *point2window();
    	char *clipprefix();
    	p = point2window (3);	/* pick a window */
    	s = p->uargv[0];		/* "full" name */
    	if (val)
    		s = clipprefix(s);	/* "clipped" name */
    	msgbox (s, (char *)0);		/* display name */
    }

SEE ALSO
ucache(1), cache(3L), decache(3L), tmenuhit(3R).