Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1027 lines
28 KiB

// TokenC.cpp -- Implementation for class CTokenCollection
#include "StdAfx.h"
#include "TokenC.h"
#include "Memex.h"
CTokenCollection *CTokenCollection::NewTokenCollection(CTextSet **papts, UINT ctsSlots, CPersist *pPersistRelations)
{
CTokenCollection *ptc= NULL;
__try
{
ptc= New CTokenCollection();
ptc->AttachParameters(papts, ctsSlots, pPersistRelations);
}
__finally
{
if (_abnormal_termination() && ptc)
{
delete ptc; ptc= NULL;
}
}
return ptc;
}
CTokenCollection::CTokenCollection() :
#ifdef _DEBUG
CTokenList(FALSE, "TokenCollection")
#else // _DEBUG
CTokenList(FALSE)
#endif // _DEBUG
{
m_ctsSlots = 0;
m_cTokens = 0;
m_fOptions = 0;
m_patsi = NULL;
m_paiTokenStart = NULL;
m_pati = NULL;
m_pcsPrimaries = NULL;
m_pisActivePrimaries = NULL;
m_paptiSorted = NULL;
m_paptiSortedRL = NULL;
m_paptiReps = NULL;
m_paiCategoryMaps = NULL;
m_fFromFileImage = FALSE;
m_fResorted = FALSE;
}
CTokenCollection::~CTokenCollection()
{
if (m_fFromFileImage && !m_fResorted)
{
m_pRLRanking = NULL;
m_paiCategoryMaps = NULL;
}
else
{
if (m_paiCategoryMaps) VFree(m_paiCategoryMaps);
}
if (m_pati ) VFree(m_pati );
if (m_paptiSorted ) VFree(m_paptiSorted );
if (m_paptiSortedRL ) VFree(m_paptiSortedRL );
if (m_paptiReps ) VFree(m_paptiReps );
if (m_paiTokenStart ) VFree(m_paiTokenStart );
if (m_pcsPrimaries ) DetachRef(m_pcsPrimaries );
if (m_pisActivePrimaries) DetachRef(m_pisActivePrimaries);
if (m_patsi)
{
UINT c= m_ctsSlots;
for (; c--; ) if (m_patsi[c].pts) DetachRef(m_patsi[c].pts);
VFree(m_patsi);
}
}
typedef struct _TokenHashInfo
{
PTokenInfo pti;
} TokenHashInfo, *PTokenHashInfo;
typedef struct _CategoryEnvironment
{
PTokenInfo ptiLimit;
} CategoryEnvironment, *PCategoryEnvironment;
void CTokenCollection::AttachParameters(CTextSet **papts, UINT ctsSlots, CPersist *pPersistRelations)
{
if (pPersistRelations) m_fFromFileImage= TRUE;
m_patsi= (PTextSetInfo) VAlloc(TRUE, ctsSlots * sizeof(TextSetInfo));
m_ctsSlots = ctsSlots;
UINT c;
for (c= ctsSlots, m_cTokens= 0; c--; )
{
CTextSet *pts= papts[c];
if (!pts) continue;
InstallTextSet(c, pts);
m_cTokens += m_patsi[c].cd;
}
if (pPersistRelations) ReconstructRelations(pPersistRelations);
InvalidateRepresentatives();
}
typedef struct _TokenRelationHeader
{
UINT ctsSlots;
UINT cTokens;
UINT offRLRanking;
UINT offaiCategoryMaps;
} TokenRelationHeader, *PTokenRelationHeader;
void CTokenCollection::RecordRelations(CPersist *pPersistDiskImage)
{
PUINT paiTokenReps = NULL;
PUINT pcRefs = NULL;
__try
{
CTokenList::StoreImage2(pPersistDiskImage);
PTokenRelationHeader ptrh= (PTokenRelationHeader) pPersistDiskImage->ReserveTableSpace(sizeof(TokenRelationHeader));
ptrh->ctsSlots = m_ctsSlots;
ptrh->cTokens = m_cTokens;
ptrh->offRLRanking = pPersistDiskImage->NextOffset(); pPersistDiskImage->WriteDWords(m_pRLRanking, m_cd);
ptrh->offaiCategoryMaps = pPersistDiskImage->NextOffset(); pPersistDiskImage->WriteDWords(m_paiCategoryMaps, m_cTokens);
}
__finally
{
if (paiTokenReps) { VFree(paiTokenReps); paiTokenReps= NULL; }
}
}
void CTokenCollection::ReconstructRelations(CPersist *pPersistRelations)
{
BOOL fNewSortOrder= CTokenList::ConnectImage2(pPersistRelations);
// We set the PREVIOUSLY_PRESENT flag for every text set we encounter.
// That's necessary to skip the call to ReconstructCollection in InvalidateRepresentatives.
// For similar reasons we also set the PREVIOUSLY_ACTIVE flag.
UINT c= m_ctsSlots;
UINT fOptions = TOPIC_SEARCH | PHRASE_SEARCH | PHRASE_FEEDBACK | VECTOR_SEARCH;
for (; c--; )
{
if (IsPresent(c)) m_patsi[c].fFlags |= PREVIOUSLY_PRESENT;
if (IsActive(c))
{
m_patsi[c].fFlags |= PREVIOUSLY_ACTIVE;
fOptions &= GetTextSet(c)->IndexOptions();
}
}
m_fOptions= fOptions;
ASSERT(!m_pisActivePrimaries);
AttachRef(m_pisActivePrimaries, CIndicatorSet::NewIndicatorSet(RowCount(), TRUE));
// Bugbug!! m_pcsPrimaries is not used anywhere. Probably should remove it.
ASSERT(!m_pcsPrimaries);
AttachRef(m_pcsPrimaries, CCompressedSet::NewCompressedSet(m_pisActivePrimaries));
PTokenRelationHeader ptrh= (PTokenRelationHeader) pPersistRelations->ReserveTableSpace(sizeof(TokenRelationHeader));
ASSERT(m_ctsSlots == ptrh->ctsSlots && m_cTokens == ptrh->cTokens);
ASSERT(!m_paiTokenStart);
m_paiTokenStart= PUINT(VAlloc(FALSE, (m_ctsSlots + 1) * sizeof(UINT)));
ASSERT(!m_pati);
m_pati= (PTokenInfo) VAlloc(TRUE, m_cTokens * sizeof(TokenInfo));
// The code below constructs most of m_paiTokenStart and m_pati.
// The ptiCloneLink fields are set up later in the code as a function
// of m_paptiReps and m_paiCategoryMaps.
PTextSetInfo ptsi = m_patsi + m_ctsSlots;
PUINT piLimit = m_paiTokenStart + m_ctsSlots + 1;
PTokenInfo pti = m_pati + m_cTokens;
for (c= m_ctsSlots; c--; )
{
*--piLimit = pti - m_pati;
if (!(PRESENT & (--ptsi)->fFlags)) continue;
CTextSet *pts= ptsi->pts;
UINT cd = pts->DescriptorCount();
for (; cd--; )
{
(--pti)->iDescriptor = cd;
pti ->iaTSSlot = c;
}
}
*--piLimit= 0;
ASSERT(!m_pRLRanking);
m_pRLRanking= (PUINT) (pPersistRelations->LocationOf(ptrh->offRLRanking));
ASSERT(!m_paiCategoryMaps);
m_paiCategoryMaps= (PUINT) (pPersistRelations->LocationOf(ptrh->offaiCategoryMaps));
if (fNewSortOrder)
{
PUINT paiRankMap = NULL;
__try
{
paiRankMap= PUINT(VAlloc(FALSE, m_cd * sizeof(UINT)));
UINT c = m_cd;
PDESCRIPTOR *ppd = m_ppdSorted + m_cd;
// We can build a rank map because the previous ranking is
// given by m_paiCategoryMaps and the iTokenInfo DESCRIPTOR field.
for (; c--; )
paiRankMap[m_paiCategoryMaps[(*--ppd)->iTokenInfo]]= c;
PUINT pRLRanking = m_pRLRanking; m_pRLRanking = NULL;
PUINT paiCategoryMaps = m_paiCategoryMaps; m_paiCategoryMaps = NULL;
m_fResorted= TRUE; // So the destructor will deallocate
// m_pRLRanking and m_paiCategoryMaps
m_pRLRanking = PUINT(VAlloc(FALSE, m_cd * sizeof(UINT)));
m_paiCategoryMaps = PUINT(VAlloc(FALSE, m_cTokens * sizeof(UINT)));
PUINT piSrc, piDest;
for (c= m_cd, piSrc= pRLRanking, piDest= m_pRLRanking; c--; )
*piDest++ = paiRankMap[*piSrc++];
for (c= m_cTokens, piSrc= paiCategoryMaps, piDest= m_paiCategoryMaps; c--;)
*piDest++ = paiRankMap[*piSrc++];
}
__finally
{
if (paiRankMap)
{
VFree(paiRankMap); paiRankMap= NULL;
}
}
}
ASSERT(!m_paptiReps);
m_paptiReps= (PTokenInfo *) VAlloc(FALSE, m_cd * sizeof(PTokenInfo));
PTokenInfo *ppti = m_paptiReps;
PDESCRIPTOR *ppd = m_ppdSorted;
for (c= m_cd; c--; )
{
UINT iTI= (*ppd++)->iTokenInfo;
*ppti++ = m_pati + iTI;
}
// The code below constructs the Clone links from m_paptiReps and m_paiCategoryMaps.
PUINT pi;
for (pi= m_paiCategoryMaps, pti= m_pati, c= m_cTokens; c--; pti++)
{
UINT iCategory= *pi++;
PTokenInfo ptiCategory = m_pati + m_ppdSorted[iCategory]->iTokenInfo;
if (ptiCategory == pti) continue;
pti ->ptiCloneLink = ptiCategory->ptiCloneLink;
ptiCategory->ptiCloneLink = pti;
}
}
void CTokenCollection::ConstructCollection()
{
m_paiTokenStart = PUINT(VAlloc(FALSE, (m_ctsSlots + 1) * sizeof(UINT)));
m_paiCategoryMaps = PUINT(VAlloc(FALSE, m_cTokens * sizeof(UINT)));
m_pati= (PTokenInfo) VAlloc(TRUE, m_cTokens * sizeof(TokenInfo));
#ifdef _DEBUG
FillMemory(m_paiCategoryMaps, m_cTokens * sizeof(UINT), UCHAR(-1));
#endif // _DEBUG
m_paptiSorted = (PTokenInfo *) VAlloc(FALSE, m_cTokens * sizeof(PTokenInfo));
m_paptiSortedRL = (PTokenInfo *) VAlloc(FALSE, m_cTokens * sizeof(PTokenInfo));
PTextSetInfo ptsi = m_patsi + m_ctsSlots;
PUINT piLimit = m_paiTokenStart + m_ctsSlots + 1;
PTokenInfo pti = m_pati + m_cTokens;
PTokenInfo *pptiLR = m_paptiSorted + m_cTokens;
PTokenInfo *pptiRL = m_paptiSortedRL + m_cTokens;
BOOL fLCID_Initialed = FALSE;
m_lcidSorting= LCID(-1); // an invalid LCID value
for (UINT c= m_ctsSlots; c--; )
{
*--piLimit = pptiLR - m_paptiSorted;
if (!(PRESENT & (--ptsi)->fFlags)) continue;
CTextSet *pts= ptsi->pts;
if (fLCID_Initialed)
{
if (m_lcidSorting != pts->SortingLCID())
m_lcidSorting = LCID(-1);
}
else
{
m_lcidSorting= pts->SortingLCID();
fLCID_Initialed= TRUE;
}
pts->SyncIndices();
INT cbMaxToken= pts->MaxTokenWidth();
if (m_cbMaxLength < cbMaxToken) m_cbMaxLength= cbMaxToken;
UINT cd = pts->DescriptorCount();
PTokenInfo ptiBase = pti -= cd;
PDESCRIPTOR *ppd = pts->m_ppdSorted + cd;
PDESCRIPTOR pdBase = pts->DescriptorBase();
// In the loop below note the tricky code which sets up the
// token info elements to be in the same sequence as the
// descriptors in the source text set.
PDESCRIPTOR *ppdRL = pts->m_ppdTailSorted + cd;
for (; cd--; )
{
PDESCRIPTOR pd= *--ppd;
PTokenInfo ptiTarget= ptiBase + (pd - pdBase);
ptiTarget->pd = pd;
ptiTarget->iRank = cd;
*--pptiLR = ptiTarget;
ASSERT( cd + 1 == pts->DescriptorCount()
|| 0 >= CompareImagesLR(ppd, ppd + 1)
);
*--pptiRL = ptiBase + (*--ppdRL - pdBase);
ASSERT( cd + 1 == pts->DescriptorCount()
|| 0 >= CompareImagesRL(ppdRL, ppdRL + 1)
);
}
#ifdef _DEBUG
PTokenInfo ptiDebug= ptiBase;
PTokenInfo *pptiLRDebug = pptiLR;
PTokenInfo *pptiRLDebug = pptiRL;
for (cd=pts->DescriptorCount();
cd--;
++ptiDebug, ++pptiLRDebug, ++pptiRLDebug
)
{
ASSERT(ptiDebug - ptiBase == ptiDebug->pd - pdBase);
ASSERT(!cd || 0 >= CompareTokenInfoRLI(pptiRLDebug, pptiRLDebug + 1));
ASSERT(!cd || 0 >= CompareTokenInfo (pptiLRDebug, pptiLRDebug + 1));
}
#endif // _DEBUG
}
*--piLimit= 0;
PTokenInfo *pptiResult= NULL;
__try
{
CombineTokenLists(m_paptiSortedRL, m_paiTokenStart, m_ctsSlots, &pptiResult, &c, CompareTokenInfoRLI);
#ifdef _DEBUG
{
for (int c=m_ctsSlots; --c > 0 ; )
ASSERT(0 >= CompareTokenInfoRLI(m_paptiSortedRL + c - 1, m_paptiSortedRL + c));
}
#endif // _DEBUG
ASSERT(c == m_cTokens);
if (m_paptiSortedRL != pptiResult)
{
VFree(m_paptiSortedRL);
m_paptiSortedRL= pptiResult;
}
pptiResult= NULL;
CombineTokenLists(m_paptiSorted, m_paiTokenStart, m_ctsSlots, &pptiResult, &c);
#ifdef _DEBUG
{
for (int c=m_ctsSlots; --c > 0 ; )
ASSERT(0 >= CompareTokenInfo(m_paptiSorted + c - 1, m_paptiSorted + c));
}
#endif // _DEBUG
ASSERT(c == m_cTokens);
if (m_paptiSorted != pptiResult)
{
VFree(m_paptiSorted);
m_paptiSorted= pptiResult;
}
pptiResult= NULL;
}
__finally
{
if (pptiResult && pptiResult != m_paptiSorted && pptiResult != m_paptiSortedRL)
{
VFree(pptiResult); pptiResult= NULL;
}
}
if (m_pcsPrimaries) DetachRef(m_pcsPrimaries);
}
void CTokenCollection::ReconstructCollection()
{
if (!m_pati) { ConstructCollection(); return; }
ASSERT(FALSE); // Collection Change to be completed...
}
void CTokenCollection::ConstructRepresentatives()
{
ASSERT(!m_pcsPrimaries);
// This routine was written assuming we'll be adding and removing
// text sets frequently. Actually the current implementation creates
// the collection once and doesn't alter it thereafter. So we'll
// change these deallocations to assertions.
ASSERT(!m_paptiReps );
ASSERT(!m_ppdSorted );
ASSERT(!m_ppdTailSorted );
ASSERT(!m_pafClassifications);
m_clsf.Initial;
UINT c;
PTokenInfo *ppti;
for (c= m_cTokens, ppti= m_paptiSorted + c; c--; ) (*--ppti)->iRank= c;
CSegHashTable *psht = NULL;
CAValRef *pavr = NULL;
CIndicatorSet *pis = NULL;
__try
{
psht= CSegHashTable::NewSegHashTable(sizeof(TokenHashInfo), sizeof(PVOID));
pavr= CAValRef::NewValRef(C_VALREF_SLOTS);
CategoryEnvironment catenv;
PTokenInfo pti;
// The loop below processes token entries against a hash table to
// construct a set of clone chains. Entries within a single chain
// have the same display image.
for (c= m_cTokens, pti= m_pati + c; c; )
{
UINT cChunk= C_VALREF_SLOTS;
if (cChunk > c) cChunk= c;
c -= cChunk;
pavr->DiscardRefs();
catenv.ptiLimit = pti;
for (; cChunk--; )
{
PDESCRIPTOR pd= (--pti)->pd;
UINT cw= CbImage(pd);
pavr->AddWCRef(pd->pbImage, cw);
}
psht->Assimilate(pavr, &catenv, MergeTokenCategory, AddTokenCategory);
}
delete pavr; pavr= NULL;
// Now we'll construct pis so that it marks the head entry for each of
// the clone chains.
AttachRef(pis, CIndicatorSet::NewIndicatorSet(m_cTokens));
psht->ForEach(pis, IndicatePrimaryClones);
pis->InvalidateCache();
// Here we store a compressed form of the clone mask.
AttachRef(m_pcsPrimaries, CCompressedSet::NewCompressedSet(pis));
}
__finally
{
delete psht; psht= NULL;
if (_abnormal_termination())
{
if (pavr) { delete pavr; pavr= NULL; }
if (pis ) DetachRef(pis);
}
}
PWCHAR pwDispImages = NULL;
PDESCRIPTOR pdTokenReps = NULL;
PUINT paiReps = NULL;
PUINT paiRanks = NULL;
PDESCRIPTOR *ppdSortRLOrder = NULL;
UINT cwDisplayTotal = 0;
// The number of 1's in pis tells us how many unique display images
// we have.
UINT cd= pis->SelectionCount();
__try
{
// Now we can begin to construct the component information for our
// parent token set. First we'll construct the array of descriptors
// and their right-to-left sorting order. As a byproduct we'll also
// calculate the space required for the unique display images.
// Here we're converting the bit mask (pis) into a sequence of
// array indices (paiReps).
paiReps = PUINT(VAlloc(FALSE, cd * sizeof(UINT)));
pis->MarkedItems(0, PINT(paiReps), cd);
PDESCRIPTOR *ppd, pdNext;
PUINT pi;
pdTokenReps = (PDESCRIPTOR ) VAlloc(FALSE, (cd+1) * sizeof( DESCRIPTOR));
for (pi= paiReps, pdNext= pdTokenReps, c= cd; c--; )
{
PTokenInfo pti = m_paptiSorted[*pi++];
PDESCRIPTOR pd = pti->pd;
*pdNext = *pd;
UINT cw= CwDisplay(pd);
pdNext->cwDisplay = cw;
pdNext->iTokenInfo = pti - m_pati;
cwDisplayTotal += CwDisplay(pd);
// We keep the new pd address in pdAux rather than
// overwriting pd because we'll need the old pd value
// later to map to an iDescriptor value relative to the
// text set for this token entry.
pti->pdAux= pdNext++;
}
// Here we're allocating space for the unique display images and
// copying those images from the text sets.
pwDispImages = PWCHAR(VAlloc(FALSE, cwDisplayTotal * sizeof(WCHAR)));
PWCHAR pwc;
for (pwc= pwDispImages, pdNext= pdTokenReps, c= cd; c--; pdNext++)
{
CopyMemory(pwc, pdNext->pwDisplay, pdNext->cwDisplay * sizeof(WCHAR));
pdNext->pwDisplay = pwc;
pwc += pdNext->cwDisplay;
}
// The last descriptor entry must point just beyond the end of the
// display images.
pdNext->pwDisplay= pwc;
ppdSortRLOrder = (PDESCRIPTOR *) VAlloc(FALSE, cd * sizeof(PDESCRIPTOR));
for (ppd= ppdSortRLOrder, c= m_cTokens, ppti= m_paptiSortedRL;
c--;
)
{
PTokenInfo pti= *ppti++;
if (pis->IsBitSet(pti->iRank)) *ppd++ = pti->pdAux;
}
DetachRef(pis);
// We'll also construct a sort ordering (m_paptiReps) for the tokens that head
// the clone lists.
m_paptiReps= (PTokenInfo *) VAlloc(FALSE, cd * sizeof(PTokenInfo));
ASSERT(sizeof(UINT) == sizeof(PDESCRIPTOR));
// Notice that we use aliasing to treat paiReps as an array of UINTs and
// as an array of PDESCRIPTOR * values.
ppd= (PDESCRIPTOR *) paiReps;
// The paiRanks array is used to construct the RL Rankings below
paiRanks= PUINT(VAlloc(FALSE, m_cTokens * sizeof(UINT)));
FillMemory(paiRanks, m_cTokens * sizeof(UINT), UCHAR(-1));
for (pi= paiReps, c= cd, ppti= m_paptiReps; c--; )
{
PTokenInfo pti;
*ppti++ = pti = m_paptiSorted[*pi++];
*ppd ++ = pti->pdAux;
paiRanks[pti - m_pati]= cd - c - 1;
}
}
__finally
{
if (_abnormal_termination())
{
if (pwDispImages ) { VFree(pwDispImages ); pwDispImages = NULL; }
if (pdTokenReps ) { VFree(pdTokenReps ); pdTokenReps = NULL; }
if (paiReps ) { VFree(paiReps ); paiReps = NULL; }
if (ppdSortRLOrder) { VFree(ppdSortRLOrder); ppdSortRLOrder = NULL; }
if (paiRanks ) { VFree(paiRanks ); paiRanks = NULL; }
}
}
__try
{
InitialTokenList(pwDispImages, cwDisplayTotal, pdTokenReps, cd,
m_lcidSorting, NULL, 0, (PDESCRIPTOR *)paiReps,
ppdSortRLOrder
);
m_pRLRanking= (PUINT) VAlloc(FALSE, m_cd * sizeof(UINT));
UINT cd2;
for (cd2= cd, c= m_cTokens, ppti= m_paptiSortedRL + m_cTokens; c--; )
{
PTokenInfo pti= *--ppti;
INT iRank= (INT) paiRanks[pti - m_pati];
if (iRank >= 0)
m_pRLRanking[--cd2]= UINT(iRank);
}
}
__finally
{
ASSERT(paiRanks);
VFree(paiRanks); paiRanks= NULL;
}
PTextSetInfo ptsi;
PTokenInfo pti;
for (ptsi= m_patsi + m_ctsSlots, pti= m_pati + m_cTokens, c= m_ctsSlots; c--; )
{
if (!(PRESENT & (--ptsi)->fFlags)) continue;
CTextSet *pts= ptsi->pts;
PDESCRIPTOR pdBase = pts->DescriptorBase ();
UINT cd = pts->DescriptorCount();
for (; cd--; )
{
(--pti)->iaTSSlot = c;
pti ->iDescriptor = pti->pd - pdBase;
}
}
for (c= m_cd, ppti= m_paptiReps; c--; )
{
PTokenInfo pti= *ppti++;
UINT iCategory= m_cd - c - 1;
for (; pti; pti= pti->ptiCloneLink)
m_paiCategoryMaps[pti->iDescriptor + m_paiTokenStart[pti->iaTSSlot]]= iCategory;
}
}
void CTokenCollection::ReconstructRepresentatives()
{
if (!m_pcsPrimaries) ConstructRepresentatives();
ChangeRef(m_pisActivePrimaries, CIndicatorSet::NewIndicatorSet(m_cd));
PTokenInfo *ppti= m_paptiReps;
UINT c= m_cd;
for (; c--; )
{
UINT iSlot= ppti - m_paptiReps;
PTokenInfo pti= *ppti++;
for (; pti; pti= pti->ptiCloneLink)
{
if ((m_patsi[pti->iaTSSlot].fFlags & ACTIVE))
{
m_pisActivePrimaries->RawSetBit(iSlot);
break;
}
}
}
m_pisActivePrimaries->InvalidateCache();
}
BOOL CTokenCollection::InvalidateRepresentatives()
{
UINT fChanges = 0;
UINT fOptions = TOPIC_SEARCH | PHRASE_SEARCH | PHRASE_FEEDBACK | VECTOR_SEARCH;
UINT c;
#ifdef _DEBUG
UINT cTokens = 0;
#endif // _DEBUG
for (c= m_ctsSlots; c--; )
{
UINT fFlags= m_patsi[c].fFlags;
ASSERT((fFlags & (PRESENT | ACTIVE)) != ACTIVE);
#ifdef _DEBUG
if (fFlags & PRESENT) cTokens += m_patsi[c].cd;
#endif // _DEBUG
if (fFlags & ACTIVE) fOptions &= GetTextSet(c)->IndexOptions();
fChanges |= (fFlags & CURRENT_STATE) ^ ((fFlags & PREVIOUS_STATE) >> TIME_SHIFT);
}
if (!fChanges)
{
ASSERT(m_cTokens == cTokens );
ASSERT(m_fOptions == fOptions);
return TRUE;
}
m_fOptions= fOptions;
if (fChanges & PRESENT) ReconstructCollection();
if (fChanges & ACTIVE || !m_pcsPrimaries) ReconstructRepresentatives();
PTextSetInfo ptsi= m_patsi;
for (c= m_ctsSlots; c--; ++ptsi)
{
UINT fOptions= ptsi->fFlags & (PRESENT | ACTIVE);
ptsi->fFlags &= ~(PRESENT | ACTIVE | PREVIOUSLY_PRESENT | PREVIOUSLY_ACTIVE);
ptsi->fFlags |= fOptions | (fOptions << TIME_SHIFT);
}
return TRUE;
}
const UINT *CTokenCollection::LRRanking()
{
ASSERT(FALSE); // Shouldn't be called!
return NULL;
}
const UINT *CTokenCollection::RLRanking()
{
ASSERT(m_pRLRanking);
return m_pRLRanking;
}
void CTokenCollection::CombineTokenLists(PTokenInfo *paptiSets, PUINT paiTokenStarts, UINT ctiSets,
PTokenInfo **ppptiSorted, PUINT pcti,
PCompareImages pfnCompareImages
)
{
PTokenInfo *paptiSortedLeft = NULL,
*paptiSortedRight = NULL;
PTokenInfo *paptiSortedResult= NULL;
UINT cFirst = 0;
UINT cSecond = 0;
__try
{
if (ctiSets == 1)
{
*ppptiSorted = paptiSets + *paiTokenStarts;
*pcti = *(paiTokenStarts + 1) - *paiTokenStarts;
__leave;
}
UINT ctiLeft = 0,
ctiRight = 0;
cFirst = ctiSets / 2;
cSecond = ctiSets - cFirst;
CombineTokenLists(paptiSets, paiTokenStarts, cFirst, &paptiSortedLeft, &ctiLeft, pfnCompareImages);
CombineTokenLists(paptiSets, paiTokenStarts + cFirst, cSecond, &paptiSortedRight, &ctiRight, pfnCompareImages);
UINT ctiResult= ctiLeft + ctiRight;
paptiSortedResult= (PTokenInfo *) VAlloc(FALSE, ctiResult * sizeof(PTokenInfo));
MergeImageRefSets((PVOID *) paptiSortedResult, ctiResult,
(PVOID *) paptiSortedLeft, ctiLeft,
(PVOID *) paptiSortedRight, ctiRight,
pfnCompareImages
);
#ifdef _DEBUG
{
for (int c=ctiResult; --c > 0 ; )
ASSERT(0 >= pfnCompareImages(paptiSortedResult + c - 1, paptiSortedResult + c));
}
#endif // _DEBUG
*ppptiSorted = paptiSortedResult; paptiSortedResult= NULL;
*pcti = ctiResult;
}
__finally
{
if (paptiSortedLeft && cFirst > 1) { VFree(paptiSortedLeft ); paptiSortedLeft = NULL; }
if (paptiSortedRight && cSecond > 1) { VFree(paptiSortedRight); paptiSortedRight = NULL; }
if (_abnormal_termination() && paptiSortedResult)
{
VFree(paptiSortedResult); paptiSortedResult = NULL;
}
}
}
int __cdecl CTokenCollection::CompareTokenInfo(const void *pvL, const void *pvR)
{
return CompareImagesLR(&(*(const TokenInfo **) pvL)->pd, &(*(const TokenInfo **) pvR)->pd);
}
int __cdecl CTokenCollection::CompareTokenInfoRLI(const void *pvL, const void *pvR)
{
return CompareImagesRL(&(*(const TokenInfo **) pvL)->pd, &(*(const TokenInfo **) pvR)->pd);
}
void CTokenCollection::MergeTokenCategory(UINT iValue, PVOID pvTag, PVOID pvEnvironment)
{
PCategoryEnvironment pcatenv= PCategoryEnvironment(pvEnvironment);
PTokenHashInfo pthi = PTokenHashInfo (pvTag );
PTokenInfo ptiNew = pcatenv->ptiLimit - (iValue + 1);
PTokenInfo ptiOld = pthi ->pti;
ASSERT(ptiNew != ptiOld);
if (ptiNew < ptiOld)
{
ptiNew->ptiCloneLink = ptiOld;
pthi ->pti = ptiNew;
}
else
{
ptiNew->ptiCloneLink = ptiOld->ptiCloneLink;
ptiOld->ptiCloneLink = ptiNew;
}
}
void CTokenCollection::AddTokenCategory(UINT iValue, PVOID pvTag, PVOID pvEnvironment)
{
PCategoryEnvironment pcatenv= PCategoryEnvironment(pvEnvironment);
PTokenHashInfo pthi = PTokenHashInfo (pvTag );
PTokenInfo ptiNew = pcatenv->ptiLimit - (iValue + 1);
ptiNew->ptiCloneLink= NULL;
pthi->pti= ptiNew;
}
void CTokenCollection::IndicatePrimaryClones(PVOID pvTag, PVOID pvEnvironment)
{
CIndicatorSet *pis = (CIndicatorSet *) pvEnvironment;
PTokenHashInfo pthi = PTokenHashInfo(pvTag);
pis->RawSetBit(pthi->pti->iRank);
}
UINT CTokenCollection::MapToTokenLists(CIndicatorSet * pisTokenReps, PTokenInfo *paptiLists, UINT cLists)
{
ASSERT(cLists >= m_ctsSlots);
PUINT paiBuffer = NULL;
UINT cTokens = 0;
__try
{
UINT cReps= pisTokenReps? pisTokenReps->SelectionCount() : m_cd;
UINT cChunk= C_INDICES_CHUNK;
if (cChunk > cReps) cChunk= cReps;
paiBuffer= PUINT(VAlloc(FALSE, cChunk * sizeof(UINT)));
ASSERT(paiBuffer);
ZeroMemory(paptiLists, cLists * sizeof(PTokenInfo));
UINT iRepFirst;
for (iRepFirst= 0; cReps; iRepFirst += cChunk, cReps -= cChunk)
{
if (cChunk > cReps) cChunk= cReps;
UINT c, i;
PUINT pi;
if (pisTokenReps) pisTokenReps->MarkedItems(iRepFirst, PINT(paiBuffer), cChunk);
else
for (i= iRepFirst, c= cChunk, pi= paiBuffer; c--; ) *pi++ = i++;
for (c= cChunk, pi= paiBuffer + cChunk; c--; )
{
PTokenInfo pti= m_pati + m_ppdSorted[*--pi]->iTokenInfo;
for (; pti; pti= pti->ptiCloneLink)
{
UINT iSlot= pti->iaTSSlot;
ASSERT(m_patsi[iSlot].fFlags & PRESENT);
if (!(ACTIVE & m_patsi[iSlot].fFlags)) continue;
++cTokens;
pti->ptiTextSetLink= paptiLists[iSlot];
paptiLists[iSlot]= pti;
}
}
}
}
__finally
{
if (paiBuffer) { VFree(paiBuffer); paiBuffer = NULL; }
}
return cTokens;
}