diff options
Diffstat (limited to 'CPP/7zip/FileManager/PanelSplitFile.cpp')
-rwxr-xr-x | CPP/7zip/FileManager/PanelSplitFile.cpp | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/CPP/7zip/FileManager/PanelSplitFile.cpp b/CPP/7zip/FileManager/PanelSplitFile.cpp new file mode 100755 index 00000000..8e095628 --- /dev/null +++ b/CPP/7zip/FileManager/PanelSplitFile.cpp @@ -0,0 +1,477 @@ +// PanelSplitFile.cpp + +#include "StdAfx.h" + +#include "resource.h" + +#include "Common/Alloc.h" +#include "Common/Types.h" +#include "Common/IntToString.h" + +#include "Windows/COM.h" +#include "Windows/FileIO.h" +#include "Windows/FileFind.h" +#include "Windows/Thread.h" +#include "Resource/ProgressDialog2/ProgressDialog.h" +#include "Resource/SplitDialog/SplitDialog.h" +#include "Resource/CopyDialog/CopyDialog.h" + +#include "../UI/Resource/Extract/resource.h" + +#include "SplitUtils.h" +#include "App.h" +#include "FormatUtils.h" +#include "LangUtils.h" + +using namespace NWindows; + +class CMyBuffer +{ + void *_data; +public: + CMyBuffer(): _data(0) {} + operator void *() { return _data; } + bool Allocate(size_t size) + { + if (_data != 0) + return false; + _data = ::MidAlloc(size); + return _data != 0; + } + ~CMyBuffer() { ::MidFree(_data); } +}; + +struct CVolSeqName +{ + UString UnchangedPart; + UString ChangedPart; + CVolSeqName(): ChangedPart(L"000") {}; + + bool ParseName(const UString &name) + { + if (name.Right(2) != L"01") + return false; + int numLetters = 2; + while (numLetters < name.Length()) + { + if (name[name.Length() - numLetters - 1] != '0') + break; + numLetters++; + } + UnchangedPart = name.Left(name.Length() - numLetters); + ChangedPart = name.Right(numLetters); + return true; + } + + UString GetNextName() + { + UString newName; + int i; + int numLetters = ChangedPart.Length(); + for (i = numLetters - 1; i >= 0; i--) + { + wchar_t c = ChangedPart[i]; + if (c == L'9') + { + c = L'0'; + newName = c + newName; + if (i == 0) + newName = UString(L'1') + newName; + continue; + } + c++; + newName = c + newName; + i--; + for (; i >= 0; i--) + newName = ChangedPart[i] + newName; + break; + } + ChangedPart = newName; + return UnchangedPart + ChangedPart; + } +}; + +static const UInt32 kBufSize = (1 << 20); + +struct CThreadSplit +{ + // HRESULT Result; + // CPanel *Panel; + CProgressDialog *ProgressDialog; + UString FilePath; + UString VolBasePath; + CRecordVector<UInt64> VolumeSizes; + UString Error; + + void Process2() + { + // NCOM::CComInitializer comInitializer; + ProgressDialog->WaitCreating(); + NFile::NIO::CInFile inFile; + if (!inFile.Open(FilePath)) + throw L"Can not open file"; + NFile::NIO::COutFile outFile; + CMyBuffer bufferObject; + if (!bufferObject.Allocate(kBufSize)) + throw L"Can not allocate buffer"; + Byte *buffer = (Byte *)(void *)bufferObject; + UInt64 curVolSize = 0; + CVolSeqName seqName; + UInt64 length; + if (!inFile.GetLength(length)) + throw "error"; + + ProgressDialog->ProgressSynch.SetProgress(length, 0); + UInt64 pos = 0; + + int volIndex = 0; + + for (;;) + { + UInt64 volSize; + if (volIndex < VolumeSizes.Size()) + volSize = VolumeSizes[volIndex]; + else + volSize = VolumeSizes.Back(); + + UInt32 needSize = (UInt32)(MyMin((UInt64)kBufSize, volSize - curVolSize)); + UInt32 processedSize; + if (!inFile.Read(buffer, needSize, processedSize)) + throw L"Can not read input file"; + if (processedSize == 0) + break; + needSize = processedSize; + if (curVolSize == 0) + { + UString name = VolBasePath; + name += L"."; + name += seqName.GetNextName(); + if (!outFile.Create(name, false)) + throw L"Can not create output file"; + ProgressDialog->ProgressSynch.SetCurrentFileName(name); + } + if (!outFile.Write(buffer, needSize, processedSize)) + throw L"Can not write output file"; + if (needSize != processedSize) + throw L"Can not write output file"; + curVolSize += processedSize; + if (curVolSize == volSize) + { + outFile.Close(); + if (volIndex < VolumeSizes.Size()) + volIndex++; + curVolSize = 0; + } + pos += processedSize; + HRESULT res = ProgressDialog->ProgressSynch.SetPosAndCheckPaused(pos); + if (res != S_OK) + return; + } + } + DWORD Process() + { + try { Process2(); } + catch(const wchar_t *s) { Error = s; } + catch(...) { Error = L"Error"; } + ProgressDialog->MyClose(); + return 0; + } + + static DWORD WINAPI MyThreadFunction(void *param) + { + return ((CThreadSplit *)param)->Process(); + } +}; + +void CApp::Split() +{ + int srcPanelIndex = GetFocusedPanelIndex(); + CPanel &srcPanel = Panels[srcPanelIndex]; + if (!srcPanel.IsFSFolder()) + { + srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208)); + return; + } + CRecordVector<UInt32> indices; + srcPanel.GetOperatedItemIndices(indices); + if (indices.IsEmpty()) + return; + if (indices.Size() != 1) + { + srcPanel.MessageBox(L"Select one file"); + return; + } + int index = indices[0]; + if (srcPanel.IsItemFolder(index)) + { + srcPanel.MessageBox(L"Select one file"); + return; + } + const UString itemName = srcPanel.GetItemName(index); + + UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); + UString path = srcPath; + int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + CPanel &destPanel = Panels[destPanelIndex]; + if (NumPanels > 1) + if (destPanel.IsFSFolder()) + path = destPanel._currentFolderPrefix; + CSplitDialog splitDialog; + splitDialog.FilePath = srcPanel.GetItemRelPath(index); + splitDialog.Path = path; + if (splitDialog.Create(srcPanel.GetParent()) == IDCANCEL) + return; + + NFile::NFind::CFileInfoW fileInfo; + if (!NFile::NFind::FindFile(srcPath + itemName, fileInfo)) + { + srcPanel.MessageBoxMyError(L"Can not find file"); + return; + } + if (fileInfo.Size <= splitDialog.VolumeSizes.Front()) + { + srcPanel.MessageBoxMyError(LangString(IDS_SPLIT_VOL_MUST_BE_SMALLER, 0x03020522)); + return; + } + const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes); + if (numVolumes >= 100) + { + wchar_t s[32]; + ConvertUInt64ToString(numVolumes, s); + if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, 0x03020521, s), + LangString(IDS_SPLIT_CONFIRM_TITLE, 0x03020520), + MB_YESNOCANCEL | MB_ICONQUESTION | MB_TASKMODAL) != IDYES) + return; + } + + path = splitDialog.Path; + NFile::NName::NormalizeDirPathPrefix(path); + if (!NFile::NDirectory::CreateComplexDirectory(path)) + { + srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); + return; + } + + CThreadSplit spliter; + // spliter.Panel = this; + + CProgressDialog progressDialog; + spliter.ProgressDialog = &progressDialog; + + UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + UString title = LangString(IDS_SPLITTING, 0x03020510); + + progressDialog.MainWindow = _window; + progressDialog.MainTitle = progressWindowTitle; + progressDialog.MainAddTitle = title + UString(L" "); + progressDialog.ProgressSynch.SetTitleFileName(itemName); + + + spliter.FilePath = srcPath + itemName; + spliter.VolBasePath = path + itemName; + spliter.VolumeSizes = splitDialog.VolumeSizes; + + // if (splitDialog.VolumeSizes.Size() == 0) return; + + // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel); + // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel); + + CThread thread; + if (!thread.Create(CThreadSplit::MyThreadFunction, &spliter)) + throw 271824; + progressDialog.Create(title, _window); + + if (!spliter.Error.IsEmpty()) + srcPanel.MessageBoxMyError(spliter.Error); + // disableTimerProcessing1.Restore(); + // disableTimerProcessing2.Restore(); + // srcPanel.SetFocusToList(); + // srcPanel.RefreshListCtrlSaveFocused(); +} + + +struct CThreadCombine +{ + CProgressDialog *ProgressDialog; + UString InputDirPrefix; + UString FirstVolumeName; + UString OutputDirPrefix; + UString Error; + + void Process2() + { + // NCOM::CComInitializer comInitializer; + ProgressDialog->WaitCreating(); + + CVolSeqName volSeqName; + if (!volSeqName.ParseName(FirstVolumeName)) + throw L"Can not detect file as splitted file"; + + UString nextName = InputDirPrefix + FirstVolumeName; + UInt64 totalSize = 0; + for (;;) + { + NFile::NFind::CFileInfoW fileInfo; + if (!NFile::NFind::FindFile(nextName, fileInfo)) + break; + if (fileInfo.IsDirectory()) + break; + totalSize += fileInfo.Size; + nextName = InputDirPrefix + volSeqName.GetNextName(); + } + if (totalSize == 0) + throw L"no data"; + ProgressDialog->ProgressSynch.SetProgress(totalSize, 0); + + if (!volSeqName.ParseName(FirstVolumeName)) + throw L"Can not detect file as splitted file"; + + UString outName = volSeqName.UnchangedPart; + while(!outName.IsEmpty()) + { + int lastIndex = outName.Length() - 1; + if (outName[lastIndex] != L'.') + break; + outName.Delete(lastIndex); + } + if (outName.IsEmpty()) + outName = L"file"; + NFile::NIO::COutFile outFile; + if (!outFile.Create(OutputDirPrefix + outName, false)) + throw L"Can create open output file"; + + NFile::NIO::CInFile inFile; + CMyBuffer bufferObject; + if (!bufferObject.Allocate(kBufSize)) + throw L"Can not allocate buffer"; + Byte *buffer = (Byte *)(void *)bufferObject; + UInt64 pos = 0; + nextName = InputDirPrefix + FirstVolumeName; + bool needOpen = true; + for (;;) + { + if (needOpen) + { + NFile::NFind::CFileInfoW fileInfo; + if (!NFile::NFind::FindFile(nextName, fileInfo)) + break; + if (fileInfo.IsDirectory()) + break; + if (!inFile.Open(nextName)) + throw L"Can not open file"; + ProgressDialog->ProgressSynch.SetCurrentFileName(fileInfo.Name); + nextName = InputDirPrefix + volSeqName.GetNextName(); + needOpen = false; + } + UInt32 processedSize; + if (!inFile.Read(buffer, kBufSize, processedSize)) + throw L"Can not read input file"; + if (processedSize == 0) + { + needOpen = true; + continue; + } + UInt32 needSize = processedSize; + if (!outFile.Write(buffer, needSize, processedSize)) + throw L"Can not write output file"; + if (needSize != processedSize) + throw L"Can not write output file"; + pos += processedSize; + HRESULT res = ProgressDialog->ProgressSynch.SetPosAndCheckPaused(pos); + if (res != S_OK) + return; + } + } + DWORD Process() + { + try { Process2(); } + catch(const wchar_t *s) { Error = s; } + catch(...) { Error = L"Error";} + ProgressDialog->MyClose(); + return 0; + } + + static DWORD WINAPI MyThreadFunction(void *param) + { + return ((CThreadCombine *)param)->Process(); + } +}; + +void CApp::Combine() +{ + int srcPanelIndex = GetFocusedPanelIndex(); + CPanel &srcPanel = Panels[srcPanelIndex]; + if (!srcPanel.IsFSFolder()) + { + srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208)); + return; + } + CRecordVector<UInt32> indices; + srcPanel.GetOperatedItemIndices(indices); + if (indices.IsEmpty()) + return; + int index = indices[0]; + if (indices.Size() != 1 || srcPanel.IsItemFolder(index)) + { + srcPanel.MessageBox(LangString(IDS_COMBINE_SELECT_ONE_FILE, 0x03020620)); + return; + } + const UString itemName = srcPanel.GetItemName(index); + + UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); + UString path = srcPath; + int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + CPanel &destPanel = Panels[destPanelIndex]; + if (NumPanels > 1) + if (destPanel.IsFSFolder()) + path = destPanel._currentFolderPrefix; + CCopyDialog copyDialog; + copyDialog.Value = path; + copyDialog.Title = LangString(IDS_COMBINE, 0x03020600); + copyDialog.Title += ' '; + copyDialog.Title += srcPanel.GetItemRelPath(index); + + copyDialog.Static = LangString(IDS_COMBINE_TO, 0x03020601);; + if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL) + return; + + CThreadCombine combiner; + // combiner.Panel = this; + + CProgressDialog progressDialog; + combiner.ProgressDialog = &progressDialog; + + UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); + UString title = LangString(IDS_COMBINING, 0x03020610); + + progressDialog.MainWindow = _window; + progressDialog.MainTitle = progressWindowTitle; + progressDialog.MainAddTitle = title + UString(L" "); + + path = copyDialog.Value; + NFile::NName::NormalizeDirPathPrefix(path); + if (!NFile::NDirectory::CreateComplexDirectory(path)) + { + srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); + return; + } + + combiner.InputDirPrefix = srcPath; + combiner.FirstVolumeName = itemName; + combiner.OutputDirPrefix = path; + + // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel); + // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel); + + CThread thread; + if (!thread.Create(CThreadCombine::MyThreadFunction, &combiner)) + throw 271824; + progressDialog.Create(title, _window); + + if (!combiner.Error.IsEmpty()) + srcPanel.MessageBoxMyError(combiner.Error); + // disableTimerProcessing1.Restore(); + // disableTimerProcessing2.Restore(); + // srcPanel.SetFocusToList(); + // srcPanel.RefreshListCtrlSaveFocused(); +} |