//
// The Fusion Library Interface for DOS
// Version 1.06c
// Copyright (C) 1990, 1991, 1992
// Software Dimensions
//
// MenuManager
//

#include "fliwin.h"

#ifdef __BCPLUSPLUS__
#pragma hdrstop
#endif

#include <alloc.h>
#include <string.h>
#include <ctype.h>

int MenuManager::IsPullDown=0;
int MenuManager::Beneath=1;

void MenuManager::MenuPullDown() { IsPullDown=1; }
void MenuManager::MenuPopDown() { IsPullDown=0; }
void MenuManager::SubMenuRight() { Beneath=0; }
void MenuManager::SubMenuBeneath() { Beneath=1; }

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// MenuManager()
//
// Constructor for MenuManager class
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

MenuManager::MenuManager()
{
  Menus=0;
  SubMenuTrack=0;
  NumberOfMenus=0;
  CurrentLevel=0;
  SetX=0;
  SetY=0;
  MouseInControl=1;
  StowedWidth=0;
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// ~MenuManager()
//
// Destructor for MenuManager class
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

MenuManager::~MenuManager()
{
  RemoveAllMenus();

  if (NumberOfMenus)
  {
    for (int i=0;i<NumberOfMenus;i++)
      delete Menus[i];
  }
  free(Menus);
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// Manager()
//
// Constructor for MenuItems class
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

int MenuManager::Manager(int Event,int IsWindow,int NumberOfWindows,
  WindowElement &Window,FusionWindow &WorkSpace)
{
  int WasRemoved=0;

  if (Event==MousedEvent)
  {
    //--------------------------------------------------------------
    //
    // Pop down Mouse controller
    //
    //--------------------------------------------------------------

    if (!IsPullDown)
    {
      if (!CurrentLevel)
        MouseInControl=1;

      MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];

      if (MouseEvent&MouseLeftButtonRelease && CurrentLevel==1 &&
        !Menu.NumberOfOptions && MouseHorizontal>=Menu.XStart
        && MouseHorizontal<=Menu.XEnd && MouseVertical==SetY
        && Menu.MenuEvent)
      {
        RemoveMenu();
        return(Menu.MenuEvent);
      }

      if (!MouseInControl && CurrentLevel)
      {
        if (MouseHorizontal>=Menu.X
            && MouseHorizontal<Menu.X+Menu.Width
            && MouseVertical>Menu.Y
            && MouseVertical<Menu.Y+Menu.Height-1)
        {
          MouseInControl=1;
          RemoveOption();
          PlaceOption(MouseVertical-Menu.Y-1);
          return MenuEvent;
        }

        if (MouseEvent&MouseLeftButtonRelease || MouseEvent&MouseLeftButtonPress)
        {
          if (CurrentLevel==1)
          {
            if ( ((MouseHorizontal<Menu.XStart ||
                   MouseHorizontal>Menu.XEnd) &&
                   MouseVertical==SetY &&
                   SetY<Menu.Y)

                   ||

                 ((MouseHorizontal<Menu.X ||
                   MouseHorizontal>=Menu.X+Menu.Width ||
                   MouseVertical<Menu.Y ||
                   MouseVertical>=Menu.Y+Menu.Height) &&
                  ((MouseVertical!=SetY &&
                    SetY<Menu.Y) ||
                    SetY>=Menu.Y)) )
            {
              MouseInControl=1;
              WasRemoved=1;
              RemoveMenu();
              return MenusRemoved;
            }
          }
          else
          {
            if (MouseHorizontal<Menu.X ||
                MouseHorizontal>=Menu.X+Menu.Width ||
                MouseVertical<Menu.Y ||
                MouseVertical>=Menu.Y+Menu.Height)
            {
              RemoveMenu();
              MouseInControl=0;
              MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];
              PlaceOption(Menu.CurrentOption);
              return MenusRemoved;
            }
          }
        }

        return MenuEvent;
      }

      if (MouseEvent&MouseLeftButtonRelease && CurrentLevel)
      {
        if (MouseHorizontal>=Menu.X
            && MouseHorizontal<Menu.X+Menu.Width
            && MouseVertical>Menu.Y
            && MouseVertical<Menu.Y+Menu.Height-1)
        {
          MouseInControl=1;

          _Options &Option=*(Menu.Option+Menu.CurrentOption);

          if (!*Option.Available || !Option.Option)
            return MenuEvent;

          if (Option.SubMenu && Option.SubMenu->Option)
          {
            PlaceMenu(*Option.SubMenu);
            MenuItems &Menu=*Option.SubMenu;
            _Options &Option=*(Menu.Option+Menu.CurrentOption);
            if (!*Option.Available || !Option.Option)
              FindNext();
            MouseInControl=0;
            return MenuEvent;
          }

          if (*Option.Available && Option.Checked)
          {
            *Option.Checked=(*Option.Checked)?0:1;
            Menu.ReCheckOption();
          }
          else
            if (*Option.Available && Option.Selectables)
            {
              *Option.Selectable=(*Option.Selectable==Option.SelectCount-1)?0:(++(*Option.Selectable));
              Menu.ReSelectOption();
            }

          return Option.Event;
        }
      }

      if (CurrentLevel==1)
      {
        if ( ((MouseHorizontal<Menu.XStart ||
               MouseHorizontal>Menu.XEnd) &&
               MouseVertical==SetY &&
               SetY<Menu.Y)

               ||

             ((MouseHorizontal<Menu.X ||
               MouseHorizontal>=Menu.X+Menu.Width ||
               MouseVertical<Menu.Y ||
               MouseVertical>=Menu.Y+Menu.Height) &&
              ((MouseVertical!=SetY &&
                SetY<Menu.Y) ||
                SetY>=Menu.Y)) )
        {
          MouseInControl=1;
          WasRemoved=1;
          RemoveMenu();
        }

        else

        if (MouseHorizontal>Menu.X &&
            MouseHorizontal<Menu.X+Menu.Width-1 &&
            MouseVertical>Menu.Y &&
            MouseVertical<Menu.Y+Menu.Height-1 &&
            (MouseVertical-Menu.Y-1)!=Menu.CurrentOption)
        {
          RemoveOption();
          PlaceOption(MouseVertical-Menu.Y-1);
        }
      }
      else if (CurrentLevel>1)
      {
        if (MouseHorizontal<Menu.X ||
            MouseHorizontal>=Menu.X+Menu.Width ||
            MouseVertical<Menu.Y ||
            MouseVertical>=Menu.Y+Menu.Height)
        {
          RemoveMenu();
          MouseInControl=0;
          MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];
          PlaceOption(Menu.CurrentOption);
        }

        else

        if (MouseHorizontal>Menu.X &&
            MouseHorizontal<Menu.X+Menu.Width-1 &&
            MouseVertical>Menu.Y &&
            MouseVertical<Menu.Y+Menu.Height-1 &&
            (MouseVertical-Menu.Y-1)!=Menu.CurrentOption)
        {
          RemoveOption();
          PlaceOption(MouseVertical-Menu.Y-1);
        }
      }

      if (!CurrentLevel)
      {
        for (register int i=0;i<NumberOfMenus;i++)
        {
          MenuItems &Menu=*Menus[i];

          if (MouseHorizontal>=Menu.XStart &&
              MouseHorizontal<=Menu.XEnd &&
              MouseVertical==SetY)
          {
            PlaceMenu(Menu);
            return MenuEvent;
          }
        }
      }

      return (CurrentLevel)?MenuEvent:((WasRemoved)?MenusRemoved:NothingEvent);
    }
    else
    {
      //--------------------------------------------------------------
      //
      // Pull down Mouse controller
      //
      //--------------------------------------------------------------

      if (!CurrentLevel)
        MouseInControl=1;

      MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];

      if (MouseEvent&MouseLeftButtonRelease && CurrentLevel==1 &&
        !Menu.NumberOfOptions && MouseHorizontal>=Menu.XStart
        && MouseHorizontal<=Menu.XEnd && MouseVertical==SetY
        && Menu.MenuEvent)
      {
        RemoveMenu();
        return(Menu.MenuEvent);
      }

//      Smart call back logic removed from pull down menu system on 10/1/91
//      to make the interface 100% SAA compliant.  Smart call backs only
//      occur in the pop down menu system.  Do not uncomment this section
//      as it isn't necessary any longer and just makes the use of pull down
//      menus a little confusing if mouse and keyboard are comingled.
//
//      if (!MouseInControl && CurrentLevel)
//      {
//        MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];
//
//        if (MouseHorizontal>=Menu.X
//            && MouseHorizontal<Menu.X+Menu.Width
//            && MouseVertical>Menu.Y
//            && MouseVertical<Menu.Y+Menu.Height-1)
//          MouseInControl=1;
//        return MenuEvent;
//      }

      if ((MouseEvent&MouseLeftButtonRelease || MouseEvent&MouseLeftButtonPress)
        && CurrentLevel)
      {
        if (CurrentLevel)
        {
          if ((MouseHorizontal<Menu.X ||
               MouseHorizontal>=Menu.X+Menu.Width ||
               MouseVertical<Menu.Y ||
               MouseVertical>=Menu.Y+Menu.Height))
          {
            if (CurrentLevel==1 && MouseHorizontal>=Menu.XStart &&
                 MouseHorizontal<=Menu.XEnd &&
                 MouseVertical==SetY &&
                 SetY<Menu.Y)
              return MenuEvent;

            RemoveMenu();
            MouseInControl=1;
            if (CurrentLevel)
            {
              MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];
              PlaceOption(Menu.CurrentOption);
            }
            return MenusRemoved;
          }
        }

        if (MouseHorizontal==Menu.X ||
          MouseHorizontal==Menu.X+Menu.Width-1 ||
          MouseVertical==Menu.Y ||
          MouseVertical==Menu.Y+Menu.Height-1)
          return MenuEvent;

        if (MouseHorizontal>=Menu.X
            && MouseHorizontal<Menu.X+Menu.Width
            && MouseVertical>Menu.Y
            && MouseVertical<Menu.Y+Menu.Height-1
            && MouseEvent&MouseLeftButtonRelease)
        {
          MouseInControl=1;

          RemoveOption();
          PlaceOption(MouseVertical-Menu.Y-1);

          _Options &Option=*(Menu.Option+Menu.CurrentOption);

          if (!*Option.Available || !Option.Option)
            return MenuEvent;

          if (Option.SubMenu && Option.SubMenu->Option)
          {
            PlaceMenu(*Option.SubMenu);
            MenuItems &Menu=*Option.SubMenu;
            _Options &Option=*(Menu.Option+Menu.CurrentOption);
            if (!*Option.Available || !Option.Option)
              FindNext();
            MouseInControl=1;
            return MenuEvent;
          }

          if (*Option.Available && Option.Checked)
          {
            *Option.Checked=(*Option.Checked)?0:1;
            Menu.ReCheckOption();
          }
          else
            if (*Option.Available && Option.Selectables)
            {
              *Option.Selectable=(*Option.Selectable==Option.SelectCount-1)?0:(++(*Option.Selectable));
              Menu.ReSelectOption();
            }

          return Option.Event;
        }
      }

      if (CurrentLevel==1 && MouseButtonStatus&LeftButton)
      {
        if (MouseHorizontal<Menu.XStart ||
            MouseHorizontal>Menu.XEnd &&
            MouseVertical==SetY &&
            SetY<Menu.Y)
        {
          RemoveMenu();
          WasRemoved=1;
        }

        else

        if (MouseHorizontal>Menu.X &&
            MouseHorizontal<Menu.X+Menu.Width-1 &&
            MouseVertical>Menu.Y &&
            MouseVertical<Menu.Y+Menu.Height-1 &&
            (MouseVertical-Menu.Y-1)!=Menu.CurrentOption)
        {
          RemoveOption();
          PlaceOption(MouseVertical-Menu.Y-1);
        }
      }
      else if (CurrentLevel>1 && MouseButtonStatus&LeftButton)
      {
        if (MouseHorizontal>Menu.X &&
            MouseHorizontal<Menu.X+Menu.Width-1 &&
            MouseVertical>Menu.Y &&
            MouseVertical<Menu.Y+Menu.Height-1 &&
            (MouseVertical-Menu.Y-1)!=Menu.CurrentOption)
        {
          RemoveOption();
          PlaceOption(MouseVertical-Menu.Y-1);
        }
      }

      if (!CurrentLevel && MouseButtonStatus&LeftButton)
      {
        for (register int i=0;i<NumberOfMenus;i++)
        {
          MenuItems &Menu=*Menus[i];

          if (MouseHorizontal>=Menu.XStart &&
              MouseHorizontal<=Menu.XEnd &&
              MouseVertical==SetY)
          {
            PlaceMenu(Menu);
            return MenuEvent;
          }
        }
      }

      return (CurrentLevel)?MenuEvent:((WasRemoved)?MenusRemoved:NothingEvent);
    }
  }
  else
  {
    //--------------------------------------------------------------
    //
    // Keyboard controller
    //
    //--------------------------------------------------------------

    switch(Event)
    {
      case kbLeft:
        if (!CurrentLevel)
          return NothingEvent;
        if (NumberOfMenus==1)
          return MenuEvent;

        RemoveAllMenus();

        int i=0;
        for (i=0;i<NumberOfMenus;i++)
          if (SubMenuTrack[0]==Menus[i])
            break;

        i=(!i)?(NumberOfMenus-1):(--i);
        PlaceMenu(*Menus[i]);
        MouseInControl=0;

        {
        MenuItems &Menu=*Menus[i];
        _Options &Option=*(Menu.Option+Menu.CurrentOption);
        if (!*Option.Available || !Option.Option)
          FindNext();
        }

        return MenuEvent;

      case kbRight:
        if (!CurrentLevel)
          return NothingEvent;
        if (NumberOfMenus==1)
          return MenuEvent;

        RemoveAllMenus();

        for (i=0;i<NumberOfMenus;i++)
          if (SubMenuTrack[0]==Menus[i])
            break;

        i=(i==NumberOfMenus-1)?0:(++i);
        PlaceMenu(*Menus[i]);
        MouseInControl=0;

        {
        MenuItems &Menu=*Menus[i];
        _Options &Option=*(Menu.Option+Menu.CurrentOption);
        if (!*Option.Available || !Option.Option)
          FindNext();
        }

        return MenuEvent;

      case kbUp:
        if (!CurrentLevel)
          return NothingEvent;

        RemoveOption();
        FindLast();

        return MenuEvent;

      case kbDown:
        if (!CurrentLevel)
          return NothingEvent;

        RemoveOption();
        FindNext();

        return MenuEvent;

      case kbEsc:
        if (!CurrentLevel)
          return NothingEvent;

        RemoveMenu();

        if (CurrentLevel)
        {
          MouseInControl=0;
          MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];
          PlaceOption(Menu.CurrentOption);
        }
        else
          MouseInControl=1;

        return MenuEvent;

      case kbCr:
        if (!CurrentLevel)
          return NothingEvent;

        {
          MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];
          _Options &Options=*(Menu.Option+Menu.CurrentOption);

          if (!Menu.NumberOfOptions)
          {
            if (CurrentLevel==1)
              RemoveMenu();
            return (!Menu.MenuEvent)?MenuEvent:Menu.MenuEvent;
          }

          if (*Options.Available && Options.SubMenu && Options.SubMenu->Option)
          {
            PlaceMenu(*Options.SubMenu);
            MenuItems &Menu=*Options.SubMenu;
            _Options &Option=*(Menu.Option+Menu.CurrentOption);
            if (!*Option.Available || !Option.Option)
              FindNext();
            MouseInControl=0;
            return MenuEvent;
          }

          if (*Options.Available && Options.Checked)
          {
            *Options.Checked=(*Options.Checked)?0:1;
            Menu.ReCheckOption();
          }
          else
            if (*Options.Available && Options.Selectables)
            {
              *Options.Selectable=(*Options.Selectable==Options.SelectCount-1)?0:(++(*Options.Selectable));
              Menu.ReSelectOption();
            }

          return (!*Options.Available || !Options.Option)?MenuEvent:Options.Event;
        }

      default:

        //------------------------------------------------------------
        //
        // Check and see if a menu activation hot key was used
        // Both global and localized window menus are checks
        //
        //------------------------------------------------------------

        for (i=0;i<NumberOfMenus;i++)
        {
          MenuItems &Menu=*Menus[i];
          if (Menu.MenuHotKey==Event)
          {
            if (!Menu.NumberOfOptions)
            {
              RemoveAllMenus();
              return (!Menu.MenuEvent)?MenuEvent:Menu.MenuEvent;
            }

            _Options &Option=*(Menu.Option+Menu.CurrentOption);

            RemoveAllMenus();

            if (!IsWindow && NumberOfWindows && Window.CurrentLevel)
              Window.RemoveAllMenus();
            if (IsWindow && WorkSpace.CurrentLevel)
              WorkSpace.RemoveAllMenus();

            PlaceMenu(Menu);
            MouseInControl=0;
            if (!*Option.Available || !Option.Option)
              FindNext();
            return MenuEvent;
          }
        }

        //------------------------------------------------------------
        //
        // See if an option quick key was pressed
        //
        //------------------------------------------------------------

        if (CurrentLevel)
        {
          MenuItems &Menu=*SubMenuTrack[CurrentLevel-1];
          for (i=0;i<Menu.NumberOfOptions;i++)
          {
            Event-=(Event<255 && (islower(Event))?32:0);
            _Options &Option=*(Menu.Option+i);
            if (Option.QuickKey==Event)
            {
              if (!*Option.Available || !Option.Option)
                return MenuEvent;
              RemoveOption();
              PlaceOption(i);

              if (Option.SubMenu)
              {
                PlaceMenu(*Option.SubMenu);
                MenuItems &Menu=*Option.SubMenu;
                _Options &Option=*(Menu.Option+Menu.CurrentOption);
                if (!*Option.Available || !Option.Option)
                  FindNext();
                MouseInControl=0;
                return MenuEvent;
              }
    
              if (*Option.Available && Option.Checked)
              {
                *Option.Checked=(*Option.Checked)?0:1;
                Menu.ReCheckOption();
              }
              else
                if (*Option.Available && Option.Selectables)
                {
                  *Option.Selectable=(*Option.Selectable==Option.SelectCount-1)?0:(++(*Option.Selectable));
                  Menu.ReSelectOption();
                }

              return Option.Event;
            }
          }
        }

        //------------------------------------------------------------
        //
        // See if a menu hot key was pressed
        //
        //------------------------------------------------------------

        int Saved;

        for (i=0;i<NumberOfMenus;i++)
        {
          if (Saved=Menus[i]->ScanMenu(Event),Saved)
            break;
        }

        if (Saved)
        {
          RemoveAllMenus();
          if (!IsWindow && NumberOfWindows && Window.CurrentLevel)
            Window.RemoveAllMenus();
          if (IsWindow && WorkSpace.CurrentLevel)
            WorkSpace.RemoveAllMenus();
          return Saved;
        }

        return NothingEvent;
    }
  }
}

