diff options
Diffstat (limited to 'sigalatvision/lib/TMenuView.cc')
-rw-r--r-- | sigalatvision/lib/TMenuView.cc | 592 |
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 |