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_Copy"), MainFrame::OnExeCopy)
\r
115 EVT_MENU(XRCID("Exe_View_Icons"), MainFrame::OnViewMode)
\r
116 EVT_MENU(XRCID("Exe_View_Details"),MainFrame::OnViewMode)
\r
117 EVT_MENU(XRCID("Exe_View_List"), MainFrame::OnViewMode)
\r
118 EVT_MENU(XRCID("Exe_View_ToolBar"),MainFrame::OnShowToolBar)
\r
119 EVT_MENU(XRCID("Exe_View_StatusBar"),MainFrame::OnShowStatusBar)
\r
120 EVT_MENU(XRCID("Exe_View_SelectAll"),MainFrame::OnSelectAll)
\r
122 EVT_TREE_SEL_CHANGED(XRCID("TreeView"), MainFrame::OnTreeChanged)
\r
123 EVT_TREE_BEGIN_DRAG( XRCID("TreeView"), MainFrame::OnTreeBeginDrag)
\r
125 EVT_LIST_ITEM_ACTIVATED(XRCID("ListView"), MainFrame::OnListItemDClick)
\r
126 EVT_LIST_BEGIN_DRAG( XRCID("ListView"), MainFrame::OnListBeginDrag)
\r
128 EVT_TEXT(XRCID("tcFilter"), MainFrame::OnFilter)
\r
131 //******************************************************************************
\r
133 //******************************************************************************
\r
135 void MainFrame::OnInit(wxInitDialogEvent&)
\r
138 this->menubar = this->GetMenuBar();
\r
139 this->toolbar = this->GetToolBar();
\r
140 this->statusbar = XRCCTRL(* this, "statusbar", wxStatusBar);
\r
141 this->tree_ctrl = XRCCTRL(* this, "TreeView", wxTreeCtrl);
\r
142 this->list_ctrl = XRCCTRL(* this, "ListView", myListCtrl);
\r
143 this->window_splitter = XRCCTRL(* this, "window_splitter", wxSplitterWindow);
\r
144 this->tcFilter = XRCCTRL(* this->toolbar, "tcFilter", wxTextCtrl);
\r
147 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
148 wxTheMimeTypesManager->Initialize(wxMAILCAP_ALL);
\r
153 icon.CopyFromBitmap(wxBitmap(L_DIR_S_ICO wxT("app.png"), wxBITMAP_TYPE_ANY));
\r
154 this->SetIcon(icon);
\r
157 this->OnArcClose(e);
\r
158 this->SetDropTarget(new myFileDropTarget(this));
\r
161 this->window_splitter->SetSashPosition(this->conf.ReadId(CONF_WINDOW_SPLITTER_POS, 200l));
\r
164 int nIconMode = this->conf.ReadId(CONF_LISTVIEW_SHOWMODE, 0l);
\r
165 e.SetId(nIconMode == 1 ? XRCID("Exe_View_Icons") : (nIconMode == 2 ? XRCID("Exe_View_List") : XRCID("Exe_View_Details")));
\r
166 this->OnViewMode(e);
\r
167 // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。
\r
168 this->list_ctrl->SetSingleStyle(wxLC_VIRTUAL);
\r
169 this->list_ctrl->InsertColumn(0, _("Filename"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_FILENAME, 140l));
\r
170 this->list_ctrl->InsertColumn(1, _("Unpacked"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_UNPACKED, 80l));
\r
171 this->list_ctrl->InsertColumn(2, _("Packed"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_PACKED, 80l));
\r
172 this->list_ctrl->InsertColumn(3, _("Ratio"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_RATIO, 50l));
\r
173 this->list_ctrl->InsertColumn(4, _("Method"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_METHOD, 60l));
\r
174 this->list_ctrl->InsertColumn(5, _("Attr"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_ATTR, 50l));
\r
175 this->list_ctrl->InsertColumn(6, _("Last modified"), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_LASTMOD, 150l));
\r
176 this->list_ctrl->InsertColumn(7, _("Path"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_PATH, 100l));
\r
177 this->list_ctrl->InsertColumn(8, _("Type"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_TYPE, 100l));
\r
178 this->list_ctrl->InsertColumn(9, _("No."), wxLIST_FORMAT_RIGHT, this->conf.ReadId(CONF_LISTVIEW_C_NO, 35l));
\r
179 this->list_ctrl->InsertColumn(10,_("Comment"), wxLIST_FORMAT_LEFT, this->conf.ReadId(CONF_LISTVIEW_C_COMMENT, 35l));
\r
180 g_nSortColumn = this->conf.ReadId(CONF_LISTVIEW_S_COLUMN, 9l);
\r
181 g_fSortAscend = this->conf.ReadId(CONF_LISTVIEW_S_ASCEND, true);
\r
183 // ツールバー/ステータスバー設定。
\r
184 int nStatusBarParts[] = {70, 70, 180, 50, -1};
\r
185 this->statusbar->SetFieldsCount(5, nStatusBarParts);
\r
186 this->SetStatusBarPane(-1);
\r
187 bool fShow = this->conf.ReadId(CONF_WINDOW_STATUSBAR, true);
\r
188 this->menubar->Check(XRCID("Exe_View_StatusBar"), fShow);
\r
189 this->statusbar->Show(fShow);
\r
190 fShow = this->conf.ReadId(CONF_WINDOW_TOOLBAR, true);
\r
191 this->menubar->Check(XRCID("Exe_View_ToolBar"), fShow);
\r
192 this->toolbar->Show(fShow);
\r
197 void MainFrame::OnExit(wxCommandEvent&)
\r
202 void MainFrame::OnArcCreate(wxCommandEvent& e)
\r
204 TPI_SWITCHES swInfo;
\r
205 swInfo.pCustomSwitches = NULL;
\r
209 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
210 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
212 if (e.GetClientData() == NULL)
\r
215 wxFileDialog fd(this, _("Choose files to compress"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
216 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
217 if (fd.ShowModal() == wxID_CANCEL)
\r
221 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
222 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
223 fd.GetFilenames(mkDlg.files);
\r
227 mkDlg.files = * (wxArrayString *) e.GetClientData();
\r
228 swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());
\r
230 for (size_t n = 0; n < mkDlg.files.GetCount(); n++)
\r
232 wxFileName fn(mkDlg.files[n]);
\r
233 fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());
\r
234 mkDlg.files[n] = fn.GetFullPath();
\r
238 this->OnArcClose(e);
\r
239 // 書庫名はファイル名の拡張子より前、もしくはディレクトリ名。
\r
240 this->fnArchive = wxFileName(mkDlg.files[0]);
\r
241 this->fnArchive.SetName(mkDlg.files.GetCount() == 1 ? (this->fnArchive.GetName().IsEmpty() ? this->fnArchive.GetDirs().Last() : this->fnArchive.GetName()) : swInfo.fnDestinationDirectory.GetDirs().Last());
\r
242 this->fnArchive.SetEmptyExt();
\r
243 this->fnArchive.SetPath(swInfo.fnDestinationDirectory.GetPath());
\r
246 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
252 swInfo.fStoreDirectoryPathes= ! mkDlg.cbIgnorePath->IsChecked();
\r
253 swInfo.fMakeSFX = mkDlg.cbMakeSFX->IsChecked();
\r
254 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
255 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
256 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
257 swInfo.fCompressHeader = mkDlg.cbCompressHeader->IsChecked();
\r
258 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
259 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
260 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
261 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
262 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
263 mkDlg.cbSplitSize->GetValue().ToULongLong(& swInfo.nSplitSize);
\r
266 int nSelected = mkDlg.chType->GetSelection();
\r
267 this->fnArchive = wxFileName(mkDlg.cbDir->GetValue(), mkDlg.cbFileName->GetValue());
\r
268 if (! tpi.InitLibrary(mkDlg.afInfo[nSelected].szTPIName, this->fnArchive.GetFullPath(), mkDlg.afInfo[nSelected].nTypeId))
\r
270 this->ErrorCheck(tpi.nErrorCode, wxT("InitLibrary"));
\r
275 tpi.SetCallbackProc(TPICallbackProc);
\r
276 this->ErrorCheck(tpi.nErrorCode, wxT("SetCallbackProc"));
\r
280 ProcessDialog procDlg;
\r
281 procDlg.Show(true);
\r
284 TPI_PROCESSINFO piInfo;
\r
285 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
286 piInfo.eStatus = 0x1000;
\r
287 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
288 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
289 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
291 tpi.Command(TPI_COMMAND_CREATE, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
292 this->ErrorCheck(tpi.nErrorCode);
\r
293 procDlg.Show(false);
\r
297 if (mkDlg.cbOpenAfter->IsChecked())
\r
300 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
303 if (mkDlg.cbExitAfter->IsChecked())
\r
310 this->OnArcOpen(e);
\r
313 void MainFrame::OnArcOpen(wxCommandEvent& e)
\r
316 if (e.GetId() == XRCID("Arc_Open"))
\r
318 wxFileDialog fd(this);
\r
319 fd.SetDirectory(this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
320 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);
\r
321 if (fd.ShowModal() == wxID_CANCEL)
\r
325 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
326 this->fnArchive = wxFileName(fd.GetPath());
\r
330 ProcessDialog procDlg;
\r
331 procDlg.Show(true);
\r
333 // DnD以外で書庫を開く場合、TPIを読み込み。
\r
334 TPI_PROCESSINFO piInfo;
\r
335 piInfo.fiInfo.nUnpackedSize = e.GetExtraLong();
\r
336 if (e.GetInt() != 1 && ! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))
\r
338 procDlg.Show(false);
\r
340 if (this->IsShown())
\r
343 this->statusbar->SetStatusText(_("No plug-in supporting this archive was found!"), 4);
\r
347 wxLogError(_("No plug-in supporting this archive was found!"));
\r
354 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
355 piInfo.eStatus = 0x1000;
\r
356 piInfo.nProcessedSize = 0;
\r
357 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
358 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
361 this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);
\r
364 this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());
\r
365 this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());
\r
366 this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());
\r
368 // 書庫のアイコンを取得し、書庫ルートを作成。
\r
369 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));
\r
370 g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));
\r
371 this->tree_ctrl->SetImageList(& g_hIconT);
\r
373 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),
\r
375 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName))),
\r
377 idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName).ConvertToImage().Rescale(16, 16))),
\r
379 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);
\r
382 if (tpi.GetFileInformation(& piInfo.fiInfo, true))
\r
384 piInfo.eStatus = 0x1001;
\r
387 piInfo.nProcessedSize++;
\r
388 if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo)) == TPI_CALLBACK_CANCEL)
\r
390 procDlg.Show(false);
\r
391 tpi.CloseArchive();
\r
393 this->OnArcClose(e);
\r
398 bool fDir = piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY;
\r
399 TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, fDir ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetPath(), true);
\r
403 if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)
\r
405 piInfo.fiInfo.eDanger = TRUE;
\r
406 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
408 // 空白の連続による拡張子偽装を検査。
\r
409 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT(" ")) != wxNOT_FOUND)
\r
411 piInfo.fiInfo.eDanger = TRUE;
\r
412 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
415 for (wxChar c = 0x200c; c <= 0x206f; c++)
\r
417 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)
\r
419 piInfo.fiInfo.eDanger = TRUE;
\r
420 wxLogWarning(_("This archive may contain extension-disguised files whose real extension is hidden by using 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
424 case 0x200f: c = 0x2027; break;
\r
425 case 0x202e: c = 0x2060; break;
\r
429 // ディレクトリ属性を含むものについては情報を保存しない。
\r
436 this->fileinfo.Add(piInfo.fiInfo);
\r
438 while (tpi.GetFileInformation(& piInfo.fiInfo));
\r
441 // GetFileInformationがエラー終了した場合。
\r
442 this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));
\r
445 tpi.GetArchiveInformation(& this->aiArchive);
\r
446 this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));
\r
449 tpi.CloseArchive();
\r
450 this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));
\r
453 this->fileinfo.Shrink();
\r
454 this->tree_ctrl->ExpandAll();
\r
455 this->tree_ctrl->ScrollTo(idArchive);
\r
456 this->tree_ctrl->SelectItem(idArchive);
\r
457 this->list_ctrl->atDangerItem.SetTextColour(* wxRED);
\r
458 this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));
\r
461 this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);
\r
462 this->statusbar->SetStatusText(wxString::Format(_("%u file(s)"), this->fileinfo.GetCount()), 1);
\r
463 this->statusbar->SetStatusText(wxString::Format(wxString("%" wxLongLongFmtSpec "uB -> %" wxLongLongFmtSpec "uB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);
\r
464 this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);
\r
465 this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);
\r
468 SetMenuToolState("Arc_Close", true);
\r
469 SetMenuToolState("Arc_Add", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD) == TPI_COMMAND_ADD && this->aiArchive.fiInfo.fArchive);
\r
470 SetMenuToolState("Arc_SFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX) == TPI_COMMAND_SFX && ! this->aiArchive.fSFX);
\r
471 SetMenuToolState("Arc_UnSFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX) == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);
\r
472 SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);
\r
473 SetMenuToolState("Arc_Delete", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);
\r
474 SetMenuToolState("Arc_Test", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST) == TPI_COMMAND_TEST);
\r
475 SetMenuToolState("Arc_Repair", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);
\r
477 procDlg.Show(false);
\r
481 void MainFrame::OnArcClose(wxCommandEvent& e)
\r
483 // ツリービュー・リストビュー設定。
\r
484 this->tree_ctrl->DeleteAllItems();
\r
485 this->list_ctrl->DeleteAllItems();
\r
486 this->list_ctrl->apShowFile.Clear();
\r
489 SetMenuToolState("Arc_Close", false);
\r
490 SetMenuToolState("Arc_Add", false);
\r
491 SetMenuToolState("Arc_SFX", false);
\r
492 SetMenuToolState("Arc_UnSFX", false);
\r
493 SetMenuToolState("Arc_Extract", false);
\r
494 SetMenuToolState("Arc_Delete", false);
\r
495 SetMenuToolState("Arc_Test", false);
\r
496 SetMenuToolState("Arc_Repair", false);
\r
498 for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)
\r
500 this->statusbar->SetStatusText(wxEmptyString, i);
\r
502 this->fileinfo.Clear();
\r
503 this->aiArchive.szComment.Empty();
\r
504 this->aiArchive.fnArchive.Clear();
\r
505 this->aiArchive.fiInfo.szTypeName.Empty();
\r
506 this->aiArchive.fiInfo.szSuffix.Empty();
\r
507 this->aiArchive.fiInfo.szEngineName.Empty();
\r
508 this->aiArchive.fiInfo.szTPIName.Empty();
\r
510 g_hIconT.RemoveAll();
\r
511 g_hIconLL.RemoveAll();
\r
512 g_hIconLS.RemoveAll();
\r
514 // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。
\r
515 if (e.GetExtraLong() == 0)
\r
521 void MainFrame::OnArcAdd(wxCommandEvent& e)
\r
525 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
526 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
527 mkDlg.uCommand = TPI_COMMAND_ADD;
\r
530 wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
531 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
532 if (fd.ShowModal() == wxID_CANCEL)
\r
536 fd.GetFilenames(mkDlg.files);
\r
537 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
540 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
546 TPI_SWITCHES swInfo;
\r
547 swInfo.pCustomSwitches = NULL;
\r
548 swInfo.fMakeSFX = false;
\r
549 swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());
\r
550 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
551 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
552 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
553 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
554 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
555 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
556 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
557 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
558 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
562 ProcessDialog procDlg;
\r
563 procDlg.Show(true);
\r
566 TPI_PROCESSINFO piInfo;
\r
567 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
568 piInfo.eStatus = 0x1000;
\r
569 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
570 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
571 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
573 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
574 this->ErrorCheck(tpi.nErrorCode);
\r
575 procDlg.Show(false);
\r
578 if (mkDlg.cbOpenAfter->IsChecked())
\r
581 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
584 if (mkDlg.cbExitAfter->IsChecked())
\r
590 // 終了しない場合は書庫を再読み込み。
\r
591 this->OnArcOpen(e);
\r
594 void MainFrame::OnArcConvert(wxCommandEvent& e)
\r
596 TPI_SWITCHES swInfo;
\r
597 swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");
\r
600 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
601 fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
\r
602 if (fd.ShowModal() == wxID_CANCEL)
\r
606 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
607 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
609 wxArrayString files;
\r
610 files.Add(fd.GetPath());
\r
612 ProcessDialog procDlg;
\r
613 procDlg.Show(true);
\r
614 tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);
\r
615 this->ErrorCheck(tpi.nErrorCode);
\r
616 procDlg.Show(false);
\r
619 void MainFrame::OnArcExtract(wxCommandEvent& e)
\r
621 TPI_SWITCHES swInfo;
\r
622 swInfo.pCustomSwitches = NULL;
\r
624 // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3、クリップボードなら4。
\r
625 int nMode = e.GetInt();
\r
627 wxFileType * ftFile = NULL;
\r
629 // 展開ダイアログを作成。DnDまたは実行時は表示しない。
\r
631 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
632 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
633 mkDlg.uCommand = TPI_COMMAND_EXTRACT;
\r
634 mkDlg.files = MakeTargetFileList(this, nMode == 1);
\r
641 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());
\r
644 // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。
\r
645 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));
\r
648 wxLogError(_("Unable to get the file type!"));
\r
655 swInfo.fStoreDirectoryPathes = false;
\r
656 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");
\r
658 if (szDestDirBase == wxT("-----"))
\r
660 // 書庫ルートのときは書庫名にしておく。
\r
661 szDestDirBase = this->fnArchive.GetName();
\r
663 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);
\r
664 if (! swInfo.fnDestinationDirectory.IsOk())
\r
666 wxLogError(_("Unable to make the temporary directory!"));
\r
672 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
678 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
679 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());
\r
680 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
681 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
683 // 必要なら書庫名でディレクトリを作成する。
\r
684 if (WillMakeDirByArcName(this, & mkDlg))
\r
686 swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);
\r
687 if (! swInfo.fnDestinationDirectory.IsOk())
\r
689 wxLogError(_("Unable to make the destination directory!"));
\r
697 ProcessDialog procDlg;
\r
698 procDlg.Show(true);
\r
701 TPI_PROCESSINFO piInfo;
\r
702 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
703 piInfo.eStatus = 0x1000;
\r
704 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
705 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
706 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
708 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
709 this->ErrorCheck(tpi.nErrorCode);
\r
710 procDlg.Show(false);
\r
715 if (mkDlg.cbOpenAfter->IsChecked())
\r
718 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
721 if (mkDlg.cbExitAfter->IsChecked())
\r
732 wxString szTempFile = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName();
\r
733 if (tpi.nErrorCode == TPI_ERROR_SUCCESS)
\r
736 // Linuxでは引用符で囲む必要がある。
\r
737 ::wxExecute(ftFile->GetOpenCommand(QuoteString(szTempFile)), wxEXEC_SYNC);
\r
739 ::wxExecute(ftFile->GetOpenCommand(szTempFile), wxEXEC_SYNC);
\r
743 ::wxRemoveFile(szTempFile);
\r
744 ::wxRmdir(swInfo.fnDestinationDirectory.GetPath());
\r
749 wxArrayString asFiles;
\r
750 myFileDataObject * objFile = new myFileDataObject();
\r
751 objFile->szTempDir = nMode == 3 ? swInfo.fnDestinationDirectory.GetPath() : swInfo.fnDestinationDirectory.GetFullPath();
\r
752 for (size_t i = 0; i < mkDlg.files.GetCount(); i++)
\r
754 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();
\r
757 asFiles.Add(szFileName);
\r
762 objFile->AddFile(szFileName);
\r
767 objFile->AddFile(objFile->szTempDir);
\r
772 wxTheClipboard->SetData(objFile);
\r
776 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。
\r
777 this->SetDropTarget(NULL);
\r
780 wxDropSource dropSource(* objFile, this);
\r
781 wxDragResult drResult = dropSource.DoDragDrop();
\r
782 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)
\r
785 // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。
\r
789 this->SetDropTarget(new myFileDropTarget(this));
\r
791 // ディレクトリDnDのときは、先にディレクトリの中のファイルを消しておく。
\r
794 for (size_t i = 0; i < asFiles.GetCount(); i++)
\r
796 ::wxRemoveFile(asFiles[i]);
\r
806 void MainFrame::OnArcDelete(wxCommandEvent& e)
\r
808 // 全ファイル削除は危険ではないかと。
\r
809 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
814 if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)
\r
821 TPI_SWITCHES swInfo;
\r
822 ProcessDialog procDlg;
\r
823 procDlg.Show(true);
\r
824 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
827 TPI_PROCESSINFO piInfo;
\r
828 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
829 piInfo.eStatus = 0x1000;
\r
830 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
831 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
832 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
834 tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
835 this->ErrorCheck(tpi.nErrorCode);
\r
836 procDlg.Show(false);
\r
840 this->OnArcOpen(e);
\r
843 void MainFrame::OnArcTest(wxCommandEvent&)
\r
846 ProcessDialog procDlg;
\r
847 procDlg.Show(true);
\r
848 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
851 TPI_PROCESSINFO piInfo;
\r
852 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
853 piInfo.eStatus = 0x1000;
\r
854 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
855 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
856 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
858 TPI_SWITCHES swInfo;
\r
859 bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
860 procDlg.Show(false);
\r
864 wxLogMessage(_("This is a correct archive."));
\r
868 this->ErrorCheck(tpi.nErrorCode);
\r
872 void MainFrame::OnArcRepair(wxCommandEvent&)
\r
875 ProcessDialog procDlg;
\r
876 procDlg.Show(true);
\r
877 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
880 TPI_PROCESSINFO piInfo;
\r
881 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
882 piInfo.eStatus = 0x1000;
\r
883 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
884 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
885 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
887 TPI_SWITCHES swInfo;
\r
888 tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
889 this->ErrorCheck(tpi.nErrorCode);
\r
890 procDlg.Show(false);
\r
893 void MainFrame::OnExeCopy(wxCommandEvent & e)
\r
895 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
900 if (! wxTheClipboard->Open())
\r
906 this->OnArcExtract(e);
\r
907 wxTheClipboard->Close();
\r
910 void MainFrame::OnViewMode(wxCommandEvent & e)
\r
913 this->menubar->Check(n, true);
\r
914 this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));
\r
915 this->list_ctrl->SetSingleStyle(wxLC_ICON, n == XRCID("Exe_View_Icons"));
\r
916 this->list_ctrl->SetSingleStyle(wxLC_LIST, n == XRCID("Exe_View_List"));
\r
919 void MainFrame::OnShowToolBar(wxCommandEvent & e)
\r
921 this->toolbar->Show(e.IsChecked());
\r
924 void MainFrame::OnShowStatusBar(wxCommandEvent & e)
\r
926 this->statusbar->Show(e.IsChecked());
\r
929 void MainFrame::OnSelectAll(wxCommandEvent &)
\r
931 for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)
\r
933 this->list_ctrl->Select(i, true);
\r
939 void MainFrame::OnTreeChanged(wxTreeEvent& e)
\r
942 wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());
\r
944 this->list_ctrl->apShowFile.Clear();
\r
945 this->list_ctrl->DeleteAllItems();
\r
946 g_hIconLL.RemoveAll();
\r
947 g_hIconLS.RemoveAll();
\r
949 // 現在のアイテムの選択状態を無効にしておく。
\r
950 long nSelected = this->list_ctrl->GetFirstSelected();
\r
951 while (nSelected != -1)
\r
953 this->list_ctrl->Select(nSelected, false);
\r
954 nSelected = this->list_ctrl->GetNextSelected(nSelected);
\r
958 this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);
\r
959 this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);
\r
961 // 配列と比較し、パスが一致しなければ消す。
\r
962 for (size_t i = 0; i < this->fileinfo.GetCount(); i++)
\r
965 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())
\r
968 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
974 if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)
\r
979 this->list_ctrl->apShowFile.Add(& this->fileinfo[i]);
\r
984 this->list_ctrl->apShowFile.Sort(& ListCtrlCompareProc);
\r
985 this->list_ctrl->SetItemCount(this->list_ctrl->apShowFile.GetCount());
\r
988 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
\r
990 // TODO : アイテムが子階層を持っていても展開できない。
\r
991 this->tree_ctrl->SelectItem(e.GetItem());
\r
995 this->OnArcExtract(e1);
\r
1000 void MainFrame::OnListItemDClick(wxListEvent&)
\r
1004 this->OnArcExtract(e);
\r
1007 void MainFrame::OnListBeginDrag(wxListEvent&)
\r
1009 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
1011 // アイテムを選択せずドラッグしようとした場合。
\r
1017 this->OnArcExtract(e);
\r
1022 void MainFrame::OnFilter(wxCommandEvent&)
\r
1025 e.SetItem(this->tree_ctrl->GetSelection());
\r
1026 this->OnTreeChanged(e);
\r
1031 bool MainFrame::LoadTPI(const wxString & szFileName, wxULongLong_t * llFileCount)
\r
1033 // 書庫を開いていれば閉じておく。
\r
1035 this->OnArcClose(e);
\r
1038 wxDir fs(L_DIR_B_LIB);
\r
1039 wxString szTPIName;
\r
1040 if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))
\r
1045 if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName))
\r
1047 tpi.FreeLibrary();
\r
1052 tpi.SetCallbackProc(TPICallbackProc);
\r
1055 if (! tpi.OpenArchive(szFileName, llFileCount))
\r
1057 tpi.FreeLibrary();
\r
1058 * llFileCount = 0;
\r
1063 while (fs.GetNext(& szTPIName));
\r
1068 int MainFrame::ErrorCheck(int nErrorCode, const wxString & szAPIName)
\r
1070 switch (nErrorCode)
\r
1072 case TPI_ERROR_SUCCESS:
\r
1073 case TPI_ERROR_S_ENDOFDATA:
\r
1074 case TPI_CALLBACK_CONTINUE:
\r
1076 case TPI_ERROR_D_UNSUPPORTED:
\r
1077 wxLogError(_("Sorry, this function is not supported yet."));
\r
1079 case TPI_ERROR_D_SKIPPED:
\r
1080 case TPI_CALLBACK_CANCEL:
\r
1081 wxLogError(_("This operation is canceled by the user."));
\r
1084 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);
\r
1086 return nErrorCode;
\r