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_C_COMMENT, this->list_ctrl->GetColumnWidth(10));
\r
89 this->conf.WriteId(CONF_LISTVIEW_S_COLUMN, g_nSortColumn);
\r
90 this->conf.WriteId(CONF_LISTVIEW_S_ASCEND, g_fSortAscend);
\r
96 //******************************************************************************
\r
98 //******************************************************************************
\r
100 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
\r
101 EVT_INIT_DIALOG( MainFrame::OnInit)
\r
103 EVT_MENU(XRCID("Arc_Create"), MainFrame::OnArcCreate)
\r
104 EVT_MENU(XRCID("Arc_Open"), MainFrame::OnArcOpen)
\r
105 EVT_MENU(XRCID("Arc_Close"), MainFrame::OnArcClose)
\r
106 EVT_MENU(XRCID("Arc_Add"), MainFrame::OnArcAdd)
\r
107 EVT_MENU(XRCID("Arc_SFX"), MainFrame::OnArcConvert)
\r
108 EVT_MENU(XRCID("Arc_UnSFX"), MainFrame::OnArcConvert)
\r
109 EVT_MENU(XRCID("Exe_Exit"), MainFrame::OnExit)
\r
110 EVT_MENU(XRCID("Arc_Extract"), MainFrame::OnArcExtract)
\r
111 EVT_MENU(XRCID("Arc_Delete"), MainFrame::OnArcDelete)
\r
112 EVT_MENU(XRCID("Arc_Test"), MainFrame::OnArcTest)
\r
113 EVT_MENU(XRCID("Arc_Repair"), MainFrame::OnArcRepair)
\r
114 EVT_MENU(XRCID("Exe_View_Icons"), MainFrame::OnViewMode)
\r
115 EVT_MENU(XRCID("Exe_View_Details"),MainFrame::OnViewMode)
\r
116 EVT_MENU(XRCID("Exe_View_List"), MainFrame::OnViewMode)
\r
117 EVT_MENU(XRCID("Exe_View_ToolBar"),MainFrame::OnShowToolBar)
\r
118 EVT_MENU(XRCID("Exe_View_StatusBar"),MainFrame::OnShowStatusBar)
\r
119 EVT_MENU(XRCID("Exe_View_SelectAll"),MainFrame::OnSelectAll)
\r
121 EVT_TREE_SEL_CHANGED(XRCID("TreeView"), MainFrame::OnTreeChanged)
\r
122 EVT_TREE_BEGIN_DRAG( XRCID("TreeView"), MainFrame::OnTreeBeginDrag)
\r
124 EVT_LIST_ITEM_ACTIVATED(XRCID("ListView"), MainFrame::OnListItemDClick)
\r
125 EVT_LIST_BEGIN_DRAG( XRCID("ListView"), MainFrame::OnListBeginDrag)
\r
127 EVT_TEXT(XRCID("tcFilter"), MainFrame::OnFilter)
\r
130 //******************************************************************************
\r
132 //******************************************************************************
\r
134 void MainFrame::OnInit(wxInitDialogEvent&)
\r
137 this->menubar = this->GetMenuBar();
\r
138 this->toolbar = this->GetToolBar();
\r
139 this->statusbar = XRCCTRL(* this, "statusbar", wxStatusBar);
\r
140 this->tree_ctrl = XRCCTRL(* this, "TreeView", wxTreeCtrl);
\r
141 this->list_ctrl = XRCCTRL(* this, "ListView", myListCtrl);
\r
142 this->window_splitter = XRCCTRL(* this, "window_splitter", wxSplitterWindow);
\r
143 this->tcFilter = XRCCTRL(* this->toolbar, "tcFilter", wxTextCtrl);
\r
146 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
147 wxTheMimeTypesManager->Initialize(wxMAILCAP_ALL);
\r
152 icon.CopyFromBitmap(wxBitmap(L_DIR_S_ICO wxT("app.png"), wxBITMAP_TYPE_ANY));
\r
153 this->SetIcon(icon);
\r
156 this->OnArcClose(e);
\r
157 this->SetDropTarget(new myFileDropTarget(this));
\r
160 this->window_splitter->SetSashPosition(this->conf.ReadId(CONF_WINDOW_SPLITTER_POS, 200l));
\r
163 int nIconMode = this->conf.ReadId(CONF_LISTVIEW_SHOWMODE, 0l);
\r
164 e.SetId(nIconMode == 1 ? XRCID("Exe_View_Icons") : (nIconMode == 2 ? XRCID("Exe_View_List") : XRCID("Exe_View_Details")));
\r
165 this->OnViewMode(e);
\r
166 // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。
\r
167 this->list_ctrl->SetSingleStyle(wxLC_VIRTUAL);
\r
168 this->list_ctrl->InsertColumn(0, _("Filename"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_FILENAME, 140l));
\r
169 this->list_ctrl->InsertColumn(1, _("Unpacked"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_UNPACKED, 80l));
\r
170 this->list_ctrl->InsertColumn(2, _("Packed"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_PACKED, 80l));
\r
171 this->list_ctrl->InsertColumn(3, _("Ratio"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_RATIO, 50l));
\r
172 this->list_ctrl->InsertColumn(4, _("Method"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_METHOD, 60l));
\r
173 this->list_ctrl->InsertColumn(5, _("Attr"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_ATTR, 50l));
\r
174 this->list_ctrl->InsertColumn(6, _("Last modified"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_LASTMOD, 150l));
\r
175 this->list_ctrl->InsertColumn(7, _("Path"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_PATH, 100l));
\r
176 this->list_ctrl->InsertColumn(8, _("Type"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_TYPE, 100l));
\r
177 this->list_ctrl->InsertColumn(9, _("No."), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_NO, 35l));
\r
178 this->list_ctrl->InsertColumn(10,_("Comment"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_COMMENT, 35l));
\r
179 g_nSortColumn = this->conf.ReadId(CONF_LISTVIEW_S_COLUMN, 9l);
\r
180 g_fSortAscend = this->conf.ReadId(CONF_LISTVIEW_S_ASCEND, true);
\r
182 // ツールバー/ステータスバー設定。
\r
183 int nStatusBarParts[] = {70, 70, 180, 50, -1};
\r
184 this->statusbar->SetFieldsCount(5, nStatusBarParts);
\r
185 this->SetStatusBarPane(-1);
\r
186 bool fShow = this->conf.ReadId(CONF_WINDOW_STATUSBAR, true);
\r
187 this->menubar->Check(XRCID("Exe_View_StatusBar"), fShow);
\r
188 this->statusbar->Show(fShow);
\r
189 fShow = this->conf.ReadId(CONF_WINDOW_TOOLBAR, true);
\r
190 this->menubar->Check(XRCID("Exe_View_ToolBar"), fShow);
\r
191 this->toolbar->Show(fShow);
\r
196 void MainFrame::OnExit(wxCommandEvent&)
\r
201 void MainFrame::OnArcCreate(wxCommandEvent& e)
\r
203 TPI_SWITCHES swInfo;
\r
204 swInfo.pCustomSwitches = NULL;
\r
208 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
209 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
211 if (e.GetClientData() == NULL)
\r
214 wxFileDialog fd(this, _("Choose files to compress"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
215 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
216 if (fd.ShowModal() == wxID_CANCEL)
\r
220 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
221 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
222 fd.GetFilenames(mkDlg.files);
\r
226 mkDlg.files = * (wxArrayString *) e.GetClientData();
\r
227 swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());
\r
229 for (size_t n = 0; n < mkDlg.files.GetCount(); n++)
\r
231 wxFileName fn(mkDlg.files[n]);
\r
232 fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());
\r
233 mkDlg.files[n] = fn.GetFullPath();
\r
237 this->OnArcClose(e);
\r
238 // 書庫名はファイル名の拡張子より前、もしくはディレクトリ名。
\r
239 this->fnArchive = wxFileName(mkDlg.files[0]);
\r
240 this->fnArchive.SetName(mkDlg.files.GetCount() == 1 ? (this->fnArchive.GetName().IsEmpty() ? this->fnArchive.GetDirs().Last() : this->fnArchive.GetName()) : swInfo.fnDestinationDirectory.GetDirs().Last());
\r
241 this->fnArchive.SetEmptyExt();
\r
242 this->fnArchive.SetPath(swInfo.fnDestinationDirectory.GetPath());
\r
245 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
251 swInfo.fStoreDirectoryPathes= ! mkDlg.cbIgnorePath->IsChecked();
\r
252 swInfo.fMakeSFX = mkDlg.cbMakeSFX->IsChecked();
\r
253 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
254 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
255 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
256 swInfo.fCompressHeader = mkDlg.cbCompressHeader->IsChecked();
\r
257 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
258 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
259 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
260 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
261 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
262 mkDlg.cbSplitSize->GetValue().ToULongLong(& swInfo.nSplitSize);
\r
265 int nSelected = mkDlg.chType->GetSelection();
\r
266 this->fnArchive = wxFileName(mkDlg.cbDir->GetValue(), mkDlg.cbFileName->GetValue());
\r
267 if (! tpi.InitLibrary(mkDlg.afInfo[nSelected].szTPIName, this->fnArchive.GetFullPath(), mkDlg.afInfo[nSelected].nTypeId))
\r
269 this->ErrorCheck(tpi.nErrorCode, wxT("InitLibrary"));
\r
274 tpi.SetCallbackProc(TPICallbackProc);
\r
275 this->ErrorCheck(tpi.nErrorCode, 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 tpi.Command(TPI_COMMAND_CREATE, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
291 this->ErrorCheck(tpi.nErrorCode);
\r
292 procDlg.Show(false);
\r
296 if (mkDlg.cbOpenAfter->IsChecked())
\r
299 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
302 if (mkDlg.cbExitAfter->IsChecked())
\r
309 this->OnArcOpen(e);
\r
312 void MainFrame::OnArcOpen(wxCommandEvent& e)
\r
315 if (e.GetId() == XRCID("Arc_Open"))
\r
317 wxFileDialog fd(this);
\r
318 fd.SetDirectory(this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
319 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);
\r
320 if (fd.ShowModal() == wxID_CANCEL)
\r
324 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
325 this->fnArchive = wxFileName(fd.GetPath());
\r
329 ProcessDialog procDlg;
\r
330 procDlg.Show(true);
\r
332 // DnD以外で書庫を開く場合、TPIを読み込み。
\r
333 TPI_PROCESSINFO piInfo;
\r
334 piInfo.fiInfo.nUnpackedSize = e.GetExtraLong();
\r
335 if (e.GetInt() != 1 && ! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))
\r
337 procDlg.Show(false);
\r
339 if (this->IsShown())
\r
342 this->statusbar->SetStatusText(_("No plug-in supporting this archive was found!"), 4);
\r
346 wxLogError(_("No plug-in supporting this archive was found!"));
\r
353 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
354 piInfo.eStatus = 0x1000;
\r
355 piInfo.nProcessedSize = 0;
\r
356 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
357 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
360 this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);
\r
363 this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());
\r
364 this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());
\r
365 this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());
\r
367 // 書庫のアイコンを取得し、書庫ルートを作成。
\r
368 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));
\r
369 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));
\r
370 this->tree_ctrl->SetImageList(& g_hIconT);
\r
372 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),
\r
374 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName))),
\r
376 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName).ConvertToImage().Rescale(16, 16))),
\r
378 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);
\r
381 if (tpi.GetFileInformation(& piInfo.fiInfo, true))
\r
383 piInfo.eStatus = 0x1001;
\r
386 piInfo.nProcessedSize++;
\r
387 if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo)) == TPI_CALLBACK_CANCEL)
\r
389 procDlg.Show(false);
\r
390 tpi.CloseArchive();
\r
392 this->OnArcClose(e);
\r
397 TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, piInfo.fiInfo.fnFileName.GetPath(), true);
\r
399 // ディレクトリ属性を含むものについては除去。
\r
400 if (piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
407 if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)
\r
409 piInfo.fiInfo.eDanger = TRUE;
\r
410 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
412 // 空白の連続による拡張子偽装を検査。
\r
413 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT(" ")) != wxNOT_FOUND)
\r
415 piInfo.fiInfo.eDanger = TRUE;
\r
416 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
419 for (wxChar c = 0x200c; c <= 0x206f; c++)
\r
421 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)
\r
423 piInfo.fiInfo.eDanger = TRUE;
\r
424 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
428 case 0x200f: c = 0x2027; break;
\r
429 case 0x202e: c = 0x2060; break;
\r
434 this->fileinfo.Add(piInfo.fiInfo);
\r
436 while (tpi.GetFileInformation(& piInfo.fiInfo));
\r
439 // GetFileInformationがエラー終了した場合。
\r
440 this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));
\r
443 tpi.GetArchiveInformation(& this->aiArchive);
\r
444 this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));
\r
447 tpi.CloseArchive();
\r
448 this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));
\r
451 this->fileinfo.Shrink();
\r
452 this->tree_ctrl->ExpandAll();
\r
453 this->tree_ctrl->ScrollTo(idArchive);
\r
454 this->tree_ctrl->SelectItem(idArchive);
\r
455 this->list_ctrl->atDangerItem.SetTextColour(* wxRED);
\r
456 this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));
\r
459 this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);
\r
460 this->statusbar->SetStatusText(wxString::Format(_("%u file(s)"), this->fileinfo.GetCount()), 1);
\r
461 this->statusbar->SetStatusText(wxString::Format(wxString("%" wxLongLongFmtSpec "uB -> %" wxLongLongFmtSpec "uB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);
\r
462 this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);
\r
463 this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);
\r
466 SetMenuToolState("Arc_Close", true);
\r
467 SetMenuToolState("Arc_Add", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD) == TPI_COMMAND_ADD && this->aiArchive.fiInfo.fArchive);
\r
468 SetMenuToolState("Arc_SFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX) == TPI_COMMAND_SFX && ! this->aiArchive.fSFX);
\r
469 SetMenuToolState("Arc_UnSFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX) == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);
\r
470 SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);
\r
471 SetMenuToolState("Arc_Delete", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);
\r
472 SetMenuToolState("Arc_Test", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST) == TPI_COMMAND_TEST);
\r
473 SetMenuToolState("Arc_Repair", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);
\r
475 procDlg.Show(false);
\r
479 void MainFrame::OnArcClose(wxCommandEvent& e)
\r
481 // ツリービュー・リストビュー設定。
\r
482 this->tree_ctrl->DeleteAllItems();
\r
483 this->list_ctrl->DeleteAllItems();
\r
484 this->list_ctrl->showFileInfo.Clear();
\r
487 SetMenuToolState("Arc_Close", false);
\r
488 SetMenuToolState("Arc_Add", false);
\r
489 SetMenuToolState("Arc_SFX", false);
\r
490 SetMenuToolState("Arc_UnSFX", false);
\r
491 SetMenuToolState("Arc_Extract", false);
\r
492 SetMenuToolState("Arc_Delete", false);
\r
493 SetMenuToolState("Arc_Test", false);
\r
494 SetMenuToolState("Arc_Repair", false);
\r
496 for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)
\r
498 this->statusbar->SetStatusText(wxEmptyString, i);
\r
500 this->fileinfo.Clear();
\r
501 this->aiArchive.szComment.Empty();
\r
502 this->aiArchive.fnArchive.Clear();
\r
503 this->aiArchive.fiInfo.szTypeName.Empty();
\r
504 this->aiArchive.fiInfo.szSuffix.Empty();
\r
505 this->aiArchive.fiInfo.szEngineName.Empty();
\r
506 this->aiArchive.fiInfo.szTPIName.Empty();
\r
508 g_hIconT.RemoveAll();
\r
509 g_hIconLL.RemoveAll();
\r
510 g_hIconLS.RemoveAll();
\r
512 // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。
\r
513 if (e.GetExtraLong() == 0)
\r
519 void MainFrame::OnArcAdd(wxCommandEvent& e)
\r
523 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
524 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
525 mkDlg.uCommand = TPI_COMMAND_ADD;
\r
528 wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
529 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
530 if (fd.ShowModal() == wxID_CANCEL)
\r
534 fd.GetFilenames(mkDlg.files);
\r
535 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
538 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
544 TPI_SWITCHES swInfo;
\r
545 swInfo.pCustomSwitches = NULL;
\r
546 swInfo.fMakeSFX = false;
\r
547 swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());
\r
548 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
549 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
550 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
551 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
552 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
553 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
554 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
555 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
556 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
560 ProcessDialog procDlg;
\r
561 procDlg.Show(true);
\r
564 TPI_PROCESSINFO piInfo;
\r
565 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
566 piInfo.eStatus = 0x1000;
\r
567 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
568 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
569 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
571 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
572 this->ErrorCheck(tpi.nErrorCode);
\r
573 procDlg.Show(false);
\r
576 if (mkDlg.cbOpenAfter->IsChecked())
\r
579 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
582 if (mkDlg.cbExitAfter->IsChecked())
\r
588 // 終了しない場合は書庫を再読み込み。
\r
589 this->OnArcOpen(e);
\r
592 void MainFrame::OnArcConvert(wxCommandEvent& e)
\r
594 TPI_SWITCHES swInfo;
\r
595 swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");
\r
598 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
599 fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
\r
600 if (fd.ShowModal() == wxID_CANCEL)
\r
604 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
605 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
607 wxArrayString files;
\r
608 files.Add(fd.GetPath());
\r
610 ProcessDialog procDlg;
\r
611 procDlg.Show(true);
\r
612 tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);
\r
613 this->ErrorCheck(tpi.nErrorCode);
\r
614 procDlg.Show(false);
\r
617 void MainFrame::OnArcExtract(wxCommandEvent& e)
\r
619 TPI_SWITCHES swInfo;
\r
620 swInfo.pCustomSwitches = NULL;
\r
622 // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3。
\r
623 int nMode = e.GetInt();
\r
625 wxFileType * ftFile = NULL;
\r
627 // 展開ダイアログを作成。DnDまたは実行時は表示しない。
\r
629 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
630 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
631 mkDlg.uCommand = TPI_COMMAND_EXTRACT;
\r
632 mkDlg.files = MakeTargetFileList(this, nMode == 1);
\r
639 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());
\r
642 // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。
\r
643 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));
\r
646 wxLogError(_("Unable to get the file type!"));
\r
653 swInfo.fStoreDirectoryPathes = false;
\r
654 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");
\r
656 if (szDestDirBase == wxT("-----"))
\r
658 // 書庫ルートのときは書庫名にしておく。
\r
659 szDestDirBase = this->fnArchive.GetName();
\r
661 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);
\r
662 if (! swInfo.fnDestinationDirectory.IsOk())
\r
664 wxLogError(_("Unable to make the temporary directory!"));
\r
670 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
676 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
677 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());
\r
678 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
679 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
681 // 必要なら書庫名でディレクトリを作成する。
\r
682 if (WillMakeDirByArcName(this, & mkDlg))
\r
684 swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);
\r
685 if (! swInfo.fnDestinationDirectory.IsOk())
\r
687 wxLogError(_("Unable to make the destination directory!"));
\r
695 ProcessDialog procDlg;
\r
696 procDlg.Show(true);
\r
699 TPI_PROCESSINFO piInfo;
\r
700 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
701 piInfo.eStatus = 0x1000;
\r
702 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
703 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
704 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
706 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
707 this->ErrorCheck(tpi.nErrorCode);
\r
708 procDlg.Show(false);
\r
713 if (mkDlg.cbOpenAfter->IsChecked())
\r
716 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
719 if (mkDlg.cbExitAfter->IsChecked())
\r
727 wxArrayString asFiles;
\r
731 asFiles.Add(swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName());
\r
732 if (tpi.nErrorCode == TPI_ERROR_SUCCESS)
\r
735 // Linuxでは引用符で囲む必要がある。
\r
736 ::wxExecute(ftFile->GetOpenCommand(QuoteString(asFiles[0])), wxEXEC_SYNC);
\r
738 ::wxExecute(ftFile->GetOpenCommand(asFiles[0]), wxEXEC_SYNC);
\r
744 // 展開対象を決定。wxGTKのwxFileDataObjectでは多バイト文字の扱いに問題があるので代替。
\r
746 myFileDataObject objFile;
\r
748 wxFileDataObject objFile;
\r
750 for (size_t i = 0; i < mkDlg.files.GetCount(); i++)
\r
752 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();
\r
756 objFile.AddFile(szFileName);
\r
758 asFiles.Add(szFileName);
\r
762 objFile.AddFile(swInfo.fnDestinationDirectory.GetPath());
\r
765 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。
\r
766 this->SetDropTarget(NULL);
\r
769 wxDropSource dropSource(objFile, this);
\r
770 wxDragResult drResult = dropSource.DoDragDrop(wxDrag_DefaultMove);
\r
771 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)
\r
774 // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。
\r
778 this->SetDropTarget(new myFileDropTarget(this));
\r
781 // ファイルと一時ディレクトリを削除。
\r
782 for (size_t i = 0; i < asFiles.GetCount(); i++)
\r
784 ::wxRemoveFile(asFiles[i]);
\r
786 ::wxRmdir(swInfo.fnDestinationDirectory.GetFullPath());
\r
790 void MainFrame::OnArcDelete(wxCommandEvent& e)
\r
792 // 全ファイル削除は危険ではないかと。
\r
793 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
798 if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)
\r
805 TPI_SWITCHES swInfo;
\r
806 ProcessDialog procDlg;
\r
807 procDlg.Show(true);
\r
808 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
811 TPI_PROCESSINFO piInfo;
\r
812 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
813 piInfo.eStatus = 0x1000;
\r
814 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
815 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
816 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
818 tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
819 this->ErrorCheck(tpi.nErrorCode);
\r
820 procDlg.Show(false);
\r
824 this->OnArcOpen(e);
\r
827 void MainFrame::OnArcTest(wxCommandEvent&)
\r
830 ProcessDialog procDlg;
\r
831 procDlg.Show(true);
\r
832 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
835 TPI_PROCESSINFO piInfo;
\r
836 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
837 piInfo.eStatus = 0x1000;
\r
838 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
839 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
840 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
842 TPI_SWITCHES swInfo;
\r
843 bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
844 procDlg.Show(false);
\r
848 wxLogMessage(_("This is a correct archive."));
\r
852 this->ErrorCheck(tpi.nErrorCode);
\r
856 void MainFrame::OnArcRepair(wxCommandEvent&)
\r
859 ProcessDialog procDlg;
\r
860 procDlg.Show(true);
\r
861 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
864 TPI_PROCESSINFO piInfo;
\r
865 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
866 piInfo.eStatus = 0x1000;
\r
867 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
868 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
869 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
871 TPI_SWITCHES swInfo;
\r
872 tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
873 this->ErrorCheck(tpi.nErrorCode);
\r
874 procDlg.Show(false);
\r
877 void MainFrame::OnViewMode(wxCommandEvent & e)
\r
880 this->menubar->Check(n, true);
\r
881 this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));
\r
882 this->list_ctrl->SetSingleStyle(wxLC_ICON, n == XRCID("Exe_View_Icons"));
\r
883 this->list_ctrl->SetSingleStyle(wxLC_LIST, n == XRCID("Exe_View_List"));
\r
886 void MainFrame::OnShowToolBar(wxCommandEvent & e)
\r
888 this->toolbar->Show(e.IsChecked());
\r
891 void MainFrame::OnShowStatusBar(wxCommandEvent & e)
\r
893 this->statusbar->Show(e.IsChecked());
\r
896 void MainFrame::OnSelectAll(wxCommandEvent &)
\r
898 for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)
\r
900 this->list_ctrl->Select(i, true);
\r
906 void MainFrame::OnTreeChanged(wxTreeEvent& e)
\r
909 wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());
\r
911 this->list_ctrl->showFileInfo.Clear();
\r
912 this->list_ctrl->DeleteAllItems();
\r
913 g_hIconLL.RemoveAll();
\r
914 g_hIconLS.RemoveAll();
\r
916 // 現在のアイテムの選択状態を無効にしておく。
\r
917 long nSelected = this->list_ctrl->GetFirstSelected();
\r
918 while (nSelected != -1)
\r
920 this->list_ctrl->Select(nSelected, false);
\r
921 nSelected = this->list_ctrl->GetNextSelected(nSelected);
\r
925 this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);
\r
926 this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);
\r
928 // 配列と比較し、パスが一致しなければ消す。
\r
929 for (size_t i = 0; i < this->fileinfo.GetCount(); i++)
\r
932 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())
\r
935 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
941 if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)
\r
946 this->list_ctrl->showFileInfo.Add(this->fileinfo[i]);
\r
951 this->list_ctrl->showFileInfo.Sort(& ListCtrlCompareProc);
\r
952 this->list_ctrl->SetItemCount(this->list_ctrl->showFileInfo.GetCount());
\r
955 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
\r
957 // TODO : アイテムが子階層を持っていても展開できない。
\r
958 this->tree_ctrl->SelectItem(e.GetItem());
\r
962 this->OnArcExtract(e1);
\r
967 void MainFrame::OnListItemDClick(wxListEvent&)
\r
971 this->OnArcExtract(e);
\r
974 void MainFrame::OnListBeginDrag(wxListEvent&)
\r
976 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
978 // アイテムを選択せずドラッグしようとした場合。
\r
984 this->OnArcExtract(e);
\r
989 void MainFrame::OnFilter(wxCommandEvent&)
\r
992 e.SetItem(this->tree_ctrl->GetSelection());
\r
993 this->OnTreeChanged(e);
\r
998 bool MainFrame::LoadTPI(wxString szFileName, wxULongLong_t * llFileCount)
\r
1000 // 書庫を開いていれば閉じておく。
\r
1002 this->OnArcClose(e);
\r
1005 wxDir fs(L_DIR_B_LIB);
\r
1006 wxString szTPIName;
\r
1007 if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))
\r
1012 if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName))
\r
1014 tpi.FreeLibrary();
\r
1019 tpi.SetCallbackProc(TPICallbackProc);
\r
1022 if (! tpi.OpenArchive(szFileName, llFileCount))
\r
1024 tpi.FreeLibrary();
\r
1025 * llFileCount = 0;
\r
1030 while (fs.GetNext(& szTPIName));
\r
1035 int MainFrame::ErrorCheck(int nErrorCode, wxString szAPIName)
\r
1037 switch (nErrorCode)
\r
1039 case TPI_ERROR_SUCCESS:
\r
1040 case TPI_ERROR_S_ENDOFDATA:
\r
1041 case TPI_CALLBACK_CONTINUE:
\r
1043 case TPI_ERROR_D_UNSUPPORTED:
\r
1044 wxLogError(_("Sorry, this function is not supported yet."));
\r
1046 case TPI_ERROR_D_SKIPPED:
\r
1047 case TPI_CALLBACK_CANCEL:
\r
1048 wxLogError(_("This operation is canceled by the user."));
\r
1051 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);
\r
1053 return nErrorCode;
\r