/*
* menu.c: stuff for the menu's..
*
* Written By Troy Rollo <troy@cbme.unsw.oz.au>
*
* Copyright (c) 1991, 1992 Troy Rollo.
* Copyright (c) 1992-2003 Matthew R. Green.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: menu.c,v 1.8 2003/01/08 20:00:54 f Exp $
*/
#include "irc.h"
#include "menu.h"
#include "list.h"
#include "ircaux.h"
#include "ircterm.h"
#include "window.h"
#include "screen.h"
#include "input.h"
#include "vars.h"
#include "output.h"
#ifndef LITE
#ifdef lines
#undef lines
#endif
Menu *MenuList = (Menu *) 0;
struct OptionTableTag
{
char *name;
void (*func) _((char *));
};
typedef struct OptionTableTag OptionTable;
static OptionTable OptionsList[] =
{
{ "PREVIOUS", menu_previous },
{ "MENU", menu_submenu },
{ "EXIT", menu_exit },
{ "CHANNELS", menu_channels },
{ "COMMAND", menu_command },
{ (char *) 0, (void (*) _((char *))) 0 }
};
static MenuOption * create_new_option _((void));
static Menu * create_new_menu _((void));
static void install_menu _((Menu *, int));
static MenuOption *
create_new_option()
{
MenuOption *NewOption;
NewOption = (MenuOption *) new_malloc(sizeof(MenuOption));
NewOption->Name = (char *) 0;
NewOption->Arguments = (char *) 0;
NewOption->Func = (void (*) _((char *))) 0;
return NewOption;
}
static Menu *
create_new_menu()
{
Menu *NewMenu;
NewMenu = (Menu *) new_malloc(sizeof(Menu));
NewMenu->Name = (char *) 0;
NewMenu->TotalOptions = 0;
NewMenu->Options = (MenuOption **) 0;
return NewMenu;
}
static void
install_menu(NewMenu, TotalMade)
Menu *NewMenu;
int TotalMade;
{
MenuOption **NewOptions;
int i;
if (!NewMenu)
return;
if (TotalMade != NewMenu->TotalOptions)
{
NewOptions = (MenuOption **) malloc(TotalMade *
sizeof(MenuOption *));
for (i = 0; i < TotalMade; i++)
NewOptions[i] = NewMenu->Options[i];
new_free(&NewMenu->Options);
NewMenu->Options = NewOptions;
NewMenu->TotalOptions = TotalMade;
}
add_to_list((List **) &MenuList, (List *) NewMenu);
say("Menu \"%s\" added", NewMenu->Name);
}
void
load_menu(FileName)
char *FileName;
{
FILE *fp;
Menu *NewMenu = NULL;
MenuOption **NewOptions;
char *line, *command;
char *name, *func;
char buffer[BIG_BUFFER_SIZE+1];
int linenum = 0;
int CurTotal = 0;
int FuncNum;
int i;
if ((fp = fopen(FileName, "r")) == (FILE *) 0)
{
say("Unable to open %s", FileName);
return;
}
while (fgets(buffer, BIG_BUFFER_SIZE, fp))
{
buffer[strlen(buffer)-1] = '\0';
linenum++;
line = buffer;
while (isspace(*line))
line++;
if (*line == '#' || !(command = next_arg(line, &line)))
continue;
if (!my_stricmp(command, "MENU"))
{
if (!line || !*line)
{
put_it("Missing argument in line %d of %s",
linenum, FileName);
continue;
}
install_menu(NewMenu, CurTotal);
NewMenu = create_new_menu();
malloc_strcpy(&NewMenu->Name, line);
}
else if (!my_stricmp(command, "OPTION"))
{
if (!(name = new_next_arg(line, &line)) ||
!(func = next_arg(line, &line)))
{
say("Missing argument in line %d of %s",
linenum, FileName);
continue;
}
for (i=0; OptionsList[i].name; i++)
if (!my_stricmp(func, OptionsList[i].name))
break;
if (!OptionsList[i].name)
{
say("Unknown menu function \"%s\" in line %d of %s",
func, linenum, FileName);
continue;
}
FuncNum = i;
if (++CurTotal > NewMenu->TotalOptions)
{
NewOptions = (MenuOption **)
new_malloc(sizeof(MenuOption *) *
(CurTotal + 4));
for (i = 0; i < NewMenu->TotalOptions; i++)
NewOptions[i] = NewMenu->Options[i];
new_free(&NewMenu->Options);
NewMenu->Options = NewOptions;
NewMenu->TotalOptions = CurTotal + 4;
}
NewMenu->Options[CurTotal-1] = create_new_option();
malloc_strcpy(&NewMenu->Options[CurTotal-1]->Name,
name);
malloc_strcpy(&NewMenu->Options[CurTotal-1]->Arguments,
line);
NewMenu->Options[CurTotal-1]->Func =
OptionsList[FuncNum].func;
}
else
say("Unkown menu command in line %d of %s",
linenum, FileName);
}
install_menu(NewMenu, CurTotal);
fclose(fp);
}
int
ShowMenuByWindow(window, flags)
Window *window;
int flags;
{
int i;
int largest;
int NumPerLine;
int len;
WindowMenu *menu_info;
Menu *ThisMenu;
int CursorLoc;
menu_info = &window->menu;
ThisMenu = menu_info->menu;
CursorLoc = menu_info->cursor;
largest = 0;
for (i = 0; i < ThisMenu->TotalOptions; i++)
if ((len = strlen(ThisMenu->Options[i]->Name))>largest)
largest = len;
NumPerLine = (current_screen->co - current_screen->co % (largest + 3)) / (largest + 3);
menu_info->items_per_line = NumPerLine;
menu_info->lines = 0;
for (i = 0; i < ThisMenu->TotalOptions; i++)
{
if ((flags & SMF_ERASE) && !(i % NumPerLine) &&
!(flags & SMF_CALCONLY))
{
term_move_cursor(0, window->top + menu_info->lines);
term_clear_to_eol();
}
if ((i == CursorLoc || !(flags&SMF_CURSONLY)) &&
!(flags & SMF_CALCONLY))
{
if (i == CursorLoc && !(flags & SMF_NOCURSOR) &&
current_screen->inside_menu == 1)
term_standout_on();
else
term_bold_on();
term_move_cursor((i % NumPerLine) * (largest + 3),
window->top+menu_info->lines);
fwrite(ThisMenu->Options[i]->Name,
strlen(ThisMenu->Options[i]->Name), 1, stdout);
if (i == CursorLoc && !(flags & SMF_NOCURSOR))
term_standout_off();
else
term_bold_off();
}
if (!((i + 1) % NumPerLine))
menu_info->lines++;
}
if (i % NumPerLine)
menu_info->lines++;
window->display_size = window->bottom - window->top - menu_info->lines;
if (window->cursor < 0)
window->cursor = 0;
fflush(stdout);
update_input(UPDATE_JUST_CURSOR);
return ThisMenu->TotalOptions;
}
int
ShowMenu(Name)
char *Name;
{
Menu *ThisMenu;
Window *window;
WindowMenu *menu_info;
window = curr_scr_win;
menu_info = &window->menu;
ThisMenu = (Menu *) find_in_list((List **) &MenuList, Name, 0);
if (!ThisMenu)
{
say("No such menu \"%s\"", Name);
return -1;
}
menu_info->cursor = 0;
menu_info->menu = ThisMenu;
return ShowMenuByWindow(window, SMF_CALCONLY);
}
void
set_menu(Value)
char *Value;
{
Window *window;
WindowMenu *menu_info;
ShrinkInfo SizeInfo;
window = curr_scr_win;
menu_info = &window->menu;
if (!Value)
{
window->display_size = window->bottom - window->top;
menu_info->menu = (Menu *) 0;
menu_info->lines = 0;
SizeInfo = resize_display(window);
redraw_resized(window, SizeInfo, 0);
update_input(UPDATE_JUST_CURSOR);
current_screen->inside_menu = -1;
}
else
{
if (ShowMenu(Value) == -1)
{
set_string_var(MENU_VAR, NULL);
return;
}
SizeInfo = resize_display(window);
redraw_resized(window, SizeInfo, 0);
ShowMenuByWindow(window, SMF_ERASE);
/*
redraw_window(window);
*/
}
}
void
enter_menu(key, ptr)
u_int key;
char * ptr;
{
if (!curr_scr_win->menu.menu)
return;
current_screen->inside_menu = 1;
ShowMenuByWindow(curr_scr_win, SMF_CURSONLY);
}
void
menu_previous(args)
char *args;
{
}
void
menu_submenu(args)
char *args;
{
}
void
menu_exit(args)
char *args;
{
current_screen->inside_menu = -1;
}
void
menu_channels(args)
char *args;
{
}
void
menu_key(ikey)
u_int ikey;
{
Window *window;
WindowMenu *menu_info;
Menu *ThisMenu;
u_char key = (u_char)ikey;
window = curr_scr_win;
menu_info = &window->menu;
ThisMenu = menu_info->menu;
ShowMenuByWindow(window, SMF_CURSONLY | SMF_NOCURSOR);
switch(key)
{
case 'U':
case 'u':
case 'P':
case 'p':
case 'k':
case 'K':
case 'U' - '@':
case 'P' - '@':
menu_info->cursor-=menu_info->items_per_line;
break;
case 'n':
case 'd':
case 'j':
case 'N':
case 'D':
case 'J':
case 'D' - '@':
case 'N' - '@':
menu_info->cursor+=menu_info->items_per_line;
break;
case 'b':
case 'h':
case 'B':
case 'H':
case 'B' - '@':
menu_info->cursor--;
break;
case 'f':
case 'l':
case 'F':
case 'L':
case 'F' - '@':
menu_info->cursor++;
break;
case '\033':
break;
case '\r':
case '\n':
hold_mode((Window *) 0, OFF, 1);
break;
case ' ':
case '.':
current_screen->inside_menu = 0;
ThisMenu->Options[menu_info->cursor]->Func(
ThisMenu->Options[menu_info->cursor]->Arguments);
if (current_screen->inside_menu != -1)
current_screen->inside_menu = 1;
else
current_screen->inside_menu = 0;
return; /* The menu may not be here any more */
}
if (menu_info->cursor>=menu_info->menu->TotalOptions)
menu_info->cursor = menu_info->menu->TotalOptions - 1;
if (menu_info->cursor < 0)
menu_info->cursor = 0;
if (current_screen->inside_menu)
ShowMenuByWindow(window, SMF_CURSONLY);
}
void
menu_command(args)
char *args;
{
parse_line((char *) 0, args, empty_string, 0, 0, 0);
}
#endif /* LITE */
syntax highlighted by Code2HTML, v. 0.9.1