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 wxString szPath = piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX);
\r
399 if (szPath.StartsWith(wxT("/")))
\r
401 piInfo.fiInfo.fnFileName = wxFileName(szPath.AfterFirst(wxT('/')), piInfo.fiInfo.fnFileName.GetFullName(), wxPATH_DOS);
\r
405 bool fDir = piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? true : false;
\r
406 TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, fDir ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetPath(), true);
\r
410 if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)
\r
412 piInfo.fiInfo.eDanger = TRUE;
\r
413 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
415 // 空白の連続による拡張子偽装を検査。
\r
416 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT(" ")) != wxNOT_FOUND)
\r
418 piInfo.fiInfo.eDanger = TRUE;
\r
419 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
422 for (wxChar c = 0x200c; c <= 0x206f; c++)
\r
424 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)
\r
426 piInfo.fiInfo.eDanger = TRUE;
\r
427 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
431 case 0x200f: c = 0x2027; break;
\r
432 case 0x202e: c = 0x2060; break;
\r
436 // ディレクトリ属性を含むものについては情報を保存しない。
\r
443 this->fileinfo.Add(piInfo.fiInfo);
\r
445 while (tpi.GetFileInformation(& piInfo.fiInfo));
\r
448 // GetFileInformationがエラー終了した場合。
\r
449 this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));
\r
452 tpi.GetArchiveInformation(& this->aiArchive);
\r
453 this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));
\r
456 tpi.CloseArchive();
\r
457 this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));
\r
460 this->fileinfo.Shrink();
\r
461 this->tree_ctrl->ExpandAll();
\r
462 this->tree_ctrl->ScrollTo(idArchive);
\r
463 this->tree_ctrl->SelectItem(idArchive);
\r
464 this->list_ctrl->atDangerItem.SetTextColour(* wxRED);
\r
465 this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));
\r
468 this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);
\r
469 this->statusbar->SetStatusText(wxString::Format(_("%u file(s)"), this->fileinfo.GetCount()), 1);
\r
470 this->statusbar->SetStatusText(wxString::Format(wxString("%" wxLongLongFmtSpec "uB -> %" wxLongLongFmtSpec "uB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);
\r
471 this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);
\r
472 this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);
\r
475 SetMenuToolState("Arc_Close", true);
\r
476 SetMenuToolState("Arc_Add", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD) == TPI_COMMAND_ADD && this->aiArchive.fiInfo.fArchive);
\r
477 SetMenuToolState("Arc_SFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX) == TPI_COMMAND_SFX && ! this->aiArchive.fSFX);
\r
478 SetMenuToolState("Arc_UnSFX", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX) == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);
\r
479 SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);
\r
480 SetMenuToolState("Arc_Delete", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);
\r
481 SetMenuToolState("Arc_Test", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST) == TPI_COMMAND_TEST);
\r
482 SetMenuToolState("Arc_Repair", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);
\r
484 procDlg.Show(false);
\r
488 void MainFrame::OnArcClose(wxCommandEvent& e)
\r
490 // ツリービュー・リストビュー設定。
\r
491 this->tree_ctrl->DeleteAllItems();
\r
492 this->list_ctrl->DeleteAllItems();
\r
493 this->list_ctrl->apShowFile.Clear();
\r
496 SetMenuToolState("Arc_Close", false);
\r
497 SetMenuToolState("Arc_Add", false);
\r
498 SetMenuToolState("Arc_SFX", false);
\r
499 SetMenuToolState("Arc_UnSFX", false);
\r
500 SetMenuToolState("Arc_Extract", false);
\r
501 SetMenuToolState("Arc_Delete", false);
\r
502 SetMenuToolState("Arc_Test", false);
\r
503 SetMenuToolState("Arc_Repair", false);
\r
505 for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)
\r
507 this->statusbar->SetStatusText(wxEmptyString, i);
\r
509 this->fileinfo.Clear();
\r
510 this->aiArchive.szComment.Empty();
\r
511 this->aiArchive.fnArchive.Clear();
\r
512 this->aiArchive.fiInfo.szTypeName.Empty();
\r
513 this->aiArchive.fiInfo.szSuffix.Empty();
\r
514 this->aiArchive.fiInfo.szEngineName.Empty();
\r
515 this->aiArchive.fiInfo.szTPIName.Empty();
\r
517 g_hIconT.RemoveAll();
\r
518 g_hIconLL.RemoveAll();
\r
519 g_hIconLS.RemoveAll();
\r
521 // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。
\r
522 if (e.GetExtraLong() == 0)
\r
528 void MainFrame::OnArcAdd(wxCommandEvent& e)
\r
532 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
533 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
534 mkDlg.uCommand = TPI_COMMAND_ADD;
\r
537 wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));
\r
538 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
\r
539 if (fd.ShowModal() == wxID_CANCEL)
\r
543 fd.GetFilenames(mkDlg.files);
\r
544 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
547 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
553 TPI_SWITCHES swInfo;
\r
554 swInfo.pCustomSwitches = NULL;
\r
555 swInfo.fMakeSFX = false;
\r
556 swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());
\r
557 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
558 swInfo.fSolid = mkDlg.cbSolid->IsChecked();
\r
559 swInfo.fMMOptimize = mkDlg.cbMMOptimize->IsChecked();
\r
560 swInfo.fEncryptHeader = mkDlg.cbEncryptHeader->IsChecked();
\r
561 swInfo.nCompressLevel = mkDlg.scLevel->GetValue();
\r
562 swInfo.nRecoveryRecord = mkDlg.scRR->GetValue();
\r
563 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
564 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
565 swInfo.szComment = mkDlg.tcComment->GetValue();
\r
569 ProcessDialog procDlg;
\r
570 procDlg.Show(true);
\r
573 TPI_PROCESSINFO piInfo;
\r
574 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
575 piInfo.eStatus = 0x1000;
\r
576 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
577 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
578 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
580 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
581 this->ErrorCheck(tpi.nErrorCode);
\r
582 procDlg.Show(false);
\r
585 if (mkDlg.cbOpenAfter->IsChecked())
\r
588 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
591 if (mkDlg.cbExitAfter->IsChecked())
\r
597 // 終了しない場合は書庫を再読み込み。
\r
598 this->OnArcOpen(e);
\r
601 void MainFrame::OnArcConvert(wxCommandEvent& e)
\r
603 TPI_SWITCHES swInfo;
\r
604 swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");
\r
607 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
608 fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
\r
609 if (fd.ShowModal() == wxID_CANCEL)
\r
613 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());
\r
614 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());
\r
616 wxArrayString files;
\r
617 files.Add(fd.GetPath());
\r
619 ProcessDialog procDlg;
\r
620 procDlg.Show(true);
\r
621 tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);
\r
622 this->ErrorCheck(tpi.nErrorCode);
\r
623 procDlg.Show(false);
\r
626 void MainFrame::OnArcExtract(wxCommandEvent& e)
\r
628 TPI_SWITCHES swInfo;
\r
629 swInfo.pCustomSwitches = NULL;
\r
631 // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3、クリップボードなら4。
\r
632 int nMode = e.GetInt();
\r
634 wxFileType * ftFile = NULL;
\r
636 // 展開ダイアログを作成。DnDまたは実行時は表示しない。
\r
638 ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
639 ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));
\r
640 mkDlg.uCommand = TPI_COMMAND_EXTRACT;
\r
641 mkDlg.files = MakeTargetFileList(this, nMode == 1);
\r
648 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());
\r
651 // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。
\r
652 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));
\r
655 wxLogError(_("Unable to get the file type!"));
\r
662 swInfo.fStoreDirectoryPathes = false;
\r
663 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");
\r
665 if (szDestDirBase == wxT("-----"))
\r
667 // 書庫ルートのときは書庫名にしておく。
\r
668 szDestDirBase = this->fnArchive.GetName();
\r
670 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);
\r
671 if (! swInfo.fnDestinationDirectory.IsOk())
\r
673 wxLogError(_("Unable to make the temporary directory!"));
\r
679 if (mkDlg.ShowModal() == wxID_CANCEL)
\r
685 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();
\r
686 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());
\r
687 swInfo.szPassword = mkDlg.tcPassword->GetValue();
\r
688 swInfo.szKeyFile = mkDlg.tcKeyfile->GetValue();
\r
690 // 必要なら書庫名でディレクトリを作成する。
\r
691 if (WillMakeDirByArcName(this, & mkDlg))
\r
693 swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);
\r
694 if (! swInfo.fnDestinationDirectory.IsOk())
\r
696 wxLogError(_("Unable to make the destination directory!"));
\r
704 ProcessDialog procDlg;
\r
705 procDlg.Show(true);
\r
708 TPI_PROCESSINFO piInfo;
\r
709 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
710 piInfo.eStatus = 0x1000;
\r
711 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
712 piInfo.fiInfo.nUnpackedSize = mkDlg.files.GetCount();
\r
713 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
715 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);
\r
716 this->ErrorCheck(tpi.nErrorCode);
\r
717 procDlg.Show(false);
\r
722 if (mkDlg.cbOpenAfter->IsChecked())
\r
725 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));
\r
728 if (mkDlg.cbExitAfter->IsChecked())
\r
739 wxString szTempFile = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName();
\r
740 if (tpi.nErrorCode == TPI_ERROR_SUCCESS)
\r
743 // Linuxでは引用符で囲む必要がある。
\r
744 ::wxExecute(ftFile->GetOpenCommand(QuoteString(szTempFile)), wxEXEC_SYNC);
\r
746 ::wxExecute(ftFile->GetOpenCommand(szTempFile), wxEXEC_SYNC);
\r
750 ::wxRemoveFile(szTempFile);
\r
751 ::wxRmdir(swInfo.fnDestinationDirectory.GetPath());
\r
756 wxArrayString asFiles;
\r
757 myFileDataObject * objFile = new myFileDataObject();
\r
758 objFile->szTempDir = nMode == 3 ? swInfo.fnDestinationDirectory.GetPath() : swInfo.fnDestinationDirectory.GetFullPath();
\r
759 for (size_t i = 0; i < mkDlg.files.GetCount(); i++)
\r
761 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();
\r
764 asFiles.Add(szFileName);
\r
769 objFile->AddFile(szFileName);
\r
774 objFile->AddFile(objFile->szTempDir);
\r
779 wxTheClipboard->SetData(objFile);
\r
783 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。
\r
784 this->SetDropTarget(NULL);
\r
787 wxDropSource dropSource(* objFile, this);
\r
788 wxDragResult drResult = dropSource.DoDragDrop();
\r
789 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)
\r
792 // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。
\r
796 this->SetDropTarget(new myFileDropTarget(this));
\r
798 // ディレクトリDnDのときは、先にディレクトリの中のファイルを消しておく。
\r
801 for (size_t i = 0; i < asFiles.GetCount(); i++)
\r
803 ::wxRemoveFile(asFiles[i]);
\r
813 void MainFrame::OnArcDelete(wxCommandEvent& e)
\r
815 // 全ファイル削除は危険ではないかと。
\r
816 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
821 if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)
\r
828 TPI_SWITCHES swInfo;
\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.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
842 this->ErrorCheck(tpi.nErrorCode);
\r
843 procDlg.Show(false);
\r
847 this->OnArcOpen(e);
\r
850 void MainFrame::OnArcTest(wxCommandEvent&)
\r
853 ProcessDialog procDlg;
\r
854 procDlg.Show(true);
\r
855 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
858 TPI_PROCESSINFO piInfo;
\r
859 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
860 piInfo.eStatus = 0x1000;
\r
861 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
862 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
863 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
865 TPI_SWITCHES swInfo;
\r
866 bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
867 procDlg.Show(false);
\r
871 wxLogMessage(_("This is a correct archive."));
\r
875 this->ErrorCheck(tpi.nErrorCode);
\r
879 void MainFrame::OnArcRepair(wxCommandEvent&)
\r
882 ProcessDialog procDlg;
\r
883 procDlg.Show(true);
\r
884 wxArrayString asFiles = MakeTargetFileList(this, false);
\r
887 TPI_PROCESSINFO piInfo;
\r
888 piInfo.eMessage = TPI_MESSAGE_STATUS;
\r
889 piInfo.eStatus = 0x1000;
\r
890 piInfo.fiInfo.fnFileName = this->fnArchive;
\r
891 piInfo.fiInfo.nUnpackedSize = asFiles.GetCount();
\r
892 procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo);
\r
894 TPI_SWITCHES swInfo;
\r
895 tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);
\r
896 this->ErrorCheck(tpi.nErrorCode);
\r
897 procDlg.Show(false);
\r
900 void MainFrame::OnExeCopy(wxCommandEvent & e)
\r
902 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
907 if (! wxTheClipboard->Open())
\r
913 this->OnArcExtract(e);
\r
914 wxTheClipboard->Close();
\r
917 void MainFrame::OnViewMode(wxCommandEvent & e)
\r
920 this->menubar->Check(n, true);
\r
921 this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));
\r
922 this->list_ctrl->SetSingleStyle(wxLC_ICON, n == XRCID("Exe_View_Icons"));
\r
923 this->list_ctrl->SetSingleStyle(wxLC_LIST, n == XRCID("Exe_View_List"));
\r
926 void MainFrame::OnShowToolBar(wxCommandEvent & e)
\r
928 this->toolbar->Show(e.IsChecked());
\r
931 void MainFrame::OnShowStatusBar(wxCommandEvent & e)
\r
933 this->statusbar->Show(e.IsChecked());
\r
936 void MainFrame::OnSelectAll(wxCommandEvent &)
\r
938 for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)
\r
940 this->list_ctrl->Select(i, true);
\r
946 void MainFrame::OnTreeChanged(wxTreeEvent& e)
\r
949 wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());
\r
951 this->list_ctrl->apShowFile.Clear();
\r
952 this->list_ctrl->DeleteAllItems();
\r
953 g_hIconLL.RemoveAll();
\r
954 g_hIconLS.RemoveAll();
\r
956 // 現在のアイテムの選択状態を無効にしておく。
\r
957 long nSelected = this->list_ctrl->GetFirstSelected();
\r
958 while (nSelected != -1)
\r
960 this->list_ctrl->Select(nSelected, false);
\r
961 nSelected = this->list_ctrl->GetNextSelected(nSelected);
\r
965 this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);
\r
966 this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);
\r
968 // 配列と比較し、パスが一致しなければ消す。
\r
969 for (size_t i = 0; i < this->fileinfo.GetCount(); i++)
\r
972 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())
\r
975 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
981 if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)
\r
986 this->list_ctrl->apShowFile.Add(& this->fileinfo[i]);
\r
991 this->list_ctrl->apShowFile.Sort(& ListCtrlCompareProc);
\r
992 this->list_ctrl->SetItemCount(this->list_ctrl->apShowFile.GetCount());
\r
995 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
\r
997 // TODO : アイテムが子階層を持っていても展開できない。
\r
998 this->tree_ctrl->SelectItem(e.GetItem());
\r
1000 wxCommandEvent e1;
\r
1002 this->OnArcExtract(e1);
\r
1007 void MainFrame::OnListItemDClick(wxListEvent&)
\r
1011 this->OnArcExtract(e);
\r
1014 void MainFrame::OnListBeginDrag(wxListEvent&)
\r
1016 if (this->list_ctrl->GetSelectedItemCount() == 0)
\r
1018 // アイテムを選択せずドラッグしようとした場合。
\r
1024 this->OnArcExtract(e);
\r
1029 void MainFrame::OnFilter(wxCommandEvent&)
\r
1032 e.SetItem(this->tree_ctrl->GetSelection());
\r
1033 this->OnTreeChanged(e);
\r
1038 bool MainFrame::LoadTPI(const wxString & szFileName, wxULongLong_t * llFileCount)
\r
1040 // 書庫を開いていれば閉じておく。
\r
1042 this->OnArcClose(e);
\r
1045 wxDir fs(L_DIR_B_LIB);
\r
1046 wxString szTPIName;
\r
1047 if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))
\r
1052 if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName))
\r
1054 tpi.FreeLibrary();
\r
1059 tpi.SetCallbackProc(TPICallbackProc);
\r
1062 if (! tpi.OpenArchive(szFileName, llFileCount))
\r
1064 tpi.FreeLibrary();
\r
1065 * llFileCount = 0;
\r
1070 while (fs.GetNext(& szTPIName));
\r
1075 int MainFrame::ErrorCheck(int nErrorCode, const wxString & szAPIName)
\r
1077 switch (nErrorCode)
\r
1079 case TPI_ERROR_SUCCESS:
\r
1080 case TPI_ERROR_S_ENDOFDATA:
\r
1081 case TPI_CALLBACK_CONTINUE:
\r
1083 case TPI_ERROR_D_UNSUPPORTED:
\r
1084 wxLogError(_("Sorry, this function is not supported yet."));
\r
1086 case TPI_ERROR_D_SKIPPED:
\r
1087 case TPI_CALLBACK_CANCEL:
\r
1088 wxLogError(_("This operation is canceled by the user."));
\r
1091 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);
\r
1093 return nErrorCode;
\r