File: [Platon] / ep / src / menu.c (download)
Revision 1.14, Fri Nov 28 17:35:11 2003 UTC (20 years, 4 months ago) by nepto
Changes since 1.13: +3 -3
lines
Changed URL from www.platon.sk to platon.sk.
|
/*
* ep - extended pipelining
*
* menu.c - ncurses menu core
* ____________________________________________________________
*
* Developed by Ondrej Jombik <nepto@platon.sk>
* and Lubomir Host <rajo@platon.sk>
* Copyright (c) 2000-2003 Platon SDG, http://platon.sk/
* All rights reserved.
*
* See README file for more information about this software.
* See COPYING file for license information.
*
* Download the latest version from
* http://platon.sk/projects/ep/
*/
/* $Platon: ep/src/menu.c,v 1.13 2003/05/03 09:58:19 nepto Exp $ */
/*
VIMGCC -DSELFTEST -ggdb -Wall -pedantic -lncurses
VIMGCC -DSELFTEST -ggdb -Wall -pedantic -lncurses -lefence
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
#endif
#if HAVE_UNISTD_H
# include <sys/types.h>
# include <unistd.h>
#endif
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
#if defined(SELF) || defined(SELFTEST)
# define MENU 1
# define PACKAGE "ep-selftest module"
# define VERSION "1.0"
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
# include <sys/types.h>
# include <unistd.h>
# include <sys/time.h>
# include <time.h>
# include <malloc.h>
# include <curses.h>
# include "m_memory.c"
# include "m_proctable.c"
# include "message.c"
#else
# include "proctable.h"
# include "m_memory.h"
# include "m_proctable.h"
#endif
#if MENU
# include <curses.h>
#include "menu.h"
typedef struct OPTION_STRUCT {
int hotkey;
char *text;
char *rtext;
int (*func)(PROCTABLE *p_ptbl, int, int);
} option;
typedef struct MENU_STRUCT {
WINDOW *win;
int nitems;
int x, y;
int width, height;
int selected;
int pos[MAXOPT];
option options[MAXOPT];
} menu;
static void
free_menu(m)
menu *m;
{
if (!m) {
#ifdef DEBUG
printw("NULL 1 in free_menu()\n");
refresh();
#endif
return;
}
#ifdef DEBUG
if (!m->win) {
printw("NULL 2 in free_menu()\n");
refresh();
}
#endif
delwin(m->win);
free(m);
}
/*
static int
destruct_window(WINDOW *win)
{
// werase(win);
// touchwin(win);
delwin(win);
}
*/
static int
confirm_args(prompt, format, args)
char *prompt;
char *format;
va_list args;
{
int c;
standout();
vwprintw(stdscr, format, args);
printw(" (%s) : ", prompt);
standend();
refresh();
c = getch();
clrtoeol();
return c;
}
static void
confirm_error(
char *format,
...)
{
va_list args;
va_start(args, format);
confirm_args("press any key", format, args);
va_end(args);
}
static int
confirm(
char *prompt,
char *format,
...)
{
va_list args;
int c;
va_start(args, format);
c = confirm_args(prompt, format, args);
va_end(args);
return c;
}
static void
menu_print_option(m, n, selected)
menu *m;
int n;
int selected;
{
int k=0;
option *o = &m->options[n];
char *s = o->text;
if (selected) {
wstandend(m->win);
mvwprintw(m->win, n + 1, 1, " ");
if (strchr(s, '&') != NULL) {
for (k=0; (s[k]!='\0' && s[k]!='&'); k++)
waddch(m->win, s[k]);
waddstr(m->win, (s+k+1));
wprintw(m->win, "%*s %s",
( m->width -
strlen(o->rtext) -
strlen(o->text) - M_EXTRA + 3),
"",
o->rtext);
}
else{
mvwprintw(m->win, n + 1, 1, " %-s %*s %s ",
o->text,
( m->width -
strlen(o->rtext) -
strlen(o->text) - M_EXTRA),
"",
o->rtext);
}
wstandout(m->win);
}
else {
mvwprintw(m->win, n + 1, 1, " ");
if (strchr(s, '&') != NULL) {
for (k=0; (s[k]!='\0' && s[k]!='&'); k++)
waddch(m->win, s[k]);
wstandend(m->win);
k++;
if (s[k]!='\0') waddch(m->win, s[k]);
wstandout(m->win);
waddstr(m->win, (s+k+1));
wprintw(m->win, "%*s %s",
( m->width -
strlen(o->rtext) -
strlen(o->text) - M_EXTRA + 3),
"",
o->rtext);
}
else {
mvwprintw(m->win, n + 1, 1, " %-s %*s %s ",
o->text,
( m->width -
strlen(o->rtext) -
strlen(o->text) - M_EXTRA),
"",
o->rtext);
}
}
wmove(m->win, m->selected+1, 1);
}
static void
menu_print(m)
menu *m;
{
int i;
chtype hbox = '-', vbox = '|';
wborder(m->win, vbox, vbox, hbox, hbox, '+', '+', '+', '+');
for (i = 0; i < m->nitems; i++)
menu_print_option(m, i, (i == m->selected));
wmove(m->win, m->selected+1, 1);
}
static void
popup_menu_print_option(m, n, selected)
menu *m;
int n;
int selected;
{
option *o = &m->options[n];
if (selected)
wstandend(m->win);
mvwprintw(m->win, 0, m->pos[n], " %s ", o->text);
if (selected) {
wmove(m->win, 0, m->pos[m->selected]);
wstandout(m->win);
}
}
static void
popup_menu_print(m)
menu *m;
{
int i;
option *o = &m->options[m->nitems-1];
wprintw(m->win, " ");
for (i = 0; i < m->nitems; i++)
popup_menu_print_option(m, i, (i == m->selected));
for (i = (m->pos[m->nitems] + strlen(o->text)+2); i < m->width; i++)
wprintw(m->win, " ");
wmove(m->win, 0, m->pos[m->selected]);
}
static int
do_menu(type, p_ptbl, items, y, x)
int type;
PROCTABLE *p_ptbl;
option items[];
int y;
int x;
{
int i;
option *pom = items;
menu *m = calloc(1, sizeof(menu));
if (!m) {
confirm_error("Out of memory");
return(0);
}
if (type) {
m->height=0;
m->width=0;
}
else {
m->height = 1;
m->width=COLS;
}
for (i=0; (pom+i)->text != NULL && m->nitems < MAXOPT; i++) {
m->nitems++;
m->options[i].text= items[i].text;
m->options[i].func= items[i].func;
if (type) {
int lenght;
char *str;
str = strchr(items[i].text, '&');
lenght = strlen(items[i].text) + strlen(items[i].rtext);
if (str != NULL) {
lenght--;
m->options[i].hotkey = // character after '&'
(str[1]>='A' && str[1]<='Z') ? str[1] -'A' +'a' : str[1];
}
if (lenght > m->width)
m->width = lenght;
m->options[i].rtext= items[i].rtext;
}
else {
m->options[i].hotkey = items[i].hotkey;
}
}
if (type) {
m->height = m->nitems + 2;
m->width += M_BOX;
if (x + m->width > COLS || y + m->height > LINES) {
confirm_error("menu too big to fit on screen");
free_menu(m);
return(0);
}
}
else {
m->pos[0] = 2;
for (i=1; (pom+i)->text != NULL && m->nitems < MAXOPT; i++) {
m->pos[i] = m->pos[i-1] + strlen(m->options[i-1].text) + 4;
}
}
if (type)
m->win = newwin(m->height, m->width, y, x);
else
m->win = newwin(m->height, m->width, 0, 0);
if (!m->win) {
confirm_error("Can't create menu (window too big)");
free_menu(m);
return(0);
}
wstandout(m->win);
if (!m->win) {
confirm_error("Out of memory");
free_menu(m);
return(0);
}
if (type) {
//leaveok(m->win, 1);
menu_print(m);
}
else {
popup_menu_print(m);
//wrefresh(m->win);
}
while (1) {
int c, i;
int s = m->selected;
int select_now = 0;
int retval;
wrefresh(m->win);
c = getch();
switch (c) {
case KEY_CANCEL:
case KEY_CLOSE:
case '\033': /* Esc */
delwin(m->win);
free_menu(m);
return(c);
break;
case KEY_REFRESH:
case 12: /* ^L */
touchwin(stdscr);
refresh();
break;
case KEY_HOME:
s = 0;
break;
case KEY_END:
s = m->nitems - 1;
break;
case KEY_BACKSPACE:
case KEY_PPAGE:
case KEY_SR:
case KEY_PREVIOUS:
case KEY_DC:
if (s > 0) s--;
else s = m->nitems - 1;
break;
case KEY_UP:
if (type) { /* do nothing */ }
else
break;
case KEY_DOWN:
if (type) {
if (s < m->nitems - 1) s++;
else s = 0;
break;
}
case '\n':
case '\r':
case KEY_ENTER:
select_now = 1;
break;
case KEY_LEFT:
if (type) { /* do nothing */ }
else {
if (s > 0) s--;
else s = m->nitems - 1;
break;
}
case KEY_RIGHT:
if (type) {
delwin(m->win);
free_menu(m);
return(c);
break;
}
case ' ':
case KEY_NPAGE:
case KEY_SF:
case KEY_NEXT:
if (s < m->nitems - 1) s++;
else s = 0;
break;
default:
if (type)
c = (c>='A' && c<='Z') ? c -'A' +'a' : c;
for (i=0; i < m->nitems; i++) {
if (m->options[i].hotkey == c) {
s = i;
select_now = 1;
goto call_func;
break;
}
}
break;
}
call_func:
if (s != m->selected) {
if (type)
menu_print_option(m, m->selected, 0);
else
popup_menu_print_option(m, m->selected, 0);
m->selected = s;
if (type)
menu_print_option(m, s, 1);
else
popup_menu_print_option(m, s, 1);
}
if (select_now) {
if (type)
wrefresh(m->win);
else {
touchwin(m->win);
wrefresh(m->win);
}
if (type)
retval = (*(m->options[m->selected].func))
(p_ptbl, y+m->pos[m->selected]+1, x+m->width);
else
retval = (*(m->options[m->selected].func))
(p_ptbl, 1, m->pos[m->selected]);
switch (retval) {
case '\033':
delwin(m->win);
free_menu(m);
return(retval);
break;
case KEY_LEFT:
if (type) { /* do nothing */ }
else {
if (s > 0) s--;
else s = m->nitems - 1;
touchwin(stdscr);
refresh();
// touchwin(m->win);
wrefresh(m->win);
goto call_func;
}
break;
case KEY_RIGHT:
if (type)
break;
else {
if (s < m->nitems - 1) s++;
else s = 0;
touchwin(stdscr);
refresh();
// touchwin(m->win);
wrefresh(m->win);
goto call_func;
break;
}
case 0:
delwin(m->win);
free_menu(m);
return(0);
break;
default:
break;
}
}
} /* end while (1) { } */
} /* end do_menu() */
static int
void_exit(p_ptbl, y, x)
PROCTABLE *p_ptbl;
int y;
int x;
{
// touchwin(stdscr);
refresh();
switch (confirm("y/n", "Quit ?")) {
case 'y':
case 'Y':
clear();
refresh();
endwin();
exit(0);
break;
default:
deleteln();
break;
}
return 0;
}
option menu_file_option[] = {
{ 'x', "Exit", "q", void_exit },
{ 0, NULL, NULL, NULL }
};
static int
file_menu(p_ptbl, y, x)
PROCTABLE *p_ptbl;
int y;
int x;
{
return do_menu(STANDARD_MENU, p_ptbl, menu_file_option, y, x);
}
option menu_memory_option[] = {
{ 'm', "Me&mory", "M", menu_memory_info },
{ 'p', "Proc&table", "P", menu_proctable_info },
{ 0, NULL, NULL, NULL }
};
static int
memory_menu(p_ptbl, y, x)
PROCTABLE *p_ptbl;
int y;
int x;
{
return do_menu(STANDARD_MENU, p_ptbl, menu_memory_option, y, x);
}
option menu_setup_option[] = {
{ '!', "&Language", "", void_exit },
{ '!', "&Process", "", void_exit },
{ '!', "Proc&table", "", void_exit },
{ '!', "&I/O", "", void_exit },
{ '!', "&Memory menu", "", memory_menu },
{ 0, NULL, NULL, NULL }
};
static int
setup_menu(p_ptbl, y, x)
PROCTABLE *p_ptbl;
int y;
int x;
{
return do_menu(STANDARD_MENU, p_ptbl, menu_setup_option, y, x);
}
option menu_help_option[] = {
{ '?', "&About", "", void_exit },
{ '?', "&Keys", "", void_exit },
{ '?', "User's &manual", "", void_exit },
{ '?', "&Copying", "", void_exit },
{ 0, NULL, NULL, NULL }
};
static int
help_menu(p_ptbl, y, x)
PROCTABLE *p_ptbl;
int y;
int x;
{
return do_menu(STANDARD_MENU, p_ptbl, menu_help_option, y, x);
}
option popup_menu_main_option[] = {
{ 'f', "File", "Q", file_menu },
{ 'v', "View", "V", memory_menu },
{ 's', "Setup", "S", setup_menu },
{ 'h', "Help", "H", help_menu },
{ 0, NULL, NULL, NULL }
};
int
menu_main(p_ptbl)
PROCTABLE *p_ptbl;
{
return do_menu(POPUP_MENU, p_ptbl, popup_menu_main_option, 0, 0);
}
void
menu_curses_init(void)
{
initscr();
clear();
cbreak(); // necaka do odklepnutia enterom
noecho(); // mackane klavesy sa nevypisuju na obrazovku
nonl();
keypad(stdscr, TRUE); // pouzivanie sipok
idlok(stdscr, TRUE);
scrollok(stdscr, TRUE);
refresh();
}
#if defined(SELF) || defined(SELFTEST)
int
main(argc, argv)
int argc;
char **argv;
{
fd_set fds;
int c;
int quit = 0;
menu_curses_init();
while (quit == 0) {
FD_ZERO(&fds);
FD_SET(0, &fds);
select(1, &fds, NULL, NULL, NULL);
if (FD_ISSET(0, &fds)) { // keybord pressed
switch ((c = getch())) {
case 'q':
quit = 1;
break;
case '\033': // ESC
case KEY_F(9):
menu_main(NULL);
break;
case KEY_F(10):
switch (confirm("y/n", "Quit ?")) {
case 'y':
case 'Y':
quit = 1;
break;
default:
clear();
refresh();
break;
}
break;
case 12: //^L
refresh();
break;
default:
break;
}
}
}
endwin();
return 0;
}
#endif /* #if defined(SELF) || defined(SELFTEST) */
#endif /* #if MENU */
Platon Group <platon@platon.org> http://platon.org/
|