diff options
Diffstat (limited to 'contrib/syslinux/latest/com32/cmenu/libmenu/menu.c')
-rw-r--r-- | contrib/syslinux/latest/com32/cmenu/libmenu/menu.c | 1273 |
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); -} |