Importing usr.bin/menuc
No Minix-specific changes needed. Change-Id: Ie663e08a515a393efaaeecacea15ef807aa8ecfb
This commit is contained in:
parent
7d85156ac0
commit
525a267e81
19 changed files with 3339 additions and 1 deletions
|
@ -402,6 +402,7 @@
|
|||
./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
|
||||
|
@ -1993,6 +1994,7 @@
|
|||
./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
|
||||
|
@ -4669,6 +4671,7 @@
|
|||
./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
|
||||
|
|
|
@ -189,6 +189,7 @@
|
|||
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
|
||||
|
|
|
@ -15,7 +15,7 @@ SUBDIR= asa \
|
|||
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 \
|
||||
|
|
22
usr.bin/menuc/Makefile
Normal file
22
usr.bin/menuc/Makefile
Normal file
|
@ -0,0 +1,22 @@
|
|||
# $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>
|
217
usr.bin/menuc/avl.c
Normal file
217
usr.bin/menuc/avl.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
/* $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);
|
||||
}
|
102
usr.bin/menuc/defs.h
Normal file
102
usr.bin/menuc/defs.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/* $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 *);
|
||||
|
115
usr.bin/menuc/main.c
Normal file
115
usr.bin/menuc/main.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/* $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);
|
||||
}
|
431
usr.bin/menuc/mdb.c
Normal file
431
usr.bin/menuc/mdb.c
Normal file
|
@ -0,0 +1,431 @@
|
|||
/* $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);
|
||||
}
|
98
usr.bin/menuc/mdb.h
Normal file
98
usr.bin/menuc/mdb.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* $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
|
827
usr.bin/menuc/menu_sys.def
Normal file
827
usr.bin/menuc/menu_sys.def
Normal file
|
@ -0,0 +1,827 @@
|
|||
/* $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;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
544
usr.bin/menuc/menuc.1
Normal file
544
usr.bin/menuc/menuc.1
Normal file
|
@ -0,0 +1,544 @@
|
|||
.\" $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.
|
228
usr.bin/menuc/parse.y
Normal file
228
usr.bin/menuc/parse.y
Normal file
|
@ -0,0 +1,228 @@
|
|||
/* $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; }
|
||||
;
|
5
usr.bin/menuc/pathnames.h
Normal file
5
usr.bin/menuc/pathnames.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
/* $NetBSD: pathnames.h,v 1.1 2001/10/15 22:20:03 bjh21 Exp $ */
|
||||
|
||||
#ifndef _PATH_DEFSYSPREFIX
|
||||
#define _PATH_DEFSYSPREFIX "/usr/share/misc"
|
||||
#endif
|
196
usr.bin/menuc/scan.l
Normal file
196
usr.bin/menuc/scan.l
Normal file
|
@ -0,0 +1,196 @@
|
|||
/* $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
|
27
usr.bin/menuc/testm/Makefile
Normal file
27
usr.bin/menuc/testm/Makefile
Normal file
|
@ -0,0 +1,27 @@
|
|||
# $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>
|
126
usr.bin/menuc/testm/main.c
Normal file
126
usr.bin/menuc/testm/main.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* $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);
|
||||
}
|
||||
|
277
usr.bin/menuc/testm/menus.mc
Normal file
277
usr.bin/menuc/testm/menus.mc
Normal file
|
@ -0,0 +1,277 @@
|
|||
/* $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 {};
|
12
usr.bin/menuc/testm/menus.msg
Normal file
12
usr.bin/menuc/testm/menus.msg
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* $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}
|
107
usr.bin/menuc/util.c
Normal file
107
usr.bin/menuc/util.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/* $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;
|
||||
}
|
Loading…
Reference in a new issue