1 /*******************************************************************************
\r
2 TPI - flexible but useless plug-in framework.
\r
3 Copyright (C) 2002-2009 Silky
\r
5 This library is free software; you can redistribute it and/or modify it under
\r
6 the terms of the GNU Lesser General Public License as published by the Free
\r
7 Software Foundation; either version 2.1 of the License, or (at your option)
\r
10 This library is distributed in the hope that it will be useful, but WITHOUT
\r
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
\r
15 You should have received a copy of the GNU Lesser General Public License along
\r
16 with this library; if not, write to the Free Software Foundation, Inc.,
\r
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
\r
20 *******************************************************************************/
\r
24 #include "frm_main.h"
\r
25 #include "cls_filedroptarget.h"
\r
26 #include "dlg_make.h"
\r
27 #include "dlg_process.h"
\r
28 #include "functions.h"
\r
30 #include <wx/arrimpl.cpp>
\r
32 WX_DEFINE_OBJARRAY(ArrayTPI_FILEINFO);
\r
34 #define SetMenuToolState(id, state) this->toolbar->EnableTool(XRCID(id), state); this->menubar->Enable(XRCID(id), state)
\r
36 //******************************************************************************
\r
38 //******************************************************************************
\r
40 wxImageList g_hIconT(16, 16), g_hIconLL(32, 32), g_hIconLS(16, 16);
\r
44 //******************************************************************************
\r
46 //******************************************************************************
\r
48 MainFrame::MainFrame(): wxFrame()
\r
52 MainFrame::~MainFrame()
\r
55 this->OnArcClose(e);
\r
58 if (! this->IsIconized() && ! this->IsMaximized())
\r
61 this->GetSize(& a, & b);
\r
62 this->conf.WriteId(CONF_WINDOW_WIDTH, a);
\r
63 this->conf.WriteId(CONF_WINDOW_HEIGHT, b);
\r
64 this->GetPosition(& a, & b);
\r
65 this->conf.WriteId(CONF_WINDOW_X, a);
\r
66 this->conf.WriteId(CONF_WINDOW_Y, b);
\r
68 this->conf.WriteId(CONF_WINDOW_SPLITTER_POS, this->window_splitter->GetSashPosition());
\r
71 this->conf.WriteId(CONF_WINDOW_STATUSBAR, this->statusbar->IsShown());
\r
72 this->conf.WriteId(CONF_WINDOW_TOOLBAR, this->toolbar->IsShown());
\r
75 this->conf.WriteId(CONF_LISTVIEW_SHOWMODE, this->menubar->IsChecked(XRCID("Exe_View_Icons")) ? 1 : this->menubar->IsChecked(XRCID("Exe_View_List")) ? 2 : 0);
\r
76 if (this->menubar->IsChecked(XRCID("Exe_View_Details")))
\r
78 this->conf.WriteId(CONF_LISTVIEW_C_FILENAME, this->list_ctrl->GetColumnWidth(0));
\r
79 this->conf.WriteId(CONF_LISTVIEW_C_UNPACKED, this->list_ctrl->GetColumnWidth(1));
\r
80 this->conf.WriteId(CONF_LISTVIEW_C_PACKED, this->list_ctrl->GetColumnWidth(2));
\r
81 this->conf.WriteId(CONF_LISTVIEW_C_RATIO, this->list_ctrl->GetColumnWidth(3));
\r
82 this->conf.WriteId(CONF_LISTVIEW_C_METHOD, this->list_ctrl->GetColumnWidth(4));
\r
83 this->conf.WriteId(CONF_LISTVIEW_C_ATTR, this->list_ctrl->GetColumnWidth(5));
\r
84 this->conf.WriteId(CONF_LISTVIEW_C_LASTMOD, this->list_ctrl->GetColumnWidth(6));
\r
85 this->conf.WriteId(CONF_LISTVIEW_C_PATH, this->list_ctrl->GetColumnWidth(7));
\r
86 this->conf.WriteId(CONF_LISTVIEW_C_TYPE, this->list_ctrl->GetColumnWidth(8));
\r
87 this->conf.WriteId(CONF_LISTVIEW_C_NO, this->list_ctrl->GetColumnWidth(9));
\r
88 this->conf.WriteId(CONF_LISTVIEW_S_COLUMN, g_nSortColumn);
\r
89 this->conf.WriteId(CONF_LISTVIEW_S_ASCEND, g_fSortAscend);
\r
95 //******************************************************************************
\r
97 //******************************************************************************
\r
99 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
\r
100 EVT_INIT_DIALOG( MainFrame::OnInit)
\r
102 EVT_MENU(XRCID("Arc_Create"), MainFrame::OnArcCreate)
\r
103 EVT_MENU(XRCID("Arc_Open"), MainFrame::OnArcOpen)
\r
104 EVT_MENU(XRCID("Arc_Close"), MainFrame::OnArcClose)
\r
105 EVT_MENU(XRCID("Arc_Add"), MainFrame::OnArcAdd)
\r
106 EVT_MENU(XRCID("Arc_SFX"), MainFrame::OnArcConvert)
\r
107 EVT_MENU(XRCID("Arc_UnSFX"), MainFrame::OnArcConvert)
\r
108 EVT_MENU(XRCID("Exe_Exit"), MainFrame::OnExit)
\r
109 EVT_MENU(XRCID("Arc_Extract"), MainFrame::OnArcExtract)
\r
110 EVT_MENU(XRCID("Arc_Delete"), MainFrame::OnArcDelete)
\r
111 EVT_MENU(XRCID("Arc_Test"), MainFrame::OnArcTest)
\r
112 EVT_MENU(XRCID("Arc_Repair"), MainFrame::OnArcRepair)
\r
113 EVT_MENU(XRCID("Exe_View_Icons"), MainFrame::OnViewMode)
\r
114 EVT_MENU(XRCID("Exe_View_Details"),MainFrame::OnViewMode)
\r
115 EVT_MENU(XRCID("Exe_View_List"), MainFrame::OnViewMode)
\r
116 EVT_MENU(XRCID("Exe_View_ToolBar"),MainFrame::OnShowToolBar)
\r
117 EVT_MENU(XRCID("Exe_View_StatusBar"),MainFrame::OnShowStatusBar)
\r
118 EVT_MENU(XRCID("Exe_View_SelectAll"),MainFrame::OnSelectAll)
\r
120 EVT_TREE_SEL_CHANGED(XRCID("TreeView"), MainFrame::OnTreeChanged)
\r
121 EVT_TREE_BEGIN_DRAG( XRCID("TreeView"), MainFrame::OnTreeBeginDrag)
\r
123 EVT_LIST_ITEM_ACTIVATED(XRCID("ListView"), MainFrame::OnListItemDClick)
\r
124 EVT_LIST_BEGIN_DRAG( XRCID("ListView"), MainFrame::OnListBeginDrag)
\r
126 EVT_TEXT(XRCID("tcFilter"), MainFrame::OnFilter)
\r
129 //******************************************************************************
\r
131 //******************************************************************************
\r
133 void MainFrame::OnInit(wxInitDialogEvent&)
\r
136 this->menubar = this->GetMenuBar();
\r
137 this->toolbar = this->GetToolBar();
\r
138 this->statusbar = XRCCTRL(* this, "statusbar", wxStatusBar);
\r
139 this->tree_ctrl = XRCCTRL(* this, "TreeView", wxTreeCtrl);
\r
140 this->list_ctrl = XRCCTRL(* this, "ListView", myListCtrl);
\r
141 this->window_splitter = XRCCTRL(* this, "window_splitter", wxSplitterWindow);
\r
142 this->tcFilter = XRCCTRL(* this->toolbar, "tcFilter", wxTextCtrl);
\r
145 this->SetSize(this->conf.ReadId(CONF_WINDOW_X, 0l), this->conf.ReadId(CONF_WINDOW_Y, 0l), this->conf.ReadId(CONF_WINDOW_WIDTH, 800l), this->conf.ReadId(CONF_WINDOW_HEIGHT, 400l), wxSIZE_ALLOW_MINUS_ONE);
\r
146 wxTheMimeTypesManager->Initialize(wxMAILCAP_ALL);
\r
151 icon.CopyFromBitmap(wxBitmap(L_DIR_S_ICO wxT("app.png"), wxBITMAP_TYPE_ANY));
\r
152 this->SetIcon(icon);
\r
155 this->OnArcClose(e);
\r
156 this->SetDropTarget(new myFileDropTarget(this));
\r
159 this->window_splitter->SetSashPosition(this->conf.ReadId(CONF_WINDOW_SPLITTER_POS, 200l));
\r
162 int nIconMode = this->conf.ReadId(CONF_LISTVIEW_SHOWMODE, 0l);
\r
163 e.SetId(nIconMode == 1 ? XRCID("Exe_View_Icons") : (nIconMode == 2 ? XRCID("Exe_View_List") : XRCID("Exe_View_Details")));
\r
164 this->OnViewMode(e);
\r
165 // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。
\r
166 this->list_ctrl->SetSingleStyle(wxLC_VIRTUAL);
\r
167 this->list_ctrl->InsertColumn(0, _("Filename"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_FILENAME, 140l));
\r
168 this->list_ctrl->InsertColumn(1, _("Unpacked"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_UNPACKED, 80l));
\r
169 this->list_ctrl->InsertColumn(2, _("Packed"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_PACKED, 80l));
\r
170 this->list_ctrl->InsertColumn(3, _("Ratio"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_RATIO, 50l));
\r
171 this->list_ctrl->InsertColumn(4, _("Method"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_METHOD, 60l));
\r
172 this->list_ctrl->InsertColumn(5, _("Attr"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_ATTR, 50l));
\r
173 this->list_ctrl->InsertColumn(6, _("Last modified"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_LASTMOD, 150l));
\r
174 this->list_ctrl->InsertColumn(7, _("Path"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_PATH, 100l));
\r
175 this->list_ctrl->InsertColumn(8, _("Type"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_TYPE, 100l));
\r
176 this->list_ctrl->InsertColumn(9, _("No."), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_NO, 35l));
\r
177 g_nSortColumn = this->conf.ReadId(CONF_LISTVIEW_S_COLUMN, 9l);
\r
178 g_fSortAscend = this->conf.ReadId(CONF_LISTVIEW_S_ASCEND, true);
\r
180 // ツールバー/ステータスバー設定。
\r
181 int nStatusBarParts[] = {70, 70, 180, 50, -1};
\r
182 this->statusbar->SetFieldsCount(5, nStatusBarParts);
\r
183 this->SetStatusBarPane(-1);
\r
184 bool fShow = this->conf.ReadId(CONF_WINDOW_STATUSBAR, true);
\r
185 this->menubar->Check(XRCID("Exe_View_StatusBar"), fShow);
\r
186 this->statusbar->Show(fShow);
\r
187 fShow = this->conf.ReadId(CONF_WINDOW_TOOLBAR, true);
\r
188 this->menubar->Check(XRCID("Exe_View_ToolBar"), fShow);
\r
189 this->toolbar->Show(fShow);
\r
194 void MainFrame::OnExit(wxCommandEvent&)
\r
199 void MainFrame::OnArcCreate(wxCommandEvent& e)
\r
201 TPI_SWITCHES swInfo;
\r
202 swInfo.pCustomSwitches = NULL;
\r
206 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
207 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
209 if (e.GetClientData() == NULL)
\r
212 wxFileDialog fd(this, _("Choose files to compress"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
213 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
214 if (fd.ShowModal() == wxID_CANCEL)
\r
218 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
219 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
220 fd.GetFilenames(mkDlg.files);
\r
224 mkDlg.files = * (wxArrayString *) e.GetClientData();
\r
225 swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());
\r
227 for (size_t n = 0; n < mkDlg.files.GetCount(); n++)
\r
229 wxFileName fn(mkDlg.files[n]);
\r
230 fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());
\r
231 mkDlg.files[n] = fn.GetFullPath();
\r
235 this->OnArcClose(e);
\r
236 // 書庫名はファイル名の拡張子より前、もしくはディレクトリ名。
\r
237 this->fnArchive = wxFileName(mkDlg.files[0]);
\r
238 this->fnArchive.SetName(mkDlg.files.GetCount() == 1 ? (this->fnArchive.GetName().IsEmpty() ? this->fnArchive.GetDirs().Last() : this->fnArchive.GetName()) : swInfo.fnDestinationDirectory.GetDirs().Last());
\r
239 this->fnArchive.SetEmptyExt();
\r
240 this->fnArchive.SetPath(swInfo.fnDestinationDirectory.GetPath());
\r
243 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
249 swInfo.fStoreDirectoryPathes= ! mkDlg.cbIgnorePath->IsChecked();
\r
250 swInfo.fMakeSFX = mkDlg.cbMakeSFX->IsChecked();
\r
251 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
252 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
253 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
254 swInfo.fCompressHeader = mkDlg.cbCompressHeader->IsChecked();
\r
255 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
256 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
257 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
258 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
259 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
260 mkDlg.cbSplitSize->GetValue().ToULongLong(& swInfo.nSplitSize);
\r
263 int nSelected = mkDlg.chType->GetSelection();
\r
264 this->fnArchive = wxFileName(mkDlg.cbDir->GetValue(), mkDlg.cbFileName->GetValue());
\r
265 if (! tpi.InitLibrary(mkDlg.afInfo[nSelected].szTPIName, this->fnArchive.GetFullPath(), mkDlg.afInfo[nSelected].nTypeId))
\r
267 wxLogError(_("Error: %s!"), wxT("InitLibrary()!"));
\r
272 if (! tpi.SetCallbackProc(TPICallbackProc))
\r
274 wxLogError(_("Error: %s!"), wxT("SetCallbackProc()!"));
\r
279 ProcessDialog procDlg;
\r
280 procDlg.Show(true);
\r
283 TPI_PROCESSINFO piInfo;
\r
284 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
285 piInfo.eStatus = 0x1000;
\r
286 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
287 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
288 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
290 if (! tpi.Command(TPI_COMMAND_CREATE, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files))
\r
292 this->ErrorCheck(tpi.nErrorCode);
\r
295 procDlg.Show(false);
\r
299 if (mkDlg.cbOpenAfter->IsChecked())
\r
302 ::wxExecute(DIR_APP + swInfo.fnDestinationDirectory.GetFullPath());
\r
305 if (mkDlg.cbExitAfter->IsChecked())
\r
312 this->OnArcOpen(e);
\r
315 void MainFrame::OnArcOpen(wxCommandEvent& e)
\r
318 if (e.GetId() == XRCID("Arc_Open"))
\r
320 wxFileDialog fd(this);
\r
321 fd.SetDirectory(this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
322 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);
\r
323 if (fd.ShowModal() == wxID_CANCEL)
\r
327 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
328 this->fnArchive = wxFileName(fd.GetPath());
\r
330 this->OnArcClose(e);
\r
333 ProcessDialog procDlg;
\r
334 procDlg.Show(true);
\r
336 // TPIを読み込み、最初のコールバックを送信。
\r
337 TPI_PROCESSINFO piInfo;
\r
338 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
339 piInfo.eStatus = 0x1000;
\r
340 piInfo.nProcessedSize = 0;
\r
341 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
342 piInfo.fiInfo.nUnpackedSize = e.GetExtraLong() != 0 ? e.GetExtraLong() : this->LoadTPI(this->fnArchive.GetFullPath());
\r
343 if (piInfo.fiInfo.nUnpackedSize == 0)
\r
345 procDlg.Show(false);
\r
347 wxLogError(_("No plug-in supporting this archive was found!"));
\r
350 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
353 this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);
\r
356 if (! tpi.OpenArchive(this->fnArchive.GetFullPath()))
\r
358 procDlg.Show(false);
\r
360 wxLogError(_("Error: %s!"), wxT("OpenArchive()"));
\r
365 this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());
\r
366 this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());
\r
367 this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());
\r
369 // 書庫のアイコンを取得し、書庫ルートを作成。
\r
370 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));
\r
371 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));
\r
372 this->tree_ctrl->SetImageList(& g_hIconT);
\r
374 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),
\r
376 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName))),
\r
378 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName).ConvertToImage().Rescale(16, 16))),
\r
380 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);
\r
383 if (tpi.GetFileInformation(& piInfo.fiInfo, true))
\r
385 piInfo.eStatus = 0x1001;
\r
388 piInfo.nProcessedSize++;
\r
389 if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo)) == TPI_CALLBACK_CANCEL)
\r
391 procDlg.Show(false);
\r
392 tpi.CloseArchive();
\r
394 this->OnArcClose(e);
\r
399 TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, piInfo.fiInfo.fnFileName.GetPath(), true);
\r
401 // ディレクトリ属性を含むものについては除去。
\r
402 if (piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
409 if (piInfo.fiInfo.fnFileName.GetPathWithSep().Find(wxT("..")) != wxNOT_FOUND)
\r
411 piInfo.fiInfo.eDanger = TRUE;
\r
412 wxLogWarning(_("This archive may have Directory Traversal Vulnerability(DTV) problem, and some danger files may be extracted to the unexpected system directory! You should use the \"Ignore file pathes\" option when extracting this archive.\nDanger file is:\n%s"), piInfo.fiInfo.fnFileName.GetFullPath().c_str());
\r
414 // 空白の連続による拡張子偽装を検査。
\r
415 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT(" ")) != wxNOT_FOUND)
\r
417 piInfo.fiInfo.eDanger = TRUE;
\r
418 wxLogWarning(_("This archive may contain extension-disguised files whose real extension is hidden by using many blank charactor and you may mistake that it is a \"safe\" file. Don\'t execute these files carelessly.\nDanger file is:\n%s"), piInfo.fiInfo.fnFileName.GetFullPath().c_str());
\r
421 for (wxChar c = 0x200c; c <= 0x206f; c++)
\r
423 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)
\r
425 piInfo.fiInfo.eDanger = TRUE;
\r
426 wxLogWarning(_("This archive may contain extension-disguised files whose real extension is hidden by using Unicode control character and you may mistake that it is a \"safe\" file. Don\'t execute these files carelessly.\nDanger file is:\n%s"), piInfo.fiInfo.fnFileName.GetFullPath().c_str());
\r
430 case 0x200f: c = 0x2027; break;
\r
431 case 0x202e: c = 0x2060; break;
\r
436 this->fileinfo.Add(piInfo.fiInfo);
\r
438 while (tpi.GetFileInformation(& piInfo.fiInfo, false));
\r
441 // GetFileInformationがエラー終了した場合。
\r
442 if (tpi.nErrorCode != TPI_ERROR_S_ENDOFDATA)
\r
444 wxLogError(_("Error: %s!"), wxT("GetFileInformation()"));
\r
448 if (! tpi.GetArchiveInformation(& this->aiArchive))
\r
450 wxLogError(_("Error: %s!"), wxT("GetArchiveInformation()"));
\r
454 if (! tpi.CloseArchive())
\r
456 wxLogError(_("Error: %s!"), wxT("CloseArchive()"));
\r
460 this->fileinfo.Shrink();
\r
461 this->tree_ctrl->ExpandAll();
\r
462 this->tree_ctrl->ScrollTo(idArchive);
\r
463 this->tree_ctrl->SelectItem(idArchive);
\r
464 this->list_ctrl->atDangerItem.SetTextColour(* wxRED);
\r
465 this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));
\r
468 this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);
\r
469 this->statusbar->SetStatusText(wxString::Format(_("%d file(s)"), this->fileinfo.GetCount()), 1);
\r
470 this->statusbar->SetStatusText(wxString::Format(_("%dB -> %dB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);
\r
471 this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);
\r
472 this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);
\r
475 SetMenuToolState("Arc_Close", true);
\r
476 SetMenuToolState("Arc_Add", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD) == TPI_COMMAND_ADD && this->aiArchive.fiInfo.fArchive);
\r
477 SetMenuToolState("Arc_SFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX) == TPI_COMMAND_SFX && ! this->aiArchive.fSFX);
\r
478 SetMenuToolState("Arc_UnSFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX) == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);
\r
479 SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);
\r
480 SetMenuToolState("Arc_Delete", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);
\r
481 SetMenuToolState("Arc_Test", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST) == TPI_COMMAND_TEST);
\r
482 SetMenuToolState("Arc_Repair", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);
\r
484 procDlg.Show(false);
\r
487 void MainFrame::OnArcClose(wxCommandEvent& e)
\r
489 // ツリービュー・リストビュー設定。
\r
490 this->tree_ctrl->DeleteAllItems();
\r
491 this->list_ctrl->DeleteAllItems();
\r
492 this->list_ctrl->showFileInfo.Clear();
\r
495 SetMenuToolState("Arc_Close", false);
\r
496 SetMenuToolState("Arc_Add", false);
\r
497 SetMenuToolState("Arc_SFX", false);
\r
498 SetMenuToolState("Arc_UnSFX", false);
\r
499 SetMenuToolState("Arc_Extract", false);
\r
500 SetMenuToolState("Arc_Delete", false);
\r
501 SetMenuToolState("Arc_Test", false);
\r
502 SetMenuToolState("Arc_Repair", false);
\r
504 for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)
\r
506 this->statusbar->SetStatusText(wxEmptyString, i);
\r
508 this->fileinfo.Clear();
\r
509 this->aiArchive.szComment.Empty();
\r
510 this->aiArchive.fnArchive.Clear();
\r
511 this->aiArchive.fiInfo.szTypeName.Empty();
\r
512 this->aiArchive.fiInfo.szSuffix.Empty();
\r
513 this->aiArchive.fiInfo.szEngineName.Empty();
\r
514 this->aiArchive.fiInfo.szTPIName.Empty();
\r
516 g_hIconT.RemoveAll();
\r
517 g_hIconLL.RemoveAll();
\r
518 g_hIconLS.RemoveAll();
\r
520 // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。
\r
521 if (e.GetExtraLong() == 0)
\r
523 this->tpi.FreeLibrary();
\r
527 void MainFrame::OnArcAdd(wxCommandEvent& e)
\r
531 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
532 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
533 mkDlg.uCommand = TPI_COMMAND_ADD;
\r
536 wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
537 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
538 if (fd.ShowModal() == wxID_CANCEL)
\r
542 fd.GetFilenames(mkDlg.files);
\r
543 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
546 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
552 TPI_SWITCHES swInfo;
\r
553 swInfo.pCustomSwitches = NULL;
\r
554 swInfo.fMakeSFX = false;
\r
555 swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());
\r
556 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
557 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
558 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
559 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
560 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
561 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
562 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
563 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
564 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
568 ProcessDialog procDlg;
\r
569 procDlg.Show(true);
\r
572 TPI_PROCESSINFO piInfo;
\r
573 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
574 piInfo.eStatus = 0x1000;
\r
575 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
576 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
577 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
579 if (! tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files))
\r
581 this->ErrorCheck(tpi.nErrorCode);
\r
583 procDlg.Show(false);
\r
586 if (mkDlg.cbOpenAfter->IsChecked())
\r
589 ::wxExecute(DIR_APP + swInfo.fnDestinationDirectory.GetFullPath());
\r
592 if (mkDlg.cbExitAfter->IsChecked())
\r
598 // 終了しない場合は書庫を再読み込み。
\r
599 this->OnArcOpen(e);
\r
602 void MainFrame::OnArcConvert(wxCommandEvent& e)
\r
604 TPI_SWITCHES swInfo;
\r
605 swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");
\r
608 wxFileDialog fd(this, swInfo.fMakeSFX ? _("Save as SFX") : _("Save as normal archive"), this->fnArchive.GetPath(), this->fnArchive.GetName() + (swInfo.fMakeSFX ? EXE_EXT : (wxString) wxEmptyString));
\r
609 fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
\r
610 if (fd.ShowModal() == wxID_CANCEL)
\r
614 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
615 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
617 wxArrayString files;
\r
618 files.Add(fd.GetPath());
\r
620 ProcessDialog procDlg;
\r
621 procDlg.Show(true);
\r
622 if (! this->tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files))
\r
624 this->ErrorCheck(tpi.nErrorCode);
\r
626 procDlg.Show(false);
\r
629 void MainFrame::OnArcExtract(wxCommandEvent& e)
\r
631 TPI_SWITCHES swInfo;
\r
632 swInfo.pCustomSwitches = NULL;
\r
634 // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3。
\r
635 int nMode = e.GetInt();
\r
637 wxFileType * ftFile = NULL;
\r
639 // 展開ダイアログを作成。DnDまたは実行時は表示しない。
\r
641 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
642 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
643 mkDlg.uCommand = TPI_COMMAND_EXTRACT;
\r
644 mkDlg.files = MakeTargetFileList(this, nMode == 1);
\r
651 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());
\r
654 // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。
\r
655 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));
\r
658 wxLogError(_("Unable to get the file type!"));
\r
665 swInfo.fStoreDirectoryPathes = false;
\r
666 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");
\r
668 if (szDestDirBase == wxT("-----"))
\r
670 // 書庫ルートのときは書庫名にしておく。
\r
671 szDestDirBase = this->fnArchive.GetName();
\r
673 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);
\r
674 if (! swInfo.fnDestinationDirectory.IsOk())
\r
676 wxLogError(_("Unable to make the temporary directory!"));
\r
682 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
688 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
689 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());
\r
690 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
691 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
693 // 必要なら書庫名でディレクトリを作成する。
\r
694 if (WillMakeDirByArcName(this, & mkDlg))
\r
696 swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);
\r
697 if (! swInfo.fnDestinationDirectory.IsOk())
\r
699 wxLogError(_("Unable to make the destination directory!"));
\r
707 ProcessDialog procDlg;
\r
708 procDlg.Show(true);
\r
711 TPI_PROCESSINFO piInfo;
\r
712 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
713 piInfo.eStatus = 0x1000;
\r
714 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
715 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
716 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
718 if (! tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files))
\r
720 this->ErrorCheck(tpi.nErrorCode);
\r
722 procDlg.Show(false);
\r
727 if (mkDlg.cbOpenAfter->IsChecked())
\r
730 ::wxExecute(DIR_APP + swInfo.fnDestinationDirectory.GetFullPath());
\r
733 if (mkDlg.cbExitAfter->IsChecked())
\r
741 wxArrayString asFiles;
\r
745 asFiles.Add(swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName());
\r
746 if (tpi.nErrorCode == TPI_ERROR_SUCCESS)
\r
749 // Linuxでは引用符で囲む必要がある。
\r
750 ::wxExecute(ftFile->GetOpenCommand(wxT('"') + asFiles[0] + wxT('"')), wxEXEC_SYNC);
\r
752 ::wxExecute(ftFile->GetOpenCommand(asFiles[0]), wxEXEC_SYNC);
\r
758 // 展開対象を決定。wxGTKのwxFileDataObjectでは多バイト文字の扱いに問題があるので代替。
\r
760 myFileDataObject objFile;
\r
762 wxFileDataObject objFile;
\r
764 for (size_t i = 0; i < mkDlg.files.GetCount(); i++)
\r
766 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();
\r
770 objFile.AddFile(szFileName);
\r
772 asFiles.Add(szFileName);
\r
776 objFile.AddFile(swInfo.fnDestinationDirectory.GetPath());
\r
779 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。
\r
780 this->SetDropTarget(NULL);
\r
783 wxDropSource dropSource(objFile, this);
\r
784 wxDragResult drResult = dropSource.DoDragDrop(wxDrag_DefaultMove);
\r
785 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)
\r
788 // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。
\r
792 this->SetDropTarget(new myFileDropTarget(this));
\r
795 // ファイルと一時ディレクトリを削除。
\r
796 for (size_t i = 0; i < asFiles.GetCount(); i++)
\r
798 ::wxRemoveFile(asFiles[i]);
\r
800 ::wxRmdir(swInfo.fnDestinationDirectory.GetFullPath());
\r
804 void MainFrame::OnArcDelete(wxCommandEvent& e)
\r
806 // 全ファイル削除は危険ではないかと。
\r
807 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
812 if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)
\r
819 TPI_SWITCHES swInfo;
\r
820 ProcessDialog procDlg;
\r
821 procDlg.Show(true);
\r
822 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
825 TPI_PROCESSINFO piInfo;
\r
826 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
827 piInfo.eStatus = 0x1000;
\r
828 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
829 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
830 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
832 if (! tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles))
\r
834 this->ErrorCheck(tpi.nErrorCode);
\r
836 procDlg.Show(false);
\r
840 this->OnArcOpen(e);
\r
843 void MainFrame::OnArcTest(wxCommandEvent&)
\r
846 ProcessDialog procDlg;
\r
847 procDlg.Show(true);
\r
848 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
851 TPI_PROCESSINFO piInfo;
\r
852 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
853 piInfo.eStatus = 0x1000;
\r
854 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
855 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
856 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
858 TPI_SWITCHES swInfo;
\r
859 bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
860 procDlg.Show(false);
\r
864 wxLogMessage(_("This is a correct archive."));
\r
868 this->ErrorCheck(tpi.nErrorCode);
\r
872 void MainFrame::OnArcRepair(wxCommandEvent&)
\r
875 ProcessDialog procDlg;
\r
876 procDlg.Show(true);
\r
877 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
880 TPI_PROCESSINFO piInfo;
\r
881 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
882 piInfo.eStatus = 0x1000;
\r
883 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
884 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
885 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
887 TPI_SWITCHES swInfo;
\r
888 if (! this->tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles))
\r
890 this->ErrorCheck(tpi.nErrorCode);
\r
892 procDlg.Show(false);
\r
895 void MainFrame::OnViewMode(wxCommandEvent & e)
\r
898 this->menubar->Check(n, true);
\r
899 this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));
\r
900 this->list_ctrl->SetSingleStyle(wxLC_ICON, n == XRCID("Exe_View_Icons"));
\r
901 this->list_ctrl->SetSingleStyle(wxLC_LIST, n == XRCID("Exe_View_List"));
\r
904 void MainFrame::OnShowToolBar(wxCommandEvent & e)
\r
906 this->toolbar->Show(e.IsChecked());
\r
909 void MainFrame::OnShowStatusBar(wxCommandEvent & e)
\r
911 this->statusbar->Show(e.IsChecked());
\r
914 void MainFrame::OnSelectAll(wxCommandEvent &)
\r
916 for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)
\r
918 this->list_ctrl->Select(i, true);
\r
924 void MainFrame::OnTreeChanged(wxTreeEvent& e)
\r
927 wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());
\r
929 this->list_ctrl->showFileInfo.Clear();
\r
930 this->list_ctrl->DeleteAllItems();
\r
931 g_hIconLL.RemoveAll();
\r
932 g_hIconLS.RemoveAll();
\r
934 // 現在のアイテムの選択状態を無効にしておく。
\r
935 long nSelected = this->list_ctrl->GetFirstSelected();
\r
936 while (nSelected != -1)
\r
938 this->list_ctrl->Select(nSelected, false);
\r
939 nSelected = this->list_ctrl->GetNextSelected(nSelected);
\r
943 this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);
\r
944 this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);
\r
946 // 配列と比較し、パスが一致しなければ消す。
\r
947 for (size_t i = 0; i < this->fileinfo.GetCount(); i++)
\r
950 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())
\r
953 if (this->fileinfo[i].fnFileName.IsDir() || ! TreeView_CheckNewerItem(this->tree_ctrl, this->tree_ctrl->GetLastChild(this->tree_ctrl->GetRootItem()), this->fileinfo[i].fnFileName.GetFullPath(), false))
\r
959 if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)
\r
964 this->list_ctrl->showFileInfo.Add(this->fileinfo[i]);
\r
969 this->list_ctrl->showFileInfo.Sort(& ListCtrlCompareProc);
\r
970 this->list_ctrl->SetItemCount(this->list_ctrl->showFileInfo.GetCount());
\r
973 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
\r
975 // TODO : アイテムが子階層を持っていても展開できない。
\r
976 this->tree_ctrl->SelectItem(e.GetItem());
\r
980 this->OnArcExtract(e1);
\r
985 void MainFrame::OnListItemDClick(wxListEvent&)
\r
989 this->OnArcExtract(e);
\r
992 void MainFrame::OnListBeginDrag(wxListEvent&)
\r
994 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
996 // アイテムを選択せずドラッグしようとした場合。
\r
1002 this->OnArcExtract(e);
\r
1007 void MainFrame::OnFilter(wxCommandEvent&)
\r
1010 e.SetItem(this->tree_ctrl->GetSelection());
\r
1011 this->OnTreeChanged(e);
\r
1016 wxULongLong_t MainFrame::LoadTPI(wxString szFileName)
\r
1019 wxDir fs(L_DIR_B_LIB);
\r
1020 wxULongLong_t llFileCount = 0;
\r
1021 wxString szTPIName;
\r
1022 if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))
\r
1027 if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName, 0))
\r
1029 tpi.FreeLibrary();
\r
1034 tpi.SetCallbackProc(TPICallbackProc);
\r
1037 if (! tpi.CheckArchive(szFileName, & llFileCount) || llFileCount == 0)
\r
1039 tpi.FreeLibrary();
\r
1045 while (fs.GetNext(& szTPIName));
\r
1047 return llFileCount;
\r
1050 int MainFrame::ErrorCheck(int nErrorCode)
\r
1052 switch (nErrorCode)
\r
1054 case TPI_ERROR_SUCCESS:
\r
1055 case TPI_CALLBACK_CONTINUE:
\r
1057 case TPI_ERROR_D_UNSUPPORTED:
\r
1058 wxLogError(_("Sorry, this function is not supported yet."));
\r
1060 case TPI_ERROR_D_SKIPPED:
\r
1061 case TPI_CALLBACK_CANCEL:
\r
1062 wxLogError(_("This operation is canceled by the user."));
\r
1065 wxLogError(_("Error code: %d"), nErrorCode);
\r
1067 return nErrorCode;
\r