/////////////////////////////////////////////////////////////////////////////
//
//   OBJMAP.CPP
//
//   Copyright (c) 1997  Galacticomm, Inc.        All Rights Reserved
//
//   Double Linked List Managemnt Class
//   Implementation
//                                               - Phil Henning 5/14/97
//
/////////////////////////////////////////////////////////////////////////////

#include "gcomm.h"
#include "majorbbs.h"
#include "objmap.h"

#define FILREV "$Revision: 6 $"

MARKSOURCE(objmap);

CObjMap::CObjMap()
{
     m_count=0;
     m_first=NULL;
     m_last=NULL;
     m_current=NULL;
}

CObjMap::~CObjMap()
{
     RemoveAll();
}


VOID
CObjMap::RemoveAll()
{
     while (m_last != NULL) {
          RemoveTail();
     }
}

INT
CObjMap::AddHead(const CHAR* pName, VOID* pObject)
{
     struct CObj* pNewObj;
     int iNameLen;

     ASSERT(pName != NULL);
     ASSERT(pObject != NULL);
     if (Find(pName)) {
          return(-1);
     }
     pNewObj=new CObj;
     ASSERT(pNewObj != NULL);
     iNameLen=strlen(pName);
     pNewObj->pName = new CHAR[iNameLen+1];
     pNewObj->pObject=pObject;
     strcpy(pNewObj->pName,pName);
     pNewObj->pPrev=NULL;
     pNewObj->pNext=m_first;
     m_first=pNewObj;
     if (pNewObj->pNext != NULL) {
          CObj* pNextObj=pNewObj->pNext;
          ASSERT(pNextObj != NULL);
          pNextObj->pPrev=m_first;
     }
     if (m_last == NULL) {
          m_last=pNewObj;
     }
     m_count++;
     return(m_count-1);
}

INT
CObjMap::AddTail(const CHAR* pName, VOID* pObject)
{
     struct CObj* pNewObj;
     int iNameLen;


     ASSERT(pName != NULL);
     ASSERT(pObject != NULL);
     pNewObj=new CObj;
     iNameLen=strlen(pName);
     ASSERT(pNewObj != NULL);
     pNewObj->pName = new CHAR[iNameLen+1];
     pNewObj->pObject=pObject;
     strcpy(pNewObj->pName,pName);
     pNewObj->pNext=NULL;
     pNewObj->pPrev=m_last;
     m_last=pNewObj;
     if (pNewObj->pPrev != NULL) {
          CObj* pPrevObj=pNewObj->pPrev;
          ASSERT(pPrevObj != NULL);
          pPrevObj->pNext=m_last;
     }
     if (m_first == NULL) {
          m_first=pNewObj;
     }
     m_count++;
     return(m_count-1);
}

INT
CObjMap::GetCount()
{
     return(m_count);
}


VOID
CObjMap::SetCurrent(
CObj* pObj)
{
     m_current=pObj;
     ASSERT(m_current != NULL);
     if (m_current != NULL) {
          m_next=m_current->pNext;
          m_prev=m_current->pPrev;
     }
     else {
          m_next=NULL;
          m_prev=NULL;
     }
}

VOID*
CObjMap::Find(
const CHAR* pName)
{
     CObj* pObj=m_first;

     ASSERT(pName != NULL);
     while (pObj != NULL) {
          ASSERT(pObj->pName != NULL);
          if (sameas(pName,pObj->pName)) {
               SetCurrent(pObj);
               return (pObj->pObject);
          }
          pObj=pObj->pNext;
     }
     return (NULL);
}


VOID*
CObjMap::Find(
const INT iIdx)
{
     INT iCount=0;
     CObj* pObj=m_first;

     if (iIdx < 0 || iIdx >= m_count) {
          return(NULL);
     }
     while (iCount < iIdx) {
          ASSERT(pObj != NULL);
          pObj=pObj->pNext;
          iCount++;
     }
     ASSERT(pObj != NULL);
     SetCurrent(pObj);
     return(pObj->pObject);
}

