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 TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, piInfo.fiInfo.fnFileName.GetPath(), true);
\r
400 // ディレクトリ属性を含むものについては除去。
\r
401 if (piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)
\r
408 if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)
\r
410 piInfo.fiInfo.eDanger = TRUE;
\r
411 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
413 // 空白の連続による拡張子偽装を検査。
\r
414 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT(" ")) != wxNOT_FOUND)
\r
416 piInfo.fiInfo.eDanger = TRUE;
\r
417 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
420 for (wxChar c = 0x200c; c <= 0x206f; c++)
\r
422 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)
\r
424 piInfo.fiInfo.eDanger = TRUE;
\r
425 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
429 case 0x200f: c = 0x2027; break;
\r
430 case 0x202e: c = 0x2060; break;
\r
435 this->fileinfo.Add(piInfo.fiInfo);
\r
437 while (tpi.GetFileInformation(& piInfo.fiInfo));
\r
440 // GetFileInformationがエラー終了した場合。
\r
441 this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));
\r
444 tpi.GetArchiveInformation(& this->aiArchive);
\r
445 this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));
\r
448 tpi.CloseArchive();
\r
449 this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));
\r
452 this->fileinfo.Shrink();
\r
453 this->tree_ctrl->ExpandAll();
\r
454 this->tree_ctrl->ScrollTo(idArchive);
\r
455 this->tree_ctrl->SelectItem(idArchive);
\r
456 this->list_ctrl->atDangerItem.SetTextColour(* wxRED);
\r
457 this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));
\r
460 this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);
\r
461 this->statusbar->SetStatusText(wxString::Format(_("%u file(s)"), this->fileinfo.GetCount()), 1);
\r
462 this->statusbar->SetStatusText(wxString::Format(wxString("%" wxLongLongFmtSpec "uB -> %" wxLongLongFmtSpec "uB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);
\r
463 this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);
\r
464 this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);
\r
467 SetMenuToolState("Arc_Close", true);
\r
468 SetMenuToolState("Arc_Add", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD) == TPI_COMMAND_ADD && this->aiArchive.fiInfo.fArchive);
\r
469 SetMenuToolState("Arc_SFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX) == TPI_COMMAND_SFX && ! this->aiArchive.fSFX);
\r
470 SetMenuToolState("Arc_UnSFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX) == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);
\r
471 SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);
\r
472 SetMenuToolState("Arc_Delete", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);
\r
473 SetMenuToolState("Arc_Test", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST) == TPI_COMMAND_TEST);
\r
474 SetMenuToolState("Arc_Repair", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);
\r
476 procDlg.Show(false);
\r
480 void MainFrame::OnArcClose(wxCommandEvent& e)
\r
482 // ツリービュー・リストビュー設定。
\r
483 this->tree_ctrl->DeleteAllItems();
\r
484 this->list_ctrl->DeleteAllItems();
\r
485 this->list_ctrl->apShowFile.Clear();
\r
488 SetMenuToolState("Arc_Close", false);
\r
489 SetMenuToolState("Arc_Add", false);
\r
490 SetMenuToolState("Arc_SFX", false);
\r
491 SetMenuToolState("Arc_UnSFX", false);
\r
492 SetMenuToolState("Arc_Extract", false);
\r
493 SetMenuToolState("Arc_Delete", false);
\r
494 SetMenuToolState("Arc_Test", false);
\r
495 SetMenuToolState("Arc_Repair", false);
\r
497 for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)
\r
499 this->statusbar->SetStatusText(wxEmptyString, i);
\r
501 this->fileinfo.Clear();
\r
502 this->aiArchive.szComment.Empty();
\r
503 this->aiArchive.fnArchive.Clear();
\r
504 this->aiArchive.fiInfo.szTypeName.Empty();
\r
505 this->aiArchive.fiInfo.szSuffix.Empty();
\r
506 this->aiArchive.fiInfo.szEngineName.Empty();
\r
507 this->aiArchive.fiInfo.szTPIName.Empty();
\r
509 g_hIconT.RemoveAll();
\r
510 g_hIconLL.RemoveAll();
\r
511 g_hIconLS.RemoveAll();
\r
513 // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。
\r
514 if (e.GetExtraLong() == 0)
\r
520 void MainFrame::OnArcAdd(wxCommandEvent& e)
\r
524 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
525 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
526 mkDlg.uCommand = TPI_COMMAND_ADD;
\r
529 wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
530 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
531 if (fd.ShowModal() == wxID_CANCEL)
\r
535 fd.GetFilenames(mkDlg.files);
\r
536 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
539 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
545 TPI_SWITCHES swInfo;
\r
546 swInfo.pCustomSwitches = NULL;
\r
547 swInfo.fMakeSFX = false;
\r
548 swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());
\r
549 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
550 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
551 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
552 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
553 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
554 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
555 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
556 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
557 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
561 ProcessDialog procDlg;
\r
562 procDlg.Show(true);
\r
565 TPI_PROCESSINFO piInfo;
\r
566 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
567 piInfo.eStatus = 0x1000;
\r
568 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
569 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
570 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
572 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
573 this->ErrorCheck(tpi.nErrorCode);
\r
574 procDlg.Show(false);
\r
577 if (mkDlg.cbOpenAfter->IsChecked())
\r
580 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
583 if (mkDlg.cbExitAfter->IsChecked())
\r
589 // 終了しない場合は書庫を再読み込み。
\r
590 this->OnArcOpen(e);
\r
593 void MainFrame::OnArcConvert(wxCommandEvent& e)
\r
595 TPI_SWITCHES swInfo;
\r
596 swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");
\r
599 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
600 fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
\r
601 if (fd.ShowModal() == wxID_CANCEL)
\r
605 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
606 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
608 wxArrayString files;
\r
609 files.Add(fd.GetPath());
\r
611 ProcessDialog procDlg;
\r
612 procDlg.Show(true);
\r
613 tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);
\r
614 this->ErrorCheck(tpi.nErrorCode);
\r
615 procDlg.Show(false);
\r
618 void MainFrame::OnArcExtract(wxCommandEvent& e)
\r
620 TPI_SWITCHES swInfo;
\r
621 swInfo.pCustomSwitches = NULL;
\r
623 // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3、クリップボードなら4。
\r
624 int nMode = e.GetInt();
\r
626 wxFileType * ftFile = NULL;
\r
628 // 展開ダイアログを作成。DnDまたは実行時は表示しない。
\r
630 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
631 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
632 mkDlg.uCommand = TPI_COMMAND_EXTRACT;
\r
633 mkDlg.files = MakeTargetFileList(this, nMode == 1);
\r
640 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());
\r
643 // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。
\r
644 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));
\r
647 wxLogError(_("Unable to get the file type!"));
\r
654 swInfo.fStoreDirectoryPathes = false;
\r
655 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");
\r
657 if (szDestDirBase == wxT("-----"))
\r
659 // 書庫ルートのときは書庫名にしておく。
\r
660 szDestDirBase = this->fnArchive.GetName();
\r
662 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);
\r
663 if (! swInfo.fnDestinationDirectory.IsOk())
\r
665 wxLogError(_("Unable to make the temporary directory!"));
\r
671 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
677 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
678 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());
\r
679 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
680 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
682 // 必要なら書庫名でディレクトリを作成する。
\r
683 if (WillMakeDirByArcName(this, & mkDlg))
\r
685 swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);
\r
686 if (! swInfo.fnDestinationDirectory.IsOk())
\r
688 wxLogError(_("Unable to make the destination directory!"));
\r
696 ProcessDialog procDlg;
\r
697 procDlg.Show(true);
\r
700 TPI_PROCESSINFO piInfo;
\r
701 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
702 piInfo.eStatus = 0x1000;
\r
703 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
704 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
705 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
707 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
708 this->ErrorCheck(tpi.nErrorCode);
\r
709 procDlg.Show(false);
\r
714 if (mkDlg.cbOpenAfter->IsChecked())
\r
717 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
720 if (mkDlg.cbExitAfter->IsChecked())
\r
728 wxArrayString asFiles;
\r
732 asFiles.Add(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(asFiles[0])), wxEXEC_SYNC);
\r
739 ::wxExecute(ftFile->GetOpenCommand(asFiles[0]), wxEXEC_SYNC);
\r
746 myFileDataObject * objFile = new myFileDataObject();
\r
747 objFile->szTempDir = swInfo.fnDestinationDirectory.GetFullPath();
\r
748 for (size_t i = 0; i < mkDlg.files.GetCount(); i++)
\r
750 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();
\r
754 objFile->AddFile(szFileName);
\r
756 asFiles.Add(szFileName);
\r
760 objFile->AddFile(swInfo.fnDestinationDirectory.GetPath());
\r
765 wxTheClipboard->SetData(objFile);
\r
769 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。
\r
770 this->SetDropTarget(NULL);
\r
773 wxDropSource dropSource(* objFile, this);
\r
774 wxDragResult drResult = dropSource.DoDragDrop(wxDrag_DefaultMove);
\r
775 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)
\r
778 // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。
\r
782 this->SetDropTarget(new myFileDropTarget(this));
\r
789 void MainFrame::OnArcDelete(wxCommandEvent& e)
\r
791 // 全ファイル削除は危険ではないかと。
\r
792 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
797 if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)
\r
804 TPI_SWITCHES swInfo;
\r
805 ProcessDialog procDlg;
\r
806 procDlg.Show(true);
\r
807 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
810 TPI_PROCESSINFO piInfo;
\r
811 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
812 piInfo.eStatus = 0x1000;
\r
813 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
814 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
815 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
817 tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
818 this->ErrorCheck(tpi.nErrorCode);
\r
819 procDlg.Show(false);
\r
823 this->OnArcOpen(e);
\r
826 void MainFrame::OnArcTest(wxCommandEvent&)
\r
829 ProcessDialog procDlg;
\r
830 procDlg.Show(true);
\r
831 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
834 TPI_PROCESSINFO piInfo;
\r
835 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
836 piInfo.eStatus = 0x1000;
\r
837 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
838 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
839 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
841 TPI_SWITCHES swInfo;
\r
842 bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
843 procDlg.Show(false);
\r
847 wxLogMessage(_("This is a correct archive."));
\r
851 this->ErrorCheck(tpi.nErrorCode);
\r
855 void MainFrame::OnArcRepair(wxCommandEvent&)
\r
858 ProcessDialog procDlg;
\r
859 procDlg.Show(true);
\r
860 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
863 TPI_PROCESSINFO piInfo;
\r
864 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
865 piInfo.eStatus = 0x1000;
\r
866 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
867 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
868 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
870 TPI_SWITCHES swInfo;
\r
871 tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
872 this->ErrorCheck(tpi.nErrorCode);
\r
873 procDlg.Show(false);
\r
876 void MainFrame::OnExeCopy(wxCommandEvent & e)
\r
878 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
883 if (! wxTheClipboard->Open())
\r
889 this->OnArcExtract(e);
\r
890 wxTheClipboard->Close();
\r
893 void MainFrame::OnViewMode(wxCommandEvent & e)
\r
896 this->menubar->Check(n, true);
\r
897 this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));
\r
898 this->list_ctrl->SetSingleStyle(wxLC_ICON, n == XRCID("Exe_View_Icons"));
\r
899 this->list_ctrl->SetSingleStyle(wxLC_LIST, n == XRCID("Exe_View_List"));
\r
902 void MainFrame::OnShowToolBar(wxCommandEvent & e)
\r
904 this->toolbar->Show(e.IsChecked());
\r
907 void MainFrame::OnShowStatusBar(wxCommandEvent & e)
\r
909 this->statusbar->Show(e.IsChecked());
\r
912 void MainFrame::OnSelectAll(wxCommandEvent &)
\r
914 for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)
\r
916 this->list_ctrl->Select(i, true);
\r
922 void MainFrame::OnTreeChanged(wxTreeEvent& e)
\r
925 wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());
\r
927 this->list_ctrl->apShowFile.Clear();
\r
928 this->list_ctrl->DeleteAllItems();
\r
929 g_hIconLL.RemoveAll();
\r
930 g_hIconLS.RemoveAll();
\r
932 // 現在のアイテムの選択状態を無効にしておく。
\r
933 long nSelected = this->list_ctrl->GetFirstSelected();
\r
934 while (nSelected != -1)
\r
936 this->list_ctrl->Select(nSelected, false);
\r
937 nSelected = this->list_ctrl->GetNextSelected(nSelected);
\r
941 this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);
\r
942 this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);
\r
944 // 配列と比較し、パスが一致しなければ消す。
\r
945 for (size_t i = 0; i < this->fileinfo.GetCount(); i++)
\r
948 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())
\r
951 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
957 if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)
\r
962 this->list_ctrl->apShowFile.Add(& this->fileinfo[i]);
\r
967 this->list_ctrl->apShowFile.Sort(& ListCtrlCompareProc);
\r
968 this->list_ctrl->SetItemCount(this->list_ctrl->apShowFile.GetCount());
\r
971 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
\r
973 // TODO : アイテムが子階層を持っていても展開できない。
\r
974 this->tree_ctrl->SelectItem(e.GetItem());
\r
978 this->OnArcExtract(e1);
\r
983 void MainFrame::OnListItemDClick(wxListEvent&)
\r
987 this->OnArcExtract(e);
\r
990 void MainFrame::OnListBeginDrag(wxListEvent&)
\r
992 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
994 // アイテムを選択せずドラッグしようとした場合。
\r
1000 this->OnArcExtract(e);
\r
1005 void MainFrame::OnFilter(wxCommandEvent&)
\r
1008 e.SetItem(this->tree_ctrl->GetSelection());
\r
1009 this->OnTreeChanged(e);
\r
1014 bool MainFrame::LoadTPI(const wxString & szFileName, wxULongLong_t * llFileCount)
\r
1016 // 書庫を開いていれば閉じておく。
\r
1018 this->OnArcClose(e);
\r
1021 wxDir fs(L_DIR_B_LIB);
\r
1022 wxString szTPIName;
\r
1023 if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))
\r
1028 if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName))
\r
1030 tpi.FreeLibrary();
\r
1035 tpi.SetCallbackProc(TPICallbackProc);
\r
1038 if (! tpi.OpenArchive(szFileName, llFileCount))
\r
1040 tpi.FreeLibrary();
\r
1041 * llFileCount = 0;
\r
1046 while (fs.GetNext(& szTPIName));
\r
1051 int MainFrame::ErrorCheck(int nErrorCode, const wxString & szAPIName)
\r
1053 switch (nErrorCode)
\r
1055 case TPI_ERROR_SUCCESS:
\r
1056 case TPI_ERROR_S_ENDOFDATA:
\r
1057 case TPI_CALLBACK_CONTINUE:
\r
1059 case TPI_ERROR_D_UNSUPPORTED:
\r
1060 wxLogError(_("Sorry, this function is not supported yet."));
\r
1062 case TPI_ERROR_D_SKIPPED:
\r
1063 case TPI_CALLBACK_CANCEL:
\r
1064 wxLogError(_("This operation is canceled by the user."));
\r
1067 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);
\r
1069 return nErrorCode;
\r