WindowsXP-SP1/enduser/netmeeting/ui/conf/mrulist2.cpp
2020-09-30 16:53:49 +02:00

473 lines
9.8 KiB
C++

// File: mrulist.cpp
#include "precomp.h"
#include "mrulist2.h"
typedef struct {
LPTSTR psz1;
LPTSTR psz2;
} SZSZ;
typedef SZSZ * PSZSZ;
typedef struct {
LPTSTR psz1;
LPTSTR psz2;
DWORD dw;
} SZSZDW;
typedef SZSZDW * PSZSZDW;
/* C M R U L I S T */
/*-------------------------------------------------------------------------
%%Function: CMRUList2
-------------------------------------------------------------------------*/
CMRUList2::CMRUList2(const DWSTR * prgDwStr, int cEntryMax, BOOL fReversed) :
m_prgDwStr (prgDwStr),
m_cEntryMax (cEntryMax),
m_fReversed (fReversed),
m_cEntry (0),
m_rgpEntry (NULL),
m_fDirty (FALSE)
{
DBGENTRY(CMRUList2::CMRUList2);
ASSERT(NULL != prgDwStr);
m_cCol = m_prgDwStr[0].dw;
int cb = m_cEntryMax * sizeof(PMRUE);
m_rgpEntry = new PMRUE[cb];
if (NULL == m_rgpEntry)
{
ERROR_OUT(("CMRUList2 - out of memory"));
return;
}
ZeroMemory(m_rgpEntry, cb);
RegEntry re(PszRegKey(), HKEY_CURRENT_USER);
if (ERROR_SUCCESS != re.GetError())
return;
m_cEntry = min(re.GetNumber(REGVAL_MRU_COUNT, 0), m_cEntryMax);
for (int i = 0; i < m_cEntry; i++)
{
m_rgpEntry[i] = LoadEntry(&re, i);
}
}
CMRUList2::~CMRUList2()
{
DBGENTRY(CMRUList2::~CMRUList2);
if (m_fDirty)
{
Save();
}
for (int i = 0; i < m_cEntry; i++)
{
DeleteEntry(m_rgpEntry[i]);
}
delete m_rgpEntry;
}
///////////////////////////////////////////////////////////////////////////
PMRUE CMRUList2::LoadEntry(RegEntry * pre, int iItem)
{
if (m_fReversed)
{
iItem = (m_cEntry - (iItem+1));
}
PMRUE pEntry = (PMRUE) new PVOID[m_cCol*sizeof(PVOID)];
if (NULL != pEntry)
{
PVOID ** ppv = (PVOID **) pEntry;
for (int iCol = 0; iCol < m_cCol; iCol++, ppv++)
{
TCHAR szKey[MAX_PATH];
wsprintf(szKey, TEXT("%s%d"), PszPrefixForCol(iCol), iItem);
switch (MruTypeForCol(iCol))
{
default:
case MRUTYPE_SZ:
* (LPTSTR *)ppv = PszAlloc(pre->GetString(szKey));
break;
case MRUTYPE_DW:
* (DWORD *) ppv = pre->GetNumber(szKey);
break;
}
}
}
return pEntry;
}
VOID CMRUList2::StoreEntry(RegEntry * pre, int iItem)
{
PVOID ** ppv = (PVOID **) GetEntry(iItem);
if (m_fReversed)
{
iItem = (m_cEntry - (iItem+1));
}
for (int iCol = 0; iCol < m_cCol; iCol++, ppv++)
{
TCHAR szKey[MAX_PATH];
wsprintf(szKey, TEXT("%s%d"), PszPrefixForCol(iCol), iItem);
switch (MruTypeForCol(iCol))
{
default:
case MRUTYPE_SZ:
pre->SetValue(szKey, * (LPCTSTR *)ppv);
break;
case MRUTYPE_DW:
pre->SetValue(szKey, * (ULONG *) ppv);
break;
}
}
}
VOID CMRUList2::DeleteEntry(PMRUE pEntry)
{
PVOID ** ppv = (PVOID **) pEntry;
for (int iCol = 0; iCol < m_cCol; iCol++, ppv++)
{
switch (MruTypeForCol(iCol))
{
default:
case MRUTYPE_SZ:
delete *ppv;
break;
case MRUTYPE_DW:
break;
}
}
delete pEntry;
}
VOID CMRUList2::DeleteEntry(int iItem)
{
if ((iItem < 0) || (iItem >= m_cEntry))
return; // nothing to do
// delete the data
DeleteEntry(m_rgpEntry[iItem]);
// decrement the count
m_cEntry--;
// shift items up
for ( ; iItem < m_cEntry; iItem++)
{
m_rgpEntry[iItem] = m_rgpEntry[iItem+1];
}
// the list has been modified
m_fDirty = TRUE;
}
//--------------------------------------------------------------------------//
// CMRUList2::DeleteEntry. //
// This DeleteEntry() deletes the first entry it finds thats primary //
// string matches the one passed in. //
//--------------------------------------------------------------------------//
void
CMRUList2::DeleteEntry
(
const TCHAR * const primaryString
){
int items = GetNumEntries();
for( int nn = 0; nn < items; nn++ )
{
if( StrCmpI( primaryString, * ((const TCHAR * const * const) m_rgpEntry[ nn ]) ) == 0 )
{
DeleteEntry( nn );
break;
}
}
} // End of CMRUList2::DeleteEntry.
/* C O M P A R E E N T R Y */
/*-------------------------------------------------------------------------
%%Function: CompareEntry
-------------------------------------------------------------------------*/
int CMRUList2::CompareEntry(int iItem, PMRUE pEntry)
{
ASSERT(NULL != pEntry);
int iRet = 0;
PVOID * ppv1 = (PVOID *) GetEntry(iItem);
PVOID * ppv2 = (PVOID *) pEntry;
for (int iCol = 0; iCol < m_cCol; iCol++, ppv1++, ppv2++)
{
switch (MruTypeForCol(iCol))
{
default:
case MRUTYPE_SZ:
iRet = lstrcmpi(* (LPCTSTR *) ppv1, * (LPCTSTR *) ppv2);
break;
case MRUTYPE_DW:
iRet = (* (int *) ppv1) - (* (int *) ppv2);
break;
}
if (0 != iRet)
break;
}
return iRet;
}
/* F I N D E N T R Y */
/*-------------------------------------------------------------------------
%%Function: FindEntry
Return -1 if the item is not found.
-------------------------------------------------------------------------*/
int CMRUList2::FindEntry(PMRUE pEntry)
{
int cItems = GetNumEntries();
for (int i = 0; i < cItems; i++)
{
if (0 == CompareEntry(i, pEntry))
{
return i;
}
}
return -1; // not found
}
/* S A V E */
/*-------------------------------------------------------------------------
%%Function: Save
-------------------------------------------------------------------------*/
HRESULT CMRUList2::Save(void)
{
DBGENTRY(CMRUList2::Save);
// Retrieve the data from the registry
RegEntry re(PszRegKey(), HKEY_CURRENT_USER);
if (ERROR_SUCCESS != re.GetError())
return E_FAIL;
re.SetValue(REGVAL_MRU_COUNT, m_cEntry);
for (int i = 0; i < m_cEntry; i++)
{
StoreEntry(&re, i);
}
return S_OK;
}
/* S H I F T E N T R I E S D O W N */
/*-------------------------------------------------------------------------
%%Function: ShiftEntriesDown
Shift the entires down by one slot leaving the first position open.
-------------------------------------------------------------------------*/
VOID CMRUList2::ShiftEntriesDown(int cItem)
{
if (cItem < 1)
return; // nothing to do
int iItem;
for (iItem = cItem; iItem > 0; iItem--)
{
m_rgpEntry[iItem] = m_rgpEntry[iItem-1];
}
// the list has been modified
m_fDirty = TRUE;
}
/* M O V E E N T R Y T O T O P */
/*-------------------------------------------------------------------------
%%Function: MoveEntryToTop
-------------------------------------------------------------------------*/
VOID CMRUList2::MoveEntryToTop(int iItem)
{
DBGENTRY(CMRUList2::MoveEntryToTop);
if ((iItem < 1) || (iItem >= m_cEntry))
return; // nothing to do
PMRUE pEntry = GetEntry(iItem);
ShiftEntriesDown(iItem);
m_rgpEntry[0] = pEntry;
}
/* A D D E N T R Y */
/*-------------------------------------------------------------------------
%%Function: AddEntry
Put the entry into the top of the list.
The data is owned by the list after this.
Returns:
S_OK - added to the head of the list
S_FALSE - already in list (item is moved to top)
-------------------------------------------------------------------------*/
HRESULT CMRUList2::AddEntry(PMRUE pEntry)
{
DBGENTRY(CMRUList2::AddEntry);
HRESULT ret = S_OK;
// the list has been modified
m_fDirty = TRUE;
int cShift;
int iItem = FindEntry(pEntry);
if (-1 != iItem)
{
// This entry already exists, delete it so we get the new info
DeleteEntry(m_rgpEntry[iItem]);
cShift = iItem;
ret = S_FALSE; // Success, but already in the list
}
else if (m_cEntryMax == m_cEntry)
{
// drop the last item
DeleteEntry(m_rgpEntry[m_cEntry-1]);
cShift = m_cEntry-1;
}
else
{
cShift = m_cEntry;
m_cEntry++;
}
ShiftEntriesDown(cShift);
// add it to the head of the list
m_rgpEntry[0] = pEntry;
return ret;
}
HRESULT CMRUList2::AddEntry(LPCTSTR pcsz)
{
LPTSTR * ppsz = new LPTSTR;
LPTSTR psz = PszAlloc(pcsz);
if ((NULL == ppsz) || (NULL == psz))
{
delete ppsz;
delete psz;
return E_OUTOFMEMORY;
}
*ppsz = psz;
return AddEntry((PMRUE) ppsz);
}
HRESULT CMRUList2::AddEntry(LPCTSTR pcsz1, LPCTSTR pcsz2)
{
PSZSZ pSzSz = new SZSZ;
if (NULL == pSzSz)
return E_OUTOFMEMORY;
pSzSz->psz1 = PszAlloc(pcsz1);
pSzSz->psz2 = PszAlloc(pcsz2);
if ((NULL == pSzSz->psz1) || (NULL == pSzSz->psz1))
{
// something failed - don't add anything
DeleteEntry(pSzSz);
return E_OUTOFMEMORY;
}
return AddEntry((PMRUE) pSzSz);
}
HRESULT CMRUList2::AddEntry(LPCTSTR pcsz1, LPCTSTR pcsz2, DWORD dw3)
{
PSZSZDW pData = new SZSZDW;
if (NULL == pData)
return E_OUTOFMEMORY;
pData->psz1 = PszAlloc(pcsz1);
pData->psz2 = PszAlloc(pcsz2);
if ((NULL == pData->psz1) || (NULL == pData->psz1))
{
// something failed - don't add anything
DeleteEntry(pData);
return E_OUTOFMEMORY;
}
pData->dw = dw3;
return AddEntry((PMRUE) pData);
}
/*-------------------------------------------------------------------------
%%Function: GetString
Return the data associated with the entry
-------------------------------------------------------------------------*/
LPCTSTR CMRUList2::GetString(int iItem, int iCol)
{
if (!FValidIndex(iItem))
{
return(NULL);
}
return(GetString(GetEntry(iItem), iCol));
}
DWORD CMRUList2::GetDWORD(int iItem, int iCol)
{
if (!FValidIndex(iItem))
{
return(0);
}
return(GetDWORD(GetEntry(iItem), iCol));
}
LPCTSTR CMRUList2::GetString(PMRUE pEntry, int iCol)
{
if (iCol >= m_cCol
|| MRUTYPE_SZ != m_prgDwStr[iCol+1].dw
)
{
return(NULL);
}
LPTSTR * ppsz = reinterpret_cast<LPTSTR *>(pEntry);
return * (ppsz+iCol);
}
DWORD CMRUList2::GetDWORD(PMRUE pEntry, int iCol)
{
if (iCol >= m_cCol
|| MRUTYPE_DW != m_prgDwStr[iCol+1].dw
)
{
return(0);
}
DWORD * ppdw = reinterpret_cast<DWORD *>(pEntry);
return * (ppdw+iCol);
}