//*************************************************************************//
// Filename:    WindowList.cpp
// Autor:       Christian Taulien of Strange Intelligence
// Purpose:     Window management implementation for FreshBar
// Creation:    17. Mai 1998
//*************************************************************************//

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/dos_protos.h>

#include "WindowList.h"
#include "VisualInfo.h"
#include "TextMeasure.h"
#include "global.h"

extern "C" void NewList(struct List *list);

void StripIntuiMessages(struct MsgPort *arg_poMsgPort, struct Window *arg_poWindow)
/*S*/
/*S*/ /* Methoden-Rahmen */
/*************************************************************************
* Name der Methode: ::StripIntuiMessages()
*
* Klasse: --
*
* Funktion:
*   function to remove and reply all IntuiMessages on a port that have been
*   sent to a particular window (note that we don't rely on the ln_Succ
*   pointer of a message after we have replied it)
*
* Zugriff: public
*
* Eingabe-Parameter: 2
*   arg_poMsgPort:  Zeiger auf den Messageport (UserPort) des Fensters
*   arg_poWindow:   Zeiger auf das Fenster um das es dabei geht.
*
* Ausgabe-Parameter: -
*
* Aufgerufen von: -
*
* Verwendung folgender globaler Variablen/Strukturen: -
*
* Benutzte Methoden: 2
*   exec.library/Remove()
*   exec.library/ReplyMsg()
*
* Version: 1.0
*
* Autor: RKRM Libraries
*
* Datum: 17. Mai 1998
*
* Letzte Änderungen/Neuerungen:
* 17. Mai 1998: Methode definiert
*
*************************************************************************/
/*E*/
{
  struct IntuiMessage *poMsg = (struct IntuiMessage *)arg_poMsgPort->mp_MsgList.lh_Head;

  struct Node *succ;
  while (succ = poMsg->ExecMessage.mn_Node.ln_Succ)
  {
    if (poMsg->IDCMPWindow == arg_poWindow)
    {
      // Intuition is about to free this message.
      // Make sure that we have politely sent it back.
      Remove((struct Node *) poMsg);

      ReplyMsg((struct Message *) poMsg);
    } // if
    poMsg = (struct IntuiMessage *) succ;
  } // while
} // StripIntuiMessages()
/*E*/
void CloseWindowSafely(struct Window *arg_poWindow)
/*S*/
/*S*/ /* Methoden-Rahmen */
/*************************************************************************
* Name der Methode: ::CloseWindowSafely()
*
* Klasse: --
*
* Funktion:
*   Strip all IntuiMessages from an IDCMP which are waiting for a specific
*   window.  When the messages are gone, set the UserPort of the window to
*   NULL and call ModifyIDCMP(win,0).  This will free the Intuition arts
*   of the IDMCMP and trun off message to this port without changing the
*   original UserPort (which may be in use by other windows).
*
* Zugriff: public
*
* Eingabe-Parameter: 1
*   arg_poWindow: Zeiger auf das Fenster
*
* Ausgabe-Parameter:
*
* Aufgerufen von:
*
* Verwendung folgender globaler Variablen/Strukturen:
*
* Benutzte Methoden: 5
*   exec.library/Forbid()
*   exec.library/Permit()
*   intuition.library/ModifyIDCMP()
*   intuition.library/CloseWindow()
*   StripIntuiMessages()
*
* Version: 1.0
*
* Autor: RKRM Libraries
*
* Datum: 17. Mai 1998
*
* Letzte Änderungen/Neuerungen:
* 17. Mai 1998: Methode definiert / RKRM-Libraries
*
*************************************************************************/
/*E*/
{
  TRACE("Entry");
  // if no valid window-pointer
  if (!arg_poWindow)
  {
    return;
  } // if

  // we forbid here to keep out of race conditions with Intuition
  Forbid();

  // send back any messages for this window  that have not yet been processed
  StripIntuiMessages(arg_poWindow->UserPort, arg_poWindow);

  // clear UserPort so Intuition will not free it
  arg_poWindow->UserPort = NULL;

  // tell Intuition to stop sending more messages
  ModifyIDCMP(arg_poWindow, 0L);

  // turn multitasking back on
  Permit();

  // Now it's safe to really close the window
  CloseWindow(arg_poWindow);
} // CloseWindowSafely()
/*E*/
char getShortCut(char *arg_sString)
/*S*/
{
  TRACE("Entry");
  char cShortCut = '\0';

  // wenn string gefunden
  if (arg_sString)
  {
    int iLen = strlen(arg_sString);
    for (int i=0; i<iLen; ++i)
    {
      // wenn underscore gefunden und noch min. ein zeichen danach
      // vorhanden
      if (arg_sString[i] == '_' && (i < iLen-1))
      {
        // shortcut gefunden. Schleife verlassen
        cShortCut = arg_sString[i+1];
        break;
      } // if
    } // for
  } // if

return ToLower(cShortCut);
}
/*E*/

