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
158 this->window_splitter->SetSashPosition(this->conf.ReadId(CONF_WINDOW_SPLITTER_POS, 200l));
\r
161 int nIconMode = this->conf.ReadId(CONF_LISTVIEW_SHOWMODE, 0l);
\r
162 e.SetId(nIconMode == 1 ? XRCID("Exe_View_Icons") : (nIconMode == 2 ? XRCID("Exe_View_List") : XRCID("Exe_View_Details")));
\r
163 this->OnViewMode(e);
\r
164 // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。
\r
165 this->list_ctrl->SetSingleStyle(wxLC_VIRTUAL);
\r
166 this->list_ctrl->InsertColumn(0, _("Filename"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_FILENAME, 140l));
\r
167 this->list_ctrl->InsertColumn(1, _("Unpacked"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_UNPACKED, 80l));
\r
168 this->list_ctrl->InsertColumn(2, _("Packed"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_PACKED, 80l));
\r
169 this->list_ctrl->InsertColumn(3, _("Ratio"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_RATIO, 50l));
\r
170 this->list_ctrl->InsertColumn(4, _("Method"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_METHOD, 60l));
\r
171 this->list_ctrl->InsertColumn(5, _("Attr"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_ATTR, 50l));
\r
172 this->list_ctrl->InsertColumn(6, _("Last modified"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_LASTMOD, 150l));
\r
173 this->list_ctrl->InsertColumn(7, _("Path"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_PATH, 100l));
\r
174 this->list_ctrl->InsertColumn(8, _("Type"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_TYPE, 100l));
\r
175 this->list_ctrl->InsertColumn(9, _("No."), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_NO, 35l));
\r
176 g_nSortColumn = this->conf.ReadId(CONF_LISTVIEW_S_COLUMN, 9l);
\r
177 g_fSortAscend = this->conf.ReadId(CONF_LISTVIEW_S_ASCEND, true);
\r
178 this->list_ctrl->SetDropTarget(new myFileDropTarget(this));
\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
303 ::wxExecute(wxT("explorer ") + swInfo.fnDestinationDirectory.GetFullPath());
\r
307 if (mkDlg.cbExitAfter->IsChecked())
\r
314 this->OnArcOpen(e);
\r
317 void MainFrame::OnArcOpen(wxCommandEvent& e)
\r
320 if (e.GetId() == XRCID("Arc_Open"))
\r
322 wxFileDialog fd(this);
\r
323 fd.SetDirectory(this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
324 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);
\r
325 if (fd.ShowModal() == wxID_CANCEL)
\r
329 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
330 this->fnArchive = wxFileName(fd.GetPath());
\r
332 this->OnArcClose(e);
\r
335 ProcessDialog procDlg;
\r
336 procDlg.Show(true);
\r
338 // TPIを読み込み、最初のコールバックを送信。
\r
339 TPI_PROCESSINFO piInfo;
\r
340 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
341 piInfo.eStatus = 0x1000;
\r
342 piInfo.nProcessedSize = 0;
\r
343 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
344 piInfo.fiInfo.nUnpackedSize = e.GetExtraLong() != 0 ? e.GetExtraLong() : this->LoadTPI(this->fnArchive.GetFullPath());
\r
345 if (piInfo.fiInfo.nUnpackedSize == 0)
\r
347 procDlg.Show(false);
\r
349 ::wxLogError(_("No plug-in supporting this archive was found!"));
\r
352 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
355 this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);
\r
358 if (! tpi.OpenArchive(this->fnArchive.GetFullPath()))
\r
360 procDlg.Show(false);
\r
362 ::wxLogError(_("Error: %s!"), wxT("OpenArchive()"));
\r
367 this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());
\r
368 this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());
\r
369 this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());
\r
371 // 書庫のアイコンを取得し、書庫ルートを作成。
\r
372 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));
\r
373 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));
\r
374 this->tree_ctrl->SetImageList(& g_hIconT);
\r
376 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),
\r
378 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName))),
\r
380 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName).ConvertToImage().Rescale(16, 16))),
\r
382 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);
\r
385 if (tpi.GetFileInformation(& piInfo.fiInfo, true))
\r
387 piInfo.eStatus = 0x1001;
\r
390 piInfo.nProcessedSize++;
\r
391 if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo)) == TPI_CALLBACK_CANCEL)
\r
393 procDlg.Show(false);
\r
394 tpi.CloseArchive();
\r
396 this->OnArcClose(e);
\r
401 TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, piInfo.fiInfo.fnFileName.GetPath(), true);
\r
403 // ディレクトリ属性を含むものについては除去。
\r
404 if (piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
411 if (piInfo.fiInfo.fnFileName.GetPathWithSep().Find(wxT("..")) != wxNOT_FOUND)
\r
413 piInfo.fiInfo.eDanger = TRUE;
\r
414 ::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
416 // 空白の連続による拡張子偽装を検査。
\r
417 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT(" ")) != wxNOT_FOUND)
\r
419 piInfo.fiInfo.eDanger = TRUE;
\r
420 ::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
423 for (wxChar c = 0x200c; c <= 0x206f; c++)
\r
425 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)
\r
427 piInfo.fiInfo.eDanger = TRUE;
\r
428 ::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
432 case 0x200f: c = 0x2027; break;
\r
433 case 0x202e: c = 0x2060; break;
\r
438 this->fileinfo.Add(piInfo.fiInfo);
\r
440 while (tpi.GetFileInformation(& piInfo.fiInfo, false));
\r
443 // GetFileInformationがエラー終了した場合。
\r
444 if (tpi.nErrorCode != TPI_ERROR_S_ENDOFDATA)
\r
446 ::wxLogError(_("Error: %s!"), wxT("GetFileInformation()"));
\r
450 if (! tpi.GetArchiveInformation(& this->aiArchive))
\r
452 ::wxLogError(_("Error: %s!"), wxT("GetArchiveInformation()"));
\r
456 if (! tpi.CloseArchive())
\r
458 ::wxLogError(_("Error: %s!"), wxT("CloseArchive()"));
\r
462 this->fileinfo.Shrink();
\r
463 this->tree_ctrl->ExpandAll();
\r
464 this->tree_ctrl->ScrollTo(idArchive);
\r
465 this->tree_ctrl->SelectItem(idArchive);
\r
466 this->list_ctrl->atDangerItem.SetTextColour(* wxRED);
\r
467 this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));
\r
470 this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);
\r
471 this->statusbar->SetStatusText(wxString::Format(_("%d file(s)"), this->fileinfo.GetCount()), 1);
\r
472 this->statusbar->SetStatusText(wxString::Format(_("%dB -> %dB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);
\r
473 this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);
\r
474 this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);
\r
477 SetMenuToolState("Arc_Close", true);
\r
478 SetMenuToolState("Arc_Add", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD) == TPI_COMMAND_ADD && this->aiArchive.fiInfo.fArchive);
\r
479 SetMenuToolState("Arc_SFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX) == TPI_COMMAND_SFX && ! this->aiArchive.fSFX);
\r
480 SetMenuToolState("Arc_UnSFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX) == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);
\r
481 SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);
\r
482 SetMenuToolState("Arc_Delete", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);
\r
483 SetMenuToolState("Arc_Test", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST) == TPI_COMMAND_TEST);
\r
484 SetMenuToolState("Arc_Repair", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);
\r
486 procDlg.Show(false);
\r
489 void MainFrame::OnArcClose(wxCommandEvent& e)
\r
491 // ツリービュー・リストビュー設定。
\r
492 this->tree_ctrl->DeleteAllItems();
\r
493 this->list_ctrl->DeleteAllItems();
\r
494 this->list_ctrl->showFileInfo.Clear();
\r
497 SetMenuToolState("Arc_Close", false);
\r
498 SetMenuToolState("Arc_Add", false);
\r
499 SetMenuToolState("Arc_SFX", false);
\r
500 SetMenuToolState("Arc_UnSFX", false);
\r
501 SetMenuToolState("Arc_Extract", false);
\r
502 SetMenuToolState("Arc_Delete", false);
\r
503 SetMenuToolState("Arc_Test", false);
\r
504 SetMenuToolState("Arc_Repair", false);
\r
506 for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)
\r
508 this->statusbar->SetStatusText(wxEmptyString, i);
\r
510 this->fileinfo.Clear();
\r
511 this->aiArchive.szComment.Empty();
\r
512 this->aiArchive.fnArchive.Clear();
\r
513 this->aiArchive.fiInfo.szTypeName.Empty();
\r
514 this->aiArchive.fiInfo.szSuffix.Empty();
\r
515 this->aiArchive.fiInfo.szEngineName.Empty();
\r
516 this->aiArchive.fiInfo.szTPIName.Empty();
\r
518 g_hIconT.RemoveAll();
\r
519 g_hIconLL.RemoveAll();
\r
520 g_hIconLS.RemoveAll();
\r
522 // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。
\r
523 if (e.GetExtraLong() == 0)
\r
525 this->tpi.FreeLibrary();
\r
529 void MainFrame::OnArcAdd(wxCommandEvent& e)
\r
533 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
534 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
535 mkDlg.uCommand = TPI_COMMAND_ADD;
\r
538 wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
539 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
540 if (fd.ShowModal() == wxID_CANCEL)
\r
544 fd.GetFilenames(mkDlg.files);
\r
545 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
548 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
554 TPI_SWITCHES swInfo;
\r
555 swInfo.pCustomSwitches = NULL;
\r
556 swInfo.fMakeSFX = false;
\r
557 swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());
\r
558 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
559 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
560 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
561 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
562 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
563 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
564 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
565 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
566 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
570 ProcessDialog procDlg;
\r
571 procDlg.Show(true);
\r
574 TPI_PROCESSINFO piInfo;
\r
575 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
576 piInfo.eStatus = 0x1000;
\r
577 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
578 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
579 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
581 if (! tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files))
\r
583 this->ErrorCheck(tpi.nErrorCode);
\r
585 procDlg.Show(false);
\r
588 if (mkDlg.cbOpenAfter->IsChecked())
\r
592 ::wxExecute(wxT("explorer ") + swInfo.fnDestinationDirectory.GetFullPath());
\r
596 if (mkDlg.cbExitAfter->IsChecked())
\r
602 // 終了しない場合は書庫を再読み込み。
\r
603 this->OnArcOpen(e);
\r
606 void MainFrame::OnArcConvert(wxCommandEvent& e)
\r
608 TPI_SWITCHES swInfo;
\r
609 swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");
\r
612 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
613 fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
\r
614 if (fd.ShowModal() == wxID_CANCEL)
\r
618 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
619 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
621 wxArrayString files;
\r
622 files.Add(fd.GetPath());
\r
624 ProcessDialog procDlg;
\r
625 procDlg.Show(true);
\r
626 if (! this->tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files))
\r
628 this->ErrorCheck(tpi.nErrorCode);
\r
630 procDlg.Show(false);
\r
633 void MainFrame::OnArcExtract(wxCommandEvent& e)
\r
635 TPI_SWITCHES swInfo;
\r
636 swInfo.pCustomSwitches = NULL;
\r
638 // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3。
\r
639 int nMode = e.GetInt();
\r
641 wxFileType * ftFile = NULL;
\r
643 // 展開ダイアログを作成。DnDまたは実行時は表示しない。
\r
645 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
646 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
647 mkDlg.uCommand = TPI_COMMAND_EXTRACT;
\r
648 mkDlg.files = MakeTargetFileList(this, nMode == 1);
\r
655 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());
\r
658 // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。
\r
659 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));
\r
662 ::wxLogError(_("Unable to get the file type!"));
\r
669 swInfo.fStoreDirectoryPathes = false;
\r
670 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");
\r
672 if (szDestDirBase == wxT("-----"))
\r
674 // 書庫ルートのときは書庫名にしておく。
\r
675 szDestDirBase = this->fnArchive.GetName();
\r
677 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);
\r
678 if (! swInfo.fnDestinationDirectory.IsOk())
\r
680 ::wxLogError(_("Unable to make the temporary directory!"));
\r
686 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
692 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
693 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());
\r
694 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
695 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
697 // 必要なら書庫名でディレクトリを作成する。
\r
698 if (WillMakeDirByArcName(this, & mkDlg))
\r
700 swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);
\r
701 if (! swInfo.fnDestinationDirectory.IsOk())
\r
703 ::wxLogError(_("Unable to make the destination directory!"));
\r
711 ProcessDialog procDlg;
\r
712 procDlg.Show(true);
\r
715 TPI_PROCESSINFO piInfo;
\r
716 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
717 piInfo.eStatus = 0x1000;
\r
718 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
719 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
720 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
722 if (! tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files))
\r
724 this->ErrorCheck(tpi.nErrorCode);
\r
726 procDlg.Show(false);
\r
731 if (mkDlg.cbOpenAfter->IsChecked())
\r
735 ::wxExecute(wxT("explorer ") + swInfo.fnDestinationDirectory.GetFullPath());
\r
739 if (mkDlg.cbExitAfter->IsChecked())
\r
747 wxArrayString asFiles;
\r
751 asFiles.Add(swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName());
\r
752 if (tpi.nErrorCode == TPI_ERROR_SUCCESS)
\r
755 // Linuxでは引用符で囲む必要がある。
\r
756 ::wxExecute(ftFile->GetOpenCommand(wxT('"') + asFiles[0] + wxT('"')), wxEXEC_SYNC);
\r
758 ::wxExecute(ftFile->GetOpenCommand(asFiles[0]), wxEXEC_SYNC);
\r
765 wxFileDataObject objFile;
\r
766 for (size_t i = 0; i < mkDlg.files.GetCount(); i++)
\r
768 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();
\r
772 objFile.AddFile(szFileName);
\r
774 asFiles.Add(szFileName);
\r
778 objFile.AddFile(swInfo.fnDestinationDirectory.GetPath());
\r
782 wxDropSource dropSource(objFile, this);
\r
783 if (dropSource.DoDragDrop() != wxDragMove)
\r
786 // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。
\r
792 // ファイルと一時ディレクトリを削除。
\r
793 for (size_t i = 0; i < asFiles.GetCount(); i++)
\r
795 ::wxRemoveFile(asFiles[i]);
\r
797 ::wxRmdir(swInfo.fnDestinationDirectory.GetFullPath());
\r
801 void MainFrame::OnArcDelete(wxCommandEvent& e)
\r
803 // 全ファイル削除は危険ではないかと。
\r
804 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
809 if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)
\r
816 TPI_SWITCHES swInfo;
\r
817 ProcessDialog procDlg;
\r
818 procDlg.Show(true);
\r
819 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
822 TPI_PROCESSINFO piInfo;
\r
823 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
824 piInfo.eStatus = 0x1000;
\r
825 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
826 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
827 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
829 if (! tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles))
\r
831 this->ErrorCheck(tpi.nErrorCode);
\r
833 procDlg.Show(false);
\r
837 this->OnArcOpen(e);
\r
840 void MainFrame::OnArcTest(wxCommandEvent&)
\r
843 ProcessDialog procDlg;
\r
844 procDlg.Show(true);
\r
845 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
848 TPI_PROCESSINFO piInfo;
\r
849 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
850 piInfo.eStatus = 0x1000;
\r
851 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
852 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
853 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
855 TPI_SWITCHES swInfo;
\r
856 bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
857 procDlg.Show(false);
\r
861 ::wxLogMessage(_("This is a correct archive."));
\r
865 this->ErrorCheck(tpi.nErrorCode);
\r
869 void MainFrame::OnArcRepair(wxCommandEvent&)
\r
872 ProcessDialog procDlg;
\r
873 procDlg.Show(true);
\r
874 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
877 TPI_PROCESSINFO piInfo;
\r
878 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
879 piInfo.eStatus = 0x1000;
\r
880 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
881 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
882 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
884 TPI_SWITCHES swInfo;
\r
885 if (! this->tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles))
\r
887 this->ErrorCheck(tpi.nErrorCode);
\r
889 procDlg.Show(false);
\r
892 void MainFrame::OnViewMode(wxCommandEvent & e)
\r
895 this->menubar->Check(n, true);
\r
896 this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));
\r
897 this->list_ctrl->SetSingleStyle(wxLC_ICON, n == XRCID("Exe_View_Icons"));
\r
898 this->list_ctrl->SetSingleStyle(wxLC_LIST, n == XRCID("Exe_View_List"));
\r
901 void MainFrame::OnShowToolBar(wxCommandEvent & e)
\r
903 this->toolbar->Show(e.IsChecked());
\r
906 void MainFrame::OnShowStatusBar(wxCommandEvent & e)
\r
908 this->statusbar->Show(e.IsChecked());
\r
911 void MainFrame::OnSelectAll(wxCommandEvent &)
\r
913 for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)
\r
915 this->list_ctrl->Select(i, true);
\r
921 void MainFrame::OnTreeChanged(wxTreeEvent& e)
\r
924 wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());
\r
926 this->list_ctrl->showFileInfo.Clear();
\r
927 this->list_ctrl->DeleteAllItems();
\r
928 g_hIconLL.RemoveAll();
\r
929 g_hIconLS.RemoveAll();
\r
931 // 現在のアイテムの選択状態を無効にしておく。
\r
932 long nSelected = this->list_ctrl->GetFirstSelected();
\r
933 while (nSelected != -1)
\r
935 this->list_ctrl->Select(nSelected, false);
\r
936 nSelected = this->list_ctrl->GetNextSelected(nSelected);
\r
940 this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);
\r
941 this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);
\r
943 // 配列と比較し、パスが一致しなければ消す。
\r
944 for (size_t i = 0; i < this->fileinfo.GetCount(); i++)
\r
947 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())
\r
950 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
956 if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)
\r
961 this->list_ctrl->showFileInfo.Add(this->fileinfo[i]);
\r
966 this->list_ctrl->showFileInfo.Sort(& ListCtrlCompareProc);
\r
967 this->list_ctrl->SetItemCount(this->list_ctrl->showFileInfo.GetCount());
\r
970 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
\r
972 // TODO : アイテムが子階層を持っていても展開できない。
\r
973 this->tree_ctrl->SelectItem(e.GetItem());
\r
977 this->OnArcExtract(e1);
\r
982 void MainFrame::OnListItemDClick(wxListEvent&)
\r
986 this->OnArcExtract(e);
\r
989 void MainFrame::OnListBeginDrag(wxListEvent&)
\r
991 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
993 // アイテムを選択せずドラッグしようとした場合。
\r
999 this->OnArcExtract(e);
\r
1004 void MainFrame::OnFilter(wxCommandEvent&)
\r
1007 e.SetItem(this->tree_ctrl->GetSelection());
\r
1008 this->OnTreeChanged(e);
\r
1013 wxULongLong_t MainFrame::LoadTPI(wxString szFileName)
\r
1016 wxDir fs(L_DIR_B_LIB);
\r
1017 wxULongLong_t llFileCount = 0;
\r
1018 wxString szTPIName;
\r
1019 if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))
\r
1024 if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName, 0))
\r
1026 tpi.FreeLibrary();
\r
1031 tpi.SetCallbackProc(TPICallbackProc);
\r
1034 if (! tpi.CheckArchive(szFileName, & llFileCount) || llFileCount == 0)
\r
1036 tpi.FreeLibrary();
\r
1042 while (fs.GetNext(& szTPIName));
\r
1044 return llFileCount;
\r
1047 int MainFrame::ErrorCheck(int nErrorCode)
\r
1049 switch (nErrorCode)
\r
1051 case TPI_ERROR_SUCCESS:
\r
1052 case TPI_CALLBACK_CONTINUE:
\r
1054 case TPI_ERROR_D_UNSUPPORTED:
\r
1055 ::wxLogError(_("Sorry, this function is not supported yet."));
\r
1057 case TPI_ERROR_D_SKIPPED:
\r
1058 case TPI_CALLBACK_CANCEL:
\r
1059 ::wxLogError(_("This operation is canceled by the user."));
\r
1062 ::wxLogError(_("Error code: %d"), nErrorCode);
\r
1064 return nErrorCode;
\r