Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Thursday, March 28, 2024

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/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top