📄 tmainfrm2.cpp
字号:
/*****************************************************************************/
/* TMainFrm2.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Worker thread functions of TMainFrame */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 03.04.03 1.00 Lad The first version of TMainFrm.cpp */
/*****************************************************************************/
#include "stdafx.h"
#include "MPQEditor.h"
#include "TMainFrm.h"
#include "TTreeView.h"
#include "TListView.h"
#include "TFileListDlg.h"
#include "TMsgBoxYNAC.h"
//-----------------------------------------------------------------------------
// Protected functions
void WINAPI TMainFrame::CompactCB(void * lpUserData, DWORD dwWorkType, DWORD dwParam1, DWORD dwParam2)
{
TMainFrame * pMainFrame = (TMainFrame *)lpUserData;
switch(dwWorkType)
{
case CCB_CHECKING_FILES:
pMainFrame->SetStatusText(IDS_CHECKING_FILES, dwParam1, dwParam2);
break;
case CCB_COMPACTING_FILES:
pMainFrame->SetStatusText(IDS_COMPACTING, dwParam1, dwParam2);
break;
case CCB_CLOSING_ARCHIVE:
pMainFrame->SetStatusText(IDS_CLOSINGARCHIVE, dwParam1, dwParam2);
break;
}
}
TFileInfo * TMainFrame::CreateFileInfo(const char * szFileName, LCID lcLocale, DWORD dwFileSize, DWORD dwFileAttr)
{
TFileInfo * pInfo;
// int nSize = sizeof(TFileInfo) + strlen(szFileName);
int nSize = sizeof(TFileInfo) + MAX_PATH; // Must be MAXPATH because of renaming
pInfo = (TFileInfo *)(new char[nSize]);
memset(pInfo, 0, nSize);
strcpy(pInfo->szFullName, szFileName);
pInfo->szPlainName = GetPlainName(pInfo->szFullName);
pInfo->lcLocale = lcLocale;
pInfo->dwFileSize = dwFileSize;
pInfo->dwAttributes = dwFileAttr;
return pInfo;
}
// This function checks if the file name is autodetected name
// in the form of "File########.*". If not, it returns the file name back.
// If yes, it converts the file name to the ordinal number and
// returns it as file name
const char * TMainFrame::GetFileOrdinal(const char * szFileName)
{
// First of all, test if we auto-detected the file names.
if(m_bNameless == FALSE)
return szFileName;
if(strncmp(szFileName, "File", 4))
return szFileName;
for(int nIndex = 4; nIndex < 12; nIndex++)
{
if(!isdigit(szFileName[nIndex]))
return szFileName;
}
// Test the point before extension
if(szFileName[12] != '.')
return szFileName;
// Now we know that it is an autodetected name.
// Convert it to the ordinal number and return
return (const char *)atoi(szFileName + 4);
}
char * TMainFrame::SkipSpaces(const char * ch)
{
while(0 < *ch && *ch <= 0x20)
ch++;
return (char *)ch;
}
BOOL TMainFrame::GetCommandParams(char * szCmd, char * szParam1, char * szParam2)
{
char * szNext;
// Initialize both parameters
*szParam1 = *szParam2 = 0;
// Get the first parameter
szNext = szCmd = SkipSpaces(szCmd);
while(*szNext != 0 && *szNext > 0x20)
szNext++;
if(*szCmd != 0)
{
strncpy(szParam1, szCmd, (szNext - szCmd));
szParam1[szNext - szCmd] = 0;
}
// Get the second parameter
szNext = szCmd = SkipSpaces(szNext);
while(*szNext != 0 && *szNext > 0x20)
szNext++;
if(*szCmd != 0)
{
strncpy(szParam2, szCmd, (szNext - szCmd));
szParam2[szNext - szCmd] = 0;
}
return TRUE;
}
// Function tests if the work was stopped. Returns TRUE if yes.
BOOL TMainFrame::WorkStopped(TWorkInfo * pWork)
{
// Test if we have to exit
if(pWork->bStop == FALSE)
{
if(WaitForSingleObject(m_hStopEvent, 0) != WAIT_TIMEOUT)
pWork->bStop = TRUE;
}
return pWork->bStop;
}
void TMainFrame::UpdateFileInfo(CPtrList * pFileList, const char * szFileName, LCID lcLocale, DWORD dwFileSize, DWORD dwFileAttr)
{
POSITION pos = pFileList->GetHeadPosition();
while(pos != NULL)
{
TFileInfo * pInfo = (TFileInfo *)pFileList->GetNext(pos);
if(!stricmp(pInfo->szFullName, szFileName))
{
strcpy(pInfo->szFullName, szFileName);
pInfo->lcLocale = lcLocale;
pInfo->dwFileSize = dwFileSize;
pInfo->dwAttributes = dwFileAttr;
return;
}
}
}
int TMainFrame::EnableDialogBars(BOOL bEnable)
{
HWND hWnd;
// Enable/disable the search mask
if((hWnd = ::GetDlgItem(m_wndDlgBar.m_hWnd, IDC_SMASKTITLE)) != NULL)
::EnableWindow(hWnd, bEnable);
if((hWnd = ::GetDlgItem(m_wndDlgBar.m_hWnd, IDC_MPQSEARCHMASK)) != NULL)
::EnableWindow(hWnd, bEnable);
return 0;
}
int TMainFrame::ReadLine(FILE * fp, TCHAR * szBuffer, int nMaxChars)
{
_TINT ch = 0;
int count = 0;
*szBuffer = 0;
if(feof(fp))
return -1;
while(!feof(fp) && (ch = _fgettc(fp)) != (TCHAR)-1)
{
if(ch == _T('\n'))
break;
if(0 <= ch && ch <= _T(' ') && ch != _T('\t'))
ch = _T(' ');
*szBuffer++ = (TCHAR)ch;
if(++count == nMaxChars)
{
// Skip line
while(!feof(fp) && fgetc(fp) != _T('\n'));
*szBuffer = 0;
return -1; // Line is to long
}
}
*szBuffer = 0;
return count;
}
int TMainFrame::SetStatusText(UINT nIDText, ...)
{
va_list argList;
char szText[512];
char szFmt[256];
// Load the string from resources
if(!LoadString(AfxGetResourceHandle(), nIDText, szFmt, sizeof(szFmt)-1))
return GetLastError();
// Format the string
va_start(argList, nIDText);
vsprintf(szText, szFmt, argList);
va_end(argList);
// Set the text into status bar
::SendMessage(m_hWnd, WM_SETSTATUSTEXT, 0, (LPARAM)szText);
return ERROR_SUCCESS;
}
int TMainFrame::CreateMpqEvent(const char * szMpqName)
{
HANDLE hEvent = NULL;
char szEventName[MAX_PATH+0x20];
int nError = ERROR_SUCCESS;
// Create event name
sprintf(szEventName, "MpqEditorEvent%s", szMpqName);
for(char * szTemp = szEventName; *szTemp != 0; szTemp++)
{
if(!isalnum(*szTemp))
*szTemp = '_';
}
// Try to open event. If exists it means that this MPQ is already open with another instance
if((hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, szEventName)) != NULL)
{
AfxMessageBox(IDS_ALREADYOPEN);
CloseHandle(hEvent);
return ERROR_ALREADY_EXISTS;
}
// Create the event
if((m_hMpqEvent = CreateEvent(NULL, FALSE, FALSE, szEventName)) == NULL)
nError = GetLastError();
return nError;
}
int TMainFrame::AddFileToTree(const char * szFileName, LCID lcLocale, DWORD dwFileSize, DWORD dwFileAttr)
{
TFileInfo * pInfo = NULL;
HTREEITEM hRootItem = NULL;
HTREEITEM hSubItem = NULL;
CPtrList * pFileList = NULL;
POSITION pos;
char szSubDir[MAX_PATH];
char * szSaveFileName = (char *)szFileName;
char * szSlash = NULL;
// int nError = ERROR_SUCCESS;
// Retrieve the parent tree
if((hRootItem = TreeView_GetRoot(m_pTreeView->GetHwnd())) == NULL)
return ERROR_CAN_NOT_COMPLETE;
// Create directory structure
while((szSlash = strchr(szFileName, '\\')) != NULL)
{
strncpy(szSubDir, szFileName, (szSlash - szFileName));
szSubDir[szSlash - szFileName] = 0;
// Try to find the tree item in the tree view
if((hSubItem = m_pTreeView->FindTreeItem(hRootItem, szSubDir, &pFileList)) == NULL)
hSubItem = m_pTreeView->InsertTreeItem(hRootItem, szSubDir, &pFileList);
// Move to the next subdir
szFileName = szSlash+1;
hRootItem = hSubItem;
}
// For sure ....
if(hSubItem == NULL && pFileList == NULL)
hSubItem = m_pTreeView->GetRootTreeItem(&pFileList);
// Test if the file name is not already in the list
szFileName = szSaveFileName;
pos = pFileList->GetHeadPosition();
while(pos != NULL)
{
pInfo = (TFileInfo *)pFileList->GetNext(pos);
if(!stricmp(pInfo->szFullName, szFileName) && pInfo->lcLocale == lcLocale)
return ERROR_ALREADY_EXISTS;
}
// Now we know the tree item and we can add the file entry into the list
pFileList->AddTail(CreateFileInfo(szFileName, lcLocale, dwFileSize, dwFileAttr));
return ERROR_SUCCESS;
}
// Adds file(s) into the archive.
int TMainFrame::AddFiles(HANDLE hMpq, TWorkInfo * pWork)
{
POSITION pos = pWork->pFileList->GetHeadPosition();
int nError = ERROR_SUCCESS;
SFileSetLocale(pWork->lcLocale);
while(nError == ERROR_SUCCESS && pos != NULL)
{
char * szFileName = (char *)pWork->pFileList->GetNext(pos);
char * szArchName = szFileName + pWork->New.nRelPathStart;
// Test if the work was not stopped
if(WorkStopped(pWork))
break;
// Update status text
SetStatusText(IDS_ADDINGFILE, szFileName);
nError = AddFileToArchive(pWork, hMpq, szFileName, szArchName);
if(nError != ERROR_SUCCESS)
break;
}
// When the adding stopped on "Already exists", it is OK.
if(nError == ERROR_ALREADY_EXISTS)
nError = ERROR_SUCCESS;
return nError;
}
// Variant with Storm.dll
int TMainFrame::LoadMpqArchiveST(const char * szMpqName, const char * szFileList)
{
HANDLE hMpq = NULL;
int nError = ERROR_SUCCESS;
// Open the archive
if(nError == ERROR_SUCCESS)
{
if(!pSFileOpenArchive(szMpqName, 0, 0, &hMpq))
nError = GetLastError();
}
// Search all files
if(nError == ERROR_SUCCESS)
{
SFILE_FIND_DATA wf;
HANDLE hFind = SFileFindFirstFileEx(NULL, m_strMask, &wf, szFileList, FALSE);
HANDLE hFile = NULL;
BOOL bResult = TRUE;
while(hFind != NULL && bResult == TRUE)
{
// Test if we have to exit
if(WaitForSingleObject(m_hStopEvent, 0) != WAIT_TIMEOUT)
break;
pSFileSetLocale(wf.lcLocale);
if(pSFileOpenFileEx(hMpq, wf.cFileName, 0, &hFile))
{
wf.dwFileSize = pSFileGetFileSize(hFile, NULL);
AddFileToTree(wf.cFileName, wf.lcLocale, wf.dwFileSize, 0);
pSFileCloseFile(hFile);
}
bResult = SFileFindNextFile(hFind, &wf);
}
// Close the search handle
if(hFind != NULL)
SFileFindClose(hFind);
}
// Close the MPQ Archive
if(hMpq != NULL)
pSFileCloseArchive(hMpq);
return nError;
}
// Variant with StormLib
int TMainFrame::LoadMpqArchiveSL(const char * szMpqName, const char * szFileList)
{
SFILE_FIND_DATA wf;
HANDLE hMpq = NULL;
HANDLE hFind = NULL;
HANDLE hFile = NULL;
DWORD dwFiles = 0;
DWORD dwFile = 0;
BOOL bResult = TRUE;
int nError = ERROR_SUCCESS;
// Open the archive
if(nError == ERROR_SUCCESS)
{
if(!SFileOpenArchive(szMpqName, 0, 0, &hMpq))
nError = GetLastError();
}
// Find the first file from the archive. If it fails, use the nameless search
if(nError == ERROR_SUCCESS && m_bNameless == FALSE)
{
dwFiles = SFileGetFileInfo(hMpq, SFILE_INFO_NUM_FILES);
if((hFind = SFileFindFirstFile(hMpq, m_strMask, &wf, szFileList)) != NULL)
{
while(hFind != NULL && bResult == TRUE)
{
// Test if we have to exit
if(WaitForSingleObject(m_hStopEvent, 0) != WAIT_TIMEOUT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -