#include "stdafx.h" #include "acp_base.h" #ifdef ACTIVE_EDITOR #include "itf/CPAWData.hpp" #pragma warning(disable:4355) CPA_WalkDataMgr::CPA_WalkDataMgr():WalkData(this, NULL) { for (iVoid=0; iVoidCheckAndGoElement (ItsData)) { pWDToInsertTo->InsertVoidElement (ItsData); UpdateIVoid(); } #else pWDToInsertTo->InsertVoidElement (ItsData); UpdateIVoid(); #endif } void CPA_WalkDataMgr::ActiveElement (CPA_DLLBase *pDLL) { GoElement (pDLL); ActiveCurrent(); } /******************** private *******************/ void CPA_WalkDataMgr::UpdateAll () { int i; for (i=iCurrent; i!=NO_ID; i=aWD[i].backprev) { ((WalkData *)aWD[i].ItsData)->UpdateList(); } } void CPA_WalkDataMgr::UpdateIVoid() { int i, j; WalkData *pWD; if (iCount!=MAX_WALKDATA_ELEMENT-1) { iVoid = ++iCount; } else {// take an element already used i=iLastUsed; do { pWD = (WalkData *)aWD[i].ItsData; i=aWD[i].next; } while (pWD->iCurrent==NO_ID); j = pWD->iLastUsed; iVoid = j; // tell DLL that the data is no longer of use. pWD->MyDLL->fn_vEraseWalkDataStructure (aWD[j].ItsData); // update list if (j == pWD->iCurrent) // this WD had only one element pWD->iCurrent = NO_ID; else { // update the element linked to the one we took pWD->iLastUsed = aWD[j].next; aWD[pWD->iLastUsed].prev = NO_ID; aWD[pWD->iLastUsed].backprev = NO_ID; } // clean new Void element (for safety) aWD[j].next = aWD[j].prev = NO_ID; aWD[j].backnext = aWD[j].backprev = NO_ID; } } int CPA_WalkDataMgr::FindOrCreateWalkData (CPA_DLLBase *pDLL) { int i, iInsertNode; for (i=iCurrent; i!=NO_ID; i=aWD[i].backprev) { if (((WalkData *)aWD[i].ItsData)->MyDLL == pDLL) { iInsertNode = i; break; } } if (i==NO_ID) { // New Node iInsertNode = iVoid; InsertVoidElement((void *)new WalkData (this, pDLL)); UpdateIVoid(); } return (iInsertNode); } void CPA_WalkDataMgr::GoElement (CPA_DLLBase *pDLL) { int iNew; UpdateAll (); iNew = FindOrCreateWalkData (pDLL); if (iNew != iCurrent) Go (iNew); UpdateList (); } inline void CPA_WalkDataMgr::ActiveCurrent() { ((WalkData *)aWD[iCurrent].ItsData)->BackActive(); } void CPA_WalkDataMgr::DBackward() { if (iCurrent!=NO_ID) if (((WalkData *)aWD[iCurrent].ItsData)->Backward()) ActiveCurrent(); } void CPA_WalkDataMgr::DForward() { if (iCurrent!=NO_ID) if (((WalkData *)aWD[iCurrent].ItsData)->Forward()) ActiveCurrent(); } void CPA_WalkDataMgr::EBackward() { if (Backward ()) ActiveCurrent(); } void CPA_WalkDataMgr::EForward() { if (Forward ()) ActiveCurrent(); } /************************* WalkData ************************/ WalkData::WalkData(CPA_WalkDataMgr *aWDM, CPA_DLLBase *pDLL) { MyWDM = aWDM; aWD = aWDM->aWD; // ne changera pas iCurrent = NO_ID; iFirst = NO_ID; iLast = NO_ID; iLastUsed = NO_ID; MyDLL = pDLL; } inline void WalkData::ABLink (int a, int b) {aWD[a].next = b; aWD[b].prev = a;BLink(a,b);} inline void WalkData::BLink (int a, int b) {aWD[a].backnext = b; aWD[b].backprev = a;} void WalkData::UpdateList(){ int i; if ((iCurrent==NO_ID) || (iLast==iCurrent)) return; for (i=iLast; i!=NO_ID; i=aWD[i].backnext) { // updatelist aWD[i].prev = aWD[i].backprev; aWD[i].next = aWD[i].backnext; }; iLast = iCurrent; } int WalkData::CheckAndGoElement (void *ItsData) { int i; for (i=iCurrent; i!=NO_ID; i=aWD[i].prev) { if ((aWD[i].ItsData == ItsData) && (aWD[i].ItsData == ItsData)) { if (i!=iCurrent) Go(i); UpdateList(); return (TRUE); } } return (FALSE); } void WalkData::InsertVoidElement (void *ItsData) { UpdateList(); iLast = iFirst = MyWDM->iVoid; if (iCurrent!=NO_ID) ABLink (iCurrent, iFirst); else { iLastUsed = iFirst; aWD[iFirst].prev = NO_ID; aWD[iFirst].backprev = NO_ID; } aWD[iFirst].aWalkData = this; aWD[iFirst].ItsData = ItsData; aWD[iFirst].next = NO_ID; aWD[iFirst].backnext = NO_ID; iCurrent = iFirst; } int WalkData::Backward() { int iNew; if (iCurrent==NO_ID) return (FALSE); iNew = aWD[iCurrent].prev; if (iNew == NO_ID) return (FALSE); Go (iNew); return (TRUE); } int WalkData::Forward() { int iNew; if (iCurrent==NO_ID) return (FALSE); iNew = aWD[iCurrent].next; if (iNew == NO_ID) return (FALSE); Go (iNew); return (TRUE); } void WalkData::Go(int iNew) { // iNew must not be iCurrent nor NO_ID int i, j, k; j = aWD[iNew].backprev; k = aWD[iNew].backnext; if (j!=NO_ID) BLink (j, k); else { aWD[k].backprev = NO_ID; if (iLast==iNew) iLast = k; else j=k; // to update iLast correctly } if (iLastUsed==iNew) iLastUsed = k; BLink (iCurrent, iNew); aWD[iNew].backnext = NO_ID; iCurrent = iNew; // update iLast if needed for (i=j; (i!=iLast) && (i!=NO_ID); i=aWD[i].backnext); if (i==iLast) iLast = j; } void WalkData::BackActive () { if (iCurrent==NO_ID) MyDLL->fn_vBackActiveMe (NULL); else MyDLL->fn_vBackActiveMe (aWD[iCurrent].ItsData); } #endif