|
|
// 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); }
|