/* * mru.c * * This file is part of Emu48 * * Copyright (C) 2007 Christoph Gießelink * */ #include "pch.h" #include "resource.h" #include "Emu48.h" static TCHAR szOriginal[MAX_PATH] = _T(""); static LPTSTR *ppszFiles = NULL; // pointer to MRU table static INT nEntry = 0; // no. of MRU entries static HMENU hMruMenu = NULL; // menu handle for MRU list static INT nMruPos; // insert position for MRU list static BOOL GetMenuPosForId(HMENU hMenu, UINT nItem) { HMENU hSubMenu; UINT nID; INT i,nMaxID; nMaxID = GetMenuItemCount(hMenu); for (i = 0; i < nMaxID; ++i) { nID = GetMenuItemID(hMenu,i); // get ID if (nID == 0) continue; // separator or invalid command if (nID == (UINT)-1) // possibly a popup menu { hSubMenu = GetSubMenu(hMenu,i); // try to get handle to popup menu if (hSubMenu != NULL) // it's a popup menu { // recursive search if (GetMenuPosForId(hSubMenu,nItem)) return TRUE; } continue; } if (nID == nItem) // found ID { hMruMenu = hMenu; // remember menu and position nMruPos = i; return TRUE; } } return FALSE; } BOOL MruInit(INT nNum) { HMENU hMenu = GetMenu(hWnd); // main menu _ASSERT(ppszFiles == NULL); // MRU already initialized if (*szOriginal == 0) // get orginal value of first MRU entry { VERIFY(GetMenuString(hMenu,ID_FILE_MRU_FILE1,szOriginal,ARRAYSIZEOF(szOriginal),MF_BYCOMMAND)); } // no. of files in MRU list nEntry = ReadSettingsInt(_T("MRU"),_T("FileCount"),nNum); // look for menu position of ID_FILE_MRU_FILE1 VERIFY(GetMenuPosForId(hMenu,ID_FILE_MRU_FILE1)); if (nEntry > 0) // allocate MRU table { // create MRU table if((ppszFiles = HeapAlloc(hHeap,0,nEntry * sizeof(*ppszFiles))) == NULL) return TRUE; // fill each entry for (nNum = 0; nNum < nEntry; ++nNum) ppszFiles[nNum] = NULL; MruReadList(); // read actual MRU list MruUpdateMenu(); // update menu } else // kill MRU menu entries { // delete MRU menu DeleteMenu(hMruMenu,nMruPos,MF_BYPOSITION); // delete following separator _ASSERT((GetMenuState(hMruMenu,nMruPos,MF_BYPOSITION) & MF_SEPARATOR) != 0); DeleteMenu(hMruMenu,nMruPos,MF_BYPOSITION); } return FALSE; } VOID MruCleanup(VOID) { INT i; MruWriteList(); // write actual MRU list for (i = 0; i < nEntry; ++i) // cleanup each entry { if (ppszFiles[i] != NULL) HeapFree(hHeap,0,ppszFiles[i]); // cleanup entry } if (ppszFiles != NULL) // table defined { HeapFree(hHeap,0,ppszFiles); // free table ppszFiles = NULL; } return; } VOID MruAdd(LPCTSTR lpszEntry) { TCHAR szFilename[MAX_PATH]; LPTSTR lpFilePart; INT i; if (nEntry == 0) return; // no entries // get full path name GetFullPathName(lpszEntry,ARRAYSIZEOF(szFilename),szFilename,&lpFilePart); // look if entry is already in table for (i = 0; i < nEntry; ++i) { // already in table -> quit if ( ppszFiles[i] != NULL && lstrcmpi(ppszFiles[i],szFilename) == 0) { MruUpdateMenu(); // update menu return; } } i = nEntry - 1; // last index if (ppszFiles[i] != NULL) HeapFree(hHeap,0,ppszFiles[i]); // free oldest entry for (; i > 0; --i) // move old entries 1 line down { ppszFiles[i] = ppszFiles[i-1]; } // add new entry to top ppszFiles[0] = DuplicateString(szFilename); MruUpdateMenu(); // update menu return; } VOID MruRemove(INT nIndex) { HeapFree(hHeap,0,ppszFiles[nIndex]); // free entry for (; nIndex < nEntry - 1; ++nIndex) // move old entries 1 line up { ppszFiles[nIndex] = ppszFiles[nIndex+1]; } ppszFiles[nIndex] = NULL; // clear last line MruUpdateMenu(); // update menu return; } INT MruEntries(VOID) { return nEntry; } LPCTSTR MruFilename(INT nIndex) { _ASSERT(ppszFiles != NULL); // MRU not initialized _ASSERT(nIndex >= 0 && nIndex < nEntry); // inside range return ppszFiles[nIndex]; } VOID MruUpdateMenu(VOID) { TCHAR szCurPath[MAX_PATH]; HANDLE hMenu; BOOL bEmpty; INT i; if (nEntry == 0) return; // no entries _ASSERT(ppszFiles != NULL); // MRU not initialized _ASSERT(hWnd != NULL); VERIFY(hMenu = GetMenu(hWnd)); // main menu bEmpty = TRUE; // MRU list empty for (i = 0; i < nEntry; ++i) // delete all menu entries { DeleteMenu(hMenu,ID_FILE_MRU_FILE1+i,MF_BYCOMMAND); if (ppszFiles[i] != NULL) // valid entry bEmpty = FALSE; // MRU list not empty } if (bEmpty) // empty MRU list { // fill with orginal string VERIFY(InsertMenu(hMruMenu,nMruPos,MF_STRING|MF_BYPOSITION|MF_GRAYED,ID_FILE_MRU_FILE1,szOriginal)); return; } // current directory GetCurrentDirectory(ARRAYSIZEOF(szCurPath),szCurPath); for (i = 0; i < nEntry; ++i) // add menu entries { if (ppszFiles[i] != NULL) // valid entry { TCHAR szMenuname[2*MAX_PATH+3]; TCHAR szFilename[MAX_PATH]; LPTSTR lpFilePart,lpszPtr; // check if file path and current path is identical if (GetFullPathName(ppszFiles[i],ARRAYSIZEOF(szFilename),szFilename,&lpFilePart)) { TCHAR szCutname[MAX_PATH]; *(lpFilePart-1) = 0; // devide path and name // name is current directory -> use only name if (lstrcmpi(szCurPath,szFilename) == 0) { // short name view } else { // full name view lpFilePart = ppszFiles[i]; } // cut filename to fit into menu GetCutPathName(lpFilePart,szCutname,ARRAYSIZEOF(szCutname),36); lpFilePart = szCutname; lpszPtr = szMenuname; // adding accelerator key *lpszPtr++ = _T('&'); *lpszPtr++ = _T('0') + ((i + 1) % 10); *lpszPtr++ = _T(' '); // copy file to view buffer and expand & to && while (*lpFilePart != 0) { if (*lpFilePart == _T('&')) { *lpszPtr++ = *lpFilePart; } *lpszPtr++ = *lpFilePart++; } *lpszPtr = 0; VERIFY(InsertMenu(hMruMenu,nMruPos+i,MF_STRING|MF_BYPOSITION,ID_FILE_MRU_FILE1+i,szMenuname)); } } } return; } VOID MruWriteList(VOID) { TCHAR szItemname[32]; INT i; // no. of files in MRU list WriteSettingsInt(_T("MRU"),_T("FileCount"),nEntry); for (i = 0; i < nEntry; ++i) // add menu entries { _ASSERT(ppszFiles != NULL); // MRU not initialized wsprintf(szItemname,_T("File%d"),i+1); if (ppszFiles[i] != NULL) { WriteSettingsString(_T("MRU"),szItemname,ppszFiles[i]); } else { DelSettingsKey(_T("MRU"),szItemname); } } return; } VOID MruReadList(VOID) { TCHAR szFilename[MAX_PATH]; TCHAR szItemname[32]; LPTSTR lpszValue; INT i; _ASSERT(ppszFiles != NULL); // MRU not initialized for (i = 0; i < nEntry; ++i) // add menu entries { wsprintf(szItemname,_T("File%d"),i+1); ReadSettingsString(_T("MRU"),szItemname,_T(""),szFilename,ARRAYSIZEOF(szFilename)); if (ppszFiles[i] != NULL) // already filled { HeapFree(hHeap,0,ppszFiles[i]); // free entry ppszFiles[i] = NULL; // clear last line lpszValue = _T(""); } if (*szFilename) // read a valid entry { ppszFiles[i] = DuplicateString(szFilename); } } return; }