/* * ep - extended pipelining * * menu.c - ncurses menu core * ____________________________________________________________ * * Developed by Ondrej Jombik * and Lubomir Host * 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 #ifdef STDC_HEADERS # include # include # include #endif #if HAVE_UNISTD_H # include # include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_MALLOC_H # include #endif #if defined(SELF) || defined(SELFTEST) # define MENU 1 # define PACKAGE "ep-selftest module" # define VERSION "1.0" # include # include # include # include # include # include # include # include # include # 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 #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 */