//******************************************************************//
//******************************************************************//
//
//  BarWindowNodeC
//
//******************************************************************//
//******************************************************************//
ULONG BarWindowNodeC::m_ulNextFreeID = 0;

BarWindowNodeC::BarWindowNodeC(BarWindowListC *arg_poBarWindowList,
                               char *arg_sName,
                               char *arg_sButtonName,
                               char *arg_sScreenName,
                               BOOL arg_bCloseGadget)
/*S*/
{
  TRACE("Konstruktor");
  if (!arg_poBarWindowList)
  {
    TRACE("Falscher Parameter!");
    throw;
  } // if

  // init the baseclassmembers
  ln_Succ       = NULL;
  ln_Pred       = NULL;
  ln_Type       = NT_USER;
  ln_Pri        = 0;

  // now our members
  m_oName              = arg_sName;
  m_oButtonText        = arg_sButtonName;
  m_poLockedScreen     = NULL;
  m_poBarWindow        = NULL;
  m_oScreenName        = arg_sScreenName;
  m_bGadgetsAttached   = FALSE;
  m_bCloseGadget       = arg_bCloseGadget;
  m_poSharedUserPort   = arg_poBarWindowList->getSharedUserPort();
  m_ulBarWindowID      = ++m_ulNextFreeID;
  m_iWidth             = 150;
  m_iHeight            = 100;
  m_iTop               = 100;
  m_iLeft              = 100;
  m_iBorderTop         = 4;
  m_iBorderLeft        = 4;
  m_iBorderBottom      = 4;
  m_iBorderRight       = 4;
  m_iMaxVisibleEntries = 15;
  m_poFirstGadget      = NULL;
  m_poButton           = NULL;

  AddTail(arg_poBarWindowList, this);
} // BarWindowNodeC::BarWindowNodeC()
/*E*/
BarWindowNodeC::~BarWindowNodeC()
/*S*/
{
  TRACE("Destruktor");

  // delete the window
  if (m_poBarWindow)
  {
    closeBarWindow();
  } // if

  // delete the name
  if (ln_Name)
  {
    delete ln_Name;
  } // if

  // if the node is in a list
  if (ln_Pred && ln_Succ)
  {
    Remove(this);
  } // if
}
/*E*/
struct Screen *BarWindowNodeC::lockScreen()
/*S*/
{
  TRACE("Entry");
  if (m_poLockedScreen)
  {
    TRACE("Screen already locked!");
    return m_poLockedScreen;
  } //

  // lock the wanted screen
  if (m_oScreenName.isEmpty())
  {
    m_poLockedScreen = LockPubScreen(NULL);
  }
  else
  {
    m_poLockedScreen = LockPubScreen(m_oScreenName);
  } // if

return m_poLockedScreen;
}
/*E*/
void BarWindowNodeC::unlockScreen()
/*S*/
{
  TRACE("Entry");
  // wenn wir einen public screen gelockt haben.
  if (m_poLockedScreen)
  {
    UnlockPubScreen(NULL, m_poLockedScreen);
    m_poLockedScreen = NULL;
  } // if
}
/*E*/
BOOL BarWindowNodeC::openBarWindow()
/*S*/
{
  TRACE("Entry");

BOOL erfolg = FALSE;
  // wenn das Fenster schon offen ist
  if (isOpen())
  {
    TRACE("schon offen");
    // dann nur aktivieren und zurückkehren
    ActivateWindow(m_poBarWindow);
    WindowToFront(m_poBarWindow);
    return TRUE;
  } // if

  // Wenn wir eine Bar-Liste haben.
  TRACE("Bars vorhanden");
  lockScreen();

  validateWindowSize();
  setBarWindowPos(-1,-1);
  createGadgets();

  if (m_poBarWindow = OpenWindowTags(NULL,
        WA_Width, m_iWidth,
        WA_Height, m_iHeight,
        WA_AutoAdjust, TRUE,
        WA_Top, m_iTop,
        WA_Left, m_iLeft,
        WA_PubScreen, m_poLockedScreen,
        WA_Activate, TRUE,
        WA_DragBar, TRUE,
        WA_DepthGadget, TRUE,
        WA_CloseGadget, m_bCloseGadget,
        WA_SizeGadget, FALSE,
        WA_SmartRefresh, TRUE,
        WA_RMBTrap, TRUE,
        WA_IDCMP, NULL,
        WA_Title, (char *) m_oName,
        TAG_DONE))
  {
    TRACE("Fenster ist jetzt offen");
    m_poBarWindow->UserPort = m_poSharedUserPort;
    ModifyIDCMP(m_poBarWindow,   CLOSEWINDOW
                               | REFRESHWINDOW
                               | BUTTONIDCMP
                               | IDCMP_VANILLAKEY
                               | IDCMP_RAWKEY);
    m_poBarWindow->UserData = (char *) this;
    showGadgets();
    erfolg = TRUE;
  } // if
return erfolg;
}
/*E*/
void BarWindowNodeC::closeBarWindow()
/*S*/
{
  TRACE("Entry");
  m_iLeft = m_poBarWindow->LeftEdge;
  m_iTop = m_poBarWindow->TopEdge;

  hideGadgets();
  CloseWindowSafely(m_poBarWindow);
  unlockScreen();
  m_poBarWindow = NULL;

  freeGadgets();
}
/*E*/
void BarWindowNodeC::setBarWindowTitle(char *arg_sName)
/*S*/
{ 
  TRACE("Entry");
  m_oName = arg_sName;
  if (isOpen())
  {      
    SetWindowTitles(m_poBarWindow, arg_sName, (char *) ~0);
  } // if
}
/*E*/
struct Gadget *BarWindowNodeC::createGadgets()
/*S*/
{
  TRACE("Entry");

  // if no button needed
  if (!hasButton())
  {
    return NULL;
  } // if

  // Rückgabe
  struct Gadget *pGad = NULL;

  // parameter-check
  if (!m_poLockedScreen)
  {
    TRACE("Wrong createGadgets()-Parameter!");
    return pGad;
  } // if

  VisualInfoC oVI(m_poLockedScreen);
  if (!oVI)
  {
    TRACE("VisualInfo failed");
    return pGad;
  } // if

  // für Gadtools erforderlich
  pGad = CreateContext(&m_poFirstGadget);
  if (pGad)
  {
    TRACE("CreateContext ok");

    // ermittle die Hoehe der Balken
    int iHeightOfBars = m_oBarList.getHeight(m_poLockedScreen);

    TextMeasureC oTeMe(m_poLockedScreen);
    struct NewGadget ng;
    ng.ng_Width      = oTeMe.getTextWidth(m_oButtonText) + 10;
    ng.ng_Height     = oTeMe.getTextHeight() + 6;
    ng.ng_TopEdge    = m_poLockedScreen->WBorTop + m_poLockedScreen->BarHeight + iHeightOfBars + oTeMe.getTextHeight() + m_iBorderTop;

    // breite und hoehe des Fensters neu anpassen
    m_iHeight = ng.ng_TopEdge + ng.ng_Height + m_poLockedScreen->WBorBottom+4;
    if (ng.ng_Width > m_iWidth - m_poLockedScreen->WBorLeft - m_poLockedScreen->WBorRight - 20)
    {
      m_iWidth = ng.ng_Width + m_poLockedScreen->WBorLeft + m_poLockedScreen->WBorRight + 20;
    } // if
    ng.ng_LeftEdge   = (m_iWidth-oTeMe.getTextWidth(m_oButtonText) - 10)/2;
    ng.ng_GadgetText = (char *) m_oButtonText;
    ng.ng_TextAttr   = m_poLockedScreen->Font;
    ng.ng_Flags      = PLACETEXT_IN;
    ng.ng_GadgetID   = 42;
    ng.ng_UserData   = NULL;
    ng.ng_VisualInfo = oVI;
    // Das Weiter-Gadget jetzt erstellen
    m_poButton = pGad = CreateGadget(BUTTON_KIND, pGad, &ng,
        GT_Underscore, '_',
        TAG_DONE);
    if (pGad)
    {
      TRACE("Gadgets ok");
    } // if
  } // if
return pGad;
}
/*E*/
void BarWindowNodeC::freeGadgets()
/*S*/
{
  TRACE("Entry");
  // if no button needed
  if (!hasButton())
  {
    return;
  } // if

  // wenn das Fenster noch offen ist
  if (m_poBarWindow)
  {
    // die gadget vorher removen
    hideGadgets();
  } // if

  // wenn die gadget "befreit" werden müssen
  if (m_poFirstGadget)
  {
    FreeGadgets(m_poFirstGadget);
    m_poFirstGadget = NULL;
    m_poButton = NULL;
  } // if
}
/*E*/
void BarWindowNodeC::clearBarWindow()
/*S*/
{
  TRACE("Entry");
  // wenn Fenster offen
  if (isOpen())
  {
    EraseRect(m_poBarWindow->RPort,
              m_poBarWindow->BorderLeft,
              m_poBarWindow->BorderTop,
              m_poBarWindow->Width-m_poBarWindow->BorderRight-1,
              m_poBarWindow->Height-m_poBarWindow->BorderBottom-1);

  } // if
}
/*E*/
void BarWindowNodeC::hideGadgets()
/*S*/
{
  TRACE("Entry");

  // if no button needed
  if (!hasButton())
  {
    return;
  } // if

  // validation check
  if (!m_poBarWindow || !m_poFirstGadget)
  {
    TRACE("Falsche Parameter");
    return;
  } // if

  if (!m_bGadgetsAttached)
  {
    TRACE("Gadgets garnicht attached");
    return;
  } // if
  RemoveGList(m_poBarWindow, m_poFirstGadget, ~0);

  m_bGadgetsAttached = FALSE;
}
/*E*/
void BarWindowNodeC::showGadgets()
/*S*/
{
  TRACE("Entry");

  clearBarWindow();
  m_oBarList.drawBars(this,
                      m_poLockedScreen->WBorLeft + m_iBorderLeft,
                      m_poLockedScreen->WBorTop + m_poLockedScreen->BarHeight + m_iBorderTop);

  // if no button needed
  if (m_oButtonText.isEmpty())
  {
    return;
  } // if

  // validation check
  if (!m_poBarWindow || !m_poFirstGadget)
  {
    TRACE("Falsche Parameter");
    return;
  } // if

  // wenn das Fenster bereits Gadgets hat
  if (m_bGadgetsAttached)
  {
    TRACE("Gadgets bereits vorhanden");
    return;
  } // if

  AddGList(m_poBarWindow, m_poFirstGadget, -1, -1, NULL);
  RefreshGList(m_poFirstGadget, m_poBarWindow, NULL, -1);
  GT_RefreshWindow(m_poBarWindow, NULL);

  VisualInfoC oVI(m_poBarWindow);
  if (oVI.isOk())
  {
    TRACE("Visualinfo ok");
    //int width = m_poBarWindow->Width - m_poBarWindow->WScreen->WBorLeft - m_poBarWindow->WScreen->WBorLeft - 8;
    int width = m_poBarWindow->Width - m_poLockedScreen->WBorLeft - m_poLockedScreen->WBorRight - m_iBorderLeft - m_iBorderRight;
    int top = m_poLockedScreen->WBorTop + m_poLockedScreen->BarHeight + m_iBorderTop;
        top += m_oBarList.getSize() * (m_poBarWindow->WScreen->Font->ta_YSize + 6);

    DrawBevelBox( m_poBarWindow->RPort,
                  m_poLockedScreen->WBorLeft + m_iBorderLeft,
                  top + 6,
                  width,
                  2,
                  GT_VisualInfo, (APTR) oVI,
                  GTBB_Recessed, TRUE,
                  TAG_DONE );
  } // if

  m_bGadgetsAttached = TRUE;
}
/*E*/
void BarWindowNodeC::validateWindowSize()
/*S*/
{ 
  TRACE("Entry");
  setBarWindowWidth(m_iWidth);
}
/*E*/
void BarWindowNodeC::setBarWindowWidth(ULONG arg_ulWidth)
/*S*/
{
  TRACE("Entry");
  // wenn das fenster offen ist
  if (isOpen())
  {
    hideGadgets();
    int iBarTitleWidth = m_oBarList.getBarTitleWidth(m_poLockedScreen)
                       + m_poLockedScreen->WBorLeft
                       + m_poLockedScreen->WBorRight
                       + m_iBorderLeft
                       + m_iBorderRight;
    m_iWidth = SIFC_MAX(arg_ulWidth, 50 + iBarTitleWidth);
    m_oBarList.setBarWidth(m_iWidth - iBarTitleWidth);
    TextMeasureC oTeMe(m_poLockedScreen);
    int iHeightOfBars = m_oBarList.getHeight(m_poLockedScreen);
    if (m_poButton)
    {
      m_poButton->LeftEdge = (m_iWidth-oTeMe.getTextWidth(m_oButtonText) - 10)/2;
      m_poButton->TopEdge  = m_poLockedScreen->WBorTop + m_poLockedScreen->BarHeight + iHeightOfBars + oTeMe.getTextHeight() + m_iBorderTop;
      m_iHeight = m_poButton->TopEdge + m_poButton->Height + m_poLockedScreen->WBorBottom+4;
    }
    else
    {
      m_iHeight = m_poLockedScreen->WBorTop + m_poLockedScreen->BarHeight + iHeightOfBars + m_poLockedScreen->WBorBottom+7;
    } // if

    ChangeWindowBox(m_poBarWindow,
                    m_poBarWindow->LeftEdge,
                    m_poBarWindow->TopEdge,
                    m_iWidth,
                    m_iHeight);
    Delay(5);
    showGadgets();
  }
  else
  {
    m_iWidth = arg_ulWidth;
    if (m_poLockedScreen)
    {
      int iBarTitleWidth = m_oBarList.getBarTitleWidth(m_poLockedScreen)
                         + m_poLockedScreen->WBorLeft
                         + m_poLockedScreen->WBorRight
                         + m_iBorderLeft
                         + m_iBorderRight;
      m_iWidth = SIFC_MAX(arg_ulWidth, 50 + iBarTitleWidth);
      m_oBarList.setBarWidth(m_iWidth - iBarTitleWidth);
      TextMeasureC oTeMe(m_poLockedScreen);
      int iHeightOfBars = m_oBarList.getHeight(m_poLockedScreen);
      if (m_poButton)
      {
        m_poButton->LeftEdge = (m_iWidth-oTeMe.getTextWidth(m_oButtonText) - 10)/2;
        m_poButton->TopEdge  = m_poLockedScreen->WBorTop + m_poLockedScreen->BarHeight + iHeightOfBars + oTeMe.getTextHeight() + m_iBorderTop;
      }
      else
      {
        m_iHeight = m_poLockedScreen->WBorTop + m_poLockedScreen->BarHeight + iHeightOfBars + m_poLockedScreen->WBorBottom+7;
      } // if
    } // if
  } // if
}
/*E*/
void BarWindowNodeC::setBarWindowPos(int arg_iPosX, int arg_iPosY)
/*S*/
{
  TRACE("Entry");
  if (!m_poLockedScreen)
  {
    return;
  } // if

  switch (arg_iPosX)
  {
    case -1:
      m_iLeft = (m_poLockedScreen->Width - m_iWidth)/2;
      break;
    case -2:
      break;
    default:
      m_iLeft = arg_iPosX;
      break;
  } // switch

  switch (arg_iPosY)
  {
    case -1:
      m_iTop = (m_poLockedScreen->Height - m_iHeight)/2;
      break;
    case -2:
      break;
    default:
      m_iTop = arg_iPosY;
      break;
  } // switch

  if (isOpen())
  {
    ChangeWindowBox(m_poBarWindow,
                    m_iLeft,
                    m_iTop,
                    m_poBarWindow->Width,
                    m_poBarWindow->Height);
  } // if
}
/*E*/
void BarWindowNodeC::refreshBars()
/*S*/
{
  TRACE("Entry");
  if (!isOpen())
  {
    return;
  } // if

  m_oBarList.fillBars(this,
                      m_poLockedScreen->WBorLeft + m_iBorderLeft,
                      m_poLockedScreen->WBorTop + m_poLockedScreen->BarHeight + m_iBorderTop);
}
/*E*/
BarNodeC *BarWindowNodeC::addBar(char *arg_sName, ULONG arg_ulMaxValue)
/*S*/
{
  TRACE("Entry");
  BarNodeC *poNode = m_oBarList.addBar(arg_sName, arg_ulMaxValue);
  validateWindowSize();
return poNode;
}
/*E*/
void BarWindowNodeC::removeBar(ULONG arg_ulBarID)
/*S*/
{
  TRACE("Entry");
  m_oBarList.removeBar(arg_ulBarID);
  validateWindowSize();
}
/*E*/
BOOL BarWindowNodeC::testOKButton()
/*S*/
{ 
  TRACE("Entry");
  // if no valid window-pointer
  if (!isOpen())
  {
    return FALSE;
  } // if

  BOOL bOk = FALSE;
  // we forbid here to keep out of race conditions with Intuition
  Forbid();

  // send back any messages for this window  that have not yet been processed
  struct IntuiMessage *poMsg = (struct IntuiMessage *)m_poBarWindow->UserPort->mp_MsgList.lh_Head;

  struct Node *succ;
  while (succ = poMsg->ExecMessage.mn_Node.ln_Succ)
  {
    if (poMsg->IDCMPWindow == m_poBarWindow)
    {
      // Intuition is about to free this message.
      // Make sure that we have politely sent it back.
      Remove((struct Node *) poMsg);

      ULONG ulClass = ((struct IntuiMessage *) poMsg)->Class;
      switch (ulClass)
      {
        case IDCMP_GADGETUP:
        case IDCMP_CLOSEWINDOW:
          bOk = TRUE;
          break;
        case IDCMP_VANILLAKEY:
          char cKey = (char) ((struct IntuiMessage *) poMsg)->Code;
          if ((cKey == 27) || (ToLower(cKey) == ::getShortCut(m_oButtonText)))
          {
            bOk = TRUE;
          } // if
          break;
      } // switch

      ReplyMsg((struct Message *) poMsg);
    } // if
    poMsg = (struct IntuiMessage *) succ;
  } // while

  // turn multitasking back on
  Permit();

return bOk;
}
/*E*/
BarWindowNodeC *BarWindowNodeC::getNext(void)
/*S*/
{
  TRACE("getNext()");
  if (ln_Succ && ln_Succ->ln_Succ)
  {
    return (BarWindowNodeC *) ln_Succ;
  } // if

return NULL;
}
/*E*/
BarWindowNodeC *BarWindowNodeC::getPrev(void)
/*S*/
{
  TRACE("getPrev()");
  if (ln_Pred && ln_Pred->ln_Pred)
  {
    return (BarWindowNodeC *) ln_Pred;
  } // if

return NULL;
}
/*E*/

