/* * menu (c)1995 Alexander Tietzel (DG6XA) * little Menu-System for use with ncurses * date activity author * 22.07.1995 wininfo->wint (vector->single chain) Alexander Tietzel (DG6XA) * 25.07.1995 some minor changes Alexander Tietzel (DG6XA) */ #define _DEFAULT_SOURCE #define _XOPEN_SOURCE #define _XOPEN_SOURCE_EXTENDED #include #include #include #include "menu.h" typedef struct { char *st_ptr; int xpos; char key; } topmenuitem; WINDOW *winopen(wint * wtab, int nlines, int ncols, int begin_y, int begin_x, int border) { while (wtab->next != NULL) wtab = wtab->next; wtab->next = (wint *) malloc(sizeof(wint)); wtab = wtab->next; wtab->next = NULL; wtab->ptr = newwin(nlines, ncols, begin_y, begin_x); if (wtab->ptr == NULL) return NULL; wtab->fline = begin_y; wtab->lline = begin_y + nlines; if (border) wborder(wtab->ptr, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE, ACS_ULCORNER, ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER); return wtab->ptr; } void winclose(wint * wtab) { wint *awin; wint *lwin; int awin_lines; if (wtab->next == NULL) return; lwin = wtab; while (lwin->next->next != NULL) lwin = lwin->next; awin = lwin->next; awin_lines = awin->lline - awin->fline; while (wtab->next != NULL) { if (wtab->fline >= 0 && wtab->lline >= 0 && awin->lline >= wtab->fline && awin->fline <= wtab->lline) { if (wtab->fline <= awin->fline) { if (wtab->lline < awin->lline) { wtouchln(wtab->ptr, awin->fline - wtab->fline, awin_lines - (awin->lline - wtab->lline), 1); } else { wtouchln(wtab->ptr, awin->fline - wtab->fline, awin_lines, 1); } } else { wtouchln(wtab->ptr, 0, awin_lines - wtab->fline + awin->fline, 1); } wnoutrefresh(wtab->ptr); } wtab = wtab->next; } doupdate(); lwin->next = NULL; free(awin); } void menu_write_line(WINDOW * win, int ypos, int menu_breite, int reverse, char st[]) { int cnt; int high = FALSE; if (reverse) wattron(win, A_REVERSE); wmove(win, ypos + 1, 1); for (cnt = 0; st[cnt] != 0; cnt++) { if (st[cnt] == '~') { if (!reverse) { wattron(win, A_BOLD); high = TRUE; } } else { waddch(win, st[cnt]); if (high == TRUE) { high = FALSE; wattroff(win, A_BOLD); } } } for (cnt = strlen(st); cnt < menu_breite; cnt++) waddch(win, ' '); if (reverse) wattroff(win, A_REVERSE); } int p_dwn_menu(wint * wtab, menuitem * menustr, int starty, int startx) { int str_max_length = 0; int cnt = 0; int ypos, oldypos; int lines = 0; int c; WINDOW *menuwin; for (lines = 0; (*(menustr[lines].st_ptr) != 0); lines++) { if (strlen(menustr[lines].st_ptr) > str_max_length) str_max_length = strlen(menustr[lines].st_ptr); } menuwin = winopen(wtab, lines + 2, str_max_length + 1, starty, startx, TRUE); wrefresh(menuwin); menu_write_line(menuwin, 0, str_max_length, TRUE, menustr[0].st_ptr); for (ypos = 1; ypos < lines; ypos++) menu_write_line(menuwin, ypos, str_max_length, FALSE, menustr[ypos].st_ptr); wrefresh(menuwin); ypos = 0; do { while ((c = getch()) == ERR); oldypos = ypos; switch (c) { case KEY_DOWN: if (++ypos >= lines) ypos = 0; break; case KEY_UP: if (ypos == 0) ypos = lines - 1; else ypos--; break; default: if ((char) c >= 'a' && (char) c <= 'z') c -= 'a' - 'A'; for (cnt = 0; menustr[cnt].key != (char) c && cnt < lines; cnt++); if (menustr[cnt].key == (char) c) ypos = cnt; break; } if (ypos != oldypos) { menu_write_line(menuwin, ypos, str_max_length, TRUE, menustr[ypos].st_ptr); menu_write_line(menuwin, oldypos, str_max_length, FALSE, menustr[oldypos].st_ptr); wrefresh(menuwin); } } while (c != KEY_ENTER && c != '\r' && c != '\n' && c != KEY_RIGHT && c != KEY_LEFT && c != 0x1b); delwin(menuwin); winclose(wtab); if (c == 0x1b) return 0; if (c == KEY_RIGHT || c == KEY_LEFT) return c; else return ypos + 1; } void menu_write_item(WINDOW * win, int xpos, int reverse, const char st[]) { int cnt; int high = FALSE; if (reverse) wattron(win, A_REVERSE); wmove(win, 1, xpos + 1); for (cnt = 0; st[cnt] != 0; cnt++) { if (st[cnt] == '~') { if (!reverse) { wattron(win, A_BOLD); high = TRUE; } } else { waddch(win, st[cnt]); if (high) { high = FALSE; wattroff(win, A_BOLD); } } } if (reverse) wattroff(win, A_REVERSE); } int top_menu(wint * wtab, menuitem menustr[], int ystart) { int str_max_length = 0; int str_length = 0; int cnt; int xpos, oldxpos; int ypos = 0; int items = 0; int c; WINDOW *menuwin; int items_xpos[12]; curs_set(0); /*cursor visibility off */ for (items = 0; *(menustr[items].st_ptr) != 0; items++) { if (items == 0) items_xpos[0] = 1; else items_xpos[items] = items_xpos[items - 1] + str_length; if (strlen(menustr[items].st_ptr) > str_max_length) str_max_length = strlen(menustr[items].st_ptr); str_length = strlen(menustr[items].st_ptr) + 1; } menuwin = winopen(wtab, 3, 80, ystart, 0, TRUE); wrefresh(menuwin); menu_write_item(menuwin, 1, TRUE, menustr[0].st_ptr); for (xpos = 1; xpos < items; xpos++) menu_write_item(menuwin, items_xpos[xpos], FALSE, menustr[xpos].st_ptr); wrefresh(menuwin); xpos = 0; do { while ((c = getch()) == ERR); oldxpos = xpos; switch (c) { case KEY_RIGHT: if (++xpos >= items) xpos = 0; break; case KEY_LEFT: if (xpos == 0) xpos = items - 1; else xpos--; break; case KEY_DOWN: case KEY_ENTER: case '\r': case '\n': ypos = 0; do { switch (ypos) { case KEY_RIGHT: if (++xpos >= items) xpos = 0; menu_write_item(menuwin, items_xpos[xpos], TRUE, menustr[xpos]. st_ptr); menu_write_item(menuwin, items_xpos [oldxpos], FALSE, menustr[oldxpos]. st_ptr); wrefresh(menuwin); oldxpos = xpos; break; case KEY_LEFT: if (xpos == 0) xpos = items - 1; else xpos--; menu_write_item(menuwin, items_xpos[xpos], TRUE, menustr[xpos]. st_ptr); menu_write_item(menuwin, items_xpos [oldxpos], FALSE, menustr[oldxpos]. st_ptr); wrefresh(menuwin); oldxpos = xpos; break; } ypos = p_dwn_menu(wtab, (menuitem *) menustr[xpos]. arg, ystart + 2, items_xpos[xpos] + 1); touchwin(menuwin); wrefresh(menuwin); } while (ypos == KEY_RIGHT || ypos == KEY_LEFT); break; default: if ((char) c >= 'a' && (char) c <= 'z') c -= 'a' - 'A'; for (cnt = 0; menustr[cnt].key != (char) c && cnt <= items; cnt++); if (menustr[cnt].key == (char) c) xpos = cnt; } if (xpos != oldxpos) { menu_write_item(menuwin, items_xpos[xpos], TRUE, menustr[xpos].st_ptr); menu_write_item(menuwin, items_xpos[oldxpos], FALSE, menustr[oldxpos].st_ptr); wrefresh(menuwin); } } while (ypos == 0 && c != 0x1b); delwin(menuwin); curs_set(1); winclose(wtab); if (c == 0x1b) return 0; return (ypos & 0x0F) | ((xpos & 0x07) << 4); }