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

#include "fli.h"
#include "elements.h"
#include "colors.h"

#ifdef __BCPLUSPLUS__
#pragma hdrstop
#endif

#include <string.h>

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// DiaPickGeneric()
//
// Constructor for DiaPickGeneric
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

DiaPickGeneric::DiaPickGeneric(int _X,int _Y,int _Width,int _Height,int &_Item,
  int &_ItemCount) :
  Item(_Item),
  ItemCount(_ItemCount)
{
  X=_X;
  Y=_Y;
  Width=_Width+3;
  Height=_Height;
  ItemAtTopOfList=0;

  if (Item>=ItemCount)
    Item=ItemCount-1;

  if (Item<0)
    Item=0;

  if (Item>=ItemAtTopOfList+Height)
    ItemAtTopOfList=(Item-Height)+1;

  if (Item<ItemAtTopOfList)
    ItemAtTopOfList=Item;
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// ScrollBar()
//
// Show the scroll bar
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

void DiaPickGeneric::ScrollBar()
{
  int Avail=(Available()==CompleteEvent);

  Blaze->CharacterRepeaterDown(X+Width-1,Y,Height,
    (Avail)?Colors.PickButton:Colors.DiaDeadLocator,0xb1);

  (*Blaze) (X+Width-1,Y)
    << ((Avail)?Colors.PickButton:Colors.DiaDeadLocator)
    << '\x1e';

  (*Blaze) (X+Width-1,Y+Height-1)
    << '\x1f';

  if (ItemCount && ItemCount>Height)
  {
    int Calc=Height-2;

    int Determine=ItemCount/Calc;
    int AnotherDetermine=0;
    if (Item)
      AnotherDetermine=Item/Determine;

    if (AnotherDetermine>=Height-2)
      AnotherDetermine=Height-3;

    (*Blaze) (X+Width-1,Y+1+AnotherDetermine)
      << '\xfe';
  }
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// Show()
//
// Show the pick list
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

void DiaPickGeneric::Show()
{
  MouseHide();

  ScrollBar();

  int LocX, LocY, LocWide, LocHigh;

  int Avail=(Available()==CompleteEvent);

  if (Avail)
  {
    if (Item>=ItemCount)
      Item=ItemCount-1;

    if (Item<0)
      Item=0;

    if (ItemAtTopOfList+Height>ItemCount && ItemCount>Height)
      ItemAtTopOfList=ItemCount-Height;

    if (Item>=ItemAtTopOfList+Height)
      ItemAtTopOfList=(Item-Height)+1;

    if (Item<ItemAtTopOfList)
      ItemAtTopOfList=Item;

    if (ItemCount<=Height && ItemAtTopOfList)
      ItemAtTopOfList=0;

    Blaze->CharacterRepeaterDown(X+Width-2,Y,Height,Colors.PickText,' ');

    if (ItemCount<Height)
      Blaze->EraseArea(X,Y+ItemCount,Width-1,Height-ItemCount,Colors.PickText);

    Blaze->WindowInformation(LocX,LocY,LocWide,LocHigh);

    BlazeClass Blaze;
    Blaze.Window(LocX+X,LocY+Y,Width-2,Height);
    +Blaze;
    !Blaze;

    if (ItemCount)
      for (int i=0;i<Height;i++)
      {
        char *ItemStore=GetItem(ItemAtTopOfList+i);

        Blaze (0,i)
          << ((ItemAtTopOfList+i==Item)?Colors.PickMarked:Colors.PickText)
          << ' '
          << ItemStore;

        int Calc=(Width-3)-strlen(ItemStore);

        if (Calc>0)
          Blaze.CharacterRepeater(strlen(ItemStore)+1,i,Calc,Colors.PickText,
            ' ');

        if (ItemAtTopOfList+i>=ItemCount-1)
          break;
      }
  }
  else
    Blaze->CharacterFill(X,Y,Width-1,Height,Colors.DiaDeadLocator,176);

  MouseShow();
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// HighLight()
//
// Highlight the current pick list item
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

void DiaPickGeneric::HighLight()
{
  MouseHide();
  Blaze->LineAttribute(X,Y+Item-ItemAtTopOfList,Width-1,
    Colors.PickHiLite);
  Blaze->WindowGotoXY(X+1,Y+Item-ItemAtTopOfList);
  MouseShow();
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// EventHandler()
//
// Handles the events
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

int DiaPickGeneric::EventHandler(int Event)
{
  if (Event==kbDown ||
    (Event==ValidatedMousedEvent
      && (MouseEvent&MouseLeftButtonRelease || MouseEvent&MouseHeldDown)
      && MouseHorizontal==X+Width-1
      && MouseVertical==Y+Height-1))
  {
    if (Item!=ItemCount-1 && ItemCount)
    {
      Item++;
      if (Item-ItemAtTopOfList>=Height)
      {
        ItemAtTopOfList++;
        Show();
      }
      else
      {
        MouseHide();
        Blaze->LineAttribute(X,(Y+Item-ItemAtTopOfList)-1,Width-1,
          Colors.PickText);
        ScrollBar();
        MouseShow();
      }
      HighLight();
    }
    return CompleteEvent;
  }

  if (Event==kbUp ||
    (Event==ValidatedMousedEvent
      && (MouseEvent&MouseLeftButtonRelease || MouseEvent&MouseHeldDown)
      && MouseHorizontal==X+Width-1
      && MouseVertical==Y))
  {
    if (Item && ItemCount)
    {
      Item--;
      if (Item<ItemAtTopOfList)
      {
        ItemAtTopOfList--;
        Show();
      }
      else
      {
        MouseHide();
        Blaze->LineAttribute(X,(Y+Item-ItemAtTopOfList)+1,Width-1,
          Colors.PickText);
        ScrollBar();
        MouseShow();
      }
      HighLight();
    }
    return CompleteEvent;
  }

  if (Event==ValidatedMousedEvent &&
    (MouseEvent&MouseDoubleClick || MouseEvent&MouseLeftButtonRelease)
    && MouseHorizontal<X+Width-1)
  {
    int Compute=(MouseVertical-Y)+ItemAtTopOfList;
    if (Compute!=Item && Compute<ItemCount && ItemCount)
    {
      Item=Compute;
      Show();
      HighLight();
    }
    return (MouseEvent&MouseDoubleClick)?ClickEvent:CompleteEvent;
  }

  if (MouseButtonStatus&LeftButton && ItemCount && ItemCount>Height && Height>3 &&
    MouseHorizontal==X+Width-1 && MouseVertical>Y && MouseVertical<Y+Height-1)
  {
    int Block=MouseVertical-Y-1;

    int Calc=Height-2;

    int Determine=ItemCount/Calc;
    int AnotherDetermine=Block*Determine;
    if (AnotherDetermine>ItemCount)
      AnotherDetermine=ItemCount-1;

    if (ItemAtTopOfList==AnotherDetermine)
      return CompleteEvent;

    Item=AnotherDetermine;
    ItemAtTopOfList=AnotherDetermine;

    if (MouseVertical==Y+Height-2)
      Item=ItemCount-1;

    Show();
    HighLight();

    return CompleteEvent;
  }

  if (Event==kbHome)
  {
    ItemAtTopOfList=0;
    Item=0;
    Show();
    HighLight();
    return CompleteEvent;
  }

  if (Event==kbEnd)
  {
    if (ItemCount>Height)
    {
      Item=ItemCount-1;
      ItemAtTopOfList=Item-(Height-1);
    }
    else
      Item=ItemCount-1;
    Show();
    HighLight();
    return CompleteEvent;
  }

  if (Event==kbPgUp)
  {
    if (ItemCount>Height)
    {
      ItemAtTopOfList-=Height;
      if (ItemAtTopOfList<0)
        ItemAtTopOfList=0;
      Item=ItemAtTopOfList;
      Show();
      HighLight();
      return CompleteEvent;
    }
  }

  if (Event==kbPgDn)
  {
    if (ItemCount>Height)
    {
      ItemAtTopOfList+=Height;
      if (ItemAtTopOfList+(Height-1)>ItemCount-1)
        ItemAtTopOfList=ItemCount-Height;
      Item=ItemAtTopOfList+(Height-1);
      Show();
      HighLight();
      return CompleteEvent;
    }
  }

  if (Event>=' ' && Event<='~') // QUIKFIND searching
  {
    int SearchFor=(Event>='a' && Event<='z')?(Event-32):Event;

    if (!Item && QuikFind(1,ItemCount,SearchFor))
      return CompleteEvent;
    else
    {
      if (Item+1<ItemCount && QuikFind(Item+1,ItemCount,SearchFor))
        return CompleteEvent;
      if (QuikFind(0,Item,SearchFor))
        return CompleteEvent;
    }
  }

  return Event;
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// QuikFind()
//
// QuikFind scanner -- scans for an item that starts with a given
// character
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

int DiaPickGeneric::QuikFind(int Low,int High,int SearchFor)
{
  if (Low==High)
    return 0;

  for (int i=Low;i<High;i++)
  {
    char *GetIt=GetItem(i);
    int Character=(*GetIt>='a' && *GetIt<='z')?(*GetIt-32):*GetIt;
    if (SearchFor==Character)
    {
      Item=i;
      Show();
      HighLight();
      return 1;
    }
  }

  return 0;
}