//******************************************************************//
//******************************************************************//
//
//  BarWindowListC
//
//******************************************************************//
//******************************************************************//
BarWindowListC::BarWindowListC()
/*S*/
{
  TRACE("Konstruktor");
  NewList(this);
  m_poSharedUserPort = CreateMsgPort();
} // BarWindowListC::BarWindowListC()
/*E*/
BarWindowListC::~BarWindowListC()
/*S*/
{
  TRACE("Destruktor");
  removeAll();

  // delete the port created in the constructor
  if (m_poSharedUserPort)
  {  
    DeleteMsgPort(m_poSharedUserPort);
  } // if
} // BarWindowListC::~FLXWacthListC()
/*E*/
void BarWindowListC::removeAll()
/*S*/
{
  TRACE("Entry");
  // wenn die Liste nicht leer ist
  if (!IsListEmpty(this))
  {
    BarWindowNodeC *poNode;
    while (poNode = (BarWindowNodeC *) RemHead(this))
    {
      // Vorgaenger und Nachfolger auf null setzen
      // weil mit RemHead schon removed und der Destruktor
      // das bei nicht nulligen nodes nochmal machen wuerde.
      poNode->ln_Succ = NULL;
      poNode->ln_Pred = NULL;
      delete poNode;
    } // while
  } // if
  NewList(this);
}
/*E*/
void BarWindowListC::removeBarWindow(ULONG arg_ulBarWindowID)
/*S*/
{ 
  TRACE("Entry");
  // just find the node an delete it
  BarWindowNodeC *poNode = findBarWindowNode(arg_ulBarWindowID);
  if (poNode)
  {
    delete poNode;
  } // if
}
/*E*/
BarWindowNodeC *BarWindowListC::addBarWindow(char *arg_sName, char *arg_sButtonName, char *arg_sScreenName, BOOL arg_bCloseGadget)
/*S*/
{
  TRACE("Entry");

  // neuen Balken erzeugen
  BarWindowNodeC *poNode = new BarWindowNodeC(this, arg_sName, arg_sButtonName, arg_sScreenName, arg_bCloseGadget);
  if (!poNode)
  {
    TRACE("Kein Speicher");
    return FALSE;
  } // if

return poNode;
}
/*E*/
BarWindowNodeC *BarWindowListC::findBarWindowNode(ULONG arg_ulBarWindowID)
/*S*/
{
  TRACE("Entry");
  BarWindowNodeC *pNode = NULL;

  // wenn die Balkenliste nicht leer ist
  if (!IsListEmpty(this))
  {
    pNode = (BarWindowNodeC *) lh_Head;
    do
    {
      if (pNode->m_ulBarWindowID == arg_ulBarWindowID)
      {
        return pNode;
      } // if
    } while (pNode = pNode->getNext());
  } // if

return pNode;
}
/*E*/
int BarWindowListC::indexOf(BarWindowNodeC *arg_pNode)
/*S*/
{
  TRACE("Entry");

  // wenn die Balkenliste nicht leer ist
  if (arg_pNode && !IsListEmpty(this))
  {
    int iIndex = 0;

    // hole 1. eintrag
    BarWindowNodeC *pNode = (BarWindowNodeC *) lh_Head;
    do
    {
      // wenn gefunden
      if (pNode==arg_pNode)
      {
        return iIndex;
      } // if

      iIndex++;
    } while (pNode = pNode->getNext());
  } // if

return -1;
}
/*E*/
BarWindowNodeC *BarWindowListC::operator[](int arg_iIndex)
/*S*/
{
  TRACE("ENTRY");

  BarWindowNodeC *pNode = NULL;

  // wenn die Balken nicht leer ist
  if (!IsListEmpty(this))
  {
    int index = 0;

    // hole 1. eintrag
    pNode = (BarWindowNodeC *) lh_Head;
    do
    {
      // wenn i.ten eintrag erreicht
      if (index == arg_iIndex)
      {
        return pNode;
      } // if

      index++;
    } while (pNode = pNode->getNext());
  } // if

return pNode;
}
/*E*/
int BarWindowListC::getSize(void)
/*S*/
{
  TRACE("Entry");
  int iSize = 0;

  // wenn die Liste nicht leer ist
  if (!IsListEmpty(this))
  {
    // hole 1. Eintrag
    BarWindowNodeC *pNode = (BarWindowNodeC *) lh_Head;
    for (iSize=1; pNode = pNode->getNext(); iSize++);
  } // if

return iSize;
}
/*E*/

