home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 5
/
DATAFILE_PDCD5.iso
/
utilities
/
v
/
vista
/
c
/
menu
< prev
next >
Wrap
Text File
|
1996-02-01
|
18KB
|
757 lines
// **************************************************************************
// Copyright 1996 David Allison
//
// VV VV IIIIII SSSSS TTTTTT AA
// VV VV II SS TT AA AA
// VV VV II SSSS TT AA AA
// VV VV II SS TT AAAAAAAA
// VV IIIIII SSSS TT AA AA
//
// MULTI-THREADED C++ WIMP CLASS LIBRARY
// for RISC OS
// **************************************************************************
//
// P U B L I C D O M A I N L I C E N C E
// -------------------------------------------
//
// This library is copyright. You may not sell the library for
// profit, but you may sell products which use it providing
// those products are presented as executable code and are not
// libraries themselves. The library is supplied without any
// warranty and the copyright owner cannot be held responsible for
// damage resulting from failure of any part of this library.
//
// See the User Manual for details of the licence.
//
// *************************************************************************
//
// menu.c
//
#include "Vista:icon.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <new.h>
#include <ctype.h>
#include <swis.h>
#include <kernel.h>
#include <stdarg.h>
#ifndef __EASY_C
// an exception here needs to close the file pointer used for the parser. This
// trick redefines the throw macro to close the file and then call __throw
static FILE *menu_fp ;
#undef throw
#define throw menu_fp?fclose(menu_fp):0,__throw
#endif
MenuItem::MenuItem (char *n, Menu *m, char *text, int length)
{
name = n ;
next = NULL ;
menu = m ;
submenu = NULL ;
index = m->add_item(this) ; // add a new menu item
MenuItemData *item = &m->data->items[index] ;
item->item_flags = 0 ;
item->window_handle = -1 ;
item->icon_flags = Icon::ITEXT + Icon::IFILLED + Icon::IVCENTRE + 7*Icon::IFORECOL ;
print (text) ;
}
MenuItem::MenuItem (char *name, Menu *menu, char *sprite, void *sprite_area)
{
}
void MenuItem::tick()
{
menu->data->items[index].item_flags |= TICKED ;
}
void MenuItem::untick()
{
menu->data->items[index].item_flags &= ~TICKED ;
}
void MenuItem::fade()
{
menu->data->items[index].icon_flags |= Icon::INOSELECT ;
}
void MenuItem::unfade()
{
menu->data->items[index].icon_flags &= ~Icon::INOSELECT ;
}
int MenuItem::flags(int f, int m)
{
int old = menu->data->items[index].item_flags ;
menu->data->items[index].item_flags = (old & ~m) | f ;
return old ;
}
int MenuItem::is_ticked()
{
return menu->data->items[index].item_flags & TICKED ;
}
int MenuItem::is_faded()
{
return menu->data->items[index].icon_flags & Icon::INOSELECT ;
}
MenuItem::operator int()
{
return index ;
}
MenuItem::operator char *()
{
return name ;
}
void MenuItem::make_writeable (char *buffer, int length, char *valid)
{
MenuItemData *i = &menu->data->items[index] ;
i->icon_data.indirecttext.buffer = buffer ;
i->icon_data.indirecttext.bufflen = length ;
i->icon_data.indirecttext.validstring = valid ;
i->icon_flags |= Icon::BWRITABLE * Icon::IBTYPE + Icon::INDIRECT +
Icon::IHCENTRE + Icon::IVCENTRE + Icon::ITEXT ;
i->item_flags |= WRITEABLE ;
}
void MenuItem::set_submenu(Menu *submenu)
{
this->submenu = submenu ;
menu->data->items[index].submenu = submenu->data ;
}
void Menu::init (char *n, char *title)
{
name = n ;
next = NULL ;
num_items = 0 ;
max_items = 5 ;
item_adjust = 0 ;
if ((data = (MenuData*)malloc (sizeof (MenuData) + sizeof (MenuItemData) * max_items)) == NULL)
throw ("Out of memory") ;
items = NULL ;
max_width = 0 ;
strncpy (data->title, title, 12) ;
data->title_fore_colour = 7 ;
data->title_back_colour = 2 ;
data->work_fore_colour = 7 ;
data->work_back_colour = 0 ;
data->item_width = strlen(title) * 16;
data->item_height = 44 ;
data->item_gap = 0 ;
}
Menu::Menu (char *name, char *title)
{
init (name, title) ;
}
Menu::Menu (char *name, char *title, MenuItem *item)
{
init (name, title) ;
item->set_submenu (this) ;
}
Menu::~Menu()
{
}
int Menu::add_item (MenuItem *item)
{
if (num_items == max_items) // out of item space?
{
max_items += 5 ;
if ((data = (MenuData*)realloc (data, sizeof (MenuData) + sizeof (MenuItemData) * max_items)) == NULL)
throw ("Out of memory") ;
}
item->next = items ; // add to list
items = item ;
return num_items++ ;
}
void Menu::finish()
{
items->flags(MenuItem::LAST) ; // set last item
}
void Menu::open (int x, int y)
{
_kernel_swi_regs r ;
_kernel_oserror *e ;
r.r[1] = (int)data ;
r.r[2] = x ;
r.r[3] = y ;
if ((e = _kernel_swi (Wimp_CreateMenu, &r, &r)) != NULL)
throw (e) ;
}
void Menu::close()
{
_kernel_swi_regs r ;
_kernel_oserror *e ;
r.r[1] = -1 ;
if ((e = _kernel_swi (Wimp_CreateMenu, &r, &r)) != NULL)
throw (e) ;
}
void Menu::iconbar_adjust (int &x, int &y)
{
x -= 16 ;
y = 96 ;
y += num_items * (data->item_height + data->item_gap) + item_adjust ;
}
MenuItem *Menu::selection (int *hits)
{
int i ;
MenuItem *item ;
Menu *m = this ;
for (i = 0 ; ; i++)
if (hits[i] == -1)
break ;
MenuItem *out_items = (MenuItem*)malloc ((i+1) * sizeof (MenuItem)) ;
if (out_items == NULL)
throw ("Out of memory") ;
for (i = 0 ; hits[i] != -1 ; i++)
for (item = m->items ; item != NULL ; item = item->next)
if (item->index == hits[i])
{
out_items[i] = *item ;
if (hits[i+1] != -1)
m = item->submenu ;
break ;
}
out_items[i].name = NULL ;
out_items[i].index = -1 ;
return out_items ;
}
bool Menu::invalid_selection (int *hits)
{
int i ;
MenuItem *item ;
MenuItem *last_item = NULL ;
Menu *m = this ;
for (i = 0 ; hits[i] != -1 ; i++)
for (item = m->items ; item != NULL ; item = item->next)
if (item->index == hits[i])
{
last_item = item ;
if (hits[i+1] != -1)
m = item->submenu ;
break ;
}
#ifdef __EASY_C
return last_item != NULL && (last_item->flags() & MenuItem::MENUWARNING) ;
#else
return (bool)(last_item != NULL && (last_item->flags() & MenuItem::MENUWARNING)) ;
#endif
}
MenuItem *Menu::item (char *iname)
{
for (MenuItem *item = items ; item != NULL ; item = item->next)
if (strcmp (item->name, iname) == 0)
return item ;
return NULL ;
}
void Menu::print (char *item_name, char *format ...)
{
MenuItem *i = item (item_name) ;
if (i == NULL)
throw ("No such menu item") ;
va_list ap ;
va_start (ap, format) ;
i->vprint (format, ap) ;
}
void MenuItem::print (char *format...)
{
char str[1024] ;
va_list arg ;
va_start (arg,format) ;
vprint (format, arg) ;
}
void MenuItem::vprint (char *format, va_list ap)
{
char str[1024] ;
vsprintf (str,format,ap) ;
int length = strlen (str) ;
MenuItemData *item = &menu->data->items[index] ;
if (length > menu->max_width)
{
menu->max_width = length ;
int l = (length + 1) * 16 ;
if (l > menu->data->item_width)
menu->data->item_width = l ;
}
if (length <= 12)
{
item->icon_flags &= ~Icon::INDIRECT ;
strncpy (item->icon_data.text, str, length) ;
if (length < 12)
item->icon_data.text[length] = 0 ;
}
else
{
item->icon_flags |= Icon::INDIRECT ;
item->icon_data.indirecttext.buffer = new char [length+1] ;
item->icon_data.indirecttext.validstring = (char *)-1 ;
item->icon_data.indirecttext.bufflen = length+1 ;
strcpy (item->icon_