/****************************************************************************
- * Copyright (c) 2005-2011,2012 Free Software Foundation, Inc. *
+ * Copyright (c) 2005-2017,2019 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
* authorization. *
****************************************************************************/
/*
- * $Id: demo_menus.c,v 1.35 2012/09/09 00:01:20 tom Exp $
+ * $Id: demo_menus.c,v 1.68 2019/08/17 21:45:32 tom Exp $
*
* Demonstrate a variety of functions from the menu library.
* Thomas Dickey - 2005/4/9
item_opts_off -
item_opts_on -
item_term -
-item_userptr -
item_visible -
menu_back -
menu_fore -
menu_pad -
menu_request_by_name -
menu_request_name -
-menu_sub -
menu_term -
menu_userptr -
set_current_item -
-set_item_init -
set_item_opts -
-set_item_term -
-set_item_userptr -
set_menu_grey -
-set_menu_init -
set_menu_items -
set_menu_opts -
set_menu_pad -
set_menu_pattern -
set_menu_spacing -
-set_menu_term -
set_menu_userptr -
set_top_row -
top_row -
#ifdef NCURSES_VERSION
#ifdef TRACE
static unsigned save_trace = TRACE_ORDINARY | TRACE_CALLS;
-extern unsigned _nc_tracing;
static MENU *mpTrace;
#endif
-#else
-#undef TRACE
#endif
typedef enum {
#define MENU_Y 1
+typedef struct {
+ NCURSES_CONST char *name;
+ void (*func) (int);
+ unsigned mask;
+} MENU_DATA;
+
+static void call_files(int);
+
static MENU *mpBanner;
static MENU *mpFile;
static MENU *mpSelect;
+static WINDOW *status;
+
static bool loaded_file = FALSE;
-#if !HAVE_STRDUP
-#define strdup my_strdup
-static char *
-strdup(char *s)
+static char empty[1];
+
+#ifdef TRACE
+static void failed(const char *s) GCC_NORETURN;
+
+static void
+failed(const char *s)
{
- char *p = typeMalloc(char, strlen(s) + 1);
- if (p)
- strcpy(p, s);
- return (p);
+ perror(s);
+ endwin();
+ ExitProgram(EXIT_FAILURE);
}
-#endif /* not HAVE_STRDUP */
+#endif
/* Common function to allow ^T to toggle trace-mode in the middle of a test
* so that trace-files can be made smaller.
int result = 0;
if (okMenuNo(number)) {
- int spc_desc, spc_rows, spc_cols;
-
+ int spc_rows;
#ifdef NCURSES_VERSION
+ int spc_desc, spc_cols;
menu_spacing(mpBanner, &spc_desc, &spc_rows, &spc_cols);
#else
spc_rows = 0;
return result;
}
+static void
+my_menu_init(MENU * menu)
+{
+ Trace(("called MenuHook my_menu_init"));
+ mvwprintw(status, 2, 0, "menu_init %p", (void *) menu);
+ wclrtoeol(status);
+ wrefresh(status);
+}
+
+static void
+my_menu_term(MENU * menu)
+{
+ Trace(("called MenuHook my_menu_term"));
+ mvwprintw(status, 2, 0, "menu_term %p", (void *) menu);
+ wclrtoeol(status);
+ wrefresh(status);
+}
+
+static void
+my_item_init(MENU * menu)
+{
+ ITEM *item = current_item(menu);
+ const char *name = item_name(item);
+
+ Trace(("called MenuHook my_item_init (%s)", name));
+ mvwprintw(status, 2, 0, "item_init %s", name);
+ wclrtoeol(status);
+ wrefresh(status);
+}
+
+static void
+my_item_term(MENU * menu)
+{
+ ITEM *item = current_item(menu);
+ const char *name = item_name(item);
+
+ Trace(("called MenuHook my_item_term (%s)", name));
+ mvwprintw(status, 2, 0, "item_term %s", name);
+ wclrtoeol(status);
+ wrefresh(status);
+}
+
static MENU *
menu_create(ITEM ** items, int count, int ncols, MenuNo number)
{
if (mcols + (2 * margin + x) >= COLS)
mcols = COLS - (2 * margin + x);
-#ifdef TRACE
- if (number == eTrace)
- menu_opts_off(result, O_ONEVALUE);
- else
- menu_opts_on(result, O_ONEVALUE);
-#endif
-
menuwin = newwin(mrows + (2 * margin), mcols + (2 * margin), y, x);
set_menu_win(result, menuwin);
keypad(menuwin, TRUE);
set_menu_sub(result, derwin(menuwin, mrows, mcols, margin, margin));
+#ifdef TRACE
+ if (number == eTrace)
+ menu_opts_off(result, O_ONEVALUE);
+ else
+ menu_opts_on(result, O_ONEVALUE);
+#endif
+#if defined(NCURSES_MOUSE_VERSION) && defined(O_MOUSE_MENU)
+ menu_opts_on(result, O_MOUSE_MENU);
+#endif
+
post_menu(result);
+ set_menu_init(result, my_menu_init);
+ set_menu_term(result, my_menu_term);
+ set_item_init(result, my_item_init);
+ set_item_term(result, my_item_term);
return result;
}
static void
menu_destroy(MENU * m)
{
- int count;
-
Trace(("menu_destroy %p", (void *) m));
if (m != 0) {
ITEM **items = menu_items(m);
const char *blob = 0;
+ int count;
count = item_count(m);
Trace(("menu_destroy %p count %d", (void *) m, count));
if ((count > 0) && (m == mpSelect)) {
if (blob && loaded_file) {
Trace(("freeing blob %p", blob));
- free((char *) blob);
+ free((void *) blob);
}
free(items);
+ items = 0;
}
#ifdef TRACE
if ((count > 0) && (m == mpTrace)) {
ITEM **ip = items;
- while (*ip)
- free(*ip++);
+ if (ip != 0) {
+ while (*ip)
+ free(*ip++);
+ }
}
#endif
}
static void
build_file_menu(MenuNo number)
{
- static CONST_MENUS char *labels[] =
+ static MENU_DATA table[] =
{
- "Exit",
- (char *) 0
+ {"Exit", call_files, 0},
+ {(char *) 0, 0, 0}
};
- static ITEM *items[SIZEOF(labels)];
+ static ITEM *items[SIZEOF(table)];
ITEM **ip = items;
- CONST_MENUS char **ap;
+ int n;
- for (ap = labels; *ap; ap++)
- *ip++ = new_item(*ap, "");
+ for (n = 0; table[n].name != 0; ++n) {
+ *ip = new_item(table[n].name, empty);
+ set_item_userptr(*ip, (void *) &table[n]);
+ ++ip;
+ }
*ip = (ITEM *) 0;
- mpFile = menu_create(items, SIZEOF(labels) - 1, 1, number);
+ mpFile = menu_create(items, SIZEOF(table) - 1, 1, number);
}
static int
/*****************************************************************************/
+static void
+call_select(int code)
+{
+ (void) code;
+ Trace(("Selected item %d", code));
+}
+
static void
build_select_menu(MenuNo number, char *filename)
{
- static CONST_MENUS char *labels[] =
+#define MY_DATA(name) { name, call_select, 0 }
+ static MENU_DATA table[] =
{
- "Lions",
- "Tigers",
- "Bears",
- "(Oh my!)",
- "Newts",
- "Platypi",
- "Lemurs",
- "(Oh really?!)",
- "Leopards",
- "Panthers",
- "Pumas",
- "Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs",
- "Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs, Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs",
- (char *) 0
+ MY_DATA("Lions"),
+ MY_DATA("Tigers"),
+ MY_DATA("Bears"),
+ MY_DATA("(Oh my!)"),
+ MY_DATA("Newts"),
+ MY_DATA("Platypi"),
+ MY_DATA("Lemurs"),
+ MY_DATA("(Oh really?!)"),
+ MY_DATA("Leopards"),
+ MY_DATA("Panthers"),
+ MY_DATA("Pumas"),
+ MY_DATA("Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs"),
+ MY_DATA("Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs, Lions, Tigers, Bears, (Oh my!), Newts, Platypi, Lemurs"),
+ {(char *) 0, 0, 0}
};
static ITEM **items;
ITEM **ip;
- CONST_MENUS char **ap = 0;
- CONST_MENUS char **myList = 0;
- unsigned count = 0;
+ MENU_DATA *ap = 0;
+ MENU_DATA *myList = 0;
+ int i;
+ size_t count = 0;
if (filename != 0) {
struct stat sb;
&& (sb.st_mode & S_IFMT) == S_IFREG
&& sb.st_size != 0) {
size_t size = (size_t) sb.st_size;
- unsigned j, k;
char *blob = typeMalloc(char, size + 1);
- CONST_MENUS char **list = typeCalloc(CONST_MENUS char *, size + 1);
+ MENU_DATA *list = typeCalloc(MENU_DATA, size + 1);
items = typeCalloc(ITEM *, size + 1);
Trace(("build_select_menu blob=%p, items=%p",
if (fp != 0) {
if (fread(blob, sizeof(char), size, fp) == size) {
bool mark = TRUE;
+ unsigned j, k;
for (j = k = 0; j < size; ++j) {
if (mark) {
- list[k++] = blob + j;
+ list[k++].name = blob + j;
mark = FALSE;
}
if (blob[j] == '\n') {
blob[j] = '\0';
- if (k > 0 && *list[k - 1] == '\0')
+ if (k > 0 && *list[k - 1].name == '\0')
--k;
mark = TRUE;
} else if (blob[j] == '\t') {
blob[j] = ' '; /* menu items are printable */
}
}
- list[k] = 0;
+ list[k].name = 0;
count = k;
ap = myList = list;
}
}
loaded_file = TRUE;
}
+ if (ap == 0)
+ free(items);
}
}
if (ap == 0) {
- count = SIZEOF(labels) - 1;
+ count = SIZEOF(table) - 1;
items = typeCalloc(ITEM *, count + 1);
- ap = labels;
+ ap = table;
}
ip = items;
- while (*ap != 0)
- *ip++ = new_item(*ap++, "");
+ for (i = 0; ap[i].name != 0; ++i) {
+ ap[i].func = call_select;
+ ap[i].mask = (unsigned) i;
+ *ip = new_item(ap[i].name, empty);
+ set_item_userptr(*ip, (void *) &table[i]);
+ ++ip;
+ }
*ip = 0;
mpSelect = menu_create(items, (int) count, 1, number);
/*****************************************************************************/
#ifdef TRACE
-#define T_TBL(name) { #name, name }
-static struct {
- const char *name;
- unsigned mask;
-} t_tbl[] = {
+
+static void
+call_trace(int code)
+{
+ (void) code;
+ Trace(("Updating trace mask %d", code));
+}
+
+#define T_TBL(name) { #name, call_trace, name }
+static MENU_DATA t_tbl[] =
+{
T_TBL(TRACE_DISABLE),
- T_TBL(TRACE_TIMES),
- T_TBL(TRACE_TPUTS),
- T_TBL(TRACE_UPDATE),
- T_TBL(TRACE_MOVE),
- T_TBL(TRACE_CHARPUT),
- T_TBL(TRACE_ORDINARY),
- T_TBL(TRACE_CALLS),
- T_TBL(TRACE_VIRTPUT),
- T_TBL(TRACE_IEVENT),
- T_TBL(TRACE_BITS),
- T_TBL(TRACE_ICALLS),
- T_TBL(TRACE_CCALLS),
- T_TBL(TRACE_DATABASE),
- T_TBL(TRACE_ATTRS),
- T_TBL(TRACE_MAXIMUM),
+ T_TBL(TRACE_TIMES),
+ T_TBL(TRACE_TPUTS),
+ T_TBL(TRACE_UPDATE),
+ T_TBL(TRACE_MOVE),
+ T_TBL(TRACE_CHARPUT),
+ T_TBL(TRACE_ORDINARY),
+ T_TBL(TRACE_CALLS),
+ T_TBL(TRACE_VIRTPUT),
+ T_TBL(TRACE_IEVENT),
+ T_TBL(TRACE_BITS),
+ T_TBL(TRACE_ICALLS),
+ T_TBL(TRACE_CCALLS),
+ T_TBL(TRACE_DATABASE),
+ T_TBL(TRACE_ATTRS),
+ T_TBL(TRACE_MAXIMUM),
{
- (char *) 0, 0
+ (char *) 0, 0, 0
}
};
ITEM **ip = items;
int n;
- for (n = 0; t_tbl[n].name != 0; n++)
- *ip++ = new_item(t_tbl[n].name, "");
+ for (n = 0; t_tbl[n].name != 0; n++) {
+ *ip = new_item(t_tbl[n].name, empty);
+ set_item_userptr(*ip, (void *) &t_tbl[n]);
+ ++ip;
+ }
*ip = (ITEM *) 0;
mpTrace = menu_create(items, SIZEOF(t_tbl) - 1, 2, number);
tracetrace(unsigned tlevel)
{
static char *buf;
+ static size_t need = 12;
int n;
if (buf == 0) {
- size_t need = 12;
for (n = 0; t_tbl[n].name != 0; n++)
need += strlen(t_tbl[n].name) + 2;
buf = typeMalloc(char, need);
+ if (!buf)
+ failed("tracetrace");
}
- sprintf(buf, "0x%02x = {", tlevel);
+ _nc_SPRINTF(buf, _nc_SLIMIT(need) "0x%02x = {", tlevel);
if (tlevel == 0) {
- sprintf(buf + strlen(buf), "%s, ", t_tbl[0].name);
+ _nc_STRCAT(buf, t_tbl[0].name, need);
+ _nc_STRCAT(buf, ", ", need);
} else {
for (n = 1; t_tbl[n].name != 0; n++)
if ((tlevel & t_tbl[n].mask) == t_tbl[n].mask) {
- strcat(buf, t_tbl[n].name);
- strcat(buf, ", ");
+ _nc_STRCAT(buf, t_tbl[n].name, need);
+ _nc_STRCAT(buf, ", ", need);
}
}
if (buf[strlen(buf) - 2] == ',')
buf[strlen(buf) - 2] = '\0';
- return (strcat(buf, "}"));
+ _nc_STRCAT(buf, "}", need);
+ return buf;
}
/* fake a dynamically reconfigurable menu using the 0th entry to deselect
/* interactively set the trace level */
{
ITEM **ip;
- unsigned newtrace;
int result;
for (ip = menu_items(mpTrace); *ip; ip++) {
- unsigned mask = t_tbl[item_index(*ip)].mask;
+ MENU_DATA *td = (MENU_DATA *) item_userptr(*ip);
+ unsigned mask = td->mask;
if (mask == 0)
set_item_value(*ip, _nc_tracing == 0);
else if ((mask & _nc_tracing) == mask)
if (result == E_OK) {
if (update_trace_menu(mpTrace) || cmd == REQ_TOGGLE_ITEM) {
- newtrace = 0;
+ unsigned newtrace = 0;
for (ip = menu_items(mpTrace); *ip; ip++) {
- if (item_value(*ip))
- newtrace |= t_tbl[item_index(*ip)].mask;
+ if (item_value(*ip)) {
+ MENU_DATA *td = (MENU_DATA *) item_userptr(*ip);
+ newtrace |= td->mask;
+ }
}
trace(newtrace);
Trace(("trace level interactively set to %s", tracetrace(_nc_tracing)));
- MvPrintw(LINES - 2, 0,
- "Trace level is %s\n", tracetrace(_nc_tracing));
- refresh();
+ MvWPrintw(status, 1, 0,
+ "Trace level is %s\n", tracetrace(_nc_tracing));
+ wrefresh(status);
}
}
return result;
return result;
}
+static void
+call_menus(int code)
+{
+ (void) code;
+ Trace(("Activated menu %d\n", code));
+}
+
static void
build_menus(char *filename)
{
- static CONST_MENUS char *labels[] =
+ static MENU_DATA table[] =
{
- "File",
- "Select",
+ {"File", call_menus, 0},
+ {"Select", call_menus, 1},
#ifdef TRACE
- "Trace",
+ {"Trace", call_menus, 2},
#endif
- (char *) 0
+ {(char *) 0, 0, 0}
};
- static ITEM *items[SIZEOF(labels)];
+ static ITEM *items[SIZEOF(table)];
ITEM **ip = items;
- CONST_MENUS char **ap;
+ int n;
- for (ap = labels; *ap; ap++)
- *ip++ = new_item(*ap, "");
+ for (n = 0; table[n].name != 0; ++n) {
+ *ip = new_item(table[n].name, empty);
+ set_item_userptr(*ip, (void *) &table[n]);
+ ++ip;
+ }
*ip = (ITEM *) 0;
- mpBanner = menu_create(items, SIZEOF(labels) - 1, SIZEOF(labels) - 1, eBanner);
+ mpBanner = menu_create(items, SIZEOF(table) - 1, SIZEOF(table) - 1, eBanner);
set_menu_mark(mpBanner, ">");
build_file_menu(eFile);
}
}
+#if defined(KEY_RESIZE) && NCURSES_EXT_FUNCS
+static void
+resize_menu(MENU ** menu)
+{
+#if 0
+ WINDOW *win = menu_win(*menu);
+ WINDOW *sub = menu_sub(*menu);
+#endif
+ (void) menu;
+}
+
+static void
+resize_menus(MENU * current)
+{
+ (void) current;
+
+ werase(status);
+ wnoutrefresh(status);
+ wresize(status, 1, COLS);
+ mvwin(status, LINES - 1, 0);
+
+ resize_menu(&mpBanner);
+ resize_menu(&mpFile);
+ resize_menu(&mpSelect);
+#ifdef TRACE
+ resize_menu(&mpTrace);
+#endif
+}
+#endif /* defined(KEY_RESIZE) && NCURSES_EXT_FUNCS */
+
static void
show_status(int ch, MENU * menu)
{
- move(LINES - 1, 0);
- printw("key %s, menu %d, mark %s, match %s",
- keyname(ch),
- menu_number(),
- menu_mark(menu),
- menu_pattern(menu));
- clrtoeol();
- refresh();
+ wmove(status, 0, 0);
+ wprintw(status, "key %s, menu %d, mark %s, match %s",
+ keyname(ch),
+ menu_number(),
+ menu_mark(menu),
+ menu_pattern(menu));
+ wclrtoeol(status);
+ wrefresh(status);
}
static void
int ch = ERR;
#ifdef NCURSES_MOUSE_VERSION
- mousemask(ALL_MOUSE_EVENTS, (mmask_t *) 0);
+ mousemask(BUTTON1_CLICKED, (mmask_t *) 0);
#endif
menu_display(last_menu);
case KEY_SRIGHT:
move_menus(last_menu, 0, 1);
continue;
+#if defined(KEY_RESIZE) && NCURSES_EXT_FUNCS
+ case KEY_RESIZE:
+ resize_menus(last_menu);
+ continue;
+#endif
}
cmd = menu_virtualize(ch);
#endif
}
+#if defined(NCURSES_MOUSE_VERSION) && defined(O_MOUSE_MENU)
if ((code == E_REQUEST_DENIED) && (cmd == KEY_MOUSE)) {
+ (void) menu_getc(mpBanner);
code = menu_driver(mpBanner, cmd);
+ if (code == E_REQUEST_DENIED) {
+ MEVENT event;
+ if (menu_getc(mpBanner) == KEY_MOUSE)
+ getmouse(&event); /* give up */
+ }
}
+#endif
break;
}
wrefresh(menu_win(last_menu));
if (code == E_UNKNOWN_COMMAND
|| code == E_NOT_POSTED) {
- if (menu_number() == eFile)
- break;
- beep();
+ ITEM *item = current_item(last_menu);
+ MENU_DATA *td = (MENU_DATA *) item_userptr(item);
+ td->func((int) td->mask);
}
if (code == E_REQUEST_DENIED)
beep();
continue;
}
-
-#ifdef NCURSES_MOUSE_VERSION
- mousemask(0, (mmask_t *) 0);
-#endif
}
static void
}
#endif /* HAVE_RIPOFFLINE */
+static void
+call_files(int code)
+{
+ switch (code) {
+ case 0:
+ destroy_menus();
+ endwin();
+ printf("DONE!\n");
+ ExitProgram(EXIT_SUCCESS);
+ }
+}
+
static void
usage(void)
{
setlocale(LC_ALL, "");
- while ((c = getopt(argc, argv, "a:de:fhmp:s:t:")) != -1) {
+ while ((c = getopt(argc, argv, "fht:")) != -1) {
switch (c) {
#if HAVE_RIPOFFLINE
case 'f':
init_pair(1, COLOR_RED, COLOR_BLACK);
init_pair(2, COLOR_BLUE, COLOR_WHITE);
}
+ status = newwin(3, COLS, LINES - 3, 0);
build_menus(argc > 1 ? argv[1] : 0);
perform_menus();
destroy_menus();