summaryrefslogtreecommitdiff
path: root/sigalatvision/lib/TMenuView.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sigalatvision/lib/TMenuView.cc')
-rw-r--r--sigalatvision/lib/TMenuView.cc592
1 files changed, 592 insertions, 0 deletions
diff --git a/sigalatvision/lib/TMenuView.cc b/sigalatvision/lib/TMenuView.cc
new file mode 100644
index 0000000..636b925
--- /dev/null
+++ b/sigalatvision/lib/TMenuView.cc
@@ -0,0 +1,592 @@
+/*
+ * TMenuView.cc
+ *
+ * Turbo Vision - Version 2.0
+ *
+ * Copyright (c) 1994 by Borland International
+ * All Rights Reserved.
+ *
+ * Modified by Sergio Sigala <sergio@sigala.it>
+ */
+
+#define Uses_TMenuItem
+#define Uses_TMenu
+#define Uses_TMenuView
+#define Uses_TKeys
+#define Uses_TRect
+#define Uses_TEvent
+#define Uses_TGroup
+#define Uses_TMenuBox
+#define Uses_opstream
+#define Uses_ipstream
+#include <tvision/tv.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+#define cpMenuView "\x02\x03\x04\x05\x06\x07"
+
+TMenuItem::TMenuItem( const char *aName,
+ ushort aCommand,
+ ushort aKeyCode,
+ ushort aHelpCtx,
+ char *p,
+ TMenuItem *aNext
+ )
+{
+ name = newStr( aName );
+ command = aCommand;
+ disabled = Boolean(!TView::commandEnabled(command));
+ keyCode = aKeyCode;
+ helpCtx = aHelpCtx;
+ if( p == 0 )
+ param = 0;
+ else
+ param = newStr( p );
+ next = aNext;
+}
+
+TMenuItem::TMenuItem( const char *aName,
+ ushort aKeyCode,
+ TMenu *aSubMenu,
+ ushort aHelpCtx,
+ TMenuItem *aNext
+ )
+{
+ name = newStr( aName );
+ command = 0;
+ disabled = Boolean(!TView::commandEnabled(command));
+ keyCode = aKeyCode;
+ helpCtx = aHelpCtx;
+ subMenu = aSubMenu;
+ next = aNext;
+}
+
+TMenuItem::~TMenuItem()
+{
+ delete (char *)name;
+ if( command == 0 )
+ delete subMenu;
+ else
+ delete (char *)param;
+}
+
+TMenu::~TMenu()
+{
+ while( items != 0 )
+ {
+ TMenuItem *temp = items;
+ items = items->next;
+ delete temp;
+ }
+}
+
+void TMenuView::trackMouse( TEvent& e, Boolean& mouseActive )
+{
+ TPoint mouse = makeLocal( e.mouse.where );
+ for( current = menu->items; current != 0; current = current->next )
+ {
+ TRect r = getItemRect( current );
+ if( r.contains(mouse) )
+ {
+ mouseActive = True;
+ return;
+ }
+ }
+}
+
+void TMenuView::nextItem()
+{
+ if( (current = current->next) == 0 )
+ current = menu->items;
+}
+
+void TMenuView::prevItem()
+{
+ TMenuItem *p;
+
+ if( (p = current) == menu->items)
+ p = 0;
+
+ do {
+ nextItem();
+ } while( current->next != p );
+}
+
+void TMenuView::trackKey( Boolean findNext )
+{
+ if( current == 0 )
+ return;
+
+ do {
+ if( findNext )
+ nextItem();
+ else
+ prevItem();
+ } while( current->name == 0 );
+}
+
+Boolean TMenuView::mouseInOwner( TEvent& e )
+{
+ if( parentMenu == 0 || parentMenu->size.y != 1 )
+ return False;
+ else
+ {
+ TPoint mouse = parentMenu->makeLocal( e.mouse.where );
+ TRect r = parentMenu->getItemRect( parentMenu->current );
+ return r.contains( mouse );
+ }
+}
+
+Boolean TMenuView::mouseInMenus( TEvent& e )
+{
+ TMenuView *p = parentMenu;
+ while( p != 0 && !p->mouseInView(e.mouse.where) )
+ p = p->parentMenu;
+
+ return Boolean( p != 0 );
+}
+
+TMenuView *TMenuView::topMenu()
+{
+ TMenuView *p = this;
+ while( p->parentMenu != 0 )
+ p = p->parentMenu;
+ return p;
+}
+
+enum menuAction { doNothing, doSelect, doReturn };
+
+ushort TMenuView::execute()
+{
+ Boolean autoSelect = False;
+ menuAction action;
+ char ch;
+ ushort result = 0;
+ TMenuItem *itemShown = 0;
+ TMenuItem *p;
+ TMenuView *target;
+ TRect r;
+ TEvent e;
+ Boolean mouseActive;
+
+ current = menu->deflt;
+ mouseActive = False;
+ do {
+ action = doNothing;
+ getEvent(e);
+ switch (e.what)
+ {
+ case evMouseDown:
+ if( mouseInView(e.mouse.where) || mouseInOwner(e) )
+ {
+ trackMouse(e, mouseActive);
+ if( size.y == 1 )
+ autoSelect = True;
+ }
+ else
+ action = doReturn;
+ break;
+ case evMouseUp:
+ trackMouse(e, mouseActive);
+ if( mouseInOwner(e) )
+ current = menu->deflt;
+ else if( current != 0 && current->name != 0 )
+ action = doSelect;
+ else if (mouseActive)
+ action = doReturn;
+ else
+ {
+ current = menu->deflt;
+ if (current == 0)
+ current = menu->items;
+ action = doNothing;
+ }
+ break;
+ case evMouseMove:
+ if( e.mouse.buttons != 0 )
+ {
+ trackMouse(e, mouseActive);
+ if( !(mouseInView(e.mouse.where) || mouseInOwner(e)) &&
+ mouseInMenus(e) )
+ action = doReturn;
+ }
+ break;
+ case evKeyDown:
+ switch( ctrlToArrow(e.keyDown.keyCode) )
+ {
+ case kbUp:
+ case kbDown:
+ if( size.y != 1 )
+ trackKey(Boolean(ctrlToArrow(e.keyDown.keyCode) == kbDown));
+ else if( e.keyDown.keyCode == kbDown )
+ autoSelect = True;
+ break;
+ case kbLeft:
+ case kbRight:
+ if( parentMenu == 0 )
+ trackKey(Boolean(ctrlToArrow(e.keyDown.keyCode) == kbRight));
+ else
+ action = doReturn;
+ break;
+ case kbHome:
+ case kbEnd:
+ if( size.y != 1 )
+ {
+ current = menu->items;
+ if( e.keyDown.keyCode == kbEnd )
+ trackKey(False);
+ }
+ break;
+ case kbEnter:
+ if( size.y == 1 )
+ autoSelect = True;
+ action = doSelect;
+ break;
+ case kbEsc:
+ action = doReturn;
+ if( parentMenu == 0 || parentMenu->size.y != 1 )
+ clearEvent(e);
+ break;
+ default:
+ target = this;
+ ch = getAltChar(e.keyDown.keyCode);
+ if( ch == 0 )
+ ch = e.keyDown.charScan.charCode;
+ else
+ target = topMenu();
+ p = target->findItem(ch);
+ if( p == 0 )
+ {
+ p = topMenu()->hotKey(e.keyDown.keyCode);
+ if( p != 0 && commandEnabled(p->command) )
+ {
+ result = p->command;
+ action = doReturn;
+ }
+ }
+ else if( target == this )
+ {
+ if( size.y == 1 )
+ autoSelect = True;
+ action = doSelect;
+ current = p;
+ }
+ else if( parentMenu != target ||
+ parentMenu->current != p )
+ action = doReturn;
+ }
+ break;
+ case evCommand:
+ if( e.message.command == cmMenu )
+ {
+ autoSelect = False;
+ if (parentMenu != 0 )
+ action = doReturn;
+ }
+ else
+ action = doReturn;
+ break;
+ }
+
+ if( itemShown != current )
+ {
+ itemShown = current;
+ drawView();
+ }
+
+ if( (action == doSelect || (action == doNothing && autoSelect)) &&
+ current != 0 &&
+ current->name != 0 )
+ if( current->command == 0 )
+ {
+ if( (e.what & (evMouseDown | evMouseMove)) != 0 )
+ putEvent(e);
+ r = getItemRect( current );
+ r.a.x = r.a.x + origin.x;
+ r.a.y = r.b.y + origin.y;
+ r.b = owner->size;
+ if( size.y == 1 )
+ r.a.x--;
+ target = topMenu()->newSubView(r, current->subMenu,this);
+ result = owner->execView(target);
+ destroy( target );
+ }
+ else if( action == doSelect )
+ result = current->command;
+
+ if( result != 0 && commandEnabled(result) )
+ {
+ action = doReturn;
+ clearEvent(e);
+ }
+ else
+ result = 0;
+ } while( action != doReturn );
+
+ if( e.what != evNothing &&
+ (parentMenu != 0 || e.what == evCommand))
+ putEvent(e);
+ if( current != 0 )
+ {
+ menu->deflt = current;
+ current = 0;
+ drawView();
+ }
+ return result;
+}
+
+TMenuItem *TMenuView::findItem( char ch )
+{
+ ch = toupper(ch);
+ TMenuItem *p = menu->items;
+ while( p != 0 )
+ {
+ if( p->name != 0 && !p->disabled )
+ {
+ char *loc = strchr( (char *) p->name, '~' );
+ if( loc != 0 && (uchar)ch == toupper( loc[1] ) )
+ return p;
+ }
+ p = p->next;
+ }
+ return 0;
+}
+
+TRect TMenuView::getItemRect( TMenuItem * )
+{
+ return TRect( 0, 0, 0, 0 );
+}
+
+ushort TMenuView::getHelpCtx()
+{
+ TMenuView *c = this;
+
+ while( c != 0 &&
+ (c->current == 0 ||
+ c->current->helpCtx == hcNoContext ||
+ c->current->name == 0 )
+ )
+ c = c->parentMenu;
+
+ if( c != 0 )
+ return c->current->helpCtx;
+ else
+ return hcNoContext;
+}
+
+TPalette& TMenuView::getPalette() const
+{
+ static TPalette palette( cpMenuView, sizeof( cpMenuView )-1 );
+ return palette;
+}
+
+Boolean TMenuView::updateMenu( TMenu *menu )
+{
+ Boolean res = False;
+ if( menu != 0 )
+ {
+ for( TMenuItem *p = menu->items; p != 0; p = p->next )
+ {
+ if( p->name != 0 )
+ if( p->command == 0 )
+ {
+ if( p->subMenu && updateMenu(p->subMenu) == True )
+ res = True;
+ }
+ else
+ {
+ Boolean commandState = commandEnabled(p->command);
+ if( p->disabled == commandState )
+ {
+ p->disabled = Boolean(!commandState);
+ res = True;
+ }
+ }
+ }
+ }
+ return res;
+}
+
+void TMenuView::do_a_select( TEvent& event )
+{
+ putEvent( event );
+ event.message.command = owner->execView(this);
+ if( event.message.command != 0 && commandEnabled(event.message.command) )
+ {
+ event.what = evCommand;
+ event.message.infoPtr = 0;
+ putEvent(event);
+ }
+ clearEvent(event);
+}
+
+void TMenuView::handleEvent( TEvent& event )
+{
+ if( menu != 0 )
+ switch (event.what)
+ {
+ case evMouseDown:
+ do_a_select(event);
+ break;
+ case evKeyDown:
+ if( findItem(getAltChar(event.keyDown.keyCode)) != 0 )
+ do_a_select(event);
+ else
+ {
+ TMenuItem *p = hotKey(event.keyDown.keyCode);
+ if( p != 0 && commandEnabled(p->command))
+ {
+ event.what = evCommand;
+ event.message.command = p->command;
+ event.message.infoPtr = 0;
+ putEvent(event);
+ clearEvent(event);
+ }
+ }
+ break;
+ case evCommand:
+ if( event.message.command == cmMenu )
+ do_a_select(event);
+ break;
+ case evBroadcast:
+ if( event.message.command == cmCommandSetChanged )
+ {
+ if( updateMenu(menu) )
+ drawView();
+ }
+ break;
+ }
+}
+
+
+TMenuItem *TMenuView::findHotKey( TMenuItem *p, ushort keyCode )
+{
+
+ while( p != 0 )
+ {
+ if( p->name != 0 )
+ if( p->command == 0 )
+ {
+ TMenuItem *T;
+ if( (T = findHotKey( p->subMenu->items, keyCode )) != 0 )
+ return T;
+ }
+ else if( !p->disabled &&
+ p->keyCode != kbNoKey &&
+ p->keyCode == keyCode
+ )
+ return p;
+ p = p->next;
+ }
+ return 0;
+}
+
+TMenuItem *TMenuView::hotKey( ushort keyCode )
+{
+ return findHotKey( menu->items, keyCode );
+}
+
+TMenuView *TMenuView::newSubView( const TRect& bounds,
+ TMenu *aMenu,
+ TMenuView *aParentMenu
+ )
+{
+ return new TMenuBox( bounds, aMenu, aParentMenu );
+}
+
+#if !defined(NO_STREAMABLE)
+
+void TMenuView::writeMenu( opstream& os, TMenu *menu )
+{
+ uchar tok = 0xFF;
+
+ assert( menu != 0 );
+
+ for( TMenuItem *item = menu->items; item != 0; item = item->next )
+ {
+ os << tok;
+ os.writeString( item->name );
+ os << item->command << (int)(item->disabled)
+ << item->keyCode << item->helpCtx;
+ if( item->name != 0 )
+ {
+ if( item->command == 0 )
+ writeMenu( os, item->subMenu );
+ else
+ os.writeString( item->param );
+ }
+ }
+
+ tok = 0;
+ os << tok;
+}
+
+void TMenuView::write( opstream& os )
+{
+ TView::write( os );
+ writeMenu( os, menu );
+}
+
+TMenu *TMenuView::readMenu( ipstream& is )
+{
+ TMenu *menu = new TMenu;
+ TMenuItem **last = &(menu->items);
+#ifndef __UNPATCHED
+ TMenuItem *item;
+#else
+ TMenuItem *item = 0;
+#endif
+
+ uchar tok;
+ is >> tok;
+
+ while( tok != 0 )
+ {
+ assert( tok == 0xFF );
+
+ /* SS: this line gave problems with egcs-1.0.3 */
+
+ item = new TMenuItem( (char *)0, 0, (TMenu *)0 );
+ *last = item;
+ last = &(item->next);
+ item->name = is.readString();
+ int temp;
+ is >> item->command >> temp
+ >> item->keyCode >> item->helpCtx;
+ item->disabled = Boolean( temp );
+ if( item->name != 0 )
+ {
+ if( item->command == 0 )
+ item->subMenu = readMenu( is );
+ else
+ item->param = is.readString();
+ }
+ is >> tok;
+ }
+ *last = 0;
+ menu->deflt = menu->items;
+ return menu;
+}
+
+void *TMenuView::read( ipstream& is )
+{
+ TView::read( is );
+ menu = readMenu( is );
+ parentMenu = 0;
+ current = 0;
+ return this;
+}
+
+TStreamable *TMenuView::build()
+{
+ return new TMenuView( streamableInit );
+}
+
+TMenuView::TMenuView( StreamableInit ) : TView( streamableInit )
+{
+}
+
+
+#endif