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 this->ErrorCheck(tpi.nErrorCode, wxT("InitLibrary"));
\r
272 tpi.SetCallbackProc(TPICallbackProc);
\r
273 this->ErrorCheck(tpi.nErrorCode, wxT("SetCallbackProc"));
\r
277 ProcessDialog procDlg;
\r
278 procDlg.Show(true);
\r
281 TPI_PROCESSINFO piInfo;
\r
282 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
283 piInfo.eStatus = 0x1000;
\r
284 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
285 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
286 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
288 tpi.Command(TPI_COMMAND_CREATE, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
289 this->ErrorCheck(tpi.nErrorCode);
\r
290 procDlg.Show(false);
\r
294 if (mkDlg.cbOpenAfter->IsChecked())
\r
297 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
300 if (mkDlg.cbExitAfter->IsChecked())
\r
307 this->OnArcOpen(e);
\r
310 void MainFrame::OnArcOpen(wxCommandEvent& e)
\r
313 if (e.GetId() == XRCID("Arc_Open"))
\r
315 wxFileDialog fd(this);
\r
316 fd.SetDirectory(this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
317 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);
\r
318 if (fd.ShowModal() == wxID_CANCEL)
\r
322 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
323 this->fnArchive = wxFileName(fd.GetPath());
\r
327 ProcessDialog procDlg;
\r
328 procDlg.Show(true);
\r
330 // DnD以外で書庫を開く場合、TPIを読み込み。
\r
331 TPI_PROCESSINFO piInfo;
\r
332 piInfo.fiInfo.nUnpackedSize = e.GetExtraLong();
\r
333 if (piInfo.fiInfo.nUnpackedSize == 0 && ! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))
\r
335 procDlg.Show(false);
\r
337 if (this->IsShown())
\r
340 this->statusbar->SetStatusText(_("No plug-in supporting this archive was found!"), 4);
\r
344 wxLogError(_("No plug-in supporting this archive was found!"));
\r
351 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
352 piInfo.eStatus = 0x1000;
\r
353 piInfo.nProcessedSize = 0;
\r
354 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
355 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
358 this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);
\r
361 this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());
\r
362 this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());
\r
363 this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());
\r
365 // 書庫のアイコンを取得し、書庫ルートを作成。
\r
366 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));
\r
367 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));
\r
368 this->tree_ctrl->SetImageList(& g_hIconT);
\r
370 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),
\r
372 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName))),
\r
374 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName).ConvertToImage().Rescale(16, 16))),
\r
376 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);
\r
379 if (tpi.GetFileInformation(& piInfo.fiInfo, true))
\r
381 piInfo.eStatus = 0x1001;
\r
384 piInfo.nProcessedSize++;
\r
385 if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo)) == TPI_CALLBACK_CANCEL)
\r
387 procDlg.Show(false);
\r
388 tpi.CloseArchive();
\r
390 this->OnArcClose(e);
\r
395 TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, piInfo.fiInfo.fnFileName.GetPath(), true);
\r
397 // ディレクトリ属性を含むものについては除去。
\r
398 if (piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
405 if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)
\r
407 piInfo.fiInfo.eDanger = TRUE;
\r
408 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
410 // 空白の連続による拡張子偽装を検査。
\r
411 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT(" ")) != wxNOT_FOUND)
\r
413 piInfo.fiInfo.eDanger = TRUE;
\r
414 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
417 for (wxChar c = 0x200c; c <= 0x206f; c++)
\r
419 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)
\r
421 piInfo.fiInfo.eDanger = TRUE;
\r
422 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
426 case 0x200f: c = 0x2027; break;
\r
427 case 0x202e: c = 0x2060; break;
\r
432 this->fileinfo.Add(piInfo.fiInfo);
\r
434 while (tpi.GetFileInformation(& piInfo.fiInfo, false));
\r
437 // GetFileInformationがエラー終了した場合。
\r
438 this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));
\r
441 tpi.GetArchiveInformation(& this->aiArchive);
\r
442 this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));
\r
445 tpi.CloseArchive();
\r
446 this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));
\r
449 this->fileinfo.Shrink();
\r
450 this->tree_ctrl->ExpandAll();
\r
451 this->tree_ctrl->ScrollTo(idArchive);
\r
452 this->tree_ctrl->SelectItem(idArchive);
\r
453 this->list_ctrl->atDangerItem.SetTextColour(* wxRED);
\r
454 this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));
\r
457 this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);
\r
458 this->statusbar->SetStatusText(wxString::Format(_("%d file(s)"), this->fileinfo.GetCount()), 1);
\r
459 this->statusbar->SetStatusText(wxString::Format(_("%dB -> %dB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);
\r
460 this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);
\r
461 this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);
\r
464 SetMenuToolState("Arc_Close", true);
\r
465 SetMenuToolState("Arc_Add", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD) == TPI_COMMAND_ADD && this->aiArchive.fiInfo.fArchive);
\r
466 SetMenuToolState("Arc_SFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX) == TPI_COMMAND_SFX && ! this->aiArchive.fSFX);
\r
467 SetMenuToolState("Arc_UnSFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX) == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);
\r
468 SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);
\r
469 SetMenuToolState("Arc_Delete", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);
\r
470 SetMenuToolState("Arc_Test", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST) == TPI_COMMAND_TEST);
\r
471 SetMenuToolState("Arc_Repair", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);
\r
473 procDlg.Show(false);
\r
477 void MainFrame::OnArcClose(wxCommandEvent& e)
\r
479 // ツリービュー・リストビュー設定。
\r
480 this->tree_ctrl->DeleteAllItems();
\r
481 this->list_ctrl->DeleteAllItems();
\r
482 this->list_ctrl->showFileInfo.Clear();
\r
485 SetMenuToolState("Arc_Close", false);
\r
486 SetMenuToolState("Arc_Add", false);
\r
487 SetMenuToolState("Arc_SFX", false);
\r
488 SetMenuToolState("Arc_UnSFX", false);
\r
489 SetMenuToolState("Arc_Extract", false);
\r
490 SetMenuToolState("Arc_Delete", false);
\r
491 SetMenuToolState("Arc_Test", false);
\r
492 SetMenuToolState("Arc_Repair", false);
\r
494 for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)
\r
496 this->statusbar->SetStatusText(wxEmptyString, i);
\r
498 this->fileinfo.Clear();
\r
499 this->aiArchive.szComment.Empty();
\r
500 this->aiArchive.fnArchive.Clear();
\r
501 this->aiArchive.fiInfo.szTypeName.Empty();
\r
502 this->aiArchive.fiInfo.szSuffix.Empty();
\r
503 this->aiArchive.fiInfo.szEngineName.Empty();
\r
504 this->aiArchive.fiInfo.szTPIName.Empty();
\r
506 g_hIconT.RemoveAll();
\r
507 g_hIconLL.RemoveAll();
\r
508 g_hIconLS.RemoveAll();
\r
510 // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。
\r
511 if (e.GetExtraLong() == 0)
\r
517 void MainFrame::OnArcAdd(wxCommandEvent& e)
\r
521 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
522 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
523 mkDlg.uCommand = TPI_COMMAND_ADD;
\r
526 wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
527 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
528 if (fd.ShowModal() == wxID_CANCEL)
\r
532 fd.GetFilenames(mkDlg.files);
\r
533 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
536 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
542 TPI_SWITCHES swInfo;
\r
543 swInfo.pCustomSwitches = NULL;
\r
544 swInfo.fMakeSFX = false;
\r
545 swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());
\r
546 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
547 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
548 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
549 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
550 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
551 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
552 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
553 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
554 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
558 ProcessDialog procDlg;
\r
559 procDlg.Show(true);
\r
562 TPI_PROCESSINFO piInfo;
\r
563 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
564 piInfo.eStatus = 0x1000;
\r
565 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
566 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
567 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
569 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
570 this->ErrorCheck(tpi.nErrorCode);
\r
571 procDlg.Show(false);
\r
574 if (mkDlg.cbOpenAfter->IsChecked())
\r
577 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
580 if (mkDlg.cbExitAfter->IsChecked())
\r
586 // 終了しない場合は書庫を再読み込み。
\r
587 this->OnArcOpen(e);
\r
590 void MainFrame::OnArcConvert(wxCommandEvent& e)
\r
592 TPI_SWITCHES swInfo;
\r
593 swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");
\r
596 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
597 fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
\r
598 if (fd.ShowModal() == wxID_CANCEL)
\r
602 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
603 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
605 wxArrayString files;
\r
606 files.Add(fd.GetPath());
\r
608 ProcessDialog procDlg;
\r
609 procDlg.Show(true);
\r
610 tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);
\r
611 this->ErrorCheck(tpi.nErrorCode);
\r
612 procDlg.Show(false);
\r
615 void MainFrame::OnArcExtract(wxCommandEvent& e)
\r
617 TPI_SWITCHES swInfo;
\r
618 swInfo.pCustomSwitches = NULL;
\r
620 // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3。
\r
621 int nMode = e.GetInt();
\r
623 wxFileType * ftFile = NULL;
\r
625 // 展開ダイアログを作成。DnDまたは実行時は表示しない。
\r
627 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
628 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
629 mkDlg.uCommand = TPI_COMMAND_EXTRACT;
\r
630 mkDlg.files = MakeTargetFileList(this, nMode == 1);
\r
637 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());
\r
640 // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。
\r
641 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));
\r
644 wxLogError(_("Unable to get the file type!"));
\r
651 swInfo.fStoreDirectoryPathes = false;
\r
652 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");
\r
654 if (szDestDirBase == wxT("-----"))
\r
656 // 書庫ルートのときは書庫名にしておく。
\r
657 szDestDirBase = this->fnArchive.GetName();
\r
659 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);
\r
660 if (! swInfo.fnDestinationDirectory.IsOk())
\r
662 wxLogError(_("Unable to make the temporary directory!"));
\r
668 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
674 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
675 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());
\r
676 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
677 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
679 // 必要なら書庫名でディレクトリを作成する。
\r
680 if (WillMakeDirByArcName(this, & mkDlg))
\r
682 swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);
\r
683 if (! swInfo.fnDestinationDirectory.IsOk())
\r
685 wxLogError(_("Unable to make the destination directory!"));
\r
693 ProcessDialog procDlg;
\r
694 procDlg.Show(true);
\r
697 TPI_PROCESSINFO piInfo;
\r
698 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
699 piInfo.eStatus = 0x1000;
\r
700 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
701 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
702 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
704 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
705 this->ErrorCheck(tpi.nErrorCode);
\r
706 procDlg.Show(false);
\r
711 if (mkDlg.cbOpenAfter->IsChecked())
\r
714 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
717 if (mkDlg.cbExitAfter->IsChecked())
\r
725 wxArrayString asFiles;
\r
729 asFiles.Add(swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName());
\r
730 if (tpi.nErrorCode == TPI_ERROR_SUCCESS)
\r
733 // Linuxでは引用符で囲む必要がある。
\r
734 ::wxExecute(ftFile->GetOpenCommand(QuoteString(asFiles[0])), wxEXEC_SYNC);
\r
736 ::wxExecute(ftFile->GetOpenCommand(asFiles[0]), wxEXEC_SYNC);
\r
742 // 展開対象を決定。wxGTKのwxFileDataObjectでは多バイト文字の扱いに問題があるので代替。
\r
744 myFileDataObject objFile;
\r
746 wxFileDataObject objFile;
\r
748 for (size_t i = 0; i < mkDlg.files.GetCount(); i++)
\r
750 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();
\r
754 objFile.AddFile(szFileName);
\r
756 asFiles.Add(szFileName);
\r
760 objFile.AddFile(swInfo.fnDestinationDirectory.GetPath());
\r
763 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。
\r
764 this->SetDropTarget(NULL);
\r
767 wxDropSource dropSource(objFile, this);
\r
768 wxDragResult drResult = dropSource.DoDragDrop(wxDrag_DefaultMove);
\r
769 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)
\r
772 // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。
\r
776 this->SetDropTarget(new myFileDropTarget(this));
\r
779 // ファイルと一時ディレクトリを削除。
\r
780 for (size_t i = 0; i < asFiles.GetCount(); i++)
\r
782 ::wxRemoveFile(asFiles[i]);
\r
784 ::wxRmdir(swInfo.fnDestinationDirectory.GetFullPath());
\r
788 void MainFrame::OnArcDelete(wxCommandEvent& e)
\r
790 // 全ファイル削除は危険ではないかと。
\r
791 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
796 if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)
\r
803 TPI_SWITCHES swInfo;
\r
804 ProcessDialog procDlg;
\r
805 procDlg.Show(true);
\r
806 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
809 TPI_PROCESSINFO piInfo;
\r
810 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
811 piInfo.eStatus = 0x1000;
\r
812 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
813 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
814 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
816 tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
817 this->ErrorCheck(tpi.nErrorCode);
\r
818 procDlg.Show(false);
\r
822 this->OnArcOpen(e);
\r
825 void MainFrame::OnArcTest(wxCommandEvent&)
\r
828 ProcessDialog procDlg;
\r
829 procDlg.Show(true);
\r
830 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
833 TPI_PROCESSINFO piInfo;
\r
834 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
835 piInfo.eStatus = 0x1000;
\r
836 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
837 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
838 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
840 TPI_SWITCHES swInfo;
\r
841 bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
842 procDlg.Show(false);
\r
846 wxLogMessage(_("This is a correct archive."));
\r
850 this->ErrorCheck(tpi.nErrorCode);
\r
854 void MainFrame::OnArcRepair(wxCommandEvent&)
\r
857 ProcessDialog procDlg;
\r
858 procDlg.Show(true);
\r
859 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
862 TPI_PROCESSINFO piInfo;
\r
863 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
864 piInfo.eStatus = 0x1000;
\r
865 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
866 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
867 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
869 TPI_SWITCHES swInfo;
\r
870 tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
871 this->ErrorCheck(tpi.nErrorCode);
\r
872 procDlg.Show(false);
\r
875 void MainFrame::OnViewMode(wxCommandEvent & e)
\r
878 this->menubar->Check(n, true);
\r
879 this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));
\r
880 this->list_ctrl->SetSingleStyle(wxLC_ICON, n == XRCID("Exe_View_Icons"));
\r
881 this->list_ctrl->SetSingleStyle(wxLC_LIST, n == XRCID("Exe_View_List"));
\r
884 void MainFrame::OnShowToolBar(wxCommandEvent & e)
\r
886 this->toolbar->Show(e.IsChecked());
\r
889 void MainFrame::OnShowStatusBar(wxCommandEvent & e)
\r
891 this->statusbar->Show(e.IsChecked());
\r
894 void MainFrame::OnSelectAll(wxCommandEvent &)
\r
896 for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)
\r
898 this->list_ctrl->Select(i, true);
\r
904 void MainFrame::OnTreeChanged(wxTreeEvent& e)
\r
907 wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());
\r
909 this->list_ctrl->showFileInfo.Clear();
\r
910 this->list_ctrl->DeleteAllItems();
\r
911 g_hIconLL.RemoveAll();
\r
912 g_hIconLS.RemoveAll();
\r
914 // 現在のアイテムの選択状態を無効にしておく。
\r
915 long nSelected = this->list_ctrl->GetFirstSelected();
\r
916 while (nSelected != -1)
\r
918 this->list_ctrl->Select(nSelected, false);
\r
919 nSelected = this->list_ctrl->GetNextSelected(nSelected);
\r
923 this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);
\r
924 this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);
\r
926 // 配列と比較し、パスが一致しなければ消す。
\r
927 for (size_t i = 0; i < this->fileinfo.GetCount(); i++)
\r
930 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())
\r
933 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
939 if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)
\r
944 this->list_ctrl->showFileInfo.Add(this->fileinfo[i]);
\r
949 this->list_ctrl->showFileInfo.Sort(& ListCtrlCompareProc);
\r
950 this->list_ctrl->SetItemCount(this->list_ctrl->showFileInfo.GetCount());
\r
953 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
\r
955 // TODO : アイテムが子階層を持っていても展開できない。
\r
956 this->tree_ctrl->SelectItem(e.GetItem());
\r
960 this->OnArcExtract(e1);
\r
965 void MainFrame::OnListItemDClick(wxListEvent&)
\r
969 this->OnArcExtract(e);
\r
972 void MainFrame::OnListBeginDrag(wxListEvent&)
\r
974 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
976 // アイテムを選択せずドラッグしようとした場合。
\r
982 this->OnArcExtract(e);
\r
987 void MainFrame::OnFilter(wxCommandEvent&)
\r
990 e.SetItem(this->tree_ctrl->GetSelection());
\r
991 this->OnTreeChanged(e);
\r
996 bool MainFrame::LoadTPI(wxString szFileName, wxULongLong_t * llFileCount)
\r
1000 this->OnArcClose(e);
\r
1003 wxDir fs(L_DIR_B_LIB);
\r
1004 wxString szTPIName;
\r
1005 if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))
\r
1010 if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName, 0))
\r
1012 tpi.FreeLibrary();
\r
1017 tpi.SetCallbackProc(TPICallbackProc);
\r
1020 if (! tpi.CheckArchive(szFileName, llFileCount) || ! tpi.OpenArchive(szFileName))
\r
1022 tpi.FreeLibrary();
\r
1023 * llFileCount = 0;
\r
1028 while (fs.GetNext(& szTPIName));
\r
1033 int MainFrame::ErrorCheck(int nErrorCode, wxString szAPIName)
\r
1035 switch (nErrorCode)
\r
1037 case TPI_ERROR_SUCCESS:
\r
1038 case TPI_ERROR_S_ENDOFDATA:
\r
1039 case TPI_CALLBACK_CONTINUE:
\r
1041 case TPI_ERROR_D_UNSUPPORTED:
\r
1042 wxLogError(_("Sorry, this function is not supported yet."));
\r
1044 case TPI_ERROR_D_SKIPPED:
\r
1045 case TPI_CALLBACK_CANCEL:
\r
1046 wxLogError(_("This operation is canceled by the user."));
\r
1049 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);
\r
1051 return nErrorCode;
\r