CObj*
CObjMap::FindInternalRef(
const CHAR* pName)
{
     CObj* pObj=m_first;

     ASSERT(pName != NULL);
     while (pObj != NULL) {
          ASSERT(pObj->pName != NULL);
          if (pObj->pName != NULL && sameas(pName,pObj->pName)) {
               SetCurrent(pObj);
               return (pObj);
          }
          pObj=pObj->pNext;
     }
     return (NULL);
}


CObj*
CObjMap::FindInternalRef(
const INT iIdx)
{
     INT iCount=0;
     CObj* pObj=m_first;

     if (iIdx < 0 || iIdx >= m_count) {
          return(NULL);
     }
     while (iCount < iIdx) {
          ASSERT(pObj != NULL);
          pObj=pObj->pNext;
          iCount++;
     }
     ASSERT(pObj != NULL);
     SetCurrent(pObj);
     return(pObj);
}


GBOOL
CObjMap::Remove(
const CHAR* pName)
{
     CObj* pObj=FindInternalRef(pName);
     if (pObj == NULL) {
          return(FALSE);
     }
     SetCurrent(pObj);
     CObj* pPrev=pObj->pPrev;
     CObj* pNext=pObj->pNext;

     delete [] pObj->pName;

     if (pPrev == NULL) {
          m_first=pNext;
     }
     else {
          pPrev->pNext=pNext;
     }
     if (pNext == NULL) {
          m_last=pPrev;
     }
     else {
          pNext->pPrev=pPrev;
     }

     delete pObj;
     m_count--;

     return(TRUE);
}

GBOOL
CObjMap::RemoveIdx(
const INT iIdx)
{
     CObj* pObj=FindInternalRef(iIdx);
     if (pObj == NULL) {
          return(FALSE);
     }
     SetCurrent(pObj);
     CObj* pPrev=pObj->pPrev;
     CObj* pNext=pObj->pNext;

     delete [] pObj->pName;
     if (pPrev == NULL) {
          m_first=pNext;
     }
     else {
          pPrev->pNext=pNext;
     }
     if (pNext == NULL) {
          m_last=pPrev;
     }
     else {
          pNext->pPrev=pPrev;
     }
     delete pObj;
     m_count--;
     return(TRUE);
}

VOID
CObjMap::RemoveHead()
{
     CObj* pObj=m_first;

     if (pObj == NULL) {
          return;
     }
     SetCurrent(pObj);
     if (m_last == m_first) {
          m_last=NULL;
     }
     m_first=pObj->pNext;
     if (m_first != NULL) {
          m_first->pPrev=NULL;
     }
     delete [] pObj->pName;
     delete pObj;
     m_count--;
}

VOID
CObjMap::RemoveTail()
{
     CObj* pObj=m_last;

     if (pObj == NULL) {
          return;
     }
     SetCurrent(pObj);
     if (m_first == m_last) {
          m_first = NULL;
     }
     m_last=pObj->pPrev;
     if (m_last != NULL) {
          m_last->pNext=NULL;
     }
     delete [] (pObj->pName);
     delete pObj;
     m_count--;
}

VOID*
CObjMap::GetHead()
{
     if (m_first != NULL) {
          SetCurrent(m_first);
          return(m_first->pObject);
     }
     return(NULL);
}

VOID*
CObjMap::GetTail()
{
     if (m_last != NULL) {
          SetCurrent(m_last);
          return(m_last->pObject);
     }
     return(NULL);
}

VOID*
CObjMap::GetNext()
{
     CObj* pObj;

     pObj=m_next;
     if (pObj != NULL) {
          SetCurrent(pObj);
          return(pObj->pObject);
     }
     return(NULL);
}

VOID*
CObjMap::GetPrev()
{
     CObj* pObj;

     pObj=m_prev;
     if (pObj != NULL) {
          SetCurrent(pObj);
          return(pObj->pObject);
     }
     return(NULL);
}

