1*f6dc9357SAndroid Build Coastguard Worker // PanelSplitFile.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/ErrorMsg.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileName.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #include "../GUI/ExtractRes.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "resource.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "App.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "CopyDialog.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "FormatUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "LangUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "SplitDialog.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "SplitUtils.h"
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker #include "PropertyNameRes.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
24*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
25*f6dc9357SAndroid Build Coastguard Worker using namespace NDir;
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker static const char * const g_Message_FileWriteError = "File write error";
28*f6dc9357SAndroid Build Coastguard Worker
29*f6dc9357SAndroid Build Coastguard Worker struct CVolSeqName
30*f6dc9357SAndroid Build Coastguard Worker {
31*f6dc9357SAndroid Build Coastguard Worker UString UnchangedPart;
32*f6dc9357SAndroid Build Coastguard Worker UString ChangedPart;
CVolSeqNameCVolSeqName33*f6dc9357SAndroid Build Coastguard Worker CVolSeqName(): ChangedPart("000") {}
34*f6dc9357SAndroid Build Coastguard Worker
SetNumDigitsCVolSeqName35*f6dc9357SAndroid Build Coastguard Worker void SetNumDigits(UInt64 numVolumes)
36*f6dc9357SAndroid Build Coastguard Worker {
37*f6dc9357SAndroid Build Coastguard Worker ChangedPart = "000";
38*f6dc9357SAndroid Build Coastguard Worker while (numVolumes > 999)
39*f6dc9357SAndroid Build Coastguard Worker {
40*f6dc9357SAndroid Build Coastguard Worker numVolumes /= 10;
41*f6dc9357SAndroid Build Coastguard Worker ChangedPart.Add_Char('0');
42*f6dc9357SAndroid Build Coastguard Worker }
43*f6dc9357SAndroid Build Coastguard Worker }
44*f6dc9357SAndroid Build Coastguard Worker
ParseNameCVolSeqName45*f6dc9357SAndroid Build Coastguard Worker bool ParseName(const UString &name)
46*f6dc9357SAndroid Build Coastguard Worker {
47*f6dc9357SAndroid Build Coastguard Worker if (name.Len() < 2)
48*f6dc9357SAndroid Build Coastguard Worker return false;
49*f6dc9357SAndroid Build Coastguard Worker if (name.Back() != L'1' || name[name.Len() - 2] != L'0')
50*f6dc9357SAndroid Build Coastguard Worker return false;
51*f6dc9357SAndroid Build Coastguard Worker
52*f6dc9357SAndroid Build Coastguard Worker unsigned pos = name.Len() - 2;
53*f6dc9357SAndroid Build Coastguard Worker for (; pos > 0 && name[pos - 1] == '0'; pos--);
54*f6dc9357SAndroid Build Coastguard Worker UnchangedPart.SetFrom(name, pos);
55*f6dc9357SAndroid Build Coastguard Worker ChangedPart = name.Ptr(pos);
56*f6dc9357SAndroid Build Coastguard Worker return true;
57*f6dc9357SAndroid Build Coastguard Worker }
58*f6dc9357SAndroid Build Coastguard Worker
59*f6dc9357SAndroid Build Coastguard Worker UString GetNextName();
60*f6dc9357SAndroid Build Coastguard Worker };
61*f6dc9357SAndroid Build Coastguard Worker
62*f6dc9357SAndroid Build Coastguard Worker
GetNextName()63*f6dc9357SAndroid Build Coastguard Worker UString CVolSeqName::GetNextName()
64*f6dc9357SAndroid Build Coastguard Worker {
65*f6dc9357SAndroid Build Coastguard Worker for (int i = (int)ChangedPart.Len() - 1; i >= 0; i--)
66*f6dc9357SAndroid Build Coastguard Worker {
67*f6dc9357SAndroid Build Coastguard Worker const wchar_t c = ChangedPart[i];
68*f6dc9357SAndroid Build Coastguard Worker if (c != L'9')
69*f6dc9357SAndroid Build Coastguard Worker {
70*f6dc9357SAndroid Build Coastguard Worker ChangedPart.ReplaceOneCharAtPos((unsigned)i, (wchar_t)(c + 1));
71*f6dc9357SAndroid Build Coastguard Worker break;
72*f6dc9357SAndroid Build Coastguard Worker }
73*f6dc9357SAndroid Build Coastguard Worker ChangedPart.ReplaceOneCharAtPos((unsigned)i, L'0');
74*f6dc9357SAndroid Build Coastguard Worker if (i == 0)
75*f6dc9357SAndroid Build Coastguard Worker ChangedPart.InsertAtFront(L'1');
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker return UnchangedPart + ChangedPart;
78*f6dc9357SAndroid Build Coastguard Worker }
79*f6dc9357SAndroid Build Coastguard Worker
80*f6dc9357SAndroid Build Coastguard Worker class CThreadSplit: public CProgressThreadVirt
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker HRESULT ProcessVirt() Z7_override;
83*f6dc9357SAndroid Build Coastguard Worker public:
84*f6dc9357SAndroid Build Coastguard Worker FString FilePath;
85*f6dc9357SAndroid Build Coastguard Worker FString VolBasePath;
86*f6dc9357SAndroid Build Coastguard Worker UInt64 NumVolumes;
87*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> VolumeSizes;
88*f6dc9357SAndroid Build Coastguard Worker };
89*f6dc9357SAndroid Build Coastguard Worker
90*f6dc9357SAndroid Build Coastguard Worker
91*f6dc9357SAndroid Build Coastguard Worker class CPreAllocOutFile
92*f6dc9357SAndroid Build Coastguard Worker {
93*f6dc9357SAndroid Build Coastguard Worker UInt64 _preAllocSize;
94*f6dc9357SAndroid Build Coastguard Worker public:
95*f6dc9357SAndroid Build Coastguard Worker NIO::COutFile File;
96*f6dc9357SAndroid Build Coastguard Worker UInt64 Written;
97*f6dc9357SAndroid Build Coastguard Worker
CPreAllocOutFile()98*f6dc9357SAndroid Build Coastguard Worker CPreAllocOutFile(): _preAllocSize(0), Written(0) {}
99*f6dc9357SAndroid Build Coastguard Worker
~CPreAllocOutFile()100*f6dc9357SAndroid Build Coastguard Worker ~CPreAllocOutFile()
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker SetCorrectFileLength();
103*f6dc9357SAndroid Build Coastguard Worker }
104*f6dc9357SAndroid Build Coastguard Worker
PreAlloc(UInt64 preAllocSize)105*f6dc9357SAndroid Build Coastguard Worker void PreAlloc(UInt64 preAllocSize)
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker _preAllocSize = 0;
108*f6dc9357SAndroid Build Coastguard Worker if (File.SetLength(preAllocSize))
109*f6dc9357SAndroid Build Coastguard Worker _preAllocSize = preAllocSize;
110*f6dc9357SAndroid Build Coastguard Worker File.SeekToBegin();
111*f6dc9357SAndroid Build Coastguard Worker }
112*f6dc9357SAndroid Build Coastguard Worker
Write(const void * data,UInt32 size,UInt32 & processedSize)113*f6dc9357SAndroid Build Coastguard Worker bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw()
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker bool res = File.Write(data, size, processedSize);
116*f6dc9357SAndroid Build Coastguard Worker Written += processedSize;
117*f6dc9357SAndroid Build Coastguard Worker return res;
118*f6dc9357SAndroid Build Coastguard Worker }
119*f6dc9357SAndroid Build Coastguard Worker
Close()120*f6dc9357SAndroid Build Coastguard Worker void Close()
121*f6dc9357SAndroid Build Coastguard Worker {
122*f6dc9357SAndroid Build Coastguard Worker SetCorrectFileLength();
123*f6dc9357SAndroid Build Coastguard Worker Written = 0;
124*f6dc9357SAndroid Build Coastguard Worker _preAllocSize = 0;
125*f6dc9357SAndroid Build Coastguard Worker File.Close();
126*f6dc9357SAndroid Build Coastguard Worker }
127*f6dc9357SAndroid Build Coastguard Worker
SetCorrectFileLength()128*f6dc9357SAndroid Build Coastguard Worker void SetCorrectFileLength()
129*f6dc9357SAndroid Build Coastguard Worker {
130*f6dc9357SAndroid Build Coastguard Worker if (Written < _preAllocSize)
131*f6dc9357SAndroid Build Coastguard Worker {
132*f6dc9357SAndroid Build Coastguard Worker File.SetLength(Written);
133*f6dc9357SAndroid Build Coastguard Worker _preAllocSize = 0;
134*f6dc9357SAndroid Build Coastguard Worker }
135*f6dc9357SAndroid Build Coastguard Worker }
136*f6dc9357SAndroid Build Coastguard Worker };
137*f6dc9357SAndroid Build Coastguard Worker
138*f6dc9357SAndroid Build Coastguard Worker
139*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kBufSize = (1 << 20);
140*f6dc9357SAndroid Build Coastguard Worker
ProcessVirt()141*f6dc9357SAndroid Build Coastguard Worker HRESULT CThreadSplit::ProcessVirt()
142*f6dc9357SAndroid Build Coastguard Worker {
143*f6dc9357SAndroid Build Coastguard Worker NIO::CInFile inFile;
144*f6dc9357SAndroid Build Coastguard Worker if (!inFile.Open(FilePath))
145*f6dc9357SAndroid Build Coastguard Worker return GetLastError_noZero_HRESULT();
146*f6dc9357SAndroid Build Coastguard Worker
147*f6dc9357SAndroid Build Coastguard Worker CPreAllocOutFile outFile;
148*f6dc9357SAndroid Build Coastguard Worker
149*f6dc9357SAndroid Build Coastguard Worker CMyBuffer buffer;
150*f6dc9357SAndroid Build Coastguard Worker if (!buffer.Allocate(kBufSize))
151*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
152*f6dc9357SAndroid Build Coastguard Worker
153*f6dc9357SAndroid Build Coastguard Worker CVolSeqName seqName;
154*f6dc9357SAndroid Build Coastguard Worker seqName.SetNumDigits(NumVolumes);
155*f6dc9357SAndroid Build Coastguard Worker
156*f6dc9357SAndroid Build Coastguard Worker UInt64 length;
157*f6dc9357SAndroid Build Coastguard Worker if (!inFile.GetLength(length))
158*f6dc9357SAndroid Build Coastguard Worker return GetLastError_noZero_HRESULT();
159*f6dc9357SAndroid Build Coastguard Worker
160*f6dc9357SAndroid Build Coastguard Worker CProgressSync &sync = Sync;
161*f6dc9357SAndroid Build Coastguard Worker sync.Set_NumBytesTotal(length);
162*f6dc9357SAndroid Build Coastguard Worker
163*f6dc9357SAndroid Build Coastguard Worker UInt64 pos = 0;
164*f6dc9357SAndroid Build Coastguard Worker UInt64 prev = 0;
165*f6dc9357SAndroid Build Coastguard Worker UInt64 numFiles = 0;
166*f6dc9357SAndroid Build Coastguard Worker unsigned volIndex = 0;
167*f6dc9357SAndroid Build Coastguard Worker
168*f6dc9357SAndroid Build Coastguard Worker for (;;)
169*f6dc9357SAndroid Build Coastguard Worker {
170*f6dc9357SAndroid Build Coastguard Worker UInt64 volSize;
171*f6dc9357SAndroid Build Coastguard Worker if (volIndex < VolumeSizes.Size())
172*f6dc9357SAndroid Build Coastguard Worker volSize = VolumeSizes[volIndex];
173*f6dc9357SAndroid Build Coastguard Worker else
174*f6dc9357SAndroid Build Coastguard Worker volSize = VolumeSizes.Back();
175*f6dc9357SAndroid Build Coastguard Worker
176*f6dc9357SAndroid Build Coastguard Worker UInt32 needSize = kBufSize;
177*f6dc9357SAndroid Build Coastguard Worker {
178*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = volSize - outFile.Written;
179*f6dc9357SAndroid Build Coastguard Worker if (needSize > rem)
180*f6dc9357SAndroid Build Coastguard Worker needSize = (UInt32)rem;
181*f6dc9357SAndroid Build Coastguard Worker }
182*f6dc9357SAndroid Build Coastguard Worker UInt32 processedSize;
183*f6dc9357SAndroid Build Coastguard Worker if (!inFile.Read(buffer, needSize, processedSize))
184*f6dc9357SAndroid Build Coastguard Worker return GetLastError_noZero_HRESULT();
185*f6dc9357SAndroid Build Coastguard Worker if (processedSize == 0)
186*f6dc9357SAndroid Build Coastguard Worker return S_OK;
187*f6dc9357SAndroid Build Coastguard Worker needSize = processedSize;
188*f6dc9357SAndroid Build Coastguard Worker
189*f6dc9357SAndroid Build Coastguard Worker if (outFile.Written == 0)
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker FString name = VolBasePath;
192*f6dc9357SAndroid Build Coastguard Worker name.Add_Dot();
193*f6dc9357SAndroid Build Coastguard Worker name += us2fs(seqName.GetNextName());
194*f6dc9357SAndroid Build Coastguard Worker sync.Set_FilePath(fs2us(name));
195*f6dc9357SAndroid Build Coastguard Worker if (!outFile.File.Create_NEW(name))
196*f6dc9357SAndroid Build Coastguard Worker {
197*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = GetLastError_noZero_HRESULT();
198*f6dc9357SAndroid Build Coastguard Worker AddErrorPath(name);
199*f6dc9357SAndroid Build Coastguard Worker return res;
200*f6dc9357SAndroid Build Coastguard Worker }
201*f6dc9357SAndroid Build Coastguard Worker UInt64 expectSize = volSize;
202*f6dc9357SAndroid Build Coastguard Worker if (pos < length)
203*f6dc9357SAndroid Build Coastguard Worker {
204*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = length - pos;
205*f6dc9357SAndroid Build Coastguard Worker if (expectSize > rem)
206*f6dc9357SAndroid Build Coastguard Worker expectSize = rem;
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker outFile.PreAlloc(expectSize);
209*f6dc9357SAndroid Build Coastguard Worker }
210*f6dc9357SAndroid Build Coastguard Worker
211*f6dc9357SAndroid Build Coastguard Worker if (!outFile.Write(buffer, needSize, processedSize))
212*f6dc9357SAndroid Build Coastguard Worker return GetLastError_noZero_HRESULT();
213*f6dc9357SAndroid Build Coastguard Worker if (needSize != processedSize)
214*f6dc9357SAndroid Build Coastguard Worker throw g_Message_FileWriteError;
215*f6dc9357SAndroid Build Coastguard Worker
216*f6dc9357SAndroid Build Coastguard Worker pos += processedSize;
217*f6dc9357SAndroid Build Coastguard Worker
218*f6dc9357SAndroid Build Coastguard Worker if (outFile.Written == volSize)
219*f6dc9357SAndroid Build Coastguard Worker {
220*f6dc9357SAndroid Build Coastguard Worker outFile.Close();
221*f6dc9357SAndroid Build Coastguard Worker sync.Set_NumFilesCur(++numFiles);
222*f6dc9357SAndroid Build Coastguard Worker if (volIndex < VolumeSizes.Size())
223*f6dc9357SAndroid Build Coastguard Worker volIndex++;
224*f6dc9357SAndroid Build Coastguard Worker }
225*f6dc9357SAndroid Build Coastguard Worker
226*f6dc9357SAndroid Build Coastguard Worker if (pos - prev >= ((UInt32)1 << 22) || outFile.Written == 0)
227*f6dc9357SAndroid Build Coastguard Worker {
228*f6dc9357SAndroid Build Coastguard Worker RINOK(sync.Set_NumBytesCur(pos))
229*f6dc9357SAndroid Build Coastguard Worker prev = pos;
230*f6dc9357SAndroid Build Coastguard Worker }
231*f6dc9357SAndroid Build Coastguard Worker }
232*f6dc9357SAndroid Build Coastguard Worker }
233*f6dc9357SAndroid Build Coastguard Worker
234*f6dc9357SAndroid Build Coastguard Worker
Split()235*f6dc9357SAndroid Build Coastguard Worker void CApp::Split()
236*f6dc9357SAndroid Build Coastguard Worker {
237*f6dc9357SAndroid Build Coastguard Worker const unsigned srcPanelIndex = GetFocusedPanelIndex();
238*f6dc9357SAndroid Build Coastguard Worker CPanel &srcPanel = Panels[srcPanelIndex];
239*f6dc9357SAndroid Build Coastguard Worker if (!srcPanel.Is_IO_FS_Folder())
240*f6dc9357SAndroid Build Coastguard Worker {
241*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_UnsupportOperation();
242*f6dc9357SAndroid Build Coastguard Worker return;
243*f6dc9357SAndroid Build Coastguard Worker }
244*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> indices;
245*f6dc9357SAndroid Build Coastguard Worker srcPanel.Get_ItemIndices_Operated(indices);
246*f6dc9357SAndroid Build Coastguard Worker if (indices.IsEmpty())
247*f6dc9357SAndroid Build Coastguard Worker return;
248*f6dc9357SAndroid Build Coastguard Worker if (indices.Size() != 1)
249*f6dc9357SAndroid Build Coastguard Worker {
250*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
251*f6dc9357SAndroid Build Coastguard Worker return;
252*f6dc9357SAndroid Build Coastguard Worker }
253*f6dc9357SAndroid Build Coastguard Worker const unsigned index = indices[0];
254*f6dc9357SAndroid Build Coastguard Worker if (srcPanel.IsItem_Folder(index))
255*f6dc9357SAndroid Build Coastguard Worker {
256*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
257*f6dc9357SAndroid Build Coastguard Worker return;
258*f6dc9357SAndroid Build Coastguard Worker }
259*f6dc9357SAndroid Build Coastguard Worker const UString itemName = srcPanel.GetItemName(index);
260*f6dc9357SAndroid Build Coastguard Worker
261*f6dc9357SAndroid Build Coastguard Worker const UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
262*f6dc9357SAndroid Build Coastguard Worker UString path = srcPath;
263*f6dc9357SAndroid Build Coastguard Worker unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
264*f6dc9357SAndroid Build Coastguard Worker CPanel &destPanel = Panels[destPanelIndex];
265*f6dc9357SAndroid Build Coastguard Worker if (NumPanels > 1)
266*f6dc9357SAndroid Build Coastguard Worker if (destPanel.IsFSFolder())
267*f6dc9357SAndroid Build Coastguard Worker path = destPanel.GetFsPath();
268*f6dc9357SAndroid Build Coastguard Worker CSplitDialog splitDialog;
269*f6dc9357SAndroid Build Coastguard Worker splitDialog.FilePath = srcPanel.GetItemRelPath(index);
270*f6dc9357SAndroid Build Coastguard Worker splitDialog.Path = path;
271*f6dc9357SAndroid Build Coastguard Worker if (splitDialog.Create(srcPanel.GetParent()) != IDOK)
272*f6dc9357SAndroid Build Coastguard Worker return;
273*f6dc9357SAndroid Build Coastguard Worker
274*f6dc9357SAndroid Build Coastguard Worker NFind::CFileInfo fileInfo;
275*f6dc9357SAndroid Build Coastguard Worker if (!fileInfo.Find(us2fs(srcPath + itemName)))
276*f6dc9357SAndroid Build Coastguard Worker {
277*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error(L"Cannot find file");
278*f6dc9357SAndroid Build Coastguard Worker return;
279*f6dc9357SAndroid Build Coastguard Worker }
280*f6dc9357SAndroid Build Coastguard Worker if (fileInfo.Size <= splitDialog.VolumeSizes.FrontItem())
281*f6dc9357SAndroid Build Coastguard Worker {
282*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_LangID(IDS_SPLIT_VOL_MUST_BE_SMALLER);
283*f6dc9357SAndroid Build Coastguard Worker return;
284*f6dc9357SAndroid Build Coastguard Worker }
285*f6dc9357SAndroid Build Coastguard Worker const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes);
286*f6dc9357SAndroid Build Coastguard Worker if (numVolumes >= 100)
287*f6dc9357SAndroid Build Coastguard Worker {
288*f6dc9357SAndroid Build Coastguard Worker wchar_t s[32];
289*f6dc9357SAndroid Build Coastguard Worker ConvertUInt64ToString(numVolumes, s);
290*f6dc9357SAndroid Build Coastguard Worker if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, s),
291*f6dc9357SAndroid Build Coastguard Worker LangString(IDS_SPLIT_CONFIRM_TITLE),
292*f6dc9357SAndroid Build Coastguard Worker MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
293*f6dc9357SAndroid Build Coastguard Worker return;
294*f6dc9357SAndroid Build Coastguard Worker }
295*f6dc9357SAndroid Build Coastguard Worker
296*f6dc9357SAndroid Build Coastguard Worker path = splitDialog.Path;
297*f6dc9357SAndroid Build Coastguard Worker NName::NormalizeDirPathPrefix(path);
298*f6dc9357SAndroid Build Coastguard Worker if (!CreateComplexDir(us2fs(path)))
299*f6dc9357SAndroid Build Coastguard Worker {
300*f6dc9357SAndroid Build Coastguard Worker const HRESULT lastError = GetLastError_noZero_HRESULT();
301*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_2Lines_Message_HRESULT(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), lastError);
302*f6dc9357SAndroid Build Coastguard Worker return;
303*f6dc9357SAndroid Build Coastguard Worker }
304*f6dc9357SAndroid Build Coastguard Worker
305*f6dc9357SAndroid Build Coastguard Worker {
306*f6dc9357SAndroid Build Coastguard Worker CThreadSplit spliter;
307*f6dc9357SAndroid Build Coastguard Worker spliter.NumVolumes = numVolumes;
308*f6dc9357SAndroid Build Coastguard Worker
309*f6dc9357SAndroid Build Coastguard Worker CProgressDialog &progressDialog = spliter;
310*f6dc9357SAndroid Build Coastguard Worker
311*f6dc9357SAndroid Build Coastguard Worker const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000);
312*f6dc9357SAndroid Build Coastguard Worker const UString title = LangString(IDS_SPLITTING);
313*f6dc9357SAndroid Build Coastguard Worker
314*f6dc9357SAndroid Build Coastguard Worker progressDialog.ShowCompressionInfo = false;
315*f6dc9357SAndroid Build Coastguard Worker
316*f6dc9357SAndroid Build Coastguard Worker progressDialog.MainWindow = _window;
317*f6dc9357SAndroid Build Coastguard Worker progressDialog.MainTitle = progressWindowTitle;
318*f6dc9357SAndroid Build Coastguard Worker progressDialog.MainAddTitle = title;
319*f6dc9357SAndroid Build Coastguard Worker progressDialog.MainAddTitle.Add_Space();
320*f6dc9357SAndroid Build Coastguard Worker progressDialog.Sync.Set_TitleFileName(itemName);
321*f6dc9357SAndroid Build Coastguard Worker
322*f6dc9357SAndroid Build Coastguard Worker
323*f6dc9357SAndroid Build Coastguard Worker spliter.FilePath = us2fs(srcPath + itemName);
324*f6dc9357SAndroid Build Coastguard Worker spliter.VolBasePath = us2fs(path + srcPanel.GetItemName_for_Copy(index));
325*f6dc9357SAndroid Build Coastguard Worker spliter.VolumeSizes = splitDialog.VolumeSizes;
326*f6dc9357SAndroid Build Coastguard Worker
327*f6dc9357SAndroid Build Coastguard Worker // if (splitDialog.VolumeSizes.Size() == 0) return;
328*f6dc9357SAndroid Build Coastguard Worker
329*f6dc9357SAndroid Build Coastguard Worker // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
330*f6dc9357SAndroid Build Coastguard Worker // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);
331*f6dc9357SAndroid Build Coastguard Worker
332*f6dc9357SAndroid Build Coastguard Worker if (spliter.Create(title, _window) != 0)
333*f6dc9357SAndroid Build Coastguard Worker return;
334*f6dc9357SAndroid Build Coastguard Worker }
335*f6dc9357SAndroid Build Coastguard Worker RefreshTitleAlways();
336*f6dc9357SAndroid Build Coastguard Worker
337*f6dc9357SAndroid Build Coastguard Worker
338*f6dc9357SAndroid Build Coastguard Worker // disableNotify.Restore();
339*f6dc9357SAndroid Build Coastguard Worker // disableNotify.Restore();
340*f6dc9357SAndroid Build Coastguard Worker // srcPanel.SetFocusToList();
341*f6dc9357SAndroid Build Coastguard Worker // srcPanel.RefreshListCtrlSaveFocused();
342*f6dc9357SAndroid Build Coastguard Worker }
343*f6dc9357SAndroid Build Coastguard Worker
344*f6dc9357SAndroid Build Coastguard Worker
345*f6dc9357SAndroid Build Coastguard Worker class CThreadCombine: public CProgressThreadVirt
346*f6dc9357SAndroid Build Coastguard Worker {
347*f6dc9357SAndroid Build Coastguard Worker HRESULT ProcessVirt() Z7_override;
348*f6dc9357SAndroid Build Coastguard Worker public:
349*f6dc9357SAndroid Build Coastguard Worker FString InputDirPrefix;
350*f6dc9357SAndroid Build Coastguard Worker FStringVector Names;
351*f6dc9357SAndroid Build Coastguard Worker FString OutputPath;
352*f6dc9357SAndroid Build Coastguard Worker UInt64 TotalSize;
353*f6dc9357SAndroid Build Coastguard Worker };
354*f6dc9357SAndroid Build Coastguard Worker
ProcessVirt()355*f6dc9357SAndroid Build Coastguard Worker HRESULT CThreadCombine::ProcessVirt()
356*f6dc9357SAndroid Build Coastguard Worker {
357*f6dc9357SAndroid Build Coastguard Worker NIO::COutFile outFile;
358*f6dc9357SAndroid Build Coastguard Worker if (!outFile.Create_NEW(OutputPath))
359*f6dc9357SAndroid Build Coastguard Worker {
360*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = GetLastError_noZero_HRESULT();
361*f6dc9357SAndroid Build Coastguard Worker AddErrorPath(OutputPath);
362*f6dc9357SAndroid Build Coastguard Worker return res;
363*f6dc9357SAndroid Build Coastguard Worker }
364*f6dc9357SAndroid Build Coastguard Worker
365*f6dc9357SAndroid Build Coastguard Worker CProgressSync &sync = Sync;
366*f6dc9357SAndroid Build Coastguard Worker sync.Set_NumBytesTotal(TotalSize);
367*f6dc9357SAndroid Build Coastguard Worker
368*f6dc9357SAndroid Build Coastguard Worker CMyBuffer bufferObject;
369*f6dc9357SAndroid Build Coastguard Worker if (!bufferObject.Allocate(kBufSize))
370*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
371*f6dc9357SAndroid Build Coastguard Worker Byte *buffer = (Byte *)(void *)bufferObject;
372*f6dc9357SAndroid Build Coastguard Worker UInt64 pos = 0;
373*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, Names)
374*f6dc9357SAndroid Build Coastguard Worker {
375*f6dc9357SAndroid Build Coastguard Worker NIO::CInFile inFile;
376*f6dc9357SAndroid Build Coastguard Worker const FString nextName = InputDirPrefix + Names[i];
377*f6dc9357SAndroid Build Coastguard Worker if (!inFile.Open(nextName))
378*f6dc9357SAndroid Build Coastguard Worker {
379*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = GetLastError_noZero_HRESULT();
380*f6dc9357SAndroid Build Coastguard Worker AddErrorPath(nextName);
381*f6dc9357SAndroid Build Coastguard Worker return res;
382*f6dc9357SAndroid Build Coastguard Worker }
383*f6dc9357SAndroid Build Coastguard Worker sync.Set_FilePath(fs2us(nextName));
384*f6dc9357SAndroid Build Coastguard Worker for (;;)
385*f6dc9357SAndroid Build Coastguard Worker {
386*f6dc9357SAndroid Build Coastguard Worker UInt32 processedSize;
387*f6dc9357SAndroid Build Coastguard Worker if (!inFile.Read(buffer, kBufSize, processedSize))
388*f6dc9357SAndroid Build Coastguard Worker {
389*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = GetLastError_noZero_HRESULT();
390*f6dc9357SAndroid Build Coastguard Worker AddErrorPath(nextName);
391*f6dc9357SAndroid Build Coastguard Worker return res;
392*f6dc9357SAndroid Build Coastguard Worker }
393*f6dc9357SAndroid Build Coastguard Worker if (processedSize == 0)
394*f6dc9357SAndroid Build Coastguard Worker break;
395*f6dc9357SAndroid Build Coastguard Worker const UInt32 needSize = processedSize;
396*f6dc9357SAndroid Build Coastguard Worker if (!outFile.Write(buffer, needSize, processedSize))
397*f6dc9357SAndroid Build Coastguard Worker {
398*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = GetLastError_noZero_HRESULT();
399*f6dc9357SAndroid Build Coastguard Worker AddErrorPath(OutputPath);
400*f6dc9357SAndroid Build Coastguard Worker return res;
401*f6dc9357SAndroid Build Coastguard Worker }
402*f6dc9357SAndroid Build Coastguard Worker if (needSize != processedSize)
403*f6dc9357SAndroid Build Coastguard Worker throw g_Message_FileWriteError;
404*f6dc9357SAndroid Build Coastguard Worker pos += processedSize;
405*f6dc9357SAndroid Build Coastguard Worker RINOK(sync.Set_NumBytesCur(pos))
406*f6dc9357SAndroid Build Coastguard Worker }
407*f6dc9357SAndroid Build Coastguard Worker }
408*f6dc9357SAndroid Build Coastguard Worker return S_OK;
409*f6dc9357SAndroid Build Coastguard Worker }
410*f6dc9357SAndroid Build Coastguard Worker
411*f6dc9357SAndroid Build Coastguard Worker extern void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size);
412*f6dc9357SAndroid Build Coastguard Worker
AddInfoFileName(UString & dest,const UString & name)413*f6dc9357SAndroid Build Coastguard Worker static void AddInfoFileName(UString &dest, const UString &name)
414*f6dc9357SAndroid Build Coastguard Worker {
415*f6dc9357SAndroid Build Coastguard Worker dest += "\n ";
416*f6dc9357SAndroid Build Coastguard Worker dest += name;
417*f6dc9357SAndroid Build Coastguard Worker }
418*f6dc9357SAndroid Build Coastguard Worker
Combine()419*f6dc9357SAndroid Build Coastguard Worker void CApp::Combine()
420*f6dc9357SAndroid Build Coastguard Worker {
421*f6dc9357SAndroid Build Coastguard Worker const unsigned srcPanelIndex = GetFocusedPanelIndex();
422*f6dc9357SAndroid Build Coastguard Worker CPanel &srcPanel = Panels[srcPanelIndex];
423*f6dc9357SAndroid Build Coastguard Worker if (!srcPanel.IsFSFolder())
424*f6dc9357SAndroid Build Coastguard Worker {
425*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_LangID(IDS_OPERATION_IS_NOT_SUPPORTED);
426*f6dc9357SAndroid Build Coastguard Worker return;
427*f6dc9357SAndroid Build Coastguard Worker }
428*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> indices;
429*f6dc9357SAndroid Build Coastguard Worker srcPanel.Get_ItemIndices_Operated(indices);
430*f6dc9357SAndroid Build Coastguard Worker if (indices.IsEmpty())
431*f6dc9357SAndroid Build Coastguard Worker return;
432*f6dc9357SAndroid Build Coastguard Worker const unsigned index = indices[0];
433*f6dc9357SAndroid Build Coastguard Worker if (indices.Size() != 1 || srcPanel.IsItem_Folder(index))
434*f6dc9357SAndroid Build Coastguard Worker {
435*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_LangID(IDS_COMBINE_SELECT_ONE_FILE);
436*f6dc9357SAndroid Build Coastguard Worker return;
437*f6dc9357SAndroid Build Coastguard Worker }
438*f6dc9357SAndroid Build Coastguard Worker const UString itemName = srcPanel.GetItemName(index);
439*f6dc9357SAndroid Build Coastguard Worker
440*f6dc9357SAndroid Build Coastguard Worker UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
441*f6dc9357SAndroid Build Coastguard Worker UString path = srcPath;
442*f6dc9357SAndroid Build Coastguard Worker unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
443*f6dc9357SAndroid Build Coastguard Worker CPanel &destPanel = Panels[destPanelIndex];
444*f6dc9357SAndroid Build Coastguard Worker if (NumPanels > 1)
445*f6dc9357SAndroid Build Coastguard Worker if (destPanel.IsFSFolder())
446*f6dc9357SAndroid Build Coastguard Worker path = destPanel.GetFsPath();
447*f6dc9357SAndroid Build Coastguard Worker
448*f6dc9357SAndroid Build Coastguard Worker CVolSeqName volSeqName;
449*f6dc9357SAndroid Build Coastguard Worker if (!volSeqName.ParseName(itemName))
450*f6dc9357SAndroid Build Coastguard Worker {
451*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_LangID(IDS_COMBINE_CANT_DETECT_SPLIT_FILE);
452*f6dc9357SAndroid Build Coastguard Worker return;
453*f6dc9357SAndroid Build Coastguard Worker }
454*f6dc9357SAndroid Build Coastguard Worker
455*f6dc9357SAndroid Build Coastguard Worker {
456*f6dc9357SAndroid Build Coastguard Worker CThreadCombine combiner;
457*f6dc9357SAndroid Build Coastguard Worker
458*f6dc9357SAndroid Build Coastguard Worker UString nextName = itemName;
459*f6dc9357SAndroid Build Coastguard Worker combiner.TotalSize = 0;
460*f6dc9357SAndroid Build Coastguard Worker for (;;)
461*f6dc9357SAndroid Build Coastguard Worker {
462*f6dc9357SAndroid Build Coastguard Worker NFind::CFileInfo fileInfo;
463*f6dc9357SAndroid Build Coastguard Worker if (!fileInfo.Find(us2fs(srcPath + nextName)) || fileInfo.IsDir())
464*f6dc9357SAndroid Build Coastguard Worker break;
465*f6dc9357SAndroid Build Coastguard Worker combiner.Names.Add(us2fs(nextName));
466*f6dc9357SAndroid Build Coastguard Worker combiner.TotalSize += fileInfo.Size;
467*f6dc9357SAndroid Build Coastguard Worker nextName = volSeqName.GetNextName();
468*f6dc9357SAndroid Build Coastguard Worker }
469*f6dc9357SAndroid Build Coastguard Worker if (combiner.Names.Size() == 1)
470*f6dc9357SAndroid Build Coastguard Worker {
471*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_LangID(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART);
472*f6dc9357SAndroid Build Coastguard Worker return;
473*f6dc9357SAndroid Build Coastguard Worker }
474*f6dc9357SAndroid Build Coastguard Worker
475*f6dc9357SAndroid Build Coastguard Worker if (combiner.TotalSize == 0)
476*f6dc9357SAndroid Build Coastguard Worker {
477*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error(L"No data");
478*f6dc9357SAndroid Build Coastguard Worker return;
479*f6dc9357SAndroid Build Coastguard Worker }
480*f6dc9357SAndroid Build Coastguard Worker
481*f6dc9357SAndroid Build Coastguard Worker UString info;
482*f6dc9357SAndroid Build Coastguard Worker AddValuePair2(info, IDS_PROP_FILES, combiner.Names.Size(), combiner.TotalSize);
483*f6dc9357SAndroid Build Coastguard Worker
484*f6dc9357SAndroid Build Coastguard Worker info.Add_LF();
485*f6dc9357SAndroid Build Coastguard Worker info += srcPath;
486*f6dc9357SAndroid Build Coastguard Worker
487*f6dc9357SAndroid Build Coastguard Worker unsigned i;
488*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < combiner.Names.Size() && i < 2; i++)
489*f6dc9357SAndroid Build Coastguard Worker AddInfoFileName(info, fs2us(combiner.Names[i]));
490*f6dc9357SAndroid Build Coastguard Worker if (i != combiner.Names.Size())
491*f6dc9357SAndroid Build Coastguard Worker {
492*f6dc9357SAndroid Build Coastguard Worker if (i + 1 != combiner.Names.Size())
493*f6dc9357SAndroid Build Coastguard Worker AddInfoFileName(info, L"...");
494*f6dc9357SAndroid Build Coastguard Worker AddInfoFileName(info, fs2us(combiner.Names.Back()));
495*f6dc9357SAndroid Build Coastguard Worker }
496*f6dc9357SAndroid Build Coastguard Worker
497*f6dc9357SAndroid Build Coastguard Worker {
498*f6dc9357SAndroid Build Coastguard Worker CCopyDialog copyDialog;
499*f6dc9357SAndroid Build Coastguard Worker copyDialog.Value = path;
500*f6dc9357SAndroid Build Coastguard Worker LangString(IDS_COMBINE, copyDialog.Title);
501*f6dc9357SAndroid Build Coastguard Worker copyDialog.Title.Add_Space();
502*f6dc9357SAndroid Build Coastguard Worker copyDialog.Title += srcPanel.GetItemRelPath(index);
503*f6dc9357SAndroid Build Coastguard Worker LangString(IDS_COMBINE_TO, copyDialog.Static);
504*f6dc9357SAndroid Build Coastguard Worker copyDialog.Info = info;
505*f6dc9357SAndroid Build Coastguard Worker if (copyDialog.Create(srcPanel.GetParent()) != IDOK)
506*f6dc9357SAndroid Build Coastguard Worker return;
507*f6dc9357SAndroid Build Coastguard Worker path = copyDialog.Value;
508*f6dc9357SAndroid Build Coastguard Worker }
509*f6dc9357SAndroid Build Coastguard Worker
510*f6dc9357SAndroid Build Coastguard Worker NName::NormalizeDirPathPrefix(path);
511*f6dc9357SAndroid Build Coastguard Worker if (!CreateComplexDir(us2fs(path)))
512*f6dc9357SAndroid Build Coastguard Worker {
513*f6dc9357SAndroid Build Coastguard Worker const HRESULT lastError = GetLastError_noZero_HRESULT();
514*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error_2Lines_Message_HRESULT(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), lastError);
515*f6dc9357SAndroid Build Coastguard Worker return;
516*f6dc9357SAndroid Build Coastguard Worker }
517*f6dc9357SAndroid Build Coastguard Worker
518*f6dc9357SAndroid Build Coastguard Worker UString outName = volSeqName.UnchangedPart;
519*f6dc9357SAndroid Build Coastguard Worker while (!outName.IsEmpty())
520*f6dc9357SAndroid Build Coastguard Worker {
521*f6dc9357SAndroid Build Coastguard Worker if (outName.Back() != L'.')
522*f6dc9357SAndroid Build Coastguard Worker break;
523*f6dc9357SAndroid Build Coastguard Worker outName.DeleteBack();
524*f6dc9357SAndroid Build Coastguard Worker }
525*f6dc9357SAndroid Build Coastguard Worker if (outName.IsEmpty())
526*f6dc9357SAndroid Build Coastguard Worker outName = "file";
527*f6dc9357SAndroid Build Coastguard Worker
528*f6dc9357SAndroid Build Coastguard Worker NFind::CFileInfo fileInfo;
529*f6dc9357SAndroid Build Coastguard Worker UString destFilePath = path + outName;
530*f6dc9357SAndroid Build Coastguard Worker combiner.OutputPath = us2fs(destFilePath);
531*f6dc9357SAndroid Build Coastguard Worker if (fileInfo.Find(combiner.OutputPath))
532*f6dc9357SAndroid Build Coastguard Worker {
533*f6dc9357SAndroid Build Coastguard Worker srcPanel.MessageBox_Error(MyFormatNew(IDS_FILE_EXIST, destFilePath));
534*f6dc9357SAndroid Build Coastguard Worker return;
535*f6dc9357SAndroid Build Coastguard Worker }
536*f6dc9357SAndroid Build Coastguard Worker
537*f6dc9357SAndroid Build Coastguard Worker CProgressDialog &progressDialog = combiner;
538*f6dc9357SAndroid Build Coastguard Worker progressDialog.ShowCompressionInfo = false;
539*f6dc9357SAndroid Build Coastguard Worker
540*f6dc9357SAndroid Build Coastguard Worker const UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000);
541*f6dc9357SAndroid Build Coastguard Worker const UString title = LangString(IDS_COMBINING);
542*f6dc9357SAndroid Build Coastguard Worker
543*f6dc9357SAndroid Build Coastguard Worker progressDialog.MainWindow = _window;
544*f6dc9357SAndroid Build Coastguard Worker progressDialog.MainTitle = progressWindowTitle;
545*f6dc9357SAndroid Build Coastguard Worker progressDialog.MainAddTitle = title;
546*f6dc9357SAndroid Build Coastguard Worker progressDialog.MainAddTitle.Add_Space();
547*f6dc9357SAndroid Build Coastguard Worker
548*f6dc9357SAndroid Build Coastguard Worker combiner.InputDirPrefix = us2fs(srcPath);
549*f6dc9357SAndroid Build Coastguard Worker
550*f6dc9357SAndroid Build Coastguard Worker // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
551*f6dc9357SAndroid Build Coastguard Worker // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);
552*f6dc9357SAndroid Build Coastguard Worker
553*f6dc9357SAndroid Build Coastguard Worker if (combiner.Create(title, _window) != 0)
554*f6dc9357SAndroid Build Coastguard Worker return;
555*f6dc9357SAndroid Build Coastguard Worker }
556*f6dc9357SAndroid Build Coastguard Worker RefreshTitleAlways();
557*f6dc9357SAndroid Build Coastguard Worker
558*f6dc9357SAndroid Build Coastguard Worker // disableNotify.Restore();
559*f6dc9357SAndroid Build Coastguard Worker // disableNotify.Restore();
560*f6dc9357SAndroid Build Coastguard Worker // srcPanel.SetFocusToList();
561*f6dc9357SAndroid Build Coastguard Worker // srcPanel.RefreshListCtrlSaveFocused();
562*f6dc9357SAndroid Build Coastguard Worker }
563