No Minix-specific changes needed.
Change-Id: Ie663e08a515a393efaaeecacea15ef807aa8ecfb
./usr/bin/md2 minix-sys
./usr/bin/md4 minix-sys
./usr/bin/md5 minix-sys
+./usr/bin/menuc minix-sys
./usr/bin/mesg minix-sys
./usr/bin/mined minix-sys
./usr/bin/ministat minix-sys
./usr/man/man1/md2.1 minix-sys
./usr/man/man1/md4.1 minix-sys
./usr/man/man1/md5.1 minix-sys
+./usr/man/man1/menuc.1 minix-sys
./usr/man/man1/mesg.1 minix-sys
./usr/man/man1/ministat.1 minix-sys
./usr/man/man1/mixer.1 minix-sys
./usr/share/misc/magic.mgc minix-sys
./usr/share/misc/man.template minix-sys
./usr/share/misc/mdoc.template minix-sys
+./usr/share/misc/menu_sys.def minix-sys
./usr/share/misc/na.phone minix-sys
./usr/share/misc/na.postal minix-sys
./usr/share/misc/NetBSD.el minix-sys
2012/10/17 12:00:00,usr.bin/Makefile
2012/10/17 12:00:00,usr.bin/Makefile.inc
2010/07/07 21:24:34,usr.bin/man
+2012/10/17 12:00:00,usr.bin/menuc
2013/10/25 12:00:00,usr.bin/mesg
2010/10/15 05:46:48,usr.bin/mkdep
2012/10/17 12:00:00,usr.bin/mkstr
head hexdump indent infocmp join \
lam ldd leave \
lock login logname lorder m4 \
- machine make man mesg \
+ machine make man menuc mesg \
mkdep mkstr mktemp \
\
nbperf newgrp nice nl nohup nvi \
--- /dev/null
+# $NetBSD: Makefile,v 1.14 2009/10/29 14:36:14 christos Exp $
+
+WARNS?= 1 # XXX -Wshadow -Wcast-qual issues
+
+.include <bsd.own.mk>
+
+PROG= menuc
+SRCS= main.c parse.y scan.l avl.c mdb.c util.c
+CPPFLAGS+= -I. -I${.CURDIR}
+YHEADER=
+
+.if ${MKSHARE} != "no"
+FILES= menu_sys.def
+FILESDIR= /usr/share/misc
+.endif
+
+.ifndef HOSTPROG
+LDADD+= -ll
+DPADD+= ${LIBL}
+.endif
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $NetBSD: avl.c,v 1.7 2005/02/11 06:21:22 simonb Exp $ */
+
+/*
+ * Copyright (c) 1997 Philip A. Nelson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Philip A. Nelson.
+ * 4. The name of Philip A. Nelson may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* avl.c: Routines for manipulation an avl tree.
+ *
+ * an include file should define the following minimum struct.:
+ * (Comments must be made into real comments.)
+ *
+ * typedef struct id_rec {
+ * / * The balanced binary tree fields. * /
+ * char *id; / * The name. * /
+ * short balance; / * For the balanced tree. * /
+ * struct id_rec *left, *right; / * Tree pointers. * /
+ *
+ * / * Other information fields. * /
+ * } id_rec;
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: avl.c,v 1.7 2005/02/11 06:21:22 simonb Exp $");
+#endif
+
+
+#include <string.h>
+
+#include "defs.h"
+
+/* find_id returns a pointer to node in TREE that has the correct
+ ID. If there is no node in TREE with ID, NULL is returned. */
+
+id_rec *
+ find_id (id_rec *tree, char *id)
+{
+ int cmp_result;
+
+ /* Check for an empty tree. */
+ if (tree == NULL)
+ return NULL;
+
+ /* Recursively search the tree. */
+ cmp_result = strcmp (id, tree->id);
+ if (cmp_result == 0)
+ return tree; /* This is the item. */
+ else if (cmp_result < 0)
+ return find_id (tree->left, id);
+ else
+ return find_id (tree->right, id);
+}
+
+
+/* insert_id inserts a NEW_ID rec into the tree whose ROOT is
+ provided. insert_id returns TRUE if the tree height from
+ ROOT down is increased otherwise it returns FALSE. This is a
+ recursive balanced binary tree insertion algorithm. */
+
+int insert_id (id_rec **root, id_rec *new_id)
+{
+ id_rec *A, *B;
+
+ /* If root is NULL, this where it is to be inserted. */
+ if (*root == NULL)
+ {
+ *root = new_id;
+ new_id->left = NULL;
+ new_id->right = NULL;
+ new_id->balance = 0;
+ return (TRUE);
+ }
+
+ /* We need to search for a leaf. */
+ if (strcmp (new_id->id, (*root)->id) < 0)
+ {
+ /* Insert it on the left. */
+ if (insert_id (&((*root)->left), new_id))
+ {
+ /* The height increased. */
+ (*root)->balance--;
+
+ switch ((*root)->balance)
+ {
+ case 0: /* no height increase. */
+ return (FALSE);
+ case -1: /* height increase. */
+ return (TRUE);
+ case -2: /* we need to do a rebalancing act. */
+ A = *root;
+ B = (*root)->left;
+ if (B->balance <= 0)
+ {
+ /* Single Rotate. */
+ A->left = B->right;
+ B->right = A;
+ *root = B;
+ A->balance = 0;
+ B->balance = 0;
+ }
+ else
+ {
+ /* Double Rotate. */
+ *root = B->right;
+ B->right = (*root)->left;
+ A->left = (*root)->right;
+ (*root)->left = B;
+ (*root)->right = A;
+ switch ((*root)->balance)
+ {
+ case -1:
+ A->balance = 1;
+ B->balance = 0;
+ break;
+ case 0:
+ A->balance = 0;
+ B->balance = 0;
+ break;
+ case 1:
+ A->balance = 0;
+ B->balance = -1;
+ break;
+ }
+ (*root)->balance = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Insert it on the right. */
+ if (insert_id (&((*root)->right), new_id))
+ {
+ /* The height increased. */
+ (*root)->balance++;
+ switch ((*root)->balance)
+ {
+ case 0: /* no height increase. */
+ return (FALSE);
+ case 1: /* height increase. */
+ return (TRUE);
+ case 2: /* we need to do a rebalancing act. */
+ A = *root;
+ B = (*root)->right;
+ if (B->balance >= 0)
+ {
+ /* Single Rotate. */
+ A->right = B->left;
+ B->left = A;
+ *root = B;
+ A->balance = 0;
+ B->balance = 0;
+ }
+ else
+ {
+ /* Double Rotate. */
+ *root = B->left;
+ B->left = (*root)->right;
+ A->right = (*root)->left;
+ (*root)->left = A;
+ (*root)->right = B;
+ switch ((*root)->balance)
+ {
+ case -1:
+ A->balance = 0;
+ B->balance = 1;
+ break;
+ case 0:
+ A->balance = 0;
+ B->balance = 0;
+ break;
+ case 1:
+ A->balance = -1;
+ B->balance = 0;
+ break;
+ }
+ (*root)->balance = 0;
+ }
+ }
+ }
+ }
+
+ /* If we fall through to here, the tree did not grow in height. */
+ return (FALSE);
+}
--- /dev/null
+/* $NetBSD: defs.h,v 1.9 2012/03/06 16:55:18 mbalmer Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* defs.h: definitions needed for the menu system. */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <stdio.h>
+
+#include "mdb.h"
+
+#ifdef MAIN
+#define EXTERN
+#define INIT(x) = x
+#else
+#define EXTERN extern
+#define INIT(x)
+#endif
+
+/* some constants */
+#define TRUE 1
+#define FALSE 0
+
+/* Global variables .. to be defined in main.c, extern elsewhere. */
+
+EXTERN char *prog_name;
+EXTERN char *src_name;
+EXTERN char *out_name INIT("menu_defs");
+EXTERN char *sys_name INIT("menu_sys.def");
+
+EXTERN int do_dynamic INIT(0);
+EXTERN int do_msgxlat INIT(0);
+EXTERN int line_no INIT(1);
+EXTERN int had_errors INIT(FALSE);
+EXTERN int max_strlen INIT(1);
+
+EXTERN id_rec *root INIT(NULL);
+
+EXTERN struct menu_info default_info;
+EXTERN id_rec default_menu;
+
+EXTERN action error_act INIT({NULL});
+
+/* Prototypes. */
+
+/* From util.c */
+void yyerror(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void buff_add_ch(char);
+char *buff_copy(void);
+
+/* from scan.l */
+int yylex(void);
+
+/* from parse.y */
+int yyparse(void);
+
+/* Vars not defined in main.c */
+extern FILE *yyin;
+
+/* from avl.c */
+id_rec *find_id(id_rec *, char *);
+int insert_id(id_rec **, id_rec *);
+
+/* from mdb.c */
+id_rec *get_menu(char *);
+void check_defined(void);
+void write_menu_file(char *);
+
--- /dev/null
+/* $NetBSD: main.c,v 1.11 2012/03/06 16:55:18 mbalmer Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* main.c - main program for menu compiler. */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: main.c,v 1.11 2012/03/06 16:55:18 mbalmer Exp $");
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define MAIN
+#include "defs.h"
+
+/* Local prototypes */
+__dead void usage(void);
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+
+ /* Process the arguments. */
+ while ((ch = getopt(argc, argv, "o:")) != -1 ) {
+ switch (ch) {
+ case 'o': /* output file name */
+ out_name = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc - 1)
+ usage();
+
+ src_name = argv[optind];
+
+ yyin = fopen(src_name, "r");
+ if (yyin == NULL) {
+ (void)fprintf(stderr, "%s: could not open %s.\n", prog_name,
+ src_name);
+ exit(1);
+ }
+
+ /* The default menu */
+ default_menu.info = &default_info;
+ default_info.title = "\"\"";
+ default_info.helpstr = NULL;
+ default_info.exitstr = NULL;
+ default_info.mopt = 0;
+ default_info.x = -1;
+ default_info.y = 0;
+ default_info.h = 0;
+ default_info.w = 0;
+ default_info.numopt = 0;
+ default_info.optns = NULL;
+ default_info.postact.code = NULL;
+ default_info.postact.endwin = FALSE;
+ default_info.exitact.code = NULL;
+ default_info.exitact.endwin = FALSE;
+
+ /* Do the parse */
+ (void)yyparse();
+
+ return had_errors ? 1 : 0;
+}
+
+
+__dead void
+usage(void)
+{
+ (void)fprintf (stderr, "%s [-o name] file\n", getprogname());
+ exit(1);
+}
--- /dev/null
+/* $NetBSD: mdb.c,v 1.46 2012/03/06 16:55:18 mbalmer Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* mdb.c - menu database manipulation */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: mdb.c,v 1.46 2012/03/06 16:55:18 mbalmer Exp $");
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mdb.h"
+#include "defs.h"
+#include "pathnames.h"
+
+/* Data */
+#undef MAX
+#define MAX 1000
+static int menu_no = 0;
+static id_rec *menus[MAX];
+
+/* Other defines */
+#define OPT_SUB 1
+#define OPT_ENDWIN 2
+#define OPT_EXIT 4
+
+
+/* get_menu returns a pointer to a newly created id_rec or an old one. */
+
+id_rec *
+get_menu(char *name)
+{
+ id_rec *temp;
+
+ temp = find_id (root, name);
+
+ if (temp == NULL) {
+ if (menu_no < MAX) {
+ temp = (id_rec *)malloc(sizeof(id_rec));
+ temp->id = strdup(name);
+ temp->info = NULL;
+ temp->menu_no = menu_no;
+ menus[menu_no++] = temp;
+ insert_id(&root, temp);
+ } else {
+ (void)fprintf(stderr, "Too many menus. "
+ "Increase MAX.\n");
+ exit(1);
+ }
+ }
+
+ return temp;
+}
+
+
+/* Verify that all menus are defined. */
+void
+check_defined(void)
+{
+ int i;
+
+ for (i = 0; i < menu_no; i++)
+ if (!menus[i]->info)
+ yyerror ("Menu '%s' undefined.", menus[i]->id);
+}
+
+
+/* Write out the menu file. */
+void
+write_menu_file(char *initcode)
+{
+ FILE *out_file, *sys_file;
+ int i, j;
+ char hname[1024], cname[1024], sname[1024];
+ char *sys_prefix, *tmpstr;
+ int name_is_code, nlen, ch;
+ optn_info *toptn;
+
+ /* Generate file names */
+ snprintf(hname, 1024, "%s.h", out_name);
+ nlen = strlen(hname);
+ if (hname[nlen-2] != '.' || hname[nlen-1] != 'h') {
+ (void)fprintf(stderr, "%s: name `%s` too long.\n",
+ prog_name, out_name);
+ exit(1);
+ }
+ snprintf(cname, 1024, "%s.c", out_name);
+
+ /* Open the menu_sys file first. */
+ sys_prefix = getenv("MENUDEF");
+ if (sys_prefix == NULL)
+ sys_prefix = _PATH_DEFSYSPREFIX;
+ snprintf(sname, 1024, "%s/%s", sys_prefix, sys_name);
+ sys_file = fopen (sname, "r");
+ if (sys_file == NULL) {
+ (void)fprintf(stderr, "%s: could not open %s.\n",
+ prog_name, sname);
+ exit(1);
+ }
+
+ /* Output the .h file first. */
+ out_file = fopen(hname, "w");
+ if (out_file == NULL) {
+ (void)fprintf(stderr, "%s: could not open %s.\n",
+ prog_name, hname);
+ exit(1);
+ }
+
+ /* Write it */
+ (void)fprintf(out_file, "%s",
+ "/* menu system definitions. */\n"
+ "\n"
+ "#ifndef MENU_DEFS_H\n"
+ "#define MENU_DEFS_H\n"
+ "#include <stdlib.h>\n"
+ "#include <string.h>\n"
+ "#include <ctype.h>\n"
+ "#include <curses.h>\n\n"
+ );
+
+ if (do_msgxlat)
+ (void)fprintf(out_file, "#define MSG_XLAT(x) msg_string(x)\n");
+ else
+ (void)fprintf(out_file, "#define MSG_XLAT(x) (x)\n");
+ if (do_dynamic)
+ (void)fprintf(out_file, "#define DYNAMIC_MENUS\n");
+ if (do_dynamic || do_msgxlat)
+ (void)fprintf(out_file, "\n");
+
+ (void)fprintf(out_file,
+ "typedef struct menudesc menudesc;\n"
+ "typedef struct menu_ent menu_ent;\n"
+ "struct menu_ent {\n"
+ " const char *opt_name;\n"
+ " int opt_menu;\n"
+ " int opt_flags;\n"
+ " int (*opt_action)(menudesc *, void *);\n"
+ "};\n\n"
+ "#define OPT_SUB 1\n"
+ "#define OPT_ENDWIN 2\n"
+ "#define OPT_EXIT 4\n"
+ "#define OPT_IGNORE 8\n"
+ "#define OPT_NOMENU -1\n\n"
+ "struct menudesc {\n"
+ " const char *title;\n"
+ " int y, x;\n"
+ " int h, w;\n"
+ " int mopt;\n"
+ " int numopts;\n"
+ " int cursel;\n"
+ " int topline;\n"
+ " menu_ent *opts;\n"
+ " WINDOW *mw;\n"
+ " WINDOW *sv_mw;\n"
+ " const char *helpstr;\n"
+ " const char *exitstr;\n"
+ " void (*post_act)(menudesc *, void *);\n"
+ " void (*exit_act)(menudesc *, void *);\n"
+ " void (*draw_line)(menudesc *, int, void *);\n"
+ "};\n"
+ "\n"
+ "/* defines for mopt field. */\n"
+#define STR(x) #x
+#define MC_OPT(x) "#define " #x " " STR(x) "\n"
+ MC_OPT(MC_NOEXITOPT)
+ MC_OPT(MC_NOBOX)
+ MC_OPT(MC_SCROLL)
+ MC_OPT(MC_NOSHORTCUT)
+ MC_OPT(MC_NOCLEAR)
+ MC_OPT(MC_DFLTEXIT)
+ MC_OPT(MC_ALWAYS_SCROLL)
+ MC_OPT(MC_SUBMENU)
+ MC_OPT(MC_VALID)
+#undef MC_OPT
+#undef STR
+ );
+
+ (void)fprintf(out_file, "%s",
+ "\n"
+ "/* Prototypes */\n"
+ "int menu_init(void);\n"
+ "void process_menu(int, void *);\n"
+ "__dead void __menu_initerror(void);\n"
+ );
+
+ if (do_dynamic)
+ (void)fprintf(out_file, "%s",
+ "int new_menu(const char *, menu_ent *, int, \n"
+ "\tint, int, int, int, int,\n"
+ "\tvoid (*)(menudesc *, void *), "
+ "void (*)(menudesc *, int, void *),\n"
+ "\tvoid (*)(menudesc *, void *), "
+ "const char *, const char *);\n"
+ "void free_menu(int);\n"
+ "void set_menu_numopts(int, int);\n"
+ );
+
+ (void)fprintf(out_file, "\n/* Menu names */\n");
+ for (i = 0; i < menu_no; i++)
+ (void)fprintf(out_file, "#define MENU_%s\t%d\n",
+ menus[i]->id, i);
+
+ if (do_dynamic)
+ (void)fprintf(out_file, "\n#define DYN_MENU_START\t%d",
+ menu_no);
+
+ (void)fprintf (out_file, "\n#define MAX_STRLEN %d\n"
+ "#endif\n", max_strlen);
+ fclose(out_file);
+
+ /* Now the C file */
+ out_file = fopen(cname, "w");
+ if (out_file == NULL) {
+ (void)fprintf(stderr, "%s: could not open %s.\n",
+ prog_name, cname);
+ exit(1);
+ }
+
+ /* initial code */
+ fprintf(out_file, "#include \"%s\"\n\n", hname);
+ fprintf(out_file, "%s\n\n", initcode);
+
+ /* data definitions */
+
+ /* func defs */
+ for (i = 0; i < menu_no; i++) {
+ if (strlen(menus[i]->info->postact.code)) {
+ (void)fprintf(out_file, "/*ARGSUSED*/\n"
+ "static void menu_%d_postact(menudesc *menu, void *arg)\n{\n", i);
+ if (menus[i]->info->postact.endwin)
+ (void)fprintf(out_file, "\tendwin();\n");
+ (void)fprintf(out_file, "\t%s\n}\n\n",
+ menus[i]->info->postact.code);
+ }
+ if (strlen(menus[i]->info->exitact.code)) {
+ (void)fprintf(out_file, "/*ARGSUSED*/\n"
+ "static void menu_%d_exitact(menudesc *menu, void *arg)\n{\n", i);
+ if (menus[i]->info->exitact.endwin)
+ (void)fprintf(out_file, "\tendwin();\n");
+ (void)fprintf(out_file, "\t%s\n}\n\n",
+ menus[i]->info->exitact.code);
+ }
+ j = 0;
+ toptn = menus[i]->info->optns;
+ for (; toptn != NULL; j++, toptn = toptn->next) {
+ if (strlen(toptn->optact.code) == 0)
+ continue;
+
+ (void)fprintf(out_file, "/*ARGSUSED*/\n"
+ "static int opt_act_%d_%d(menudesc *m, void *arg)\n"
+ "{\n\t%s\n\treturn %s;\n}\n\n",
+ i, j, toptn->optact.code,
+ (toptn->doexit ? "1" : "0"));
+ }
+
+ }
+
+ /* optentX */
+ for (i = 0; i < menu_no; i++) {
+ if (menus[i]->info->numopt > 53) {
+ (void)fprintf(stderr, "Menu %s has "
+ "too many options.\n",
+ menus[i]->info->title);
+ exit(1);
+ }
+ (void)fprintf(out_file, "static menu_ent optent%d[] = {\n", i);
+ name_is_code = 0;
+ for (j = 0, toptn = menus[i]->info->optns; toptn;
+ toptn = toptn->next, j++) {
+ name_is_code += toptn->name_is_code;
+ (void)fprintf(out_file, "\t{%s,%d,%d,",
+ toptn->name_is_code ? "0" : toptn->name,
+ toptn->menu,
+ (toptn->issub ? OPT_SUB : 0)
+ +(toptn->doexit ? OPT_EXIT : 0)
+ +(toptn->optact.endwin ? OPT_ENDWIN : 0));
+ if (strlen(toptn->optact.code))
+ (void)fprintf(out_file, "opt_act_%d_%d}", i, j);
+ else
+ (void)fprintf(out_file, "NULL}");
+ (void)fprintf(out_file, "%s\n",
+ (toptn->next ? "," : ""));
+ }
+ (void)fprintf(out_file, "\t};\n\n");
+
+ if (name_is_code) {
+ menus[i]->info->name_is_code = 1;
+ fprintf(out_file, "static void menu_%d_legend("
+ "menudesc *menu, int opt, void *arg)\n{\n"
+ "\tswitch (opt) {\n", i);
+ for (j = 0, toptn = menus[i]->info->optns; toptn;
+ toptn = toptn->next, j++) {
+ if (!toptn->name_is_code)
+ continue;
+ fprintf(out_file, "\tcase %d:\n\t\t{%s};\n"
+ "\t\tbreak;\n", j, toptn->name);
+ }
+ fprintf(out_file, "\t}\n}\n\n");
+ }
+ }
+
+
+ /* menus */
+ if (!do_dynamic)
+ (void)fprintf(out_file, "static int num_menus = %d;\n",
+ menu_no);
+
+ (void)fprintf(out_file, "static struct menudesc menu_def[] = {\n");
+ for (i = 0; i < menu_no; i++) {
+ (void)fprintf(out_file,
+ "\t{%s,%d,%d,%d,%d,%d,%d,0,0,optent%d,NULL,NULL,",
+ menus[i]->info->title, menus[i]->info->y,
+ menus[i]->info->x, menus[i]->info->h,
+ menus[i]->info->w, menus[i]->info->mopt,
+ menus[i]->info->numopt, i);
+ if (menus[i]->info->helpstr == NULL)
+ (void)fprintf(out_file, "NULL");
+ else {
+ tmpstr = menus[i]->info->helpstr;
+ if (*tmpstr != '"')
+ (void)fprintf(out_file, "%s", tmpstr);
+ else {
+ /* Skip an initial newline. */
+ if (tmpstr[1] == '\n')
+ *++tmpstr = '"';
+ (void)fprintf(out_file, "\n");
+ while (*tmpstr) {
+ if (*tmpstr != '\n') {
+ fputc(*tmpstr++, out_file);
+ continue;
+ }
+ (void)fprintf(out_file, "\\n\"\n\"");
+ tmpstr++;
+ }
+ }
+ }
+ (void)fprintf(out_file, ",");
+ if (menus[i]->info->mopt & MC_NOEXITOPT)
+ (void) fprintf (out_file, "NULL");
+ else if (menus[i]->info->exitstr != NULL)
+ (void)fprintf(out_file, "%s", menus[i]->info->exitstr);
+ else
+ (void)fprintf(out_file, "\"Exit\"");
+ if (strlen(menus[i]->info->postact.code))
+ (void)fprintf(out_file, ",menu_%d_postact", i);
+ else
+ (void)fprintf(out_file, ",NULL");
+ if (strlen(menus[i]->info->exitact.code))
+ (void)fprintf(out_file, ",menu_%d_exitact", i);
+ else
+ (void)fprintf(out_file, ",NULL");
+ if (menus[i]->info->name_is_code)
+ (void)fprintf(out_file, ",menu_%d_legend", i);
+ else
+ (void)fprintf(out_file, ",NULL");
+
+ (void)fprintf(out_file, "},\n");
+
+ }
+ (void)fprintf(out_file, "{NULL, 0, 0, 0, 0, 0, 0, 0, 0, "
+ "NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};\n\n");
+
+ /* __menu_initerror: initscr failed. */
+ (void)fprintf(out_file,
+ "/* __menu_initerror: initscr failed. */\n"
+ "void __menu_initerror (void) {\n");
+ if (error_act.code == NULL) {
+ (void)fprintf(out_file,
+ "\t(void) fprintf (stderr, "
+ "\"%%s: Could not initialize curses\\n\", "
+ "getprogname());\n"
+ "\texit(1);\n"
+ "}\n");
+ } else {
+ if (error_act.endwin)
+ (void)fprintf(out_file, "\tendwin();\n");
+ (void)fprintf(out_file, "%s\n}\n", error_act.code);
+ }
+
+ /* Copy menu_sys.def file. */
+ while ((ch = fgetc(sys_file)) != '\014') /* Control-L */
+ fputc(ch, out_file);
+
+ if (do_dynamic) {
+ while ((ch = fgetc(sys_file)) != '\n')
+ /* skip it */;
+ while ((ch = fgetc(sys_file)) != EOF)
+ fputc(ch, out_file);
+ }
+ fclose(out_file);
+ fclose(sys_file);
+}
--- /dev/null
+/* $NetBSD: mdb.h,v 1.9 2012/03/06 16:55:18 mbalmer Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* mdb.h - definitions for the menu database. */
+
+#ifndef MDB_H
+#define MDB_H
+
+/* forward declaration */
+typedef struct menu_info menu_info;
+
+/* The declarations for the balanced binary trees. */
+
+typedef struct id_rec {
+ /* The balanced binary tree fields. */
+ char *id; /* The name. */
+ short balance; /* For the balanced tree. */
+ struct id_rec *left, *right; /* Tree pointers. */
+
+ /* Other information fields. */
+ menu_info *info;
+ int menu_no;
+} id_rec;
+
+
+/* menu definitions records. */
+
+typedef struct action {
+ char *code;
+ int endwin;
+} action;
+
+typedef struct optn_info {
+ char *name;
+ int name_is_code;
+ int menu;
+ int issub;
+ int doexit;
+ action optact;
+ struct optn_info *next;
+} optn_info;
+
+struct menu_info {
+ char *title;
+ char *helpstr;
+ char *exitstr;
+ int mopt;
+ int y, x;
+ int h, w;
+ int numopt;
+ int name_is_code;
+ optn_info *optns;
+ action postact;
+ action exitact;
+};
+
+/* defines for mopt */
+#define MC_NOEXITOPT 1
+#define MC_NOBOX 2
+#define MC_SCROLL 4
+#define MC_NOSHORTCUT 8
+#define MC_NOCLEAR 16
+#define MC_DFLTEXIT 32
+#define MC_ALWAYS_SCROLL 64
+#define MC_SUBMENU 128
+#define MC_VALID 0x10000
+#endif
--- /dev/null
+/* $NetBSD: menu_sys.def,v 1.59 2012/03/06 16:55:18 mbalmer Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* menu_sys.defs -- Menu system standard routines. */
+
+#include <string.h>
+#include <ctype.h>
+
+#define REQ_EXECUTE 1000
+#define REQ_NEXT_ITEM 1001
+#define REQ_PREV_ITEM 1002
+#define REQ_REDISPLAY 1003
+#define REQ_SCROLLDOWN 1004
+#define REQ_SCROLLUP 1005
+#define REQ_HELP 1006
+
+/* Macros */
+#define MAX(x,y) ((x)>(y)?(x):(y))
+#define MIN(x,y) ((x)<(y)?(x):(y))
+
+/* Initialization state. */
+static int __menu_init = 0;
+static int max_lines = 0, max_cols = 0;
+#ifndef scrolltext
+static const char *scrolltext = " <: page up, >: page down";
+#endif
+
+#ifdef DYNAMIC_MENUS
+static int num_menus = 0;
+#define DYN_INIT_NUM 32
+static menudesc **menu_list;
+#define MENUS(n) (*(menu_list[n]))
+#else
+#define MENUS(n) (menu_def[n])
+#endif
+
+/* prototypes for in here! */
+static void init_menu(menudesc *m);
+static char opt_ch(menudesc *m, int op_no);
+static void draw_menu(menudesc *m, void *arg);
+static void process_help(menudesc *m);
+static void process_req(menudesc *m, void *arg, int req);
+static int menucmd(WINDOW *w);
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* menu system processing routines */
+#define mbeep() (void)fputc('\a', stderr)
+
+static int
+menucmd(WINDOW *w)
+{
+ int ch;
+
+ while (TRUE) {
+ ch = wgetch(w);
+
+ switch (ch) {
+ case '\n':
+ return REQ_EXECUTE;
+ case '\016': /* Control-P */
+ case KEY_DOWN:
+ return REQ_NEXT_ITEM;
+ case '\020': /* Control-N */
+ case KEY_UP:
+ return REQ_PREV_ITEM;
+ case '\014': /* Control-L */
+ return REQ_REDISPLAY;
+ case '<':
+ case '\010': /* Control-H (backspace) */
+ case KEY_PPAGE:
+ case KEY_LEFT:
+ return REQ_SCROLLUP;
+ case '\026': /* Control-V */
+ case '>':
+ case ' ':
+ case KEY_NPAGE:
+ case KEY_RIGHT:
+ return REQ_SCROLLDOWN;
+ case '?':
+ return REQ_HELP;
+ case '\033': /* esc-v is scroll down */
+ ch = wgetch(w);
+ if (ch == 'v')
+ return REQ_SCROLLUP;
+ else
+ ch = 0; /* zap char so we beep */
+ }
+
+ if (isalpha(ch))
+ return ch;
+
+ mbeep();
+ wrefresh(w);
+ }
+}
+
+static void
+init_menu(menudesc *m)
+{
+ int wmax;
+ int hadd, wadd, exithadd;
+ int i;
+ int x, y, w;
+ const char *title, *tp, *ep;
+
+ x = m->x;
+ y = m->y;
+ w = m->w;
+ wmax = 0;
+ hadd = ((m->mopt & MC_NOBOX) ? 0 : 2);
+ wadd = ((m->mopt & MC_NOBOX) ? 2 : 4);
+ if (!(m->mopt & MC_NOSHORTCUT))
+ wadd += 3;
+
+ if (m->title && *(title = MSG_XLAT(m->title)) != 0) {
+ /* Allow multiple line titles */
+ for (tp = title; (ep = strchr(tp, '\n')); tp = ep + 1) {
+ i = ep - tp;
+ wmax = MAX(wmax, i);
+ hadd++;
+ }
+ hadd++;
+ i = strlen(tp);
+ wmax = MAX(wmax, i);
+ if (i != 0)
+ hadd++;
+ } else {
+ m->title = NULL;
+ title = "untitled";
+ }
+ exithadd = ((m->mopt & MC_NOEXITOPT) ? 0 : 1);
+
+#ifdef MSG_DEFS_H
+ if (y < 0) {
+ /* put menu box below message text */
+ y = -y;
+ i = msg_row();
+ if (i > y)
+ y = i;
+ }
+#endif
+
+ /* Calculate h? h == number of visible options. */
+ if (m->h == 0)
+ m->h = m->numopts + exithadd;
+
+ if (m->h > max_lines - y - hadd) {
+ /* Not enough space for all the options */
+ if (m->h <= 4 || !(m->mopt & (MC_SCROLL | MC_ALWAYS_SCROLL))) {
+ /* move menu up screen */
+ y = max_lines - hadd - m->h;
+ if (y < 0)
+ y = 0;
+ }
+ m->h = max_lines - y - hadd;
+ }
+
+ if (m->h < m->numopts + exithadd || m->mopt & MC_ALWAYS_SCROLL) {
+ /* We need to add the scroll text...
+ * The used to be a check for MC_SCROLL here, but it is
+ * fairly pointless - you just don't want the program
+ * to exit on this sort of error.
+ */
+ if (m->h < 3) {
+ endwin();
+ (void)fprintf(stderr,
+ "Window too short (m->h %d, m->numopts %d, exithadd %d, y %d, max_lines %d, hadd %d) for menu \"%.30s\"\n",
+ m->h, m->numopts, exithadd, y, max_lines, hadd,
+ title);
+ exit(1);
+ }
+ hadd++;
+ m->h = MIN(m->h, max_lines - y - hadd);
+ i = strlen(scrolltext);
+ wmax = MAX(wmax, i);
+ }
+
+ /* Calculate w? */
+ if (w == 0) {
+ int l;
+ for (i = 0; i < m->numopts; i++) {
+ tp = MSG_XLAT(m->opts[i].opt_name);
+ if (tp == NULL)
+ continue;
+ l = strlen(tp);
+ wmax = MAX(wmax, l);
+ }
+ w = wmax;
+ }
+
+ /* check and adjust for screen fit */
+ if (w + wadd > max_cols) {
+ endwin();
+ (void)fprintf(stderr,
+ "Screen too narrow (%d + %d > %d) for menu \"%s\"\n",
+ w, wadd, max_cols, title);
+ exit(1);
+
+ }
+
+ if (x == -1)
+ x = (max_cols - (w + wadd)) / 2; /* center */
+ else if (x + w + wadd > max_cols)
+ x = max_cols - (w + wadd); /* right align */
+
+ if (y == 0) {
+ /* Center - rather than top */
+ y = (max_lines - hadd - m->h) / 2;
+ }
+
+ /* Get the windows. */
+ m->mw = newwin(m->h + hadd, w + wadd, y, x);
+
+ if (m->mw == NULL) {
+ endwin();
+ (void)fprintf(stderr,
+ "Could not create window (%d + %d, %d + %d, %d, %d) for menu \"%s\"\n",
+ m->h, hadd, w, wadd, y, x, title);
+ exit(1);
+ }
+ keypad(m->mw, TRUE); /* enable multi-key assembling for win */
+
+ /* XXX is it even worth doing this right? */
+ if (has_colors()) {
+ wbkgd(m->mw, COLOR_PAIR(1));
+ wattrset(m->mw, COLOR_PAIR(1));
+ }
+
+ if (m->mopt & MC_SUBMENU) {
+ /* Keep a copy of what is on the screen under the window */
+ m->sv_mw = newwin(m->h + hadd, w + wadd, y, x);
+ /*
+ * cursrc contains post-doupdate() data, not post-refresh()
+ * data so we must call doupdate to ensure we save the
+ * correct data. Avoids PR 26660.
+ */
+ doupdate();
+ if (m->sv_mw)
+ overwrite(curscr, m->sv_mw);
+ }
+}
+
+static char
+opt_ch(menudesc *m, int op_no)
+{
+ char c;
+
+ if (op_no == m->numopts)
+ return 'x';
+
+ if (op_no < 25) {
+ c = 'a' + op_no;
+ if (c >= 'x')
+ c++;
+ } else
+ c = 'A' + op_no - 25;
+ return c;
+}
+
+static void
+draw_menu_line(menudesc *m, int opt, int cury, void *arg, const char *text)
+{
+ int hasbox = m->mopt & MC_NOBOX ? 0 : 1;
+
+ if (m->cursel == opt) {
+ mvwaddstr(m->mw, cury, hasbox, ">");
+ wstandout(m->mw);
+ } else
+ mvwaddstr(m->mw, cury, hasbox, " ");
+ if (!(m->mopt & MC_NOSHORTCUT))
+ wprintw(m->mw, "%c: ", opt_ch(m, opt));
+
+ if (!text && m->draw_line)
+ m->draw_line(m, opt, arg);
+ else
+ waddstr(m->mw, MSG_XLAT(text));
+ if (m->cursel == opt)
+ wstandend(m->mw);
+}
+
+static void
+draw_menu(menudesc *m, void *arg)
+{
+ int opt;
+ int hasbox, cury, maxy;
+ int tadd;
+ int hasexit = (m->mopt & MC_NOEXITOPT ? 0 : 1);
+ const char *tp, *ep;
+
+ hasbox = (m->mopt & MC_NOBOX ? 0 : 1);
+
+ /* Clear the window */
+ wclear(m->mw);
+
+ tadd = hasbox;
+ if (m->title) {
+ for (tp = MSG_XLAT(m->title); ; tp = ep + 1) {
+ ep = strchr(tp , '\n');
+ mvwaddnstr(m->mw, tadd++, hasbox + 1, tp,
+ ep ? ep - tp : -1);
+ if (ep == NULL || *ep == 0)
+ break;
+ }
+ tadd++;
+ }
+
+ cury = tadd;
+ maxy = getmaxy(m->mw) - hasbox;
+ if (m->numopts + hasexit > m->h)
+ /* allow for scroll text */
+ maxy--;
+
+ if (m->cursel == -1) {
+ m->cursel = m->numopts;
+ if (m->h <= m->numopts)
+ m->topline = m->numopts + 1 - m->h;
+ }
+
+ while (m->cursel >= m->topline + m->h)
+ m->topline = MIN(m->topline + m->h,
+ m->numopts + hasexit - m->h);
+ while (m->cursel < m->topline)
+ m->topline = MAX(0, m->topline - m->h);
+
+ for (opt = m->topline; opt < m->numopts; opt++) {
+ if (cury >= maxy)
+ break;
+ draw_menu_line(m, opt, cury++, arg, m->opts[opt].opt_name);
+ }
+
+ /* Add the exit option. */
+ if (!(m->mopt & MC_NOEXITOPT)) {
+ if (cury < maxy)
+ draw_menu_line(m, m->numopts, cury++, arg, m->exitstr);
+ else
+ opt = 0;
+ }
+
+ /* Add the scroll line */
+ if (opt != m->numopts || m->topline != 0)
+ mvwaddstr(m->mw, cury, hasbox, scrolltext);
+
+ /* Add the box. */
+ if (!(m->mopt & MC_NOBOX))
+ box(m->mw, 0, 0);
+
+ wmove(m->mw, tadd + m->cursel - m->topline, hasbox);
+ wrefresh(m->mw);
+}
+
+
+static void
+/*ARGSUSED*/
+process_help(menudesc *m)
+{
+ const char *help = m->helpstr;
+ WINDOW *sv_curscr;
+ int lineoff = 0;
+ int curoff = 0;
+ int again;
+ int winin;
+
+ /* Is there help? */
+ if (!help) {
+ mbeep();
+ return;
+ }
+ sv_curscr = newwin(getmaxy(curscr), getmaxx(curscr), 0, 0);
+ if (!sv_curscr) {
+ mbeep();
+ return;
+ }
+ /*
+ * Save screen contents so we can restore before returning.
+ * cursrc contains post-doupdate() data, not post-refresh()
+ * data so we must call doupdate to ensure we save the
+ * correct data. Avoids PR 26660.
+ */
+ doupdate();
+ overwrite(curscr, sv_curscr);
+ touchwin(stdscr);
+
+ help = MSG_XLAT(help);
+ /* Display the help information. */
+ do {
+ if (lineoff < curoff) {
+ help = MSG_XLAT(m->helpstr);
+ curoff = 0;
+ }
+ while (*help && curoff < lineoff) {
+ if (*help == '\n')
+ curoff++;
+ help++;
+ }
+
+ wclear(stdscr);
+ mvwaddstr(stdscr, 0, 0,
+ "Help: exit: x, page up: u <, page down: d >");
+ mvwaddstr(stdscr, 2, 0, help);
+ wmove(stdscr, 1, 0);
+ wrefresh(stdscr);
+
+ do {
+ winin = wgetch(stdscr);
+ if (winin < KEY_MIN)
+ winin = tolower(winin);
+ again = 0;
+ switch (winin) {
+ case '<':
+ case 'u':
+ case KEY_UP:
+ case KEY_LEFT:
+ case KEY_PPAGE:
+ if (lineoff)
+ lineoff -= max_lines - 2;
+ else
+ again = 1;
+ break;
+ case '>':
+ case 'd':
+ case KEY_DOWN:
+ case KEY_RIGHT:
+ case KEY_NPAGE:
+ if (*help)
+ lineoff += max_lines - 2;
+ else
+ again = 1;
+ break;
+ case 'q':
+ break;
+ case 'x':
+ winin = 'q';
+ break;
+ default:
+ again = 1;
+ }
+ if (again)
+ mbeep();
+ } while (again);
+ } while (winin != 'q');
+
+ /* Restore the original screen contents */
+ touchwin(sv_curscr);
+ wnoutrefresh(sv_curscr);
+ delwin(sv_curscr);
+
+ /* Some code thinks that wrefresh(stdout) is a good idea... */
+ wclear(stdscr);
+}
+
+static void
+process_req(menudesc *m, void *arg, int req)
+{
+ int ch;
+ int hasexit = (m->mopt & MC_NOEXITOPT ? 0 : 1);
+
+ switch(req) {
+
+ case REQ_EXECUTE:
+ return;
+
+ case REQ_NEXT_ITEM:
+ ch = m->cursel;
+ for (;;) {
+ ch++;
+ if (ch >= m->numopts + hasexit) {
+ mbeep();
+ return;
+ }
+ if (hasexit && ch == m->numopts)
+ break;
+ if (!(m->opts[ch].opt_flags & OPT_IGNORE))
+ break;
+ }
+ m->cursel = ch;
+ if (m->cursel >= m->topline + m->h)
+ m->topline = m->cursel - m->h + 1;
+ break;
+
+ case REQ_PREV_ITEM:
+ ch = m->cursel;
+ for (;;) {
+ if (ch <= 0) {
+ mbeep();
+ return;
+ }
+ ch--;
+ if (!(m->opts[ch].opt_flags & OPT_IGNORE))
+ break;
+ }
+ m->cursel = ch;
+ if (m->cursel < m->topline)
+ m->topline = m->cursel;
+ break;
+
+ case REQ_HELP:
+ process_help(m);
+ break;
+
+ case REQ_REDISPLAY:
+ endwin();
+ doupdate();
+ break;
+
+ case REQ_SCROLLUP:
+ if (m->cursel == 0) {
+ mbeep();
+ return;
+ }
+ m->topline = MAX(0, m->topline - m->h);
+ m->cursel = MAX(0, m->cursel - m->h);
+ wclear(m->mw);
+ break;
+
+ case REQ_SCROLLDOWN:
+ if (m->cursel >= m->numopts + hasexit - 1) {
+ mbeep();
+ return;
+ }
+ m->topline = MIN(m->topline + m->h,
+ MAX(m->numopts + hasexit - m->h, 0));
+ m->cursel = MIN(m->numopts + hasexit - 1, m->cursel + m->h);
+ wclear(m->mw);
+ break;
+
+ default:
+ ch = req;
+ if (ch == 'x' && hasexit) {
+ m->cursel = m->numopts;
+ break;
+ }
+ if (m->mopt & MC_NOSHORTCUT) {
+ mbeep();
+ return;
+ }
+ if (ch > 'z')
+ ch = 255;
+ if (ch >= 'a') {
+ if (ch > 'x')
+ ch--;
+ ch = ch - 'a';
+ } else
+ ch = 25 + ch - 'A';
+ if (ch < 0 || ch >= m->numopts) {
+ mbeep();
+ return;
+ }
+ if (m->opts[ch].opt_flags & OPT_IGNORE) {
+ mbeep();
+ return;
+ }
+ m->cursel = ch;
+ }
+
+ draw_menu(m, arg);
+}
+
+int
+menu_init(void)
+{
+ int i;
+
+ if (__menu_init)
+ return 0;
+
+#ifdef USER_MENU_INIT
+ if (USER_MENU_INIT)
+ return 1;
+#endif
+
+ if (initscr() == NULL)
+ return 1;
+
+ cbreak();
+ noecho();
+
+ /* XXX Should be configurable but it almost isn't worth it. */
+ if (has_colors()) {
+ start_color();
+ init_pair(1, COLOR_WHITE, COLOR_BLUE);
+ bkgd(COLOR_PAIR(1));
+ attrset(COLOR_PAIR(1));
+ }
+
+ max_lines = getmaxy(stdscr);
+ max_cols = getmaxx(stdscr);
+ keypad(stdscr, TRUE);
+#ifdef DYNAMIC_MENUS
+ num_menus = DYN_INIT_NUM;
+ while (num_menus < DYN_MENU_START)
+ num_menus *= 2;
+ menu_list = malloc(sizeof *menu_list * num_menus);
+ if (menu_list == NULL)
+ return 2;
+ (void)memset(menu_list, 0, sizeof *menu_list * num_menus);
+ for (i = 0; i < DYN_MENU_START; i++)
+ menu_list[i] = &menu_def[i];
+#endif
+
+ __menu_init = 1;
+ return 0;
+}
+
+void
+process_menu(int num, void *arg)
+{
+ int sel = 0;
+ int req;
+ menu_ent *opt;
+
+ menudesc *m;
+
+ /* Initialize? */
+ if (menu_init()) {
+ __menu_initerror();
+ return;
+ }
+
+ if (num < 0 || num >= num_menus)
+ return;
+ m = &MENUS(num);
+ if (m == NULL)
+ return;
+
+ /* Default to select option 0 and display from 0 */
+ m->topline = 0;
+ if ((m->mopt & (MC_DFLTEXIT | MC_NOEXITOPT)) == MC_DFLTEXIT)
+ m->cursel = -1;
+ else
+ m->cursel = 0;
+
+ for (;;) {
+ if (isendwin())
+ /* I'm not sure this is needed with netbsd's curses */
+ doupdate();
+ /* Process the display action */
+ if (m->post_act)
+ (*m->post_act)(m, arg);
+ if (m->mw == NULL)
+ init_menu(m);
+ draw_menu(m, arg);
+
+ while ((req = menucmd(m->mw)) != REQ_EXECUTE)
+ process_req(m, arg, req);
+
+ sel = m->cursel;
+ if (!(m->mopt & MC_NOCLEAR)) {
+ wclear(m->mw);
+ if (m->sv_mw)
+ overwrite(m->sv_mw, m->mw);
+ wnoutrefresh(m->mw);
+ }
+
+ /* Process the items */
+ if (sel >= m->numopts)
+ /* exit option */
+ break;
+
+ opt = &m->opts[sel];
+ if (opt->opt_flags & OPT_IGNORE)
+ continue;
+ if (opt->opt_flags & OPT_ENDWIN)
+ endwin();
+ if (opt->opt_action && (*opt->opt_action)(m, arg))
+ break;
+
+ if (opt->opt_menu != -1) {
+ if (!(opt->opt_flags & OPT_SUB)) {
+ num = opt->opt_menu;
+ wclear(m->mw);
+ if (m->sv_mw) {
+ overwrite(m->sv_mw, m->mw);
+ delwin(m->sv_mw);
+ m->sv_mw = NULL;
+ }
+ wnoutrefresh(m->mw);
+ delwin(m->mw);
+ m->mw = NULL;
+ m = &MENUS(num);
+ continue;
+ }
+ process_menu(opt->opt_menu, arg);
+ }
+ if (opt->opt_flags & OPT_EXIT)
+ break;
+ }
+
+ if (m->mopt & MC_NOCLEAR) {
+ wclear(m->mw);
+ if (m->sv_mw)
+ overwrite(m->sv_mw, m->mw);
+ wnoutrefresh(m->mw);
+ }
+
+ /* Process the exit action */
+ if (m->exit_act)
+ (*m->exit_act)(m, arg);
+ delwin(m->mw);
+ m->mw = NULL;
+ if (m->sv_mw) {
+ delwin(m->sv_mw);
+ m->sv_mw = NULL;
+ }
+}
+
+
+void
+set_menu_numopts(int menu, int numopts)
+{
+
+ MENUS(menu).numopts = numopts;
+}
+
+\f/* Control L is end of standard routines, remaining only for dynamic. */
+
+/* Beginning of routines for dynamic menus. */
+
+static int
+double_menus(void)
+{
+ menudesc **temp;
+ int sz = sizeof *menu_list * num_menus;
+
+ temp = realloc(menu_list, sz * 2);
+ if (temp == NULL)
+ return 0;
+ (void)memset(temp + num_menus, 0, sz);
+ menu_list = temp;
+ num_menus *= 2;
+
+ return 1;
+}
+
+int
+new_menu(const char *title, menu_ent *opts, int numopts,
+ int x, int y, int h, int w, int mopt,
+ void (*post_act)(menudesc *, void *),
+ void (*draw_line)(menudesc *, int, void *),
+ void (*exit_act)(menudesc *, void *),
+ const char *help, const char *exit_str)
+{
+ int ix;
+ menudesc *m;
+
+ /* Find free menu entry. */
+ for (ix = DYN_MENU_START; ; ix++) {
+ if (ix >= num_menus && !double_menus())
+ return -1;
+ m = menu_list[ix];
+ if (m == NULL) {
+ m = calloc(sizeof *m, 1);
+ if (m == NULL)
+ return -1;
+ menu_list[ix] = m;
+ break;
+ }
+ if (!(m->mopt & MC_VALID))
+ break;
+ }
+
+ /* Set Entries */
+ m->title = title;
+ m->opts = opts;
+ m->numopts = numopts;
+ m->x = x;
+ m->y = y;
+ m->h = h;
+ m->w = w;
+ m->mopt = mopt | MC_VALID;
+ m->post_act = post_act;
+ m->draw_line = draw_line;
+ m->exit_act = exit_act;
+ m->helpstr = help;
+ m->exitstr = exit_str ? exit_str : "Exit";
+
+ return ix;
+}
+
+void
+free_menu(int menu_no)
+{
+ menudesc *m;
+
+ if (menu_no < 0 || menu_no >= num_menus)
+ return;
+
+ m = menu_list[menu_no];
+ if (!(m->mopt & MC_VALID))
+ return;
+ if (m->mw != NULL)
+ delwin(m->mw);
+ memset(m, 0, sizeof *m);
+}
--- /dev/null
+.\" $NetBSD: menuc.1,v 1.30 2012/03/06 16:55:18 mbalmer Exp $
+.\"
+.\" Copyright 1997 Piermont Information Systems Inc.
+.\" All rights reserved.
+.\"
+.\" Written by Philip A. Nelson for Piermont Information Systems Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. The name of Piermont Information Systems Inc. may not be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd August 2, 2004
+.Dt MENUC 1
+.Os
+.Sh NAME
+.Nm menuc
+.Nd menu compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl o Ar name
+.Ar file
+.Sh DESCRIPTION
+This implements a curses based menu system.
+A source file that describes menus, their options, and how to process
+the options is given to
+.Nm
+and produces both a .c and a .h file that implement the menu system.
+The standard base name of the files is
+.Pa menu_defs .
+The
+.Fl o Ar name
+can be used to specify a different base name.
+.Sh ENVIRONMENT
+.Bl -tag -width MENUDEF
+.It Ev MENUDEF
+Can be set to point to a different set of definition files for
+.Nm .
+The current location defaults to
+.Pa /usr/share/misc .
+.El
+.Sh MENU DESCRIPTIONS
+The input
+.Ar file
+defines static menus and options for processing those menus.
+It also contains comments, initial C code that is required to provide
+for definitions and other code necessary for the menu system, and an
+option declaration if dynamic menus are requested.
+.Pp
+Comments may appear anywhere in the input
+.Ar file
+and are like a space in the input.
+They are like C comments starting with
+.Em /*
+and ending with
+.Em */ .
+They are unlike C comments in that they may be nested.
+A comment does not end until a matching end comment is found.
+.Pp
+In many places, C code is included in the definition
+.Ar file .
+All C code is passed verbatim to the C output file.
+.Nm
+comments do not start in C code and comments in the C code are
+passed verbatim to the output.
+The C comments are not recognized by
+.Nm .
+In all cases, C code starts with a left brace
+.Pq Em \&{
+and ends with the matching right brace
+.Pq Em \&} .
+It is important to recognize that in code segments, any brace
+will be counted, even if it is in a C comment inside the code.
+.Pp
+The
+.Ar file
+contains an initial (and optional) code block followed by any
+number of menu definition elements in any order.
+The initial code block usually contains includes of header files used by
+code in the menu code blocks later in the
+.Ar file .
+If
+.Dv USER_MENU_INIT
+is #defined, then it will be evaluated before the
+rest of the menu is initialised, if it evaluates to a non-zero value
+then the initialisation will fail.
+The file is free format, so the actual formatting of the input
+.Ar file
+is to the taste of the programmer.
+.Pp
+All other C code that will appear in an
+.Em action .
+This will be specified as
+.Aq Em action
+in later text.
+Such an action will appear as:
+.Dl action \*[Lt]opt_endwin\*[Gt] \*[Lt]code\*[Gt]
+in the
+.Ar file .
+The
+.Aq Em opt_endwin ,
+if present is:
+.Dl ( endwin )
+and specifies that the curses
+.Fn endwin
+function should be called before executing the code and
+then reinstating the current curses window after the
+code has been run.
+The
+.Aq Em code
+is as described above.
+.Pp
+There are four kinds of menu definition elements.
+The first one just declares whether the programmer wants dynamic menus
+available.
+The default is static menus only.
+The static menus are the ones defined by the menu definitions and do not
+change at run time.
+The dynamic menus provide the programmer with a method to create and
+modify menus during the running of the program.
+To include dynamic menus, one needs only add the declaration:
+.Dl allow dynamic menus ;
+The semicolon is required to terminate this declaration.
+This declaration may appear anywhere in the
+.Ar file ,
+but usually appears before any menus are defined.
+.Pp
+The next element is a code block to execute if the curses
+screen can not be successfully initialized.
+The declaration
+.Dl error code ;
+tells the menu system to execute the associated code block
+if the initialization fails.
+If no code is provided, a default code block is used that prints
+.Dl Could not initialize curses.
+and exits.
+This element may appear anywhere in the
+.Ar file
+but usually appears before any menus are defined.
+.Pp
+The next element defines default options for menus.
+Each menu is built from a list of options.
+These options include the location of the upper left corner of the menu,
+whether there is a "box" drawn around the menu, whether the menu is
+scrollable, the menu's title, whether shortcut letters are
+allowed, whether a standard exit option should be included
+in the menu and text associated with the standard exit option.
+The general format is:
+.Dl default \*[Lt]comma separated option list\*[Gt] ;
+.Pp
+The supported options are:
+.Bl -tag -width ".Ic exitstring Va text"
+.It Ic x = Va startx
+The column number of the upper left corner of the menu window.
+If
+.Va startx
+is -1 the menu will be centered horizontally.
+.It Ic y = Va starty
+The row number of the upper left corner of the menu window.
+If
+.Va starty
+is negative then the menu will be placed below any message text, but
+in at least row
+.Va -starty .
+.It Ic h = Va height
+Specifies the number of menu entries to be displayed.
+If zero, the height will be based on the number of entries.
+.It Ic h = Va width
+Specifies the width of the menu window.
+If zero, the width will be that of the longest menu text line.
+.It Ic title Va text
+The specified
+.Va text
+will be displayed at the top of the menu window (inside any box).
+.It Ic box
+If specified, draw a box around the menu.
+.It Ic clear
+If specified, clear the window before performing the
+.Va action .
+.It Ic exit
+If specified add an addition option to exit the menu.
+.It Ic exitstring Va text
+The menu label for the
+.Va exit
+option.
+If not specified defaults to "exit".
+.It Ic default exit
+If specified, place the cursor on the
+.Va exit
+line of the menu, instead of the top line.
+.It Ic shortcut
+If specified, add alphabetic tags to each menu line.
+.It Ic scrollable
+If specified, and the menu has more lines than will fit in its window, then
+only part of the menu will be displayed and the
+.Sq \*[Lt]
+and
+.Sq \*[Gt]
+keys will scroll the displayed menu lines.
+.It Ic always scroll
+If specified, allow for the scroll message line even if the menu doesn't
+appear to have too many lines.
+Useful for dynamic menus, when the number of entries isn't known when the
+menu window is created..
+.It Ic sub menu
+If specified, the screen contents that the menu window overwrites are saved
+and restored when the menu exits.
+.El
+The
+.Ic box , clear , exit , default exit , shortcut , scrollable , always scroll ,
+and
+.Ic sub menu
+options can be preceded by
+.Ic no
+in order to negate a default.
+.Pp
+The
+.Va text
+arguments can be either a quoted text string or a name #defined to something
+suitable for initialising a const char * field.
+.Pp
+The default declaration may appear multiple times.
+Each time, it sets the default values for menu definitions that follow
+in the
+.Ar file .
+In each menu definition, any or all of these default definitions
+may be overridden for that menu.
+.Pp
+The final element is the actual static menu definitions.
+The format and order for a menu definition is:
+.Bd -ragged -offset indent
+menu \*[Lt]name\*[Gt] \*[Lt]options\*[Gt] ;
+ \*[Lt]display action\*[Gt]
+ \*[Lt]menu items\*[Gt]
+ \*[Lt]exit action\*[Gt]
+ \*[Lt]help text\*[Gt]
+.Ed
+.Pp
+Names are unquoted strings of alpha-numeric and underscore
+characters.
+They must start with an alpha character.
+In C source, a menu named
+.Dq foo
+is appears as
+.Dq MENU_foo .
+(Capitalization is important.)
+This is important, because the menu is displayed and processed by
+calling the function
+.Dl process_menu (MENU_foo, arg) ;
+.Pp
+The options are a comma separated list of options as in the
+.Dq default
+declaration.
+These override the options from the most recent default declaration.
+.Pp
+The display action is optional and provides C code to
+execute at each and every time the menu is displayed for processing.
+If it is included, the format is:
+.Dl display \*[Lt]action\*[Gt] ;
+.Pp
+The bulk of the menu definition is the specification
+of the menu items.
+The general format of a menu item is:
+.Dl option \*[Lt]string\*[Gt], \*[Lt]element_list\*[Gt] ;
+The
+.Aq Em string
+is the text displayed for the menu item, this must be a quoted string
+or a name #defined to something that will initialise a const char * field.
+There may be an arbitrary number of these items.
+(If there are shortcuts in the menu, a practical limit
+of 51 should be recognized.
+It produces shortcuts a to w, y, z, and A to Z.
+x is the shortcut for the exit item.)
+.Pp
+The
+.Aq Em element_list
+is a comma separated list of what to do when the item is selected.
+They may appear in any order.
+.Pp
+The first element processed when a menu item
+is selected is the associated action.
+The next element to be processed is the sub or next menu option.
+They are declared as:
+.Dl next menu \*[Lt]name\*[Gt]
+.Dl sub menu \*[Lt]name\*[Gt]
+The difference between these two is that a sub
+menu will return to the current menu when exited.
+The next menu will just replace the current
+menu and when exited, will return to where the
+current menu would have gone.
+Only one of menu element may be used for each menu item.
+Finally, after processing both the action and a sub menu,
+the current menu will be exited if the element
+.Dl exit
+is specified.
+.Em Note :
+If
+.Em exit
+is specified, next menu will not work because
+the menu system will exit the
+.Em current
+menu, even if current has been set by
+.Em next menu .
+.Pp
+After all menu items, the final two menu definition
+elements may appear.
+The exit action is optional and provides C code to
+execute in the process of exiting a menu.
+If it is included, the format is:
+.Dl exit \*[Lt]action\*[Gt] ;
+.Pp
+The final part of the menu definition is the optional
+help string.
+The format is:
+.Dl help \*[Lt]text\*[Gt] ;
+This text is displayed in a full page
+help window if the question mark is typed.
+The actual help text starts with a left brace
+.Pq Em \&{
+and ends with the matching right brace
+.Pq Em \&} .
+The braces are not included in the
+help string, but all other characters between
+them are included.
+Newlines in the code translate to newlines in the help text.
+Alternatively, the name of a const char * variable may be given.
+.Sh DYNAMIC MENUS
+If requested,
+.Nm
+supports dynamic menus by allowing the user to create new
+menus.
+The related definitions for using dynamic menus are:
+.Bd -literal
+struct menudesc;
+
+typedef
+struct menu_ent {
+ const char *opt_name;
+ int opt_menu;
+ int opt_flags;
+ int (*opt_action)(struct menudesc *, void *);
+} menu_ent ;
+
+/* For opt_menu */
+#define OPT_NOMENU -1
+
+/* For opt_flags */
+#define OPT_SUB 1
+#define OPT_ENDWIN 2
+#define OPT_EXIT 4
+
+typedef
+struct menudesc {
+ const char *title;
+ int y, x;
+ int h, w;
+ int mopt;
+ int numopts;
+ int cursel;
+ int topline;
+ menu_ent *opts;
+ WINDOW *mw;
+ WINDOW *sv_mw;
+ const char *helpstr;
+ const char *exitstr;
+ void (*post_act)(struct menudesc *, void *);
+ void (*exit_act)(struct menudesc *, void *);
+ void (*draw_line)(struct menudesc *, int, void *);
+} menudesc ;
+
+/* defines for mopt field. */
+#define MC_NOEXITOPT 1
+#define MC_NOBOX 2
+#define MC_SCROLL 4
+#define MC_NOSHORTCUT 8
+#define MC_NOCLEAR 16
+#define MC_DFLTEXIT 32
+#define MC_ALWAYS_SCROLL 64
+#define MC_SUBMENU 128
+
+int new_menu(const char *title, menu_ent *opts, int numopts,
+ int x, int y, int h, int w, int mopt,
+ void (*post_act)(struct menudesc *, void *),
+ void (*draw_line)(struct menudesc *, int, void *),
+ void (*exit_act)(struct menudesc *, void *),
+ const char *help, const char *exitstr);
+
+void free_menu (int menu_no);
+.Ed
+.Pp
+The
+.Ar title
+is the title displayed at the top of the menu.
+The
+.Ar opts
+is an array of menu entry definitions that has
+.Ar numopts
+elements.
+The programmer must build this array and
+fill in all of the fields before processing calling
+.Fn process_menu
+for the new menu.
+The fields of the
+.Ar opts
+may change at any time.
+For example,
+.Em opt_name
+may change as a result of selecting that option.
+When the menu is redisplayed, the new text is printed.
+Arguments,
+.Ar x , y , h ,
+and
+.Ar w
+are the same as the options in the menu description.
+.Ar mopt
+is the boolean options.
+Note, box, clear, exit and shortcuts are enabled by default.
+You need to add option flags to turn them off or turn on scrollable menus.
+The options
+.Ar post_act ,
+and
+.Ar exit_act
+are function pointers to the display action and the exit action.
+If they are
+.Dv NULL ,
+no call will be made.
+.Ar draw_line
+will be called to display the menu line if the corresponding opt_name
+field is
+.Dv NULL .
+.Ar help
+is the text to display in a help screen.
+And finally,
+.Ar exitstr
+is the text for the 'exit' line of the menu.
+If
+.Dv NULL ,
+"Exit" is used.
+A
+.Dv NULL
+help pointer will disable the help feature for the menu.
+.Sh FILES
+.Bl -item
+.It
+.Pa /usr/share/misc/menu_sys.def
+.El
+.Sh EXAMPLES
+The following is a simple menu definition file.
+It is complete in that the output of
+.Nm
+may be compiled into a complete program.
+For example, if the following was in a file called
+.Pa example.mc ,
+an executable program could be produced by the following commands.
+.Bd -literal -offset indent
+menuc -o example example.mc
+cc -o example example.c -lcurses
+.Ed
+A much more complete example is available with the source
+distribution in a subdirectory called
+.Em testm .
+.Bd -literal
+/* This is an example menu definition file for menuc. */
+
+{
+#include \*[Lt]stdio.h\*[Gt]
+#include \*[Lt]unistd.h\*[Gt]
+
+/* Main program! This is often in a different file. */
+int
+main()
+ {
+ process_menu (MENU_main, NULL);
+ endwin();
+ return 0;
+ }
+
+/* Example initialize function! */
+void
+init_main()
+ {
+ }
+}
+
+default x=20, y=10, box, scrollable, exit;
+
+error action {
+ fprintf (stderr, "Example Menu: Could not initialize curses.");
+ exit(1);
+};
+
+menu main, title "Main Menu", no exit, no shortcut;
+ display action { init_main(); };
+ option "Option 1",
+ action (endwin) {
+ printf ("That was option 1!");
+ sleep(3);
+ };
+ option "Sub Menu", sub menu othermenu;
+ option "Next Menu", next menu othermenu;
+ option "Quit", exit;
+ help {
+This is a simple help screen for an example menu definition file.
+};
+
+menu othermenu, title "Sub/Next Menu", x=5, y=5, no box;
+ option "Do Nothing!", action { };
+.Ed
+.Sh SEE ALSO
+.Xr msgc 1
+.Sh AUTHORS
+.An Philip A. Nelson
+for Piermont Information Systems Inc.
+Initial ideas for this were developed and implemented in Pascal at the
+Leiden University, Netherlands, in the summer of 1980.
+.Sh BUGS
+Both
+.Nm
+and
+.Nm msgc
+are probably only used by
+.Nm sysinst .
+The features of both have been tailored for
+.Nm sysinst ,
+and further changes are likely to occur.
--- /dev/null
+/* $NetBSD: parse.y,v 1.16 2012/03/06 16:55:18 mbalmer Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+%{
+
+#include <stdio.h>
+#include "defs.h"
+
+static id_rec *cur_menu;
+static optn_info *cur_optn;
+
+%}
+
+%union {
+ char *s_value;
+ int i_value;
+ optn_info *optn_value;
+ action a_value;
+}
+
+
+%token <i_value> X Y W H NO BOX SUB HELP MENU NEXT EXIT ACTION ENDWIN OPTION
+%token <i_value> TITLE DEFAULT DISPLAY ERROR EXITSTRING ALLOW DYNAMIC MENUS
+ SCROLLABLE SHORTCUT CLEAR MESSAGES ALWAYS SCROLL
+%token <s_value> STRING NAME CODE INT_CONST CHAR_CONST
+
+%type <s_value> init_code system helpstr text
+%type <optn_value> option option_list
+%type <i_value> act_opt
+%type <a_value> action exitact
+
+%start system
+
+%%
+
+system : init_code menu_list
+ { check_defined();
+ if (!had_errors)
+ write_menu_file($1);
+ }
+ ;
+
+init_code : /* empty */ { $$ = ""; }
+ | CODE
+ ;
+
+menu_list : /* empty */
+ | menu_list menu_def
+ | menu_list default_def
+ | menu_list initerror_def
+ | menu_list dynamic_def
+ | menu_list msgxlat_def
+ ;
+
+dynamic_def : ALLOW DYNAMIC MENUS ';'
+ { do_dynamic = 1; }
+
+msgxlat_def : ALLOW DYNAMIC MESSAGES ';'
+ { do_msgxlat = 1; }
+
+initerror_def : ERROR action ';'
+ { error_act = $2; }
+
+default_def : DEFAULT
+ { cur_menu = &default_menu; }
+ opt opt_list ";"
+
+menu_def : MENU NAME
+ { cur_menu = get_menu ($2);
+ if (cur_menu->info != NULL)
+ yyerror ("Menu %s defined twice", $2);
+ else {
+ cur_menu->info =
+ (menu_info *) malloc (sizeof (menu_info));
+ *(cur_menu->info) = default_info;
+ }
+ }
+ opts ";" dispact option_list exitact helpstr
+ { optn_info *t;
+ cur_menu->info->optns = NULL;
+ while ($7 != NULL) {
+ t = $7;
+ $7 = $7->next;
+ t->next = cur_menu->info->optns;
+ cur_menu->info->optns = t;
+ cur_menu->info->numopt++;
+ }
+ }
+ ;
+
+opts : /* empty */
+ | opt_list
+ ;
+
+opt_list : "," opt
+ | opt_list "," opt
+ ;
+
+text : NAME | STRING
+
+opt : NO EXIT { cur_menu->info->mopt |= MC_NOEXITOPT; }
+ | EXIT { cur_menu->info->mopt &= ~MC_NOEXITOPT; }
+ | NO BOX { cur_menu->info->mopt |= MC_NOBOX; }
+ | BOX { cur_menu->info->mopt &= ~MC_NOBOX; }
+ | NO SCROLLABLE { cur_menu->info->mopt &= ~MC_SCROLL; }
+ | SCROLLABLE { cur_menu->info->mopt |= MC_SCROLL; }
+ | NO SHORTCUT { cur_menu->info->mopt |= MC_NOSHORTCUT; }
+ | SHORTCUT { cur_menu->info->mopt &= ~MC_NOSHORTCUT; }
+ | NO CLEAR { cur_menu->info->mopt |= MC_NOCLEAR; }
+ | CLEAR { cur_menu->info->mopt &= ~MC_NOCLEAR; }
+ | NO DEFAULT EXIT { cur_menu->info->mopt &= ~MC_DFLTEXIT; }
+ | DEFAULT EXIT { cur_menu->info->mopt |= MC_DFLTEXIT; }
+ | NO ALWAYS SCROLL { cur_menu->info->mopt &= ~MC_ALWAYS_SCROLL; }
+ | ALWAYS SCROLL { cur_menu->info->mopt |= MC_ALWAYS_SCROLL; }
+ | NO SUB MENU { cur_menu->info->mopt &= ~MC_SUBMENU; }
+ | SUB MENU { cur_menu->info->mopt |= MC_SUBMENU; }
+ | X "=" INT_CONST { cur_menu->info->x = atoi($3); }
+ | Y "=" INT_CONST { cur_menu->info->y = atoi($3); }
+ | W "=" INT_CONST { cur_menu->info->w = atoi($3); }
+ | H "=" INT_CONST { cur_menu->info->h = atoi($3); }
+ | TITLE text { cur_menu->info->title = $2; }
+ | EXITSTRING text { cur_menu->info->exitstr = $2;
+ cur_menu->info->mopt &= ~MC_NOEXITOPT; }
+ ;
+
+option_list : option
+ | option_list option { $2->next = $1; $$ = $2; }
+ ;
+
+option : OPTION
+ { cur_optn = (optn_info *) malloc (sizeof(optn_info));
+ cur_optn->menu = -1;
+ cur_optn->name = NULL;
+ cur_optn->name_is_code = FALSE;
+ cur_optn->issub = FALSE;
+ cur_optn->doexit = FALSE;
+ cur_optn->optact.code = "";
+ cur_optn->optact.endwin = FALSE;
+ cur_optn->next = NULL;
+ }
+ option_legend ","
+ elem_list ";"
+ { $$ = cur_optn; }
+ ;
+
+option_legend : text { cur_optn->name = $1; }
+ | CODE { cur_optn->name = $1; cur_optn->name_is_code = TRUE;}
+
+elem_list : elem
+ | elem_list "," elem
+ ;
+
+elem : NEXT MENU NAME
+ { id_rec *t = get_menu ($3);
+ if (cur_optn->menu != -1)
+ yyerror ("Double sub/next menu definition");
+ else {
+ cur_optn->menu = t->menu_no;
+ }
+ }
+ | SUB MENU NAME
+ { id_rec *t = get_menu ($3);
+ if (cur_optn->menu != -1)
+ yyerror ("Double sub/next menu definition");
+ else {
+ cur_optn->menu = t->menu_no;
+ cur_optn->issub = TRUE;
+ }
+ }
+ | action { cur_optn->optact = $1; }
+ | EXIT { cur_optn->doexit = TRUE; }
+ ;
+
+action : ACTION act_opt CODE
+ { $$.code = $3;
+ $$.endwin = $2;
+ }
+ ;
+
+act_opt : /* empty */ { $$ = 0; }
+ | "(" ENDWIN ")" { $$ = 1; }
+ ;
+
+dispact : /* empty */ { cur_menu->info->postact.code = ""; }
+ | DISPLAY action ";" { cur_menu->info->postact = $2; }
+ ;
+
+
+exitact : /* empty */ { cur_menu->info->exitact.code = ""; }
+ | EXIT action ";" { cur_menu->info->exitact = $2; }
+ ;
+
+helpstr : /* empty */ { cur_menu->info->helpstr = NULL; }
+ | HELP CODE ";" { asprintf(&cur_menu->info->helpstr, "\"%s\"", $2); }
+ | HELP text ";" { cur_menu->info->helpstr = $2; }
+ ;
--- /dev/null
+/* $NetBSD: pathnames.h,v 1.1 2001/10/15 22:20:03 bjh21 Exp $ */
+
+#ifndef _PATH_DEFSYSPREFIX
+#define _PATH_DEFSYSPREFIX "/usr/share/misc"
+#endif
--- /dev/null
+/* $NetBSD: scan.l,v 1.16 2012/03/06 16:55:18 mbalmer Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+%{
+/* scan.l: scanner description for menu compiler. */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "parse.h"
+
+static int level; /* For nested comments. */
+static int comstart; /* line number of comment start. */
+
+%}
+
+%x COMMENT
+%x BRACE
+
+%option noinput
+
+%%
+
+[ \t]+ { /* ignore spaces and tabs */ }
+
+[\n] { line_no++; }
+
+"="|";"|","|"("|")" { return (int)yytext[0]; }
+
+x { return X; }
+
+y { return Y; }
+
+w { return W; }
+
+h { return H; }
+
+no { return NO; }
+
+box { return BOX; }
+
+sub { return SUB; }
+
+help { return HELP; }
+
+menu { return MENU; }
+
+menus { return MENUS; }
+
+next { return NEXT; }
+
+exit { return EXIT; }
+
+exitstring { return EXITSTRING; }
+
+title { return TITLE; }
+
+action { return ACTION; }
+
+endwin { return ENDWIN; }
+
+option { return OPTION; }
+
+default { return DEFAULT; }
+
+display { return DISPLAY; }
+
+error { return ERROR; }
+
+allow { return ALLOW; }
+
+dynamic { return DYNAMIC; }
+
+messages { return MESSAGES; }
+
+scrollable { return SCROLLABLE; }
+
+shortcut { return SHORTCUT; }
+
+clear { return CLEAR; }
+
+always { return ALWAYS; }
+
+scroll { return SCROLL; }
+
+\"([^\"\n]*(\\\")?)*\" {
+ yylval.s_value = strdup (yytext);
+ max_strlen = max_strlen > strlen(yytext)
+ ? max_strlen : strlen(yytext) + 1;
+ return STRING;
+ }
+
+[a-zA-Z][a-zA-Z0-9_]* {
+ yylval.s_value = strdup(yytext);
+ return(NAME);
+ }
+
+0|[-1-9][0-9]* {
+ yylval.s_value = strdup(yytext);
+ return(INT_CONST);
+ }
+
+"'"[^'\\]|(\\[athrn])|(\\[0-9][0-9]?[0-9]?)"'" {
+ yylval.s_value = strdup(yytext);
+ return(CHAR_CONST);
+ }
+
+"/*" { level = 1; comstart = line_no; BEGIN COMMENT; }
+
+<COMMENT>"/*" { level++; }
+
+<COMMENT>"*/" { if (level-- == 1) BEGIN 0; }
+
+<COMMENT>"\n" { line_no++; }
+
+<COMMENT><<EOF>> {
+ yyerror ("EOF inside a comment that started at line %d",
+ comstart);
+ exit (1);
+ }
+
+<COMMENT>. {/* eat character */}
+
+"{" { level = 1; BEGIN BRACE; }
+
+<BRACE>"{" { buff_add_ch(yytext[0]); level++; }
+
+<BRACE>"}" { if (level-- == 1) {
+ BEGIN 0;
+ yylval.s_value = buff_copy();
+ return CODE;
+ } else
+ buff_add_ch (yytext[0]);
+ }
+
+<BRACE>"\n" { buff_add_ch (yytext[0]); line_no++; }
+
+<BRACE>. { buff_add_ch (yytext[0]); }
+
+. {
+ if (yytext[0] < ' ')
+ yyerror ("illegal character: ^%c",yytext[0] + '@');
+ else
+ if (yytext[0] > '~')
+ yyerror ("illegal character: \\%3d", (int) yytext[0]);
+ else
+ yyerror ("illegal character: %s",yytext);
+
+ /* To quiet the compiler */
+ if (0) unput(0);
+ }
+%%
+
+#ifdef SCAN
+YYSTYPE yylval;
+
+main()
+{
+ int val;
+
+ line_no = 1;
+ while ( (val = yylex()) != 0 )
+ printf ("val = %d\n yytext = %s\n", val, yytext);
+}
+#endif
--- /dev/null
+# $NetBSD: Makefile,v 1.17 2012/04/21 12:27:29 roy Exp $
+
+NOMAN= # defined
+
+.include <bsd.own.mk>
+
+MENUCDIR!= cd $(.CURDIR)/..; ${PRINTOBJDIR}
+MENUC= ${MENUCDIR}/menuc
+${MENUC}:
+ cd ${.CURDIR}/..; ${MAKE}
+
+PROG= testm
+SRCS= msg_defs.c menu_defs.c main.c
+CFLAGS+=-g
+CPPFLAGS+=-I.
+LDADD+= -lcurses -lterminfo
+DPADD+= ${LIBCURSES}
+
+CLEANFILES+= menu_defs.c menu_defs.h msg_defs.c msg_defs.h
+
+menu_defs.c menu_defs.h: menus.mc ${MENUC} ${.CURDIR}/../menu_sys.def
+ MENUDEF=${.CURDIR}/.. ${MENUC} ${.CURDIR}/menus.mc
+
+msg_defs.c msg_defs.h: menus.msg
+ msgc ${.CURDIR}/menus.msg
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $NetBSD: main.c,v 1.6 2004/09/17 18:16:44 wrstuden Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software develooped for the NetBSD Project by
+ * Piermont Information Systems Inc.
+ * 4. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* main sysinst program. */
+
+#include "menu_defs.h"
+#include "msg_defs.h"
+
+int main(void);
+
+int main(void)
+{
+
+ /* Menu processing */
+ process_menu (MENU_root, NULL);
+
+ return 0;
+}
+
+/* Dynamic menu suff! */
+
+char ent_text[5][50] = {"name: ", "strt: ", "city: ", "opt 4", "NUM: "};
+
+/* opt processing routines .. */
+
+int opt_1 (struct menudesc *m, void *p);
+
+int opt_1 (struct menudesc *m, void *p)
+{
+ msg_clear();
+ msg_prompt (MSG_name, "", &ent_text[0][6], 40);
+ msg_clear();
+ return 0;
+}
+
+int opt_2 (struct menudesc *m, void *p);
+
+int opt_2 (struct menudesc *m, void *p)
+{
+ msg_clear();
+ msg_prompt (MSG_street, "", &ent_text[1][6], 40);
+ msg_clear();
+ return 0;
+}
+
+int opt_3 (struct menudesc *m, void *p);
+
+int opt_3 (struct menudesc *m, void *p)
+{
+ msg_clear();
+ msg_prompt (MSG_city, "", &ent_text[2][6], 40);
+ msg_clear();
+ return 0;
+}
+
+
+menu_ent mymenu [5] = {
+ { ent_text[0], OPT_NOMENU, 0, opt_1},
+ { ent_text[1], OPT_NOMENU, 0, opt_2},
+ { ent_text[2], OPT_NOMENU, 0, opt_3},
+ { ent_text[3], OPT_NOMENU, 0, NULL},
+ { ent_text[4], OPT_NOMENU, 0, NULL} };
+
+int num = 0;
+
+
+void do_dynamic(void);
+void dyn_disp (struct menudesc *, void *);
+void dyn_disp (struct menudesc *m, void *p)
+{
+ sprintf (&ent_text[4][5], "%d", num++);
+}
+
+void do_dynamic(void)
+{
+ int menu_no;
+
+ num = 0;
+ menu_no = new_menu (" A test dynamic menu! ", mymenu, 5, 10, 10,
+ 0, 55, MC_SCROLL, dyn_disp, NULL, NULL,
+ "Make sure you try at least one option before exiting.\n"
+ "Then look at what changes.\n", "Done now!");
+ if (menu_no < 0) {
+ endwin();
+ (void) fprintf (stderr, "Dynamic memu creation failure. \n");
+ exit (1);
+ }
+ process_menu (menu_no, NULL);
+ free_menu (menu_no);
+}
+
--- /dev/null
+/* $NetBSD: menus.mc,v 1.11 2004/09/17 18:16:31 wrstuden Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software develooped for the NetBSD Project by
+ * Piermont Information Systems Inc.
+ * 4. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+{
+
+#include "msg_defs.h"
+
+/* Initial code for definitions and includes and prototypes. */
+void do_dynamic (void);
+static int msg_init = 0;
+
+}
+
+default x=20, y=10;
+
+allow dynamic menus;
+
+error action { fprintf (stderr, "Testm: Could not initialize curses.\n");
+ exit(1); };
+
+menu root, title " Main Menu of Test System", x=10;
+ display action {
+ /* Message initialization */
+ if (!msg_init) {
+ msg_window (stdscr);
+ msg_init = 1;
+ }
+ msg_display (MSG_welcome);
+ wrefresh(stdscr); };
+ option "Do nothing option",
+ action { }
+ ;
+ option "Try a sub menu",
+ sub menu submenu
+ ;
+ option "A scrollable menu",
+ sub menu scrollit
+ ;
+ option "Another scrollable menu",
+ sub menu scrollit2
+ ;
+ option "Big non-scrollable menu, bombs on small screens",
+ sub menu bigscroll
+ ;
+ option "A menu with no shortcuts",
+ sub menu noshort
+ ;
+ option "A dynamic menu ...",
+ action { do_dynamic (); }
+ ;
+ option "Run a shell...",
+ action (endwin) { system ("/bin/sh"); }
+ ;
+ exit action (endwin) { printf ("Thanks for playing\n"); };
+ help {
+ Main Menu Help Screen
+
+This is help text for the main menu of the menu test system. This
+text should appear verbatim when asked for by use of the ? key by
+the user. This should allow scrolling, if needed. If the first
+character in the help is the newline (as the case for this help),
+then that newline is not included in the help text.
+
+Now this tests lines for scrolling:
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+};
+
+menu submenu, title " submenu test";
+ option "upper right", sub menu upperright;
+ option "lower left", sub menu lowerleft;
+ option "middle, no title", sub menu middle;
+ option "next menu", next menu nextmenu;
+
+menu upperright, title "upper right", y=2, x=60, no exit;
+ option "Just Exit!", exit;
+
+menu lowerleft, title "lower left", y=19, x=2, no exit;
+ option "Just Exit!", exit;
+
+menu middle, no box;
+ option "Just Exit!", exit;
+
+menu nextmenu, title " A next window! ? for comments", no exit;
+ option "Just Exit!:", exit;
+
+menu noshort, title " No shortcut characters!", no shortcut;
+ option "first", action {};
+ option "second", action {};
+ option "third", action {};
+
+menu scrollit, scrollable, h=4, title " Scrollable Menu";
+ option "option 1", action {};
+ option "option 2", action {};
+ option "option 3", action {};
+ option "option 4", action {};
+ option "option 5", action {};
+ option "option 6", action {};
+
+menu bigscroll, no scrollable, title " Non-scrollable Menu";
+ option "option 1", action {};
+ option "option 2", action {};
+ option "option 3", action {};
+ option "option 4", action {};
+ option "option 5", action {};
+ option "option 6", action {};
+ option "option 7", action {};
+ option "option 8", action {};
+ option "option 9", action {};
+ option "option 10", action {};
+ option "option 11", action {};
+ option "option 12", action {};
+ option "option 13", action {};
+ option "option 14", action {};
+ option "option 15", action {};
+ option "option 16", action {};
+ option "option 17", action {};
+ option "option 18", action {};
+ option "option 19", action {};
+ option "option 20", action {};
+
+menu scrollit2, scrollable, title " Big scrollable Menu";
+ option "option 1", action {};
+ option "option 2", action {};
+ option "option 3", action {};
+ option "option 4", action {};
+ option "option 5", action {};
+ option "option 6", action {};
+ option "option 7", action {};
+ option "option 8", action {};
+ option "option 9", action {};
+ option "option 10", action {};
+ option "option 11", action {};
+ option "option 12", action {};
+ option "option 13", action {};
+ option "option 14", action {};
+ option "option 15", action {};
+ option "option 16", action {};
+ option "option 17", action {};
+ option "option 18", action {};
+ option "option 19", action {};
+ option "option 20", action {};
+ option "option 21", action {};
+ option "option 22", action {};
+ option "option 23", action {};
+ option "option 24", action {};
+ option "option 25", action {};
+ option "option 26", action {};
+ option "option 27", action {};
+ option "option 28", action {};
+ option "option 29", action {};
+ option "option 30", action {};
+ option "option 31", action {};
+ option "option 32", action {};
+ option "option 33", action {};
+ option "option 34", action {};
+ option "option 35", action {};
+ option "option 36", action {};
+ option "option 37", action {};
+ option "option 38", action {};
+ option "option 39", action {};
+ option "option 40", action {};
+ option "option 41", action {};
+ option "option 42", action {};
+ option "option 43", action {};
+ option "option 44", action {};
+ option "option 45", action {};
+ option "option 46", action {};
+ option "option 47", action {};
+ option "option 48", action {};
+ option "option 49", action {};
+ option "option 50", action {};
+ option "option 51", action {};
--- /dev/null
+/* $NetBSD: menus.msg,v 1.1 1998/07/16 07:08:26 phil Exp $ */
+
+message welcome {
+
+ Welcome to the menuc (and msg) test program!
+}
+
+message name {name}
+
+message street {street address}
+
+message city {city, state zip}
\ No newline at end of file
--- /dev/null
+/* $NetBSD: util.c,v 1.5 2012/03/06 16:55:18 mbalmer Exp $ */
+
+/*
+ * Copyright 1997 Piermont Information Systems Inc.
+ * All rights reserved.
+ *
+ * Written by Philip A. Nelson for Piermont Information Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Piermont Information Systems Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* util.c - utility routines. */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: util.c,v 1.5 2012/03/06 16:55:18 mbalmer Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "defs.h"
+
+/* Error routine */
+void
+yyerror(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ printf("%s:%d: ", src_name, line_no);
+ vfprintf(stdout, fmt, args);
+ printf("\n");
+ va_end(args);
+ had_errors = TRUE;
+}
+
+/* Buffer routines */
+static char *mc_buff = NULL;
+static int mc_size = 0;
+static int mc_loc = 0;
+
+void
+buff_add_ch(char ch)
+{
+ char *t;
+
+ if (mc_loc >= mc_size-1) {
+ if (mc_size == 0)
+ mc_size = 80;
+ else
+ mc_size *= 2;
+ t = (char *)malloc(mc_size);
+ if (t == NULL) {
+ (void)fprintf(stderr, "%s:%d: Malloc error\n",
+ src_name, line_no);
+ exit(1);
+ }
+ if (mc_buff != NULL) {
+ strcpy(t, mc_buff);
+ free(mc_buff);
+ }
+ mc_buff = t;
+ }
+ mc_buff[mc_loc++] = ch;
+ mc_buff[mc_loc] = '\0';
+}
+
+/* get a copy of the string ! */
+char *
+buff_copy(void)
+{
+ char *res = strdup(mc_buff);
+
+ mc_loc = 0;
+ mc_buff[0] = '\0';
+ return res;
+}