xref: /netbsd-src/usr.bin/menuc/menuc.1 (revision fb5eed702691094bd687fbf1ded189c87457cd35)
1.\"	$NetBSD: menuc.1,v 1.39 2021/11/07 09:48:08 andvar Exp $
2.\"
3.\" Copyright 1997 Piermont Information Systems Inc.
4.\" All rights reserved.
5.\"
6.\" Written by Philip A. Nelson for Piermont Information Systems Inc.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\"    notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\"    notice, this list of conditions and the following disclaimer in the
15.\"    documentation and/or other materials provided with the distribution.
16.\" 3. The name of Piermont Information Systems Inc. may not be used to endorse
17.\"    or promote products derived from this software without specific prior
18.\"    written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
21.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
24.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30.\" THE POSSIBILITY OF SUCH DAMAGE.
31.\"
32.Dd February 25, 2019
33.Dt MENUC 1
34.Os
35.Sh NAME
36.Nm menuc
37.Nd menu compiler
38.Sh SYNOPSIS
39.Nm
40.Op Fl o Ar name
41.Ar file
42.Sh DESCRIPTION
43This implements a curses based menu system.
44A source file that describes menus, their options, and how to process
45the options is given to
46.Nm
47and produces both a .c and a .h file that implement the menu system.
48The standard base name of the files is
49.Pa menu_defs .
50The
51.Fl o Ar name
52can be used to specify a different base name.
53.Sh MENU DESCRIPTIONS
54The input
55.Ar file
56defines static menus and options for processing those menus.
57It also contains comments, initial C code that is required to provide
58for definitions and other code necessary for the menu system, and an
59option declaration if dynamic menus are requested.
60.Pp
61Comments may appear anywhere in the input file
62and are like a space in the input.
63They are like C comments starting with
64.Li "/*"
65and ending with
66.Li "*/" .
67They are unlike C comments in that they may be nested.
68A comment does not end until a matching end comment is found.
69.Pp
70In many places, C code is included in the definition file.
71All C code is passed verbatim to the C output file.
72.Nm
73comments do not start in C code and comments in the C code are
74passed verbatim to the output.
75The C comments are not recognized by
76.Nm .
77In all cases, C code starts with a left brace
78.Pq Ql \&{
79and ends with the matching right brace
80.Pq Ql \&} .
81It is important to recognize that in code segments, any brace
82will be counted, even if it is in a C comment inside the code.
83.Pp
84The file
85contains an initial (and optional) code block followed by any
86number of menu definition elements in any order.
87The initial code block usually contains includes of header files used by
88code in the menu code blocks later in the file.
89If
90.Dv USER_MENU_INIT
91preprocessor symbol
92is defined, then it will be evaluated before the
93rest of the menu is initialised, if it evaluates to a non-zero value
94then the initialisation will fail.
95The file is free format, so the actual formatting of the input file
96is to the taste of the programmer.
97.Pp
98All other C code that will appear in an
99.Em action .
100This will be specified as
101.Aq Em action
102in later text.
103Such an action will appear as:
104.Pp
105.D1 Li action Ao Em opt_endwin Ac Ao Em code Ac
106.Pp
107in the file.
108The
109.Aq Em opt_endwin ,
110is optional
111.Ql "(endwin)"
112and specifies that the curses
113.Xr endwin 3
114function should be called before executing the code and
115then reinstating the current curses window after the
116code has been run.
117The
118.Aq Em code
119is as described above.
120.Pp
121There are four kinds of menu definition elements.
122The first one just declares whether the programmer wants dynamic menus,
123dynamic messages and argument expansion in menus available.
124All these option default to off (or static only).
125.Pp
126Static menus are the ones defined by the menu definitions and do not
127change at run time.
128Dynamic menus provide the programmer with a method to create and
129modify menus during the running of the program.
130To include dynamic menus, one needs only add the declaration:
131.Pp
132.Dl "allow dynamic menus;"
133.Pp
134The semicolon is required to terminate this declaration.
135This declaration may appear anywhere in the file,
136but usually appears before any menus are defined.
137See below for a detailed explanation of dynamic menus.
138.Pp
139To enable internationalization by loading message files at
140run time one needs to add the declaration:
141.Pp
142.Dl "allow dynamic messages;"
143.Pp
144To allow argument expansion on static menu strings (see below for a
145detailed explanation), one needs to add the declaration:
146.Pp
147.Dl "allow expand;"
148.Pp
149The next element is a code block to execute if the curses
150screen can not be successfully initialized.
151The declaration
152.Pp
153.D1 Li error Li action Ao Em code Ac Ns Li \&;
154.Pp
155tells the menu system to execute the associated code block
156if the initialization fails.
157If no code is provided, a default code block is used that prints
158.Dq Could not initialize curses.
159and exits.
160This element may appear anywhere in the file
161but usually appears before any menus are defined.
162.Pp
163Each menu is built from a list of options.
164These options include the location of the upper left corner of the menu,
165whether there is a
166.Dq box
167drawn around the menu, whether the menu is
168scrollable, the menu's title, whether shortcut letters are
169allowed, whether a standard exit option should be included
170in the menu and text associated with the standard exit option.
171.Pp
172The
173.Ic default
174declaration defines default options for menus.
175The general format is:
176.Pp
177.D1 Li default Ao Em comma separated option list Ac Ns Li \&;
178.Pp
179The supported options are:
180.Bl -tag -width ".Ic exitstring Va text" -offset indent
181.It Ic y = Va starty
182The row number of the upper left corner of the menu window.
183If
184.Va starty
185is negative then the menu will be placed below any message text, but
186in at least row
187.Va -starty .
188.It Ic x = Va startx
189The column number of the upper left corner of the menu window.
190If
191.Va startx
192is -1 the menu will be centered horizontally.
193.It Ic h = Va height
194Specifies the number of menu entries to be displayed.
195If zero, the height will be based on the number of entries.
196.It Ic w = Va width
197Specifies the width of the menu window.
198If zero, the width will be that of the longest menu text line.
199.It Ic title Va text
200The specified
201.Va text
202will be displayed at the top of the menu window (inside any box).
203.It Ic box
204If specified, draw a box around the menu.
205.It Ic clear
206If specified, clear the window before performing the
207.Va action .
208.It Ic exit
209If specified, add an additional option to exit the menu.
210.It Ic exitstring Va text
211The menu label for the
212.Va exit
213option.
214If not specified defaults to
215.Dq "Exit" .
216.It Ic default exit
217If specified, place the cursor on the exit
218line of the menu, instead of the top line.
219.It Ic shortcut
220If specified, add alphabetic tags to each menu line.
221.It Ic scrollable
222If specified, and the menu has more lines than will fit in its window, then
223only part of the menu will be displayed and the
224.Ql <
225and
226.Ql >
227keys will scroll the displayed menu lines.
228.It Ic always scroll
229If specified, allow for the scroll message line even if the menu doesn't
230appear to have too many lines.
231Useful for dynamic menus, when the number of entries isn't known when the
232menu window is created.
233.It Ic sub menu
234If specified, the screen contents that the menu window overwrites are saved
235and restored when the menu exits.
236.It Ic continuous title
237If specified there is no vertical space between the title and the menu
238content.
239.El
240.Pp
241The
242.Ic box , clear , exit , default exit , shortcut , scrollable , always scroll ,
243and
244.Ic sub menu
245options can be preceded by
246.Ic no
247in order to negate a default.
248.Pp
249The
250.Va text
251arguments can be either a quoted text string or a preprocessor symbol defined
252to something suitable for initialising a
253.Vt "const char *"
254field.
255.Pp
256The
257.Ic default
258declaration may appear multiple times.
259Each time, it sets the default values for menu definitions that follow
260in the file.
261In each menu definition, any or all of these default definitions
262may be overridden for that menu.
263.Pp
264The
265.Ic menu
266element is the actual static menu definitions.
267The format and order for a menu definition is:
268.Bd -unfilled -offset indent
269.Li menu Ao Em name Ac Ao Em options Ac Ns Li \&;
270.Li " " Aq Em expand action
271.Li " " Aq Em display action
272.Li " " Aq Em menu items
273.Li " " Aq Em exit action
274.Li " " Aq Em help text
275.Ed
276.Pp
277Menu names are unquoted strings of alpha-numeric and underscore
278characters.
279They must start with an alpha character.
280In C source, a menu named
281.Dq foo
282is appears as
283.Li MENU_foo .
284(Capitalization is important.)
285This is important, because the menu is displayed and processed by
286calling the function
287.Pp
288.Dl "process_menu(MENU_foo, arg);"
289.Pp
290The options are a comma separated list of options as in the
291.Ic default
292declaration.
293These override the options from the most recent default declaration.
294.Pp
295The expand action is optional and only available if the global option
296.Ic allow expand
297has been declared (see above).
298For an example see below.
299.Pp
300The display action is optional and provides C code to
301execute at each and every time the menu is displayed for processing.
302If it is included, the format is:
303.Pp
304.Dl display Ao Em action Ac Ns Li \&;
305.Pp
306The bulk of the menu definition is the specification
307of the menu items.
308The general format of a menu item is:
309.Pp
310.Dl option Ao Em string Ac Ns Li \&, Ao Em element_list Ac Ns Li \&;
311.Pp
312The
313.Aq Em string
314is the text displayed for the menu item, this must be a quoted string
315or a preprocessor symbol defined to something that will initialise a
316.Vt "const char *"
317field.
318There may be an arbitrary number of these items.
319(If there are shortcuts in the menu, a practical limit
320of 51 should be recognized.
321It produces shortcuts
322.Sq a
323to
324.Sq w ,
325.Sq y ,
326.Sq z ,
327and
328.Sq A
329to
330.Sq Z .
331.Sq x
332is the shortcut for the exit item.)
333.Pp
334The
335.Aq Em element_list
336is a comma separated list of what to do when the item is selected.
337They may appear in any order.
338.Pp
339The first element processed when a menu item
340is selected is the associated action.
341The next element to be processed is the
342.Ic sub
343or
344.Ic next menu
345option.
346They are declared as:
347.Pp
348.Dl sub menu Aq Em name
349and
350.Dl next menu Aq Em name
351.Pp
352The difference between these two is that a
353.Dq sub
354menu will return to the current menu when exited.
355The
356.Dq next
357menu will just replace the current
358menu and when exited, will return to where the
359current menu would have gone.
360Only one of
361.Ic menu
362element may be used for each menu item.
363Finally, after processing both the action and a sub menu,
364the current menu will be exited if the element
365.Pp
366.Dl exit
367.Pp
368is specified.
369.Em Note :
370If
371.Ic exit
372is specified,
373.Ic next menu
374will not work because
375the menu system will exit the
376.Em current
377menu, even if current has been set by
378.Ic next menu .
379.Pp
380After all menu items, the final two menu definition
381elements may appear.
382The
383.Aq Em exit action
384is optional and provides C code to
385execute in the process of exiting a menu.
386If it is included, the format is:
387.Pp
388.Dl exit Ao Em action Ac Ns Li \&;
389.Pp
390The final part of the menu definition is the optional
391.Aq Em help string .
392The format is:
393.Pp
394.Dl help Ao Em text Ac Ns Li \&;
395.Pp
396This text is displayed in a full page
397help window if the question mark is typed.
398The actual help text starts with a left brace
399.Pq Ql \&{
400and ends with the matching right brace
401.Pq Ql \&} .
402The braces are not included in the
403help string, but all other characters between
404them are included.
405Newlines in the code translate to newlines in the help text.
406Alternatively, the name of a
407.Vt const char *
408variable may be given.
409.Sh DYNAMIC MENUS
410If requested,
411.Nm
412supports dynamic menus by allowing the user to create new
413menus.
414The related definitions for using dynamic menus are:
415.Bd -literal
416struct menudesc;
417
418typedef
419struct menu_ent {
420        const char  *opt_name;
421        int         opt_menu;
422        int         opt_flags;
423        int         (*opt_action)(struct menudesc *, void *);
424} menu_ent ;
425
426/* For opt_menu */
427#define OPT_NOMENU 0
428
429/* For opt_flags */
430#define OPT_SUB     1
431#define OPT_ENDWIN  2
432#define OPT_EXIT    4
433#define OPT_IGNORE  8
434#define OPT_NOSHORT 16
435
436typedef
437struct menudesc {
438        const char  *title;
439        int         y, x;
440        int         h, w;
441        int         mopt;
442        int         numopts;
443        int         cursel;
444        int         topline;
445        menu_ent    *opts;
446        WINDOW      *mw;
447        WINDOW      *sv_mw;
448        const char  *helpstr;
449        const char  *exitstr;
450        void       (*post_act)(struct menudesc *, void *);
451        void       (*exit_act)(struct menudesc *, void *);
452        void       (*draw_line)(struct menudesc *, int, void *);
453} menudesc ;
454
455/* defines for mopt field. */
456#define MC_NOEXITOPT 1
457#define MC_NOBOX 2
458#define MC_SCROLL 4
459#define MC_NOSHORTCUT 8
460#define MC_NOCLEAR 16
461#define MC_DFLTEXIT 32
462#define MC_ALWAYS_SCROLL 64
463#define MC_SUBMENU 128
464#define MC_CONTINUOUS 256
465
466int new_menu(const char *title, menu_ent *opts, int numopts,
467        int x, int y, int h, int w, int mopt,
468        void (*post_act)(struct menudesc *, void *),
469        void (*draw_line)(struct menudesc *, int, void *),
470        void (*exit_act)(struct menudesc *, void *),
471	const char *help, const char *exitstr);
472
473void free_menu (int menu_no);
474.Ed
475.Pp
476If
477.Ic allow expand
478has been declared, the
479.Vt menudesc
480structure contains another member,
481.Fa expand_act :
482.Pp
483.Dl "void (*expand_act)(struct menudesc *, void *);"
484.Pp
485This function (if not null) is called once when initializing
486a menu, before the display action
487.Fa post_act
488is called.
489.Pp
490The
491.Fa title
492is the title displayed at the top of the menu.
493The
494.Fa opts
495is an array of menu entry definitions that has
496.Fa numopts
497elements.
498The programmer must build this array and
499fill in all of the fields before processing calling
500.Fn process_menu
501for the new menu.
502The fields of the
503.Fa opts
504may change at any time.
505For example,
506.Fa opt_name
507may change as a result of selecting that option.
508When the menu is redisplayed, the new text is printed.
509Arguments
510.Fa x , y , h ,
511and
512.Fa w
513are the same as the options in the menu description.
514.Fa mopt
515is the boolean options.
516Note,
517.Ic box ,
518.Ic clear ,
519.Ic exit
520and
521.Ic shortcuts
522are enabled by default.
523You need to add option flags to turn them off or turn on scrollable menus.
524The options
525.Fa post_act ,
526and
527.Fa exit_act
528are function pointers to the display action and the exit action.
529If they are null,
530no call will be made.
531.Fa draw_line
532will be called to display the menu line if the corresponding
533.Fa opt_name
534field is null.
535.Fa help
536is the text to display in a help screen.
537A null
538.Fa help
539pointer will disable the help feature for the menu.
540And finally,
541.Fa exitstr
542is the text for the exit line of the menu.
543If it's null, string
544.Dq Exit
545is used.
546.Sh MENU ITEM ACTIONS
547When creating dynamic menus, the programmer supplies function pointers
548for the menu items
549.Dv opt_action
550member.
551This functions return one of three possible values:
552.Bl -tag -width "-1" -compact
553.It 0
554process sub menu (if set) and continue with the current (or new) menu
555as usual.
556.It 1
557exit the current menu.
558This is equivalent to specifying
559.Dq exit
560in a non-dynamic menu specification.
561.It -1
562do not handle the current item any further and restart handling the (same)
563menu.
564This return value is used when actions modify the menu definition on the
565fly, e.g. adding or removing additional menu items.
566The action may set
567.Dq cursel
568to jump to an arbitrary menu item (in the modified menu).
569.El
570.Sh MENU ITEM EXPANSION
571With the
572.Ic enable expansion
573declaration in effect, static menus may be customized before being displayed.
574This allows parameter substitution or special formatting of the menu item
575strings without having to resort to a full dynamic menu.
576Expanded strings are stored in the
577.Fa opt_exp_name
578member of struct
579.Vt menu_ent .
580This string is preferred over the non-expanded string
581.Fa opt_name
582when displaying the menu.
583The expand action code is responsible for filling this pointers.
584When leaving the menu, all
585.Fa opt_exp_name
586pointers that are populated will be automatically freed by calling
587.Xr free 3 .
588.Pp
589A very simple (and nonsensical) example for an expand option would
590be:
591.Bd -literal -offset indent
592expand action {
593	int i;
594	for (i = 0; i < menu->numopts; i++) {
595		const char *s = MSG_XLAT(menu->opts[i].opt_name);
596		if (s == NULL)
597			continue;
598		char *t = strdup(s);
599		t[0] = tolower((unsigned char)t[0]);
600		menu->opts[i].opt_exp_name = t;
601	}
602};
603.Ed
604which would force the first character of all menu items to lower case.
605The
606.Xr free 3
607call for the
608.Xr strdup 3
609call in above code is automatically handled on menu exit.
610.Sh ENVIRONMENT
611.Bl -tag -width ".Ev MENUDEF"
612.It Ev MENUDEF
613Can be set to point to a different set of definition files for
614.Nm .
615The current location defaults to
616.Pa /usr/share/misc .
617.El
618.Sh FILES
619.Bl -item
620.It
621.Pa /usr/share/misc/menu_sys.def
622.El
623.Sh EXAMPLES
624The following is a simple menu definition file.
625It is complete in that the output of
626.Nm
627may be compiled into a complete program.
628For example, if the following was in a file called
629.Pa example.mc ,
630an executable program could be produced by the following commands.
631.Bd -literal -offset indent
632menuc -o example example.mc
633cc -o example example.c -lcurses
634.Ed
635.Pp
636A much more complete example is available with the source
637distribution in a subdirectory called
638.Pa testm .
639.Bd -literal
640/* This is an example menu definition file for menuc. */
641
642{
643#include <stdio.h>
644#include <unistd.h>
645
646/* Main program! This is often in a different file. */
647int
648main()
649  {
650    process_menu (MENU_main, NULL);
651    endwin();
652    return 0;
653  }
654
655/* Example initialize function! */
656void
657init_main()
658  {
659  }
660}
661
662default x=20, y=10, box, scrollable, exit;
663
664error action {
665   fprintf (stderr, "Example Menu: Could not initialize curses.");
666   exit(1);
667};
668
669menu main, title "Main Menu", no exit, no shortcut;
670   display action { init_main(); };
671   option "Option 1",
672      action (endwin) {
673        printf ("That was option 1!");
674        sleep(3);
675      };
676   option "Sub Menu", sub menu othermenu;
677   option "Next Menu", next menu othermenu;
678   option "Quit", exit;
679   help {
680This is a simple help screen for an example menu definition file.
681};
682
683menu othermenu, title "Sub/Next Menu", x=5, y=5, no box;
684   option "Do Nothing!", action { };
685.Ed
686.Sh SEE ALSO
687.Xr msgc 1
688.Sh AUTHORS
689.An Philip A. Nelson
690for Piermont Information Systems Inc.
691Initial ideas for this were developed and implemented in Pascal at the
692Leiden University, Netherlands, in the summer of 1980.
693.Sh BUGS
694Both
695.Nm
696and
697.Nm msgc
698are probably only used by
699.Nm sysinst .
700The features of both have been tailored for
701.Nm sysinst ,
702and further changes are likely to occur.
703