blob: a0d2d0ee915b81c9ddbd0a4a25f96eae49492759 [file] [log] [blame]
/*
* Copyright (c) 2002 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <xfs/xfs.h>
#include <xfs/jdm.h>
#include <ncurses.h>
#include <ctype.h>
#include "types.h"
#include "cmenu.h"
#include "list.h"
#include "invutil.h"
int
put_all_options(WINDOW *win, node_t *list, node_t *current)
{
int i;
int attr;
data_t *d;
node_t *node;
i = 0;
node = list;
while(node != NULL) {
d = ((data_t *)(node->data));
if(d->hidden == BOOL_TRUE) {
node = node->next;
continue;
}
if(node == current) {
attr = A_REVERSE;
}
else {
attr = 0;
}
put_option(win, i, d->text, attr);
node = node->next;
i++;
}
return 0;
}
void
put_helpscreen(int keyc, menukey_t *keyv)
{
int k;
int l;
int winline;
WINDOW *helpscreen;
winline = LINES - (keyc + 5);
if(winline < 0)
winline = 0;
helpscreen = newwin(keyc + 4, 29, winline, COLS - 30);
keypad(helpscreen, TRUE);
wattron(helpscreen, A_REVERSE);
wmove(helpscreen, 0, 0);
waddstr(helpscreen, " --------------------------- ");
wmove(helpscreen, 1, 0);
waddstr(helpscreen, "| Menu Help |");
wmove(helpscreen, 2, 0);
waddstr(helpscreen, "| |");
l = 3;
for(k = 0; k < keyc + 1; k++) {
if(keyv[k].text == NULL)
continue;
wmove(helpscreen, l, 0);
waddstr(helpscreen, keyv[k].text);
l++;
}
wmove(helpscreen, l, 0);
waddstr(helpscreen, " --------------------------- ");
wrefresh(helpscreen);
wattroff(helpscreen, A_REVERSE);
hitanykey();
wclear(helpscreen);
wrefresh(helpscreen);
delwin(helpscreen);
}
int
menu(WINDOW *win, int line, int col, node_t *list, int keyc, menukey_t *keyv)
{
int c;
int k;
int quit;
char txt[256];
node_t *current;
node_t *last;
data_t *d;
int current_line;
int last_line;
int size;
current = list;
last = current;
current_line = 0;
last_line = current_line;
redraw_screen = BOOL_TRUE;
quit = BOOL_FALSE;
while(quit != BOOL_TRUE) {
if(current == NULL && current->data == NULL) {
current = list;
}
d = (data_t *)(current->data);
if(redraw_screen == BOOL_TRUE) {
wclear(win);
snprintf(txt, sizeof(txt), "%s: %s", g_programName, g_programVersion);
put_header(txt, ALIGN_LEFT);
if(d->hidden == BOOL_TRUE) {
current = list;
current_line = 0;
d = (data_t *)(current->data);
}
put_all_options(win, list, current);
redraw_screen = BOOL_FALSE;
if(d->ops != NULL && d->ops->op_highlight != NULL) {
quit = d->ops->op_highlight(win, current, list);
}
}
else if (last != current || redraw_options) {
put_option(win, last_line, ((data_t *)(last->data))->text, 0);
put_option(win, current_line, d->text, A_REVERSE);
redraw_options = BOOL_FALSE;
if(((data_t *)(last->data))->ops != NULL
&& ((data_t *)(last->data))->ops->op_unhighlight != NULL) {
quit = ((data_t *)(last->data))->ops->op_unhighlight(win, current, list);
}
if(d->ops != NULL && d->ops->op_highlight != NULL) {
quit = d->ops->op_highlight(win, current, list);
}
}
last = current;
last_line = current_line;
wrefresh(stdscr);
wrefresh(infowin);
size = (LINES - 2) - INFO_SIZE;
prefresh(win,
current_line - (size - 1), 0,
line, col,
size, COLS - 1);
if(quit == BOOL_TRUE)
continue;
c=wgetch(win);
switch(c) {
case '?':
case KEY_F(1):
/* online help */
put_helpscreen(keyc, keyv);
redraw_screen = BOOL_TRUE;
break;
case KEY_UP:
case 'k':
/* go to previous option */
{
data_t *d;
node_t *n = current->prev;
while(n != NULL) {
d = ((data_t *)(n->data));
if(d == NULL) {
n = n->prev;
continue;
}
if(d->hidden == BOOL_FALSE) {
break;
}
n = n->prev;
}
if(n != NULL) {
current = n;
current_line--;
}
}
break;
case KEY_DOWN:
case 'j':
/* go to next option */
{
data_t *d;
node_t *n = current->next;
while(n != NULL) {
d = ((data_t *)(n->data));
if(d == NULL) {
n = n->next;
continue;
}
if(d->hidden == BOOL_FALSE) {
break;
}
n = n->next;
}
if(n != NULL) {
current = n;
current_line++;
}
}
break;
case KEY_RIGHT:
case 'l':
/* go to next child */
{
node_t *n = current->next;
int l;
if(current != NULL && ((data_t *)(current->data)) == NULL) {
break;
}
l = ((data_t *)(current->data))->level;
if(n != NULL && ((data_t *)(n->data)) != NULL && ((data_t *)(n->data))->level > l) {
if(((data_t *)(n->data))->hidden == BOOL_TRUE) {
menu_expand(win, current, list);
}
current = n;
current_line++;
}
}
break;
case KEY_LEFT:
case 'h':
/* go to parent */
{
data_t *d;
node_t *n = current->prev;
int l = 0;
int i;
if(current != NULL && ((data_t *)(current->data)) != NULL) {
l = ((data_t *)(current->data))->level;
}
i = current_line - 1;
while(n != NULL) {
d = ((data_t *)(n->data));
if(d == NULL) {
n = n->prev;
continue;
}
if(d->hidden == BOOL_TRUE) {
n = n->prev;
continue;
}
if(d->level < l) {
break;
}
n = n->prev;
i--;
}
if(n != NULL) {
current = n;
current_line = i;;
}
}
break;
case ERR:
if(errno == EINTR) {
/* mainmenu window has been recreated - use new one */
win = mainmenu;
}
break;
default:
for(k = 0; k < keyc; k++) {
if(c == keyv[k].key || tolower(c) == keyv[k].key) {
if (keyv[k].fn != NULL) {
quit = keyv[k].fn(win, current, list);
break;
}
else {
put_footer("internal error: can't execute function", ALIGN_CENTRE);
break;
}
}
}
break;
}
}
return 0;
}