summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux/latest/com32/cmenu/libmenu/menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux/latest/com32/cmenu/libmenu/menu.c')
-rw-r--r--contrib/syslinux/latest/com32/cmenu/libmenu/menu.c1273
1 files changed, 0 insertions, 1273 deletions
diff --git a/contrib/syslinux/latest/com32/cmenu/libmenu/menu.c b/contrib/syslinux/latest/com32/cmenu/libmenu/menu.c
deleted file mode 100644
index 19a7e59..0000000
--- a/contrib/syslinux/latest/com32/cmenu/libmenu/menu.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-/* -*- c -*- ------------------------------------------------------------- *
- *
- * Copyright 2004-2005 Murali Krishnan Ganapathy - 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, Inc., 53 Temple Place Ste 330,
- * Boston MA 02111-1307, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-#include "menu.h"
-#include "com32io.h"
-#include <stdlib.h>
-#include <console.h>
-
-// Local Variables
-static pt_menusystem ms; // Pointer to the menusystem
-char TITLESTR[] =
- "COMBOOT Menu System for SYSLINUX developed by Murali Krishnan Ganapathy";
-char TITLELONG[] = " TITLE too long ";
-char ITEMLONG[] = " ITEM too long ";
-char ACTIONLONG[] = " ACTION too long ";
-char STATUSLONG[] = " STATUS too long ";
-char EMPTYSTR[] = "";
-
-/* Forward declarations */
-int calc_visible(pt_menu menu, int first);
-int next_visible(pt_menu menu, int index);
-int prev_visible(pt_menu menu, int index);
-int next_visible_sep(pt_menu menu, int index);
-int prev_visible_sep(pt_menu menu, int index);
-int calc_first_early(pt_menu menu, int curr);
-int calc_first_late(pt_menu menu, int curr);
-int isvisible(pt_menu menu, int first, int curr);
-
-/* Basic Menu routines */
-
-// This is same as inputc except it honors the ontimeout handler
-// and calls it when needed. For the callee, there is no difference
-// as this will not return unless a key has been pressed.
-static int getch(void)
-{
- t_timeout_handler th;
- int key;
- unsigned long i;
-
- // Wait until keypress if no handler specified
- if ((ms->ontimeout == NULL) && (ms->ontotaltimeout == NULL))
- return get_key(stdin, 0);
-
- th = ms->ontimeout;
- for (;;) {
- for (i = 0; i < ms->tm_numsteps; i++) {
- key = get_key(stdin, ms->tm_stepsize);
- if (key != KEY_NONE)
- return key;
-
- if ((ms->tm_total_timeout == 0) || (ms->ontotaltimeout == NULL))
- continue; // Dont bother with calculations if no handler
- ms->tm_sofar_timeout += ms->tm_stepsize;
- if (ms->tm_sofar_timeout >= ms->tm_total_timeout) {
- th = ms->ontotaltimeout;
- ms->tm_sofar_timeout = 0;
- break; // Get out of the for loop
- }
- }
- if (!th)
- continue; // no handler
- key = th();
- switch (key) {
- case CODE_ENTER: // Pretend user hit enter
- return KEY_ENTER;
- case CODE_ESCAPE: // Pretend user hit escape
- return KEY_ESC;
- default:
- break;
- }
- }
- return KEY_NONE;
-}
-
-int find_shortcut(pt_menu menu, uchar shortcut, int index)
-// Find the next index with specified shortcut key
-{
- int ans;
- pt_menuitem mi;
-
- // Garbage in garbage out
- if ((index < 0) || (index >= menu->numitems))
- return index;
- ans = index + 1;
- // Go till end of menu
- while (ans < menu->numitems) {
- mi = menu->items[ans];
- if ((mi->action == OPT_INVISIBLE) || (mi->action == OPT_SEP)
- || (mi->shortcut != shortcut))
- ans++;
- else
- return ans;
- }
- // Start at the beginning and try again
- ans = 0;
- while (ans < index) {
- mi = menu->items[ans];
- if ((mi->action == OPT_INVISIBLE) || (mi->action == OPT_SEP)
- || (mi->shortcut != shortcut))
- ans++;
- else
- return ans;
- }
- return index; // Sorry not found
-}
-
-/* Redraw background and title */
-static void reset_ui(void)
-{
- uchar tpos;
-
- cls();
- clearwindow(ms->minrow, ms->mincol, ms->maxrow, ms->maxcol,
- ms->fillchar, ms->fillattr);
-
- tpos = (ms->numcols - strlen(ms->title) - 1) >> 1; // center it on line
- gotoxy(ms->minrow, ms->mincol);
- cprint(ms->tfillchar, ms->titleattr, ms->numcols);
- gotoxy(ms->minrow, ms->mincol + tpos);
- csprint(ms->title, ms->titleattr);
-
- cursoroff();
-}
-
-/*
- * Print a menu item
- *
- * attr[0] is non-hilite attr, attr[1] is highlight attr
- */
-void printmenuitem(const char *str, uchar * attr)
-{
- int hlite = NOHLITE; // Initially no highlighting
-
- while (*str) {
- switch (*str) {
- case BELL: // No Bell Char
- break;
- case ENABLEHLITE: // Switch on highlighting
- hlite = HLITE;
- break;
- case DISABLEHLITE: // Turn off highlighting
- hlite = NOHLITE;
- break;
- default:
- putch(*str, attr[hlite]);
- }
- str++;
- }
-}
-
-
-/**
- * print_line - Print a whole line in a menu
- * @menu: current menu to handle
- * @curr: index of the current entry highlighted
- * @top: top coordinate of the @menu
- * @left: left coordinate of the @menu
- * @x: index in the menu of curr
- * @row: row currently displayed
- * @radio: radio item?
- **/
-static void print_line(pt_menu menu, int curr, uchar top, uchar left,
- int x, int row, bool radio)
-{
- pt_menuitem ci;
- char fchar[6], lchar[6]; // The first and last char in for each entry
- const char *str; // Item string (cf printmenuitem)
- char sep[MENULEN]; // Separator (OPT_SEP)
- uchar *attr; // Attribute
- int menuwidth = menu->menuwidth + 3;
-
- if (row >= menu->menuheight)
- return;
-
- ci = menu->items[x];
-
- memset(sep, ms->box_horiz, menuwidth);
- sep[menuwidth - 1] = 0;
-
- // Setup the defaults now
- if (radio) {
- fchar[0] = '\b';
- fchar[1] = SO;
- fchar[2] = (x == curr ? RADIOSEL : RADIOUNSEL);
- fchar[3] = SI;
- fchar[4] = '\0'; // Unselected ( )
- lchar[0] = '\0'; // Nothing special after
- attr = ms->normalattr; // Always same attribute
- } else {
- lchar[0] = fchar[0] = ' ';
- lchar[1] = fchar[1] = '\0'; // fchar and lchar are just spaces
- attr = (x == curr ? ms->reverseattr : ms->normalattr); // Normal attributes
- }
- str = ci->item; // Pointer to item string
- switch (ci->action) // set up attr,str,fchar,lchar for everything
- {
- case OPT_INACTIVE:
- if (radio)
- attr = ms->inactattr;
- else
- attr = (x == curr ? ms->revinactattr : ms->inactattr);
- break;
- case OPT_SUBMENU:
- if (radio)
- break; // Not supported for radio menu
- lchar[0] = '>';
- lchar[1] = 0;
- break;
- case OPT_RADIOMENU:
- if (radio)
- break; // Not supported for radio menu
- lchar[0] = RADIOMENUCHAR;
- lchar[1] = 0;
- break;
- case OPT_CHECKBOX:
- if (radio)
- break; // Not supported for radio menu
- lchar[0] = '\b';
- lchar[1] = SO;
- lchar[2] = (ci->itemdata.checked ? CHECKED : UNCHECKED);
- lchar[3] = SI;
- lchar[4] = 0;
- break;
- case OPT_SEP:
- fchar[0] = '\b';
- fchar[1] = SO;
- fchar[2] = LEFT_MIDDLE_BORDER;
- fchar[3] = MIDDLE_BORDER;
- fchar[4] = MIDDLE_BORDER;
- fchar[5] = 0;
- memset(sep, MIDDLE_BORDER, menuwidth);
- sep[menuwidth - 1] = 0;
- str = sep;
- lchar[0] = MIDDLE_BORDER;
- lchar[1] = RIGHT_MIDDLE_BORDER;
- lchar[2] = SI;
- lchar[3] = 0;
- break;
- case OPT_EXITMENU:
- if (radio)
- break; // Not supported for radio menu
- fchar[0] = '<';
- fchar[1] = 0;
- break;
- default: // Just to keep the compiler happy
- break;
- }
-
- // Wipe area with spaces
- gotoxy(top + row, left - 2);
- cprint(ms->spacechar, attr[NOHLITE], menuwidth + 2);
-
- // Print first part
- gotoxy(top + row, left - 2);
- csprint(fchar, attr[NOHLITE]);
-
- // Print main part
- gotoxy(top + row, left);
- printmenuitem(str, attr);
-
- // Print last part
- gotoxy(top + row, left + menuwidth - 1);
- csprint(lchar, attr[NOHLITE]);
-}
-
-// print the menu starting from FIRST
-// will print a maximum of menu->menuheight items
-static void printmenu(pt_menu menu, int curr, uchar top, uchar left, uchar first, bool radio)
-{
- int x, row; // x = index, row = position from top
- int numitems, menuwidth;
- pt_menuitem ci;
-
- numitems = calc_visible(menu, first);
- if (numitems > menu->menuheight)
- numitems = menu->menuheight;
-
- menuwidth = menu->menuwidth + 3;
- clearwindow(top, left - 2, top + numitems + 1, left + menuwidth + 1,
- ms->fillchar, ms->shadowattr);
- drawbox(top - 1, left - 3, top + numitems, left + menuwidth,
- ms->normalattr[NOHLITE]);
-
- // Menu title
- x = (menuwidth - strlen(menu->title) - 1) >> 1;
- gotoxy(top - 1, left + x);
- printmenuitem(menu->title, ms->normalattr);
-
- // All lines in the menu
- row = -1; // 1 less than inital value of x
- for (x = first; x < menu->numitems; x++) {
- ci = menu->items[x];
- if (ci->action == OPT_INVISIBLE)
- continue;
- row++;
- if (row >= numitems)
- break; // Already have enough number of items
- print_line(menu, curr, top, left, x, row, radio);
- }
- // Check if we need to MOREABOVE and MOREBELOW to be added
- // reuse x
- row = 0;
- x = next_visible_sep(menu, 0); // First item
- if (!isvisible(menu, first, x)) // There is more above
- {
- row = 1;
- gotoxy(top, left + menuwidth);
- cprint(MOREABOVE, ms->normalattr[NOHLITE], 1);
- }
- x = prev_visible_sep(menu, menu->numitems); // last item
- if (!isvisible(menu, first, x)) // There is more above
- {
- row = 1;
- gotoxy(top + numitems - 1, left + menuwidth);
- cprint(MOREBELOW, ms->normalattr[NOHLITE], 1);
- }
- // Add a scroll box
- x = ((numitems - 1) * curr) / (menu->numitems);
- if ((x > 0) && (row == 1)) {
- gotoxy(top + x, left + menuwidth);
- csprint("\016\141\017", ms->normalattr[NOHLITE]);
- }
- if (ms->handler)
- ms->handler(ms, menu->items[curr]);
-}
-
-void cleanupmenu(pt_menu menu, uchar top, uchar left, int numitems)
-{
- if (numitems > menu->menuheight)
- numitems = menu->menuheight;
- clearwindow(top, left - 2, top + numitems + 1, left + menu->menuwidth + 4, ms->fillchar, ms->fillattr); // Clear the shadow
- clearwindow(top - 1, left - 3, top + numitems, left + menu->menuwidth + 3, ms->fillchar, ms->fillattr); // main window
-}
-
-
-/* Handle one menu */
-static pt_menuitem getmenuoption(pt_menu menu, uchar top, uchar left, uchar startopt, bool radio)
- // Return item chosen or NULL if ESC was hit.
-{
- int prev, prev_first, curr, i, first, tmp;
- int asc = 0;
- bool redraw = true; // Need to draw the menu the first time
- uchar numitems;
- pt_menuitem ci; // Current item
- t_handler_return hr; // Return value of handler
-
- numitems = calc_visible(menu, 0);
- // Setup status line
- gotoxy(ms->minrow + ms->statline, ms->mincol);
- cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols);
-
- // Initialise current menu item
- curr = next_visible(menu, startopt);
- prev = curr;
-
- gotoxy(ms->minrow + ms->statline, ms->mincol);
- cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols);
- gotoxy(ms->minrow + ms->statline, ms->mincol);
- printmenuitem(menu->items[curr]->status, ms->statusattr);
- first = calc_first_early(menu, curr);
- prev_first = first;
- while (1) // Forever
- {
- /* Redraw everything if:
- * + we need to scroll (take care of scroll bars, ...)
- * + menuoption
- */
- if (prev_first != first || redraw) {
- printmenu(menu, curr, top, left, first, radio);
- } else {
- /* Redraw only the highlighted entry */
- print_line(menu, curr, top, left, prev, prev - first, radio);
- print_line(menu, curr, top, left, curr, curr - first, radio);
- }
- redraw = false;
- prev = curr;
- prev_first = first;
- ci = menu->items[curr];
- asc = getch();
- switch (asc) {
- case KEY_CTRL('L'):
- redraw = true;
- break;
- case KEY_HOME:
- curr = next_visible(menu, 0);
- first = calc_first_early(menu, curr);
- break;
- case KEY_END:
- curr = prev_visible(menu, numitems - 1);
- first = calc_first_late(menu, curr);
- break;
- case KEY_PGDN:
- for (i = 0; i < 5; i++)
- curr = next_visible(menu, curr + 1);
- first = calc_first_late(menu, curr);
- break;
- case KEY_PGUP:
- for (i = 0; i < 5; i++)
- curr = prev_visible(menu, curr - 1);
- first = calc_first_early(menu, curr);
- break;
- case KEY_UP:
- curr = prev_visible(menu, curr - 1);
- if (curr < first)
- first = calc_first_early(menu, curr);
- break;
- case KEY_DOWN:
- curr = next_visible(menu, curr + 1);
- if (!isvisible(menu, first, curr))
- first = calc_first_late(menu, curr);
- break;
- case KEY_LEFT:
- case KEY_ESC:
- return NULL;
- break;
- case KEY_RIGHT:
- case KEY_ENTER:
- if (ci->action == OPT_INACTIVE)
- break;
- if (ci->action == OPT_CHECKBOX)
- break;
- if (ci->action == OPT_SEP)
- break;
- if (ci->action == OPT_EXITMENU)
- return NULL; // As if we hit Esc
- // If we are going into a radio menu, dont call handler, return ci
- if (ci->action == OPT_RADIOMENU)
- return ci;
- if (ci->handler != NULL) // Do we have a handler
- {
- hr = ci->handler(ms, ci);
- if (hr.refresh) // Do we need to refresh
- {
- // Cleanup menu using old number of items
- cleanupmenu(menu, top, left, numitems);
- // Recalculate the number of items
- numitems = calc_visible(menu, 0);
- // Reprint the menu
- printmenu(menu, curr, top, left, first, radio);
- }
- if (hr.valid)
- return ci;
- } else
- return ci;
- break;
- case SPACECHAR:
- if (ci->action != OPT_CHECKBOX)
- break;
- ci->itemdata.checked = !ci->itemdata.checked;
- if (ci->handler != NULL) // Do we have a handler
- {
- hr = ci->handler(ms, ci);
- if (hr.refresh) // Do we need to refresh
- {
- // Cleanup menu using old number of items
- cleanupmenu(menu, top, left, numitems);
- // Recalculate the number of items
- numitems = calc_visible(menu, 0);
- // Reprint the menu
- printmenu(menu, curr, top, left, first, radio);
- }
- }
- break;
- default:
- // Check if this is a shortcut key
- if (((asc >= 'A') && (asc <= 'Z')) ||
- ((asc >= 'a') && (asc <= 'z')) ||
- ((asc >= '0') && (asc <= '9'))) {
- tmp = find_shortcut(menu, asc, curr);
- if ((tmp > curr) && (!isvisible(menu, first, tmp)))
- first = calc_first_late(menu, tmp);
- if (tmp < curr)
- first = calc_first_early(menu, tmp);
- curr = tmp;
- } else {
- if (ms->keys_handler) // Call extra keys handler
- ms->keys_handler(ms, menu->items[curr], asc);
-
- /* The handler may have changed the UI, reset it on exit */
- reset_ui();
- // Cleanup menu using old number of items
- cleanupmenu(menu, top, left, numitems);
- // Recalculate the number of items
- numitems = calc_visible(menu, 0);
- // Reprint the menu
- printmenu(menu, curr, top, left, first, radio);
- }
- break;
- }
- // Update status line
- /* Erase the previous status */
- gotoxy(ms->minrow + ms->statline, ms->mincol);
- cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols);
- /* Print the new status */
- gotoxy(ms->minrow + ms->statline, ms->mincol);
- printmenuitem(menu->items[curr]->status, ms->statusattr);
- }
- return NULL; // Should never come here
-}
-
-/* Handle the entire system of menu's. */
-pt_menuitem runmenusystem(uchar top, uchar left, pt_menu cmenu, uchar startopt,
- uchar menutype)
- /*
- * cmenu
- * Which menu should be currently displayed
- * top,left
- * What is the position of the top,left corner of the menu
- * startopt
- * which menu item do I start with
- * menutype
- * NORMALMENU or RADIOMENU
- *
- * Return Value:
- * Returns a pointer to the final item chosen, or NULL if nothing chosen.
- */
-{
- pt_menuitem opt, choice;
- uchar startat, mt;
- uchar row, col;
-
- if (cmenu == NULL)
- return NULL;
-
-startover:
- // Set the menu height
- cmenu->menuheight = ms->maxrow - top - 3;
- if (cmenu->menuheight > ms->maxmenuheight)
- cmenu->menuheight = ms->maxmenuheight;
- if (menutype == NORMALMENU)
- opt = getmenuoption(cmenu, top, left, startopt, false);
- else // menutype == RADIOMENU
- opt = getmenuoption(cmenu, top, left, startopt, true);
-
- if (opt == NULL) {
- // User hit Esc
- cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0));
- return NULL;
- }
- // Are we done with the menu system?
- if ((opt->action != OPT_SUBMENU) && (opt->action != OPT_RADIOMENU)) {
- cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0));
- return opt; // parent cleanup other menus
- }
- // Either radiomenu or submenu
- // Do we have a valid menu number? The next hack uses the fact that
- // itemdata.submenunum = itemdata.radiomenunum (since enum data type)
- if (opt->itemdata.submenunum >= ms->nummenus) // This is Bad....
- {
- gotoxy(12, 12); // Middle of screen
- csprint("ERROR: Invalid submenu requested.", 0x07);
- cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0));
- return NULL; // Pretend user hit esc
- }
- // Call recursively for submenu
- // Position the submenu below the current item,
- // covering half the current window (horizontally)
- row = ms->menus[(unsigned int)opt->itemdata.submenunum]->row;
- col = ms->menus[(unsigned int)opt->itemdata.submenunum]->col;
- if (row == 0xFF)
- row = top + opt->index + 2;
- if (col == 0xFF)
- col = left + 3 + (cmenu->menuwidth >> 1);
- mt = (opt->action == OPT_SUBMENU ? NORMALMENU : RADIOMENU);
- startat = 0;
- if ((opt->action == OPT_RADIOMENU) && (opt->data != NULL))
- startat = ((t_menuitem *) opt->data)->index;
-
- choice = runmenusystem(row, col,
- ms->menus[(unsigned int)opt->itemdata.submenunum],
- startat, mt);
- if (opt->action == OPT_RADIOMENU) {
- if (choice != NULL)
- opt->data = (void *)choice; // store choice in data field
- if (opt->handler != NULL)
- opt->handler(ms, opt);
- choice = NULL; // Pretend user hit esc
- }
- if (choice == NULL) // User hit Esc in submenu
- {
- // Startover
- startopt = opt->index;
- goto startover;
- } else {
- cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0));
- return choice;
- }
-}
-
-// Finds the indexof the menu with given name
-uchar find_menu_num(const char *name)
-{
- int i;
- pt_menu m;
-
- if (name == NULL)
- return (uchar) (-1);
- for (i = 0; i < ms->nummenus; i++) {
- m = ms->menus[i];
- if ((m->name) && (strcmp(m->name, name) == 0))
- return i;
- }
- return (uchar) (-1);
-}
-
-// Run through all items and if they are submenus
-// with a non-trivial "action" and trivial submenunum
-// replace submenunum with the menu with name "action"
-void fix_submenus(void)
-{
- int i, j;
- pt_menu m;
- pt_menuitem mi;
-
- i = 0;
- for (i = 0; i < ms->nummenus; i++) {
- m = ms->menus[i];
- for (j = 0; j < m->numitems; j++) {
- mi = m->items[j];
- // if item is a submenu and has non-empty non-trivial data string
- if (mi->data && strlen(mi->data) > 0 &&
- ((mi->action == OPT_SUBMENU)
- || (mi->action == OPT_RADIOMENU))) {
- mi->itemdata.submenunum = find_menu_num(mi->data);
- }
- }
- }
-}
-
-/* User Callable functions */
-
-pt_menuitem showmenus(uchar startmenu)
-{
- pt_menuitem rv;
-
- fix_submenus(); // Fix submenu numbers incase nick names were used
-
- /* Turn autowrap off, to avoid scrolling the menu */
- printf(CSI "?7l");
-
- // Setup screen for menusystem
- reset_ui();
-
- // Go, main menu cannot be a radio menu
- rv = runmenusystem(ms->minrow + MENUROW, ms->mincol + MENUCOL,
- ms->menus[(unsigned int)startmenu], 0, NORMALMENU);
-
- // Hide the garbage we left on the screen
- cls();
- gotoxy(ms->minrow, ms->mincol);
- cursoron();
-
- // Return user choice
- return rv;
-}
-
-pt_menusystem init_menusystem(const char *title)
-{
- int i;
-
- ms = NULL;
- ms = (pt_menusystem) malloc(sizeof(t_menusystem));
- if (ms == NULL)
- return NULL;
- ms->nummenus = 0;
- // Initialise all menu pointers
- for (i = 0; i < MAXMENUS; i++)
- ms->menus[i] = NULL;
-
- ms->title = (char *)malloc(TITLELEN + 1);
- if (title == NULL)
- strcpy(ms->title, TITLESTR); // Copy string
- else
- strcpy(ms->title, title);
-
- // Timeout settings
- ms->tm_stepsize = TIMEOUTSTEPSIZE;
- ms->tm_numsteps = TIMEOUTNUMSTEPS;
-
- ms->normalattr[NOHLITE] = NORMALATTR;
- ms->normalattr[HLITE] = NORMALHLITE;
-
- ms->reverseattr[NOHLITE] = REVERSEATTR;
- ms->reverseattr[HLITE] = REVERSEHLITE;
-
- ms->inactattr[NOHLITE] = INACTATTR;
- ms->inactattr[HLITE] = INACTHLITE;
-
- ms->revinactattr[NOHLITE] = REVINACTATTR;
- ms->revinactattr[HLITE] = REVINACTHLITE;
-
- ms->statusattr[NOHLITE] = STATUSATTR;
- ms->statusattr[HLITE] = STATUSHLITE;
-
- ms->statline = STATLINE;
- ms->tfillchar = TFILLCHAR;
- ms->titleattr = TITLEATTR;
-
- ms->fillchar = FILLCHAR;
- ms->fillattr = FILLATTR;
- ms->spacechar = SPACECHAR;
- ms->shadowattr = SHADOWATTR;
-
- ms->menupage = MENUPAGE; // Usually no need to change this at all
-
- // Initialise all handlers
- ms->handler = NULL;
- ms->keys_handler = NULL;
- ms->ontimeout = NULL; // No timeout handler
- ms->tm_total_timeout = 0;
- ms->tm_sofar_timeout = 0;
- ms->ontotaltimeout = NULL;
-
- // Setup ACTION_{,IN}VALID
- ACTION_VALID.valid = 1;
- ACTION_VALID.refresh = 0;
- ACTION_INVALID.valid = 0;
- ACTION_INVALID.refresh = 0;
-
- // Figure out the size of the screen we are in now.
- // By default we use the whole screen for our menu
- if (getscreensize(1, &ms->numrows, &ms->numcols)) {
- /* Unknown screen size? */
- ms->numcols = 80;
- ms->numrows = 24;
- }
- ms->minrow = ms->mincol = 0;
- ms->maxcol = ms->numcols - 1;
- ms->maxrow = ms->numrows - 1;
-
- // How many entries per menu can we display at a time
- ms->maxmenuheight = ms->maxrow - ms->minrow - 3;
- if (ms->maxmenuheight > MAXMENUHEIGHT)
- ms->maxmenuheight = MAXMENUHEIGHT;
-
- console_ansi_raw();
-
- return ms;
-}
-
-void set_normal_attr(uchar normal, uchar selected, uchar inactivenormal,
- uchar inactiveselected)
-{
- if (normal != 0xFF)
- ms->normalattr[0] = normal;
- if (selected != 0xFF)
- ms->reverseattr[0] = selected;
- if (inactivenormal != 0xFF)
- ms->inactattr[0] = inactivenormal;
- if (inactiveselected != 0xFF)
- ms->revinactattr[0] = inactiveselected;
-}
-
-void set_normal_hlite(uchar normal, uchar selected, uchar inactivenormal,
- uchar inactiveselected)
-{
- if (normal != 0xFF)
- ms->normalattr[1] = normal;
- if (selected != 0xFF)
- ms->reverseattr[1] = selected;
- if (inactivenormal != 0xFF)
- ms->inactattr[1] = inactivenormal;
- if (inactiveselected != 0xFF)
- ms->revinactattr[1] = inactiveselected;
-}
-
-void set_status_info(uchar statusattr, uchar statushlite, uchar statline)
-{
- if (statusattr != 0xFF)
- ms->statusattr[NOHLITE] = statusattr;
- if (statushlite != 0xFF)
- ms->statusattr[HLITE] = statushlite;
- // statline is relative to minrow
- if (statline >= ms->numrows)
- statline = ms->numrows - 1;
- ms->statline = statline; // relative to ms->minrow, 0 based
-}
-
-void set_title_info(uchar tfillchar, uchar titleattr)
-{
- if (tfillchar != 0xFF)
- ms->tfillchar = tfillchar;
- if (titleattr != 0xFF)
- ms->titleattr = titleattr;
-}
-
-void set_misc_info(uchar fillchar, uchar fillattr, uchar spacechar,
- uchar shadowattr)
-{
- if (fillchar != 0xFF)
- ms->fillchar = fillchar;
- if (fillattr != 0xFF)
- ms->fillattr = fillattr;
- if (spacechar != 0xFF)
- ms->spacechar = spacechar;
- if (shadowattr != 0xFF)
- ms->shadowattr = shadowattr;
-}
-
-void set_menu_options(uchar maxmenuheight)
-{
- if (maxmenuheight != 0xFF)
- ms->maxmenuheight = maxmenuheight;
-}
-
-// Set the window which menusystem should use
-void set_window_size(uchar top, uchar left, uchar bot, uchar right)
-{
- int nr, nc;
-
- if ((top > bot) || (left > right))
- return; // Sorry no change will happen here
-
- if (getscreensize(1, &nr, &nc)) {
- /* Unknown screen size? */
- nr = 80;
- nc = 24;
- }
- if (bot >= nr)
- bot = nr - 1;
- if (right >= nc)
- right = nc - 1;
- ms->minrow = top;
- ms->mincol = left;
- ms->maxrow = bot;
- ms->maxcol = right;
- ms->numcols = right - left + 1;
- ms->numrows = bot - top + 1;
- if (ms->statline >= ms->numrows)
- ms->statline = ms->numrows - 1; // Clip statline if need be
-}
-
-void reg_handler(t_handler htype, void *handler)
-{
- // If bad value set to default screen handler
- switch (htype) {
- case HDLR_KEYS:
- ms->keys_handler = (t_keys_handler) handler;
- break;
- default:
- ms->handler = (t_menusystem_handler) handler;
- break;
- }
-}
-
-void unreg_handler(t_handler htype)
-{
- switch (htype) {
- case HDLR_KEYS:
- ms->keys_handler = NULL;
- break;
- default:
- ms->handler = NULL;
- break;
- }
-}
-
-void reg_ontimeout(t_timeout_handler handler, unsigned int numsteps,
- unsigned int stepsize)
-{
- ms->ontimeout = handler;
- if (numsteps != 0)
- ms->tm_numsteps = numsteps;
- if (stepsize != 0)
- ms->tm_stepsize = stepsize;
-}
-
-void unreg_ontimeout(void)
-{
- ms->ontimeout = NULL;
-}
-
-void reg_ontotaltimeout(t_timeout_handler handler,
- unsigned long numcentiseconds)
-{
- if (numcentiseconds != 0) {
- ms->ontotaltimeout = handler;
- ms->tm_total_timeout = numcentiseconds * 10; // to convert to milliseconds
- ms->tm_sofar_timeout = 0;
- }
-}
-
-void unreg_ontotaltimeout(void)
-{
- ms->ontotaltimeout = NULL;
-}
-
-int next_visible(pt_menu menu, int index)
-{
- int ans;
- if (index < 0)
- ans = 0;
- else if (index >= menu->numitems)
- ans = menu->numitems - 1;
- else
- ans = index;
- while ((ans < menu->numitems - 1) &&
- ((menu->items[ans]->action == OPT_INVISIBLE) ||
- (menu->items[ans]->action == OPT_SEP)))
- ans++;
- return ans;
-}
-
-int prev_visible(pt_menu menu, int index) // Return index of prev visible
-{
- int ans;
- if (index < 0)
- ans = 0;
- else if (index >= menu->numitems)
- ans = menu->numitems - 1;
- else
- ans = index;
- while ((ans > 0) &&
- ((menu->items[ans]->action == OPT_INVISIBLE) ||
- (menu->items[ans]->action == OPT_SEP)))
- ans--;
- return ans;
-}
-
-int next_visible_sep(pt_menu menu, int index)
-{
- int ans;
- if (index < 0)
- ans = 0;
- else if (index >= menu->numitems)
- ans = menu->numitems - 1;
- else
- ans = index;
- while ((ans < menu->numitems - 1) &&
- (menu->items[ans]->action == OPT_INVISIBLE))
- ans++;
- return ans;
-}
-
-int prev_visible_sep(pt_menu menu, int index) // Return index of prev visible
-{
- int ans;
- if (index < 0)
- ans = 0;
- else if (index >= menu->numitems)
- ans = menu->numitems - 1;
- else
- ans = index;
- while ((ans > 0) && (menu->items[ans]->action == OPT_INVISIBLE))
- ans--;
- return ans;
-}
-
-int calc_visible(pt_menu menu, int first)
-{
- int ans, i;
-
- if (menu == NULL)
- return 0;
- ans = 0;
- for (i = first; i < menu->numitems; i++)
- if (menu->items[i]->action != OPT_INVISIBLE)
- ans++;
- return ans;
-}
-
-// is curr visible if first entry is first?
-int isvisible(pt_menu menu, int first, int curr)
-{
- if (curr < first)
- return 0;
- return (calc_visible(menu, first) - calc_visible(menu, curr) <
- menu->menuheight);
-}
-
-// Calculate the first entry to be displayed
-// so that curr is visible and make curr as late as possible
-int calc_first_late(pt_menu menu, int curr)
-{
- int ans, i, nv;
-
- nv = calc_visible(menu, 0);
- if (nv <= menu->menuheight)
- return 0;
- // Start with curr and go back menu->menuheight times
- ans = curr + 1;
- for (i = 0; i < menu->menuheight; i++)
- ans = prev_visible_sep(menu, ans - 1);
- return ans;
-}
-
-// Calculate the first entry to be displayed
-// so that curr is visible and make curr as early as possible
-int calc_first_early(pt_menu menu, int curr)
-{
- int ans, i, nv;
-
- nv = calc_visible(menu, 0);
- if (nv <= menu->menuheight)
- return 0;
- // Start with curr and go back till >= menu->menuheight
- // items are visible
- nv = calc_visible(menu, curr); // Already nv of them are visible
- ans = curr;
- for (i = 0; i < menu->menuheight - nv; i++)
- ans = prev_visible_sep(menu, ans - 1);
- return ans;
-}
-
-// Create a new menu and return its position
-uchar add_menu(const char *title, int maxmenusize)
-{
- int num, i;
- pt_menu m;
-
- num = ms->nummenus;
- if (num >= MAXMENUS)
- return -1;
- m = NULL;
- m = (pt_menu) malloc(sizeof(t_menu));
- if (m == NULL)
- return -1;
- ms->menus[num] = m;
- m->numitems = 0;
- m->name = NULL;
- m->row = 0xFF;
- m->col = 0xFF;
- if (maxmenusize < 1)
- m->maxmenusize = MAXMENUSIZE;
- else
- m->maxmenusize = maxmenusize;
- m->items = (pt_menuitem *) malloc(sizeof(pt_menuitem) * (m->maxmenusize));
- for (i = 0; i < m->maxmenusize; i++)
- m->items[i] = NULL;
-
- m->title = (char *)malloc(MENULEN + 1);
- if (title) {
- if (strlen(title) > MENULEN - 2)
- strcpy(m->title, TITLELONG);
- else
- strcpy(m->title, title);
- } else
- strcpy(m->title, EMPTYSTR);
- m->menuwidth = strlen(m->title);
- ms->nummenus++;
- return ms->nummenus - 1;
-}
-
-void set_menu_name(const char *name) // Set the "name" of this menu
-{
- pt_menu m;
-
- m = ms->menus[ms->nummenus - 1];
- if (m->name) // Free up previous name
- {
- free(m->name);
- m->name = NULL;
- }
-
- if (name) {
- m->name = (char *)malloc(strlen(name) + 1);
- strcpy(m->name, name);
- }
-}
-
-// Create a new named menu and return its position
-uchar add_named_menu(const char *name, const char *title, int maxmenusize)
-{
- add_menu(title, maxmenusize);
- set_menu_name(name);
- return ms->nummenus - 1;
-}
-
-void set_menu_pos(uchar row, uchar col) // Set the position of this menu.
-{
- pt_menu m;
-
- m = ms->menus[ms->nummenus - 1];
- m->row = row;
- m->col = col;
-}
-
-pt_menuitem add_sep(void) // Add a separator to current menu
-{
- pt_menuitem mi;
- pt_menu m;
-
- m = (ms->menus[ms->nummenus - 1]);
- mi = NULL;
- mi = (pt_menuitem) malloc(sizeof(t_menuitem));
- if (mi == NULL)
- return NULL;
- m->items[(unsigned int)m->numitems] = mi;
- mi->handler = NULL; // No handler
- mi->item = mi->status = mi->data = NULL;
- mi->action = OPT_SEP;
- mi->index = m->numitems++;
- mi->parindex = ms->nummenus - 1;
- mi->shortcut = 0;
- mi->helpid = 0;
- return mi;
-}
-
-// Add item to the "current" menu
-pt_menuitem add_item(const char *item, const char *status, t_action action,
- const char *data, uchar itemdata)
-{
- pt_menuitem mi;
- pt_menu m;
- const char *str;
- uchar inhlite = 0; // Are we inside hlite area
-
- m = (ms->menus[ms->nummenus - 1]);
- mi = NULL;
- mi = (pt_menuitem) malloc(sizeof(t_menuitem));
- if (mi == NULL)
- return NULL;
- m->items[(unsigned int)m->numitems] = mi;
- mi->handler = NULL; // No handler
-
- // Allocate space to store stuff
- mi->item = (char *)malloc(MENULEN + 1);
- mi->status = (char *)malloc(STATLEN + 1);
- mi->data = (char *)malloc(ACTIONLEN + 1);
-
- if (item) {
- if (strlen(item) > MENULEN) {
- strcpy(mi->item, ITEMLONG);
- } else {
- strcpy(mi->item, item);
- }
- if (strlen(mi->item) > m->menuwidth)
- m->menuwidth = strlen(mi->item);
- } else
- strcpy(mi->item, EMPTYSTR);
-
- if (status) {
- if (strlen(status) > STATLEN) {
- strcpy(mi->status, STATUSLONG);
- } else {
- strcpy(mi->status, status);
- }
- } else
- strcpy(mi->status, EMPTYSTR);
-
- mi->action = action;
- str = mi->item;
- mi->shortcut = 0;
- mi->helpid = 0xFFFF;
- inhlite = 0; // We have not yet seen an ENABLEHLITE char
- // Find the first char in [A-Za-z0-9] after ENABLEHLITE and not arg to control char
- while (*str) {
- if (*str == ENABLEHLITE) {
- inhlite = 1;
- }
- if (*str == DISABLEHLITE) {
- inhlite = 0;
- }
- if ((inhlite == 1) &&
- (((*str >= 'A') && (*str <= 'Z')) ||
- ((*str >= 'a') && (*str <= 'z')) ||
- ((*str >= '0') && (*str <= '9')))) {
- mi->shortcut = *str;
- break;
- }
- ++str;
- }
- if ((mi->shortcut >= 'A') && (mi->shortcut <= 'Z')) // Make lower case
- mi->shortcut = mi->shortcut - 'A' + 'a';
-
- if (data) {
- if (strlen(data) > ACTIONLEN) {
- strcpy(mi->data, ACTIONLONG);
- } else {
- strcpy(mi->data, data);
- }
- } else
- strcpy(mi->data, EMPTYSTR);
-
- switch (action) {
- case OPT_SUBMENU:
- mi->itemdata.submenunum = itemdata;
- break;
- case OPT_CHECKBOX:
- mi->itemdata.checked = itemdata;
- break;
- case OPT_RADIOMENU:
- mi->itemdata.radiomenunum = itemdata;
- if (mi->data)
- free(mi->data);
- mi->data = NULL; // No selection made
- break;
- default: // to keep the compiler happy
- break;
- }
- mi->index = m->numitems++;
- mi->parindex = ms->nummenus - 1;
- return mi;
-}
-
-// Set the shortcut key for the current item
-void set_item_options(uchar shortcut, int helpid)
-{
- pt_menuitem mi;
- pt_menu m;
-
- m = (ms->menus[ms->nummenus - 1]);
- if (m->numitems <= 0)
- return;
- mi = m->items[(unsigned int)m->numitems - 1];
-
- if (shortcut != 0xFF)
- mi->shortcut = shortcut;
- if (helpid != 0xFFFF)
- mi->helpid = helpid;
-}
-
-// Free internal datasutructures
-void close_menusystem(void)
-{
-}
-
-// append_line_helper(pt_menu menu,char *line)
-void append_line_helper(int menunum, char *line)
-{
- pt_menu menu;
- pt_menuitem mi, ri;
- char *app;
- int ctr;
-
- menu = ms->menus[menunum];
- for (ctr = 0; ctr < (int)menu->numitems; ctr++) {
- mi = menu->items[ctr];
- app = NULL; //What to append
- switch (mi->action) {
- case OPT_CHECKBOX:
- if (mi->itemdata.checked)
- app = mi->data;
- break;
- case OPT_RADIOMENU:
- if (mi->data) { // Some selection has been made
- ri = (pt_menuitem) (mi->data);
- app = ri->data;
- }
- break;
- case OPT_SUBMENU:
- append_line_helper(mi->itemdata.submenunum, line);
- break;
- default:
- break;
- }
- if (app) {
- strcat(line, " ");
- strcat(line, app);
- }
- }
-}
-
-// Generate string based on state of checkboxes and radioitem in given menu
-// Assume line points to large enough buffer
-void gen_append_line(const char *menu_name, char *line)
-{
- int menunum;
-
- menunum = find_menu_num(menu_name);
- if (menunum < 0)
- return; // No such menu
- append_line_helper(menunum, line);
-}