NT4/private/windows/win4help/ftsrch/titlec.cpp
2020-09-30 17:12:29 +02:00

607 lines
17 KiB
C++

// TitleC.cpp -- Implementation for class CTitleCollection
#include "StdAfx.h"
#include "TextSet.h"
#include "Tokens.h"
#include "TitleC.h"
#include "Memex.h"
CTitleCollection *CTitleCollection::NewTitleCollection(CTextSet **papts, UINT ctsSlots, CPersist *pPersistRelations)
{
CTitleCollection *ptc= NULL;
__try
{
ptc= New CTitleCollection();
ptc->AttachParameters(papts, ctsSlots, pPersistRelations);
}
__finally
{
if (_abnormal_termination() && ptc)
{
delete ptc; ptc= NULL;
}
}
return ptc;
}
CTitleCollection::CTitleCollection() :
#ifdef _DEBUG
CTokenList(FALSE, "TitleCollection")
#else // _DEBUG
CTokenList(FALSE)
#endif // _DEBUG
{
m_ctsSlots = 0;
m_cTitles = 0;
m_patsi = NULL;
m_paiTitleStart = NULL;
m_pati = NULL;
m_paptiSorted = NULL;
m_paiCategoryMaps = NULL;
m_pisActiveTitles = NULL;
m_fFromFile = FALSE;
}
CTitleCollection::~CTitleCollection()
{
if (m_pati ) VFree(m_pati );
if (m_paptiSorted ) VFree(m_paptiSorted );
if (m_paiTitleStart ) VFree(m_paiTitleStart );
if (m_paiCategoryMaps) VFree(m_paiCategoryMaps);
if (m_pisActiveTitles) DetachRef(m_pisActiveTitles);
if (m_patsi)
{
UINT c= m_ctsSlots;
for (; c--; ) if (m_patsi[c].pts) DetachRef(m_patsi[c].pts);
VFree(m_patsi);
}
}
void CTitleCollection::AttachParameters(CTextSet **papts, UINT ctsSlots, CPersist *pPersistRelations)
{
m_fFromFile= BOOL(pPersistRelations);
m_patsi= (PTextSetInfo) VAlloc(TRUE, ctsSlots * sizeof(TextSetInfo));
m_ctsSlots = ctsSlots;
UINT c;
for (c= ctsSlots; c--; )
{
CTextSet *pts= papts[c];
if (!pts) continue;
InstallTextSet(c, pts);
}
if (m_fFromFile) ReconstructRelations(pPersistRelations);
InvalidateRepresentatives(pPersistRelations);
}
typedef struct _TitleRelationHeader
{
UINT ctsSlots;
UINT cTitles;
} TitleRelationHeader, *PTitleRelationHeader;
void CTitleCollection::ReconstructRelations(CPersist *pPersistRelations)
{
CTokenList::ConnectImage2(pPersistRelations, TRUE);
// 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;
for (; c--; )
{
if (IsPresent(c)) m_patsi[c].fFlags |= PREVIOUSLY_PRESENT;
if (IsActive (c)) m_patsi[c].fFlags |= PREVIOUSLY_ACTIVE;
}
ASSERT(!m_pisActiveTitles);
AttachRef(m_pisActiveTitles, CIndicatorSet::NewIndicatorSet(m_cd, TRUE));
BuildTitleStarts();
PTitleRelationHeader ptrh= PTitleRelationHeader(pPersistRelations->ReserveTableSpace(sizeof(TitleRelationHeader)));
ASSERT(m_ctsSlots == ptrh->ctsSlots && m_cTitles == ptrh->cTitles);
m_paiCategoryMaps = PUINT(VAlloc(FALSE, m_cTitles * sizeof(UINT)));
PDESCRIPTOR *ppd;
for (c= m_cd, ppd= m_ppdSorted + m_cd; c--; )
m_paiCategoryMaps[*--ppd - m_pd] = c;
m_pati= (PTitleInfo) VAlloc(TRUE, m_cTitles * sizeof(TitleInfo));
PTitleInfo pti = m_pati + m_cTitles;
PTextSetInfo ptsi;
for (ptsi= m_patsi + m_ctsSlots, c= m_ctsSlots; c--; )
{
if (!(PRESENT & (--ptsi)->fFlags)) continue;
CTextSet *pts = ptsi->pts;
CTokenList *ptl = pts->TitleList();
UINT cd = pts->TopicCount();
for (; cd--; )
{
(--pti)->iaTSSlot = c;
pti ->iPartition = cd;
}
}
}
void CTitleCollection::BuildTitleStarts()
{
m_paiTitleStart= PUINT(VAlloc(FALSE, (m_ctsSlots + 1) * sizeof(UINT)));
PUINT piStart = m_paiTitleStart;
PTextSetInfo ptsi = m_patsi;
UINT c = m_ctsSlots;
for (m_cTitles= 0, *piStart++= 0; c--; ptsi++)
{
if (ptsi->fFlags & PRESENT)
m_cTitles += ptsi->cd;
*piStart++= m_cTitles;
}
}
void CTitleCollection::ConstructCollection()
{
BuildTitleStarts();
m_pati= (PTitleInfo) VAlloc(TRUE, m_cTitles * sizeof(TitleInfo));
m_paptiSorted= (PTitleInfo *) VAlloc(FALSE, m_cTitles * sizeof(PTitleInfo));
PTitleInfo pti = m_pati + m_cTitles;
PTitleInfo *ppti = m_paptiSorted + m_cTitles;
m_lcidSorting = LCID(-1); // an invalid LCID value
BOOL fLCID_Initialed = FALSE;
PTextSetInfo ptsi;
UINT c;
for (ptsi= m_patsi + m_ctsSlots, c= m_ctsSlots; c--; )
{
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();
CTokenList *ptl= pts->TitleList();
INT cbMaxTitle= ptl->MaxWidthToken();
if (cbMaxTitle > m_cbMaxLength) m_cbMaxLength= cbMaxTitle;
UINT cd = ptl->m_cd;
PDESCRIPTOR *ppd = ptl->m_ppdSorted + cd;
PTitleInfo ptiBase = pti -= cd;
PDESCRIPTOR pdBase = ptl->m_pd;
for (; cd--; )
{
PDESCRIPTOR pd = *--ppd;
UINT iPartition = pd - pdBase;
PTitleInfo ptiTarget = ptiBase + iPartition;
ptiTarget->pd= pd;
ptiTarget->iaTSSlot = c;
ptiTarget->iPartition = iPartition;
*--ppti= ptiTarget;
}
}
CombineTitleLists(m_paptiSorted, m_paiTitleStart, m_ctsSlots, &ppti, &c);
ASSERT(c == m_cTitles);
if (m_ctsSlots > 1)
{
VFree(m_paptiSorted);
m_paptiSorted= ppti;
}
if (m_paiCategoryMaps)
{
VFree(m_paiCategoryMaps);
m_paiCategoryMaps= NULL;
}
}
BOOL CTitleCollection::InvalidateRepresentatives(CPersist *pPersistRelations)
{
UINT fChanges = 0;
UINT c;
for (c= m_ctsSlots; c--; )
{
UINT fFlags= m_patsi[c].fFlags;
ASSERT((fFlags & (PRESENT | ACTIVE)) != ACTIVE);
fChanges |= (fFlags & CURRENT_STATE) ^ ((fFlags & PREVIOUS_STATE) >> TIME_SHIFT);
}
if (!fChanges) return TRUE;
if (fChanges & PRESENT) ReconstructCollection();
if (fChanges & ACTIVE || !m_paiCategoryMaps) 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;
}
void CTitleCollection::ReconstructCollection()
{
if (!m_pati) { ConstructCollection(); return; }
ASSERT(FALSE); // Collection Change to be completed...
}
void CTitleCollection::ConstructRepresentatives()
{
ASSERT(!m_paiCategoryMaps);
UINT c = m_ctsSlots;
PTextSetInfo ptsi = m_patsi;
PTitleInfo *ppti;
UINT cwcDisplayImages = 0;
UINT cwcSortKeyImages = 0;
for (c= m_cTitles, ppti= m_paptiSorted; c--; )
{
PDESCRIPTOR pd = (*ppti++)->pd;
cwcDisplayImages += CwDisplay(pd);
cwcSortKeyImages += CbImage (pd);
}
PWCHAR pwcDisplayImages = NULL;
PWCHAR pwcSortKeyImages = NULL;
PDESCRIPTOR pdTitles = NULL;
PDESCRIPTOR *ppdSortedTitles = NULL;
__try
{
ValidateHeap();
pdTitles = PDESCRIPTOR (VAlloc(FALSE, (m_cTitles+1) * sizeof(DESCRIPTOR )));
ppdSortedTitles = (PDESCRIPTOR *) VAlloc(FALSE, m_cTitles * sizeof(PDESCRIPTOR));
pwcDisplayImages = PWCHAR(VAlloc(FALSE, cwcDisplayImages * sizeof(WCHAR)));
pwcSortKeyImages = PWCHAR(VAlloc(FALSE, cwcSortKeyImages * sizeof(WCHAR)));
ValidateHeap();
PWCHAR pwcDisplay = pwcDisplayImages;
PWCHAR pwcSortKey = pwcSortKeyImages;
PDESCRIPTOR pd;
PDESCRIPTOR *ppd;
PTitleInfo pti;
for (c= m_cTitles, pti= m_pati, pd= pdTitles; c--; pti++, pd++)
{
PDESCRIPTOR pdTS = pti->pd;
pti->pd = pd;
*pd = *pdTS;
UINT cwcDisplay = CwDisplay(pdTS);
UINT cwcSortKey = CbImage (pdTS);
pd->iTextSet = pti->iaTSSlot;
pd->pwDisplay = pwcDisplay;
pd->pbImage = pwcSortKey;
CopyMemory(pwcDisplay, pdTS->pwDisplay, cwcDisplay * sizeof(WCHAR));
CopyMemory(pwcSortKey, pdTS->pbImage , cwcSortKey * sizeof(WCHAR));
pwcDisplay += cwcDisplay;
pwcSortKey += cwcSortKey;
}
ValidateHeap();
pd->pwDisplay = pwcDisplay; // To set a limit on the length of the last display image.
pd->pbImage = pwcSortKey; // To set a limit on the length of the last sort key.
ValidateHeap();
m_paiCategoryMaps = (PUINT) VAlloc(FALSE, m_cTitles * sizeof(UINT));
#ifdef _DEBUG
FillMemory(m_paiCategoryMaps, m_cTitles * sizeof(UINT), UCHAR(-1));
#endif // _DEBUG
for (c= m_cTitles, ppd= ppdSortedTitles + m_cTitles, ppti= m_paptiSorted + m_cTitles; c--; )
{
PDESCRIPTOR pd = (*--ppti)->pd;
*--ppd = pd;
m_paiCategoryMaps[pd - pdTitles] = c;
}
ValidateHeap();
}
__finally
{
if (_abnormal_termination())
{
if(pwcDisplayImages) { VFree(pwcDisplayImages); pwcDisplayImages = NULL; }
if(pwcSortKeyImages) { VFree(pwcSortKeyImages); pwcSortKeyImages = NULL; }
if(pdTitles ) { VFree(pdTitles ); pdTitles = NULL; }
if(ppdSortedTitles ) { VFree(ppdSortedTitles ); ppdSortedTitles = NULL; }
}
}
InitialTokenList(pwcDisplayImages, cwcDisplayImages, pdTitles,
m_cTitles, m_lcidSorting, pwcSortKeyImages, cwcSortKeyImages,
ppdSortedTitles, NULL
);
NotifyViewers (ShapeChange);
NotifyInterface(ShapeChange);
}
void CTitleCollection::ReconstructRepresentatives()
{
if (!m_paiCategoryMaps) ConstructRepresentatives();
ChangeRef(m_pisActiveTitles, CIndicatorSet::NewIndicatorSet(m_cd));
PDESCRIPTOR *ppd;
UINT c;
for (c= m_cd, ppd= m_ppdSorted + m_cd; c--; )
{
if ((m_patsi[(*--ppd)->iTextSet].fFlags & ACTIVE))
m_pisActiveTitles->RawSetBit(c);
}
m_pisActiveTitles->InvalidateCache();
}
#if 0
WORD auCredits[] =
{
0x2d30, 0x4420, 0x7665, 0x6c65, 0x706f, 0x656d, 0x746e, 0x5420, 0x6165,
0x206d, 0x002d, 0x5231, 0x6e6f, 0x4d20, 0x7275, 0x6172, 0x0079, 0x5231,
0x646f, 0x656e, 0x2079, 0x6f4b, 0x6e72, 0x3100, 0x6952, 0x6863, 0x7261,
0x2064, 0x614b, 0x7a74, 0x3100, 0x6f4a, 0x6e68, 0x4820, 0x6c61, 0x006c,
0x4b31, 0x6972, 0x6873, 0x616e, 0x4e20, 0x7261, 0x6465, 0x7964, 0x3100,
0x6152, 0x706c, 0x2068, 0x6157, 0x646c, 0x6e65, 0x3100, 0x794c, 0x6e6e,
0x4220, 0x6f72, 0x6e77, 0x6c65, 0x006c, 0x4d31, 0x6369, 0x6168, 0x6c65,
0x4620, 0x202e, 0x2e43, 0x4320, 0x6972, 0x6b63, 0x3100, 0x0020, 0x0032,
0x2d30, 0x5520, 0x6573, 0x2072, 0x6e49, 0x6574, 0x6672, 0x6361, 0x2065,
0x6544, 0x6973, 0x6e67, 0x2d20, 0x3100, 0x6f52, 0x206e, 0x754d, 0x7272,
0x7961, 0x3100, 0x6f52, 0x6e64, 0x7965, 0x4b20, 0x726f, 0x006e, 0x4731,
0x7961, 0x656c, 0x5020, 0x6369, 0x656b, 0x006e, 0x4931, 0x6572, 0x656e,
0x5020, 0x7361, 0x6574, 0x6e72, 0x6361, 0x006b, 0x5431, 0x6d61, 0x2069,
0x6542, 0x7475, 0x6c65, 0x3100, 0x7553, 0x617a, 0x206e, 0x614d, 0x6172,
0x6873, 0x0069, 0x4b31, 0x6e65, 0x2074, 0x7553, 0x6c6c, 0x7669, 0x6e61,
0x3100, 0x6550, 0x7274, 0x2061, 0x6f48, 0x6666, 0x616d, 0x006e, 0x4a31,
0x6e61, 0x2065, 0x6144, 0x6c69, 0x7965, 0x3100, 0x0020, 0x0032, 0x2d30,
0x4720, 0x6f6c, 0x6162, 0x696c, 0x617a, 0x6974, 0x6e6f, 0x2d20, 0x3100,
0x6f52, 0x206e, 0x754d, 0x7272, 0x7961, 0x3100, 0x6952, 0x6863, 0x7261,
0x2064, 0x614b, 0x7a74, 0x3100, 0x7341, 0x756d, 0x2073, 0x7246, 0x7965,
0x6174, 0x0067, 0x2031, 0x6120, 0x616b, 0x4420, 0x2e72, 0x5520, 0x696e,
0x6f63, 0x6564, 0x3100, 0x6f4c, 0x6972, 0x4820, 0x656f, 0x7472, 0x0068,
0x4331, 0x7461, 0x6568, 0x6972, 0x656e, 0x5720, 0x7369, 0x6973, 0x6b6e,
0x3100, 0x2e4b, 0x4420, 0x202e, 0x6843, 0x6e61, 0x0067, 0x2031, 0x3200,
0x3000, 0x202d, 0x6554, 0x7473, 0x6e69, 0x2067, 0x002d, 0x5431, 0x6d69,
0x4c20, 0x7765, 0x7369, 0x3100, 0x6152, 0x646e, 0x6c61, 0x206c, 0x7453,
0x6d69, 0x7370, 0x6e6f, 0x3100, 0x0020, 0x0032, 0x2d30, 0x4220, 0x7275,
0x6165, 0x6375, 0x6172, 0x7963, 0x4320, 0x6e6f, 0x7274, 0x6c6f, 0x2d20,
0x3100, 0x614d, 0x6972, 0x6e6f, 0x4820, 0x676f, 0x6e61, 0x3100, 0x694e,
0x6f63, 0x656c, 0x4d20, 0x7469, 0x6b73, 0x676f, 0x3100, 0x6952, 0x6b63,
0x5320, 0x6765, 0x6c61, 0x3100, 0x6154, 0x6d6d, 0x2079, 0x7453, 0x6565,
0x656c, 0x3100, 0x0020, 0x0032, 0x2d30, 0x5320, 0x6570, 0x6963, 0x6c61,
0x5420, 0x6168, 0x6b6e, 0x2073, 0x002d, 0x4331, 0x7268, 0x7369, 0x4d20,
0x7275, 0x6172, 0x2079, 0x3100, 0x6c45, 0x7a69, 0x6261, 0x7465, 0x2068,
0x6f4b, 0x6e72, 0x3100, 0x694c, 0x206e, 0x7548, 0x6e61, 0x0067, 0x5331,
0x7269, 0x7369, 0x6168, 0x4420, 0x6e6f, 0x6974, 0x6572, 0x6464, 0x0079,
0x2031, 0x3200, 0x0000, 0x6e45, 0x2064, 0x666f, 0x6420, 0x7461, 0x0061,
0x0000
};
UINT cnCode = 0;
UINT cbData = sizeof(auCredits);
UINT offData = 0;
#endif // 0
void CTitleCollection::RecordRelations(CPersist *pPersistDiskImage)
{
PUINT paiPermute= NULL;
CTokenList::StoreImage2(pPersistDiskImage, TRUE);
PTitleRelationHeader ptrh= (PTitleRelationHeader) (pPersistDiskImage->ReserveTableSpace(sizeof(TitleRelationHeader)));
ptrh->ctsSlots = m_ctsSlots;
ptrh->cTitles = m_cTitles;
#if 0
offData = pPersistDiskImage->NextOffset();
cnCode = pPersistDiskImage->Encode(PBYTE(auCredits), cbData);
#endif // 0
}
void CTitleCollection::CombineTitleLists(PTitleInfo *paptiSets, PUINT paiTitleStarts, UINT ctiSets,
PTitleInfo **ppptiSorted, PUINT pcti
)
{
PTitleInfo *paptiSortedLeft = NULL,
*paptiSortedRight = NULL;
PTitleInfo *paptiSortedResult= NULL;
UINT cFirst = 0;
UINT cSecond = 0;
__try
{
if (ctiSets == 1)
{
*ppptiSorted = paptiSets + *paiTitleStarts;
*pcti = *(paiTitleStarts + 1) - *paiTitleStarts;
__leave;
}
UINT ctiLeft = 0,
ctiRight = 0;
cFirst = ctiSets / 2;
cSecond = ctiSets - cFirst;
CombineTitleLists(paptiSets, paiTitleStarts, cFirst, &paptiSortedLeft, &ctiLeft);
CombineTitleLists(paptiSets, paiTitleStarts + cFirst, cSecond, &paptiSortedRight, &ctiRight);
UINT ctiResult= ctiLeft + ctiRight;
paptiSortedResult= (PTitleInfo *) VAlloc(FALSE, ctiResult * sizeof(PTitleInfo));
MergeImageRefSets((PVOID *) paptiSortedResult, ctiResult,
(PVOID *) paptiSortedLeft, ctiLeft,
(PVOID *) paptiSortedRight, ctiRight,
CompareTitleInfo
);
*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 CTitleCollection::CompareTitleInfo(const void *pvL, const void *pvR)
{
return CompareImagesLR(&(*(const TitleInfo **) pvL)->pd, &(*(const TitleInfo **) pvR)->pd);
}
UINT CTitleCollection::MapToTitleLists(CIndicatorSet * pisTitles, PTitleInfo *paptiLists, UINT cLists)
{
PUINT paiBuffer= NULL;
UINT cTitlesFound= 0;
__try
{
ASSERT(cLists >= m_ctsSlots);
UINT cTitles= pisTitles? pisTitles->SelectionCount() : m_cd;
UINT cChunk= C_INDICES_CHUNK;
if (cChunk > cTitles) cChunk= cTitles;
paiBuffer= PUINT(VAlloc(FALSE, cChunk * sizeof(UINT)));
ZeroMemory(paptiLists, cLists * sizeof(PTokenInfo));
UINT iTitleFirst;
for (iTitleFirst= 0; cTitles; iTitleFirst += cChunk, cTitles -= cChunk)
{
if (cChunk > cTitles) cChunk= cTitles;
UINT c, i;
PUINT pi;
if (pisTitles) pisTitles->MarkedItems(iTitleFirst, PINT(paiBuffer), cChunk);
else
for (i= iTitleFirst, c= cChunk, pi= paiBuffer; c--; ) *pi++ = i++;
for (c= cChunk, pi= paiBuffer + cChunk; c--; )
{
PTitleInfo pti= m_pati + (m_ppdSorted[*--pi] - m_pd);
UINT iSlot= pti->iaTSSlot;
ASSERT(m_patsi[iSlot].fFlags & PRESENT);
if (!(ACTIVE & m_patsi[iSlot].fFlags)) continue;
++cTitlesFound;
pti->ptiNext= paptiLists[iSlot];
paptiLists[iSlot]= pti;
}
}
}
__finally
{
if (paiBuffer) { VFree(paiBuffer); paiBuffer= NULL; }
}
return cTitlesFound;
}