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 + 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
325 this->OnArcClose(e);
\r
328 ProcessDialog procDlg;
\r
329 procDlg.Show(true);
\r
331 // TPIを読み込み、最初のコールバックを送信。
\r
332 TPI_PROCESSINFO piInfo;
\r
333 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
334 piInfo.eStatus = 0x1000;
\r
335 piInfo.nProcessedSize = 0;
\r
336 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
337 piInfo.fiInfo.nUnpackedSize = e.GetExtraLong() != 0 ? e.GetExtraLong() : this->LoadTPI(this->fnArchive.GetFullPath());
\r
338 if (piInfo.fiInfo.nUnpackedSize == 0)
\r
340 procDlg.Show(false);
\r
342 if (this->IsShown())
\r
345 this->statusbar->SetStatusText(_("No plug-in supporting this archive was found!"), 4);
\r
349 wxLogError(_("No plug-in supporting this archive was found!"));
\r
354 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
357 this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);
\r
360 if (! tpi.OpenArchive(this->fnArchive.GetFullPath()))
\r
362 procDlg.Show(false);
\r
364 this->ErrorCheck(tpi.nErrorCode, wxT("OpenArchive"));
\r
369 this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());
\r
370 this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());
\r
371 this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());
\r
373 // 書庫のアイコンを取得し、書庫ルートを作成。
\r
374 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));
\r
375 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));
\r
376 this->tree_ctrl->SetImageList(& g_hIconT);
\r
378 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),
\r
380 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName))),
\r
382 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName).ConvertToImage().Rescale(16, 16))),
\r
384 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);
\r
387 if (tpi.GetFileInformation(& piInfo.fiInfo, true))
\r
389 piInfo.eStatus = 0x1001;
\r
392 piInfo.nProcessedSize++;
\r
393 if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo)) == TPI_CALLBACK_CANCEL)
\r
395 procDlg.Show(false);
\r
396 tpi.CloseArchive();
\r
398 this->OnArcClose(e);
\r
403 TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, piInfo.fiInfo.fnFileName.GetPath(), true);
\r
405 // ディレクトリ属性を含むものについては除去。
\r
406 if (piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
413 if (piInfo.fiInfo.fnFileName.GetPathWithSep().Find(wxT("..")) != wxNOT_FOUND)
\r
415 piInfo.fiInfo.eDanger = TRUE;
\r
416 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
418 // 空白の連続による拡張子偽装を検査。
\r
419 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT(" ")) != 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 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
425 for (wxChar c = 0x200c; c <= 0x206f; c++)
\r
427 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)
\r
429 piInfo.fiInfo.eDanger = TRUE;
\r
430 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
434 case 0x200f: c = 0x2027; break;
\r
435 case 0x202e: c = 0x2060; break;
\r
440 this->fileinfo.Add(piInfo.fiInfo);
\r
442 while (tpi.GetFileInformation(& piInfo.fiInfo, false));
\r
445 // GetFileInformationがエラー終了した場合。
\r
446 this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));
\r
449 tpi.GetArchiveInformation(& this->aiArchive);
\r
450 this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));
\r
453 tpi.CloseArchive();
\r
454 this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));
\r
457 this->fileinfo.Shrink();
\r
458 this->tree_ctrl->ExpandAll();
\r
459 this->tree_ctrl->ScrollTo(idArchive);
\r
460 this->tree_ctrl->SelectItem(idArchive);
\r
461 this->list_ctrl->atDangerItem.SetTextColour(* wxRED);
\r
462 this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));
\r
465 this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);
\r
466 this->statusbar->SetStatusText(wxString::Format(_("%d file(s)"), this->fileinfo.GetCount()), 1);
\r
467 this->statusbar->SetStatusText(wxString::Format(_("%dB -> %dB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);
\r
468 this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);
\r
469 this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);
\r
472 SetMenuToolState("Arc_Close", true);
\r
473 SetMenuToolState("Arc_Add", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD) == TPI_COMMAND_ADD && this->aiArchive.fiInfo.fArchive);
\r
474 SetMenuToolState("Arc_SFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX) == TPI_COMMAND_SFX && ! this->aiArchive.fSFX);
\r
475 SetMenuToolState("Arc_UnSFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX) == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);
\r
476 SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);
\r
477 SetMenuToolState("Arc_Delete", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);
\r
478 SetMenuToolState("Arc_Test", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST) == TPI_COMMAND_TEST);
\r
479 SetMenuToolState("Arc_Repair", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);
\r
481 procDlg.Show(false);
\r
485 void MainFrame::OnArcClose(wxCommandEvent& e)
\r
487 // ツリービュー・リストビュー設定。
\r
488 this->tree_ctrl->DeleteAllItems();
\r
489 this->list_ctrl->DeleteAllItems();
\r
490 this->list_ctrl->showFileInfo.Clear();
\r
493 SetMenuToolState("Arc_Close", false);
\r
494 SetMenuToolState("Arc_Add", false);
\r
495 SetMenuToolState("Arc_SFX", false);
\r
496 SetMenuToolState("Arc_UnSFX", false);
\r
497 SetMenuToolState("Arc_Extract", false);
\r
498 SetMenuToolState("Arc_Delete", false);
\r
499 SetMenuToolState("Arc_Test", false);
\r
500 SetMenuToolState("Arc_Repair", false);
\r
502 for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)
\r
504 this->statusbar->SetStatusText(wxEmptyString, i);
\r
506 this->fileinfo.Clear();
\r
507 this->aiArchive.szComment.Empty();
\r
508 this->aiArchive.fnArchive.Clear();
\r
509 this->aiArchive.fiInfo.szTypeName.Empty();
\r
510 this->aiArchive.fiInfo.szSuffix.Empty();
\r
511 this->aiArchive.fiInfo.szEngineName.Empty();
\r
512 this->aiArchive.fiInfo.szTPIName.Empty();
\r
514 g_hIconT.RemoveAll();
\r
515 g_hIconLL.RemoveAll();
\r
516 g_hIconLS.RemoveAll();
\r
518 // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。
\r
519 if (e.GetExtraLong() == 0)
\r
525 void MainFrame::OnArcAdd(wxCommandEvent& e)
\r
529 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
530 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
531 mkDlg.uCommand = TPI_COMMAND_ADD;
\r
534 wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
535 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
536 if (fd.ShowModal() == wxID_CANCEL)
\r
540 fd.GetFilenames(mkDlg.files);
\r
541 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
544 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
550 TPI_SWITCHES swInfo;
\r
551 swInfo.pCustomSwitches = NULL;
\r
552 swInfo.fMakeSFX = false;
\r
553 swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());
\r
554 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
555 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
556 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
557 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
558 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
559 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
560 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
561 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
562 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
566 ProcessDialog procDlg;
\r
567 procDlg.Show(true);
\r
570 TPI_PROCESSINFO piInfo;
\r
571 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
572 piInfo.eStatus = 0x1000;
\r
573 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
574 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
575 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
577 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
578 this->ErrorCheck(tpi.nErrorCode);
\r
579 procDlg.Show(false);
\r
582 if (mkDlg.cbOpenAfter->IsChecked())
\r
585 ::wxExecute(DIR_APP + swInfo.fnDestinationDirectory.GetFullPath());
\r
588 if (mkDlg.cbExitAfter->IsChecked())
\r
594 // 終了しない場合は書庫を再読み込み。
\r
595 this->OnArcOpen(e);
\r
598 void MainFrame::OnArcConvert(wxCommandEvent& e)
\r
600 TPI_SWITCHES swInfo;
\r
601 swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");
\r
604 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
605 fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
\r
606 if (fd.ShowModal() == wxID_CANCEL)
\r
610 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
611 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
613 wxArrayString files;
\r
614 files.Add(fd.GetPath());
\r
616 ProcessDialog procDlg;
\r
617 procDlg.Show(true);
\r
618 tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);
\r
619 this->ErrorCheck(tpi.nErrorCode);
\r
620 procDlg.Show(false);
\r
623 void MainFrame::OnArcExtract(wxCommandEvent& e)
\r
625 TPI_SWITCHES swInfo;
\r
626 swInfo.pCustomSwitches = NULL;
\r
628 // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3。
\r
629 int nMode = e.GetInt();
\r
631 wxFileType * ftFile = NULL;
\r
633 // 展開ダイアログを作成。DnDまたは実行時は表示しない。
\r
635 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
636 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
637 mkDlg.uCommand = TPI_COMMAND_EXTRACT;
\r
638 mkDlg.files = MakeTargetFileList(this, nMode == 1);
\r
645 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());
\r
648 // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。
\r
649 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));
\r
652 wxLogError(_("Unable to get the file type!"));
\r
659 swInfo.fStoreDirectoryPathes = false;
\r
660 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");
\r
662 if (szDestDirBase == wxT("-----"))
\r
664 // 書庫ルートのときは書庫名にしておく。
\r
665 szDestDirBase = this->fnArchive.GetName();
\r
667 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);
\r
668 if (! swInfo.fnDestinationDirectory.IsOk())
\r
670 wxLogError(_("Unable to make the temporary directory!"));
\r
676 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
682 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
683 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());
\r
684 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
685 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
687 // 必要なら書庫名でディレクトリを作成する。
\r
688 if (WillMakeDirByArcName(this, & mkDlg))
\r
690 swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);
\r
691 if (! swInfo.fnDestinationDirectory.IsOk())
\r
693 wxLogError(_("Unable to make the destination directory!"));
\r
701 ProcessDialog procDlg;
\r
702 procDlg.Show(true);
\r
705 TPI_PROCESSINFO piInfo;
\r
706 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
707 piInfo.eStatus = 0x1000;
\r
708 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
709 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
710 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
712 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
713 this->ErrorCheck(tpi.nErrorCode);
\r
714 procDlg.Show(false);
\r
719 if (mkDlg.cbOpenAfter->IsChecked())
\r
722 ::wxExecute(DIR_APP + swInfo.fnDestinationDirectory.GetFullPath());
\r
725 if (mkDlg.cbExitAfter->IsChecked())
\r
733 wxArrayString asFiles;
\r
737 asFiles.Add(swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName());
\r
738 if (tpi.nErrorCode == TPI_ERROR_SUCCESS)
\r
741 // Linuxでは引用符で囲む必要がある。
\r
742 ::wxExecute(ftFile->GetOpenCommand(wxT('"') + asFiles[0] + wxT('"')), wxEXEC_SYNC);
\r
744 ::wxExecute(ftFile->GetOpenCommand(asFiles[0]), wxEXEC_SYNC);
\r
750 // 展開対象を決定。wxGTKのwxFileDataObjectでは多バイト文字の扱いに問題があるので代替。
\r
752 myFileDataObject objFile;
\r
754 wxFileDataObject objFile;
\r
756 for (size_t i = 0; i < mkDlg.files.GetCount(); i++)
\r
758 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();
\r
762 objFile.AddFile(szFileName);
\r
764 asFiles.Add(szFileName);
\r
768 objFile.AddFile(swInfo.fnDestinationDirectory.GetPath());
\r
771 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。
\r
772 this->SetDropTarget(NULL);
\r
775 wxDropSource dropSource(objFile, this);
\r
776 wxDragResult drResult = dropSource.DoDragDrop(wxDrag_DefaultMove);
\r
777 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)
\r
780 // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。
\r
784 this->SetDropTarget(new myFileDropTarget(this));
\r
787 // ファイルと一時ディレクトリを削除。
\r
788 for (size_t i = 0; i < asFiles.GetCount(); i++)
\r
790 ::wxRemoveFile(asFiles[i]);
\r
792 ::wxRmdir(swInfo.fnDestinationDirectory.GetFullPath());
\r
796 void MainFrame::OnArcDelete(wxCommandEvent& e)
\r
798 // 全ファイル削除は危険ではないかと。
\r
799 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
804 if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)
\r
811 TPI_SWITCHES swInfo;
\r
812 ProcessDialog procDlg;
\r
813 procDlg.Show(true);
\r
814 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
817 TPI_PROCESSINFO piInfo;
\r
818 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
819 piInfo.eStatus = 0x1000;
\r
820 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
821 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
822 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
824 tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
825 this->ErrorCheck(tpi.nErrorCode);
\r
826 procDlg.Show(false);
\r
830 this->OnArcOpen(e);
\r
833 void MainFrame::OnArcTest(wxCommandEvent&)
\r
836 ProcessDialog procDlg;
\r
837 procDlg.Show(true);
\r
838 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
841 TPI_PROCESSINFO piInfo;
\r
842 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
843 piInfo.eStatus = 0x1000;
\r
844 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
845 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
846 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
848 TPI_SWITCHES swInfo;
\r
849 bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
850 procDlg.Show(false);
\r
854 wxLogMessage(_("This is a correct archive."));
\r
858 this->ErrorCheck(tpi.nErrorCode);
\r
862 void MainFrame::OnArcRepair(wxCommandEvent&)
\r
865 ProcessDialog procDlg;
\r
866 procDlg.Show(true);
\r
867 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
870 TPI_PROCESSINFO piInfo;
\r
871 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
872 piInfo.eStatus = 0x1000;
\r
873 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
874 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
875 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
877 TPI_SWITCHES swInfo;
\r
878 tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
879 this->ErrorCheck(tpi.nErrorCode);
\r
880 procDlg.Show(false);
\r
883 void MainFrame::OnViewMode(wxCommandEvent & e)
\r
886 this->menubar->Check(n, true);
\r
887 this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));
\r
888 this->list_ctrl->SetSingleStyle(wxLC_ICON, n == XRCID("Exe_View_Icons"));
\r
889 this->list_ctrl->SetSingleStyle(wxLC_LIST, n == XRCID("Exe_View_List"));
\r
892 void MainFrame::OnShowToolBar(wxCommandEvent & e)
\r
894 this->toolbar->Show(e.IsChecked());
\r
897 void MainFrame::OnShowStatusBar(wxCommandEvent & e)
\r
899 this->statusbar->Show(e.IsChecked());
\r
902 void MainFrame::OnSelectAll(wxCommandEvent &)
\r
904 for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)
\r
906 this->list_ctrl->Select(i, true);
\r
912 void MainFrame::OnTreeChanged(wxTreeEvent& e)
\r
915 wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());
\r
917 this->list_ctrl->showFileInfo.Clear();
\r
918 this->list_ctrl->DeleteAllItems();
\r
919 g_hIconLL.RemoveAll();
\r
920 g_hIconLS.RemoveAll();
\r
922 // 現在のアイテムの選択状態を無効にしておく。
\r
923 long nSelected = this->list_ctrl->GetFirstSelected();
\r
924 while (nSelected != -1)
\r
926 this->list_ctrl->Select(nSelected, false);
\r
927 nSelected = this->list_ctrl->GetNextSelected(nSelected);
\r
931 this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);
\r
932 this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);
\r
934 // 配列と比較し、パスが一致しなければ消す。
\r
935 for (size_t i = 0; i < this->fileinfo.GetCount(); i++)
\r
938 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())
\r
941 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
947 if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)
\r
952 this->list_ctrl->showFileInfo.Add(this->fileinfo[i]);
\r
957 this->list_ctrl->showFileInfo.Sort(& ListCtrlCompareProc);
\r
958 this->list_ctrl->SetItemCount(this->list_ctrl->showFileInfo.GetCount());
\r
961 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
\r
963 // TODO : アイテムが子階層を持っていても展開できない。
\r
964 this->tree_ctrl->SelectItem(e.GetItem());
\r
968 this->OnArcExtract(e1);
\r
973 void MainFrame::OnListItemDClick(wxListEvent&)
\r
977 this->OnArcExtract(e);
\r
980 void MainFrame::OnListBeginDrag(wxListEvent&)
\r
982 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
984 // アイテムを選択せずドラッグしようとした場合。
\r
990 this->OnArcExtract(e);
\r
995 void MainFrame::OnFilter(wxCommandEvent&)
\r
998 e.SetItem(this->tree_ctrl->GetSelection());
\r
999 this->OnTreeChanged(e);
\r
1004 wxULongLong_t MainFrame::LoadTPI(wxString szFileName)
\r
1007 wxDir fs(L_DIR_B_LIB);
\r
1008 wxULongLong_t llFileCount = 0;
\r
1009 wxString szTPIName;
\r
1010 if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))
\r
1015 if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName, 0))
\r
1017 tpi.FreeLibrary();
\r
1022 tpi.SetCallbackProc(TPICallbackProc);
\r
1025 if (! tpi.CheckArchive(szFileName, & llFileCount) || llFileCount == 0)
\r
1027 tpi.FreeLibrary();
\r
1033 while (fs.GetNext(& szTPIName));
\r
1035 return llFileCount;
\r
1038 int MainFrame::ErrorCheck(int nErrorCode, wxString szAPIName)
\r
1040 switch (nErrorCode)
\r
1042 case TPI_ERROR_SUCCESS:
\r
1043 case TPI_ERROR_S_ENDOFDATA:
\r
1044 case TPI_CALLBACK_CONTINUE:
\r
1046 case TPI_ERROR_D_UNSUPPORTED:
\r
1047 wxLogError(_("Sorry, this function is not supported yet."));
\r
1049 case TPI_ERROR_D_SKIPPED:
\r
1050 case TPI_CALLBACK_CANCEL:
\r
1051 wxLogError(_("This operation is canceled by the user."));
\r
1054 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);
\r
1056 return nErrorCode;
\r