home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_CORE1_SEG
- #pragma code_seg(AFX_CORE1_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // lpszCanon = C:\MYAPP\DEBUGS\C\TESWIN.C
- //
- // cchMax b Result
- // ------ - ---------
- // 1- 7 F <empty>
- // 1- 7 T TESWIN.C
- // 8-14 x TESWIN.C
- // 15-16 x C:\...\TESWIN.C
- // 17-23 x C:\...\C\TESWIN.C
- // 24-25 x C:\...\DEBUGS\C\TESWIN.C
- // 26+ x C:\MYAPP\DEBUGS\C\TESWIN.C
-
- AFX_STATIC void AFXAPI _AfxAbbreviateName(LPTSTR lpszCanon, int cchMax, BOOL bAtLeastName)
- {
- int cchFullPath, cchFileName, cchVolName;
- const TCHAR* lpszCur;
- const TCHAR* lpszBase;
- const TCHAR* lpszFileName;
-
- lpszBase = lpszCanon;
- cchFullPath = lstrlen(lpszCanon);
-
- cchFileName = AfxGetFileName(lpszCanon, NULL, 0) - 1;
- lpszFileName = lpszBase + (cchFullPath-cchFileName);
-
- // If cchMax is more than enough to hold the full path name, we're done.
- // This is probably a pretty common case, so we'll put it first.
- if (cchMax >= cchFullPath)
- return;
-
- // If cchMax isn't enough to hold at least the basename, we're done
- if (cchMax < cchFileName)
- {
- lstrcpy(lpszCanon, (bAtLeastName) ? lpszFileName : &afxChNil);
- return;
- }
-
- // Calculate the length of the volume name. Normally, this is two characters
- // (e.g., "C:", "D:", etc.), but for a UNC name, it could be more (e.g.,
- // "\\server\share").
- //
- // If cchMax isn't enough to hold at least <volume_name>\...\<base_name>, the
- // result is the base filename.
-
- lpszCur = lpszBase + 2; // Skip "C:" or leading "\\"
-
- if (lpszBase[0] == '\\' && lpszBase[1] == '\\') // UNC pathname
- {
- // First skip to the '\' between the server name and the share name,
- while (*lpszCur != '\\')
- {
- lpszCur = _tcsinc(lpszCur);
- ASSERT(*lpszCur != '\0');
- }
- }
- // if a UNC get the share name, if a drive get at least one directory
- ASSERT(*lpszCur == '\\');
- // make sure there is another directory, not just c:\filename.ext
- if (cchFullPath - cchFileName > 3)
- {
- lpszCur = _tcsinc(lpszCur);
- while (*lpszCur != '\\')
- {
- lpszCur = _tcsinc(lpszCur);
- ASSERT(*lpszCur != '\0');
- }
- }
- ASSERT(*lpszCur == '\\');
-
- cchVolName = lpszCur - lpszBase;
- if (cchMax < cchVolName + 5 + cchFileName)
- {
- lstrcpy(lpszCanon, lpszFileName);
- return;
- }
-
- // Now loop through the remaining directory components until something
- // of the form <volume_name>\...\<one_or_more_dirs>\<base_name> fits.
- //
- // Assert that the whole filename doesn't fit -- this should have been
- // handled earlier.
-
- ASSERT(cchVolName + (int)lstrlen(lpszCur) > cchMax);
- while (cchVolName + 4 + (int)lstrlen(lpszCur) > cchMax)
- {
- do
- {
- lpszCur = _tcsinc(lpszCur);
- ASSERT(*lpszCur != '\0');
- }
- while (*lpszCur != '\\');
- }
-
- // Form the resultant string and we're done.
- lpszCanon[cchVolName] = '\0';
- lstrcat(lpszCanon, _T("\\..."));
- lstrcat(lpszCanon, lpszCur);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CRecentFileList
-
- CRecentFileList::CRecentFileList(UINT nStart, LPCTSTR lpszSection,
- LPCTSTR lpszEntryFormat, int nSize, int nMaxDispLen)
- {
- ASSERT(nSize != 0);
- m_arrNames = new CString[nSize];
- m_nSize = nSize;
-
- m_nStart = nStart;
- m_strSectionName = lpszSection;
- m_strEntryFormat = lpszEntryFormat;
- m_nMaxDisplayLength = nMaxDispLen;
- }
-
- CRecentFileList::~CRecentFileList()
- {
- delete[] m_arrNames;
- }
-
- // Operations
- void CRecentFileList::Add(LPCTSTR lpszPathName)
- {
- ASSERT(m_arrNames != NULL);
- ASSERT(lpszPathName != NULL);
- ASSERT(AfxIsValidString(lpszPathName));
-
- // fully qualify the path name
- TCHAR szTemp[_MAX_PATH];
- AfxFullPath(szTemp, lpszPathName);
-
- // update the MRU list, if an existing MRU string matches file name
- for (int iMRU = 0; iMRU < m_nSize-1; iMRU++)
- {
- if (AfxComparePath(m_arrNames[iMRU], szTemp))
- break; // iMRU will point to matching entry
- }
- // move MRU strings before this one down
- for (; iMRU > 0; iMRU--)
- {
- ASSERT(iMRU > 0);
- ASSERT(iMRU < m_nSize);
- m_arrNames[iMRU] = m_arrNames[iMRU-1];
- }
- // place this one at the beginning
- m_arrNames[0] = szTemp;
- }
-
- void CRecentFileList::Remove(int nIndex)
- {
- ASSERT(nIndex >= 0);
- ASSERT(nIndex < m_nSize);
-
- m_arrNames[nIndex].Empty();
- for (int iMRU = nIndex; iMRU < m_nSize-1; iMRU++)
- m_arrNames[iMRU] = m_arrNames[iMRU+1];
-
- ASSERT(iMRU < m_nSize);
- m_arrNames[iMRU].Empty();
- }
-
- BOOL CRecentFileList::GetDisplayName(CString& strName, int nIndex,
- LPCTSTR lpszCurDir, int nCurDir, BOOL bAtLeastName) const
- {
- ASSERT(lpszCurDir == NULL || AfxIsValidString(lpszCurDir, nCurDir));
-
- ASSERT(m_arrNames != NULL);
- ASSERT(nIndex < m_nSize);
- if (m_arrNames[nIndex].IsEmpty())
- return FALSE;
-
- LPTSTR lpch = strName.GetBuffer(_MAX_PATH);
- lstrcpy(lpch, m_arrNames[nIndex]);
- // nLenDir is the length of the directory part of the full path
- int nLenDir = lstrlen(lpch) - (AfxGetFileName(lpch, NULL, 0) - 1);
- BOOL bSameDir = FALSE;
- if (nLenDir == nCurDir)
- {
- TCHAR chSave = lpch[nLenDir];
- lpch[nCurDir] = 0; // terminate at same location as current dir
- bSameDir = lstrcmpi(lpszCurDir, lpch) == 0;
- lpch[nLenDir] = chSave;
- }
- // copy the full path, otherwise abbreviate the name
- if (bSameDir)
- {
- // copy file name only since directories are same
- TCHAR szTemp[_MAX_PATH];
- AfxGetFileTitle(lpch+nCurDir, szTemp, _countof(szTemp));
- lstrcpyn(lpch, szTemp, _MAX_PATH);
- }
- else if (m_nMaxDisplayLength != -1)
- {
- // strip the extension if the system calls for it
- TCHAR szTemp[_MAX_PATH];
- AfxGetFileTitle(lpch+nLenDir, szTemp, _countof(szTemp));
- lstrcpyn(lpch+nLenDir, szTemp, _MAX_PATH-nLenDir);
-
- // abbreviate name based on what will fit in limited space
- _AfxAbbreviateName(lpch, m_nMaxDisplayLength, bAtLeastName);
- }
- strName.ReleaseBuffer();
- return TRUE;
- }
-
- void CRecentFileList::UpdateMenu(CCmdUI* pCmdUI)
- {
- ASSERT(m_arrNames != NULL);
-
- CMenu* pMenu = pCmdUI->m_pMenu;
- if (m_strOriginal.IsEmpty() && pMenu != NULL)
- pMenu->GetMenuString(pCmdUI->m_nID, m_strOriginal, MF_BYCOMMAND);
-
- if (m_arrNames[0].IsEmpty())
- {
- // no MRU files
- if (!m_strOriginal.IsEmpty())
- pCmdUI->SetText(m_strOriginal);
- pCmdUI->Enable(FALSE);
- return;
- }
-
- if (pCmdUI->m_pMenu == NULL)
- return;
-
- for (int iMRU = 0; iMRU < m_nSize; iMRU++)
- pCmdUI->m_pMenu->DeleteMenu(pCmdUI->m_nID + iMRU, MF_BYCOMMAND);
-
- TCHAR szCurDir[_MAX_PATH];
- GetCurrentDirectory(_MAX_PATH, szCurDir);
- int nCurDir = lstrlen(szCurDir);
- ASSERT(nCurDir >= 0);
- szCurDir[nCurDir] = '\\';
- szCurDir[++nCurDir] = '\0';
-
- CString strName;
- CString strTemp;
- for (iMRU = 0; iMRU < m_nSize; iMRU++)
- {
- if (!GetDisplayName(strName, iMRU, szCurDir, nCurDir))
- break;
-
- // double up any '&' characters so they are not underlined
- LPCTSTR lpszSrc = strName;
- LPTSTR lpszDest = strTemp.GetBuffer(strName.GetLength()*2);
- while (*lpszSrc != 0)
- {
- if (*lpszSrc == '&')
- *lpszDest++ = '&';
- if (_istlead(*lpszSrc))
- *lpszDest++ = *lpszSrc++;
- *lpszDest++ = *lpszSrc++;
- }
- *lpszDest = 0;
- strTemp.ReleaseBuffer();
-
- // insert mnemonic + the file name
- TCHAR buf[10];
- wsprintf(buf, _T("&%d "), (iMRU+1+m_nStart) % 10);
- pCmdUI->m_pMenu->InsertMenu(pCmdUI->m_nIndex++,
- MF_STRING | MF_BYPOSITION, pCmdUI->m_nID++,
- CString(buf) + strTemp);
- }
-
- // update end menu count
- pCmdUI->m_nIndex--; // point to last menu added
- pCmdUI->m_nIndexMax = pCmdUI->m_pMenu->GetMenuItemCount();
-
- pCmdUI->m_bEnableChanged = TRUE; // all the added items are enabled
- }
-
- void CRecentFileList::WriteList()
- {
- ASSERT(m_arrNames != NULL);
- ASSERT(!m_strSectionName.IsEmpty());
- ASSERT(!m_strEntryFormat.IsEmpty());
- LPTSTR pszEntry = new TCHAR[m_strEntryFormat.GetLength()+5];
- CWinApp* pApp = AfxGetApp();
- pApp->WriteProfileString(m_strSectionName, NULL, NULL);
- for (int iMRU = 0; iMRU < m_nSize; iMRU++)
- {
- wsprintf(pszEntry, m_strEntryFormat, iMRU + 1);
- if (!m_arrNames[iMRU].IsEmpty())
- {
- pApp->WriteProfileString(m_strSectionName, pszEntry,
- m_arrNames[iMRU]);
- }
- }
- delete[] pszEntry;
- }
-
- void CRecentFileList::ReadList()
- {
- ASSERT(m_arrNames != NULL);
- ASSERT(!m_strSectionName.IsEmpty());
- ASSERT(!m_strEntryFormat.IsEmpty());
- LPTSTR pszEntry = new TCHAR[m_strEntryFormat.GetLength()+5];
- CWinApp* pApp = AfxGetApp();
- for (int iMRU = 0; iMRU < m_nSize; iMRU++)
- {
- wsprintf(pszEntry, m_strEntryFormat, iMRU + 1);
- m_arrNames[iMRU] = pApp->GetProfileString(
- m_strSectionName, pszEntry, &afxChNil);
- }
- delete[] pszEntry;
- }
-
- /////////////////////////////////////////////////////////////////////////////
-