OSDN Git Service

ProcessDialogのコンストラクタに渡す引数を削減。
[tpi/lychee.git] / src / lychee / frm_main.cpp
1 /*******************************************************************************\r
2   TPI - flexible but useless plug-in framework.\r
3   Copyright (C) 2002-2009 Silky\r
4 \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
8   any later version.\r
9 \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
13   for more details.\r
14 \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
18 \r
19   $Id$\r
20 *******************************************************************************/\r
21 \r
22 #include "lychee.h"\r
23 \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
29 \r
30 #include <wx/arrimpl.cpp>\r
31 \r
32 WX_DEFINE_OBJARRAY(ArrayTPI_FILEINFO);\r
33 \r
34 #define SetMenuToolState(id, state) this->toolbar->EnableTool(XRCID(id), state); this->menubar->Enable(XRCID(id), state)\r
35 \r
36 //******************************************************************************\r
37 //    グローバル変数\r
38 //******************************************************************************\r
39 \r
40 wxImageList g_hIconT(16, 16), g_hIconLL(32, 32), g_hIconLS(16, 16);\r
41 int g_nSortColumn;\r
42 bool g_fSortAscend;\r
43 \r
44 //******************************************************************************\r
45 // MainFrame\r
46 //******************************************************************************\r
47 \r
48 MainFrame::MainFrame(): wxFrame()\r
49 {\r
50 }\r
51 \r
52 MainFrame::~MainFrame()\r
53 {\r
54         wxCommandEvent e;\r
55         this->OnArcClose(e);\r
56 \r
57         // 設定を記録。\r
58         if (! this->IsIconized() && ! this->IsMaximized())\r
59         {\r
60                 int a, b;\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
67         }\r
68         this->conf.WriteId(CONF_WINDOW_SPLITTER_POS, this->window_splitter->GetSashPosition());\r
69 \r
70         // ツールバー/ステータスバー関連。\r
71         this->conf.WriteId(CONF_WINDOW_STATUSBAR, this->statusbar->IsShown());\r
72         this->conf.WriteId(CONF_WINDOW_TOOLBAR,   this->toolbar->IsShown());\r
73 \r
74         // ListView関連。\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
77         {\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
91         }\r
92 \r
93         this->Close(true);\r
94 }\r
95 \r
96 //******************************************************************************\r
97 // Event Table.\r
98 //******************************************************************************\r
99 \r
100 BEGIN_EVENT_TABLE(MainFrame, wxFrame)\r
101         EVT_INIT_DIALOG(      MainFrame::OnInit)\r
102         // Menu\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_Clone"),   MainFrame::OnArcClone)\r
107         EVT_MENU(XRCID("Arc_Add"),     MainFrame::OnArcAdd)\r
108         EVT_MENU(XRCID("Arc_SFX"),     MainFrame::OnArcConvert)\r
109         EVT_MENU(XRCID("Arc_UnSFX"),   MainFrame::OnArcConvert)\r
110         EVT_MENU(XRCID("Exe_Exit"),    MainFrame::OnExit)\r
111         EVT_MENU(XRCID("Arc_Extract"), MainFrame::OnArcExtract)\r
112         EVT_MENU(XRCID("Arc_Delete"),  MainFrame::OnArcDelete)\r
113         EVT_MENU(XRCID("Arc_Test"),    MainFrame::OnArcTest)\r
114         EVT_MENU(XRCID("Arc_Repair"),  MainFrame::OnArcRepair)\r
115         EVT_MENU(XRCID("Exe_Copy"),    MainFrame::OnExeCopy)\r
116         EVT_MENU(XRCID("Exe_View_Icons"),  MainFrame::OnViewMode)\r
117         EVT_MENU(XRCID("Exe_View_Details"),MainFrame::OnViewMode)\r
118         EVT_MENU(XRCID("Exe_View_List"),   MainFrame::OnViewMode)\r
119         EVT_MENU(XRCID("Exe_View_ToolBar"),MainFrame::OnShowToolBar)\r
120         EVT_MENU(XRCID("Exe_View_StatusBar"),MainFrame::OnShowStatusBar)\r
121         EVT_MENU(XRCID("Exe_View_SelectAll"),MainFrame::OnSelectAll)\r
122         // TreeView\r
123         EVT_TREE_SEL_CHANGED(XRCID("TreeView"), MainFrame::OnTreeChanged)\r
124         EVT_TREE_BEGIN_DRAG( XRCID("TreeView"), MainFrame::OnTreeBeginDrag)\r
125         EVT_COMMAND_CONTEXT_MENU(XRCID("TreeView"), MainFrame::OnContextMenu)\r
126         // ListView\r
127         EVT_LIST_ITEM_SELECTED(  XRCID("ListView"), MainFrame::OnListItemSelect)\r
128         EVT_LIST_ITEM_DESELECTED(XRCID("ListView"), MainFrame::OnListItemSelect)\r
129         EVT_LIST_ITEM_ACTIVATED( XRCID("ListView"), MainFrame::OnListItemDClick)\r
130         EVT_LIST_BEGIN_DRAG(     XRCID("ListView"), MainFrame::OnListBeginDrag)\r
131         EVT_COMMAND_CONTEXT_MENU(XRCID("ListView"), MainFrame::OnContextMenu)\r
132         // Filter\r
133         EVT_TEXT(XRCID("tcFilter"), MainFrame::OnFilter)\r
134 END_EVENT_TABLE()\r
135 \r
136 //******************************************************************************\r
137 // Event handler.\r
138 //******************************************************************************\r
139 \r
140 void MainFrame::OnInit(wxInitDialogEvent&)\r
141 {\r
142         // XRCと結びつけ。\r
143         this->menubar    = this->GetMenuBar();\r
144         this->toolbar    = this->GetToolBar();\r
145         this->statusbar = XRCCTRL(* this, "statusbar", wxStatusBar);\r
146         this->tree_ctrl = XRCCTRL(* this, "TreeView", wxTreeCtrl);\r
147         this->list_ctrl = XRCCTRL(* this, "ListView", myListCtrl);\r
148         this->window_splitter = XRCCTRL(* this, "window_splitter", wxSplitterWindow);\r
149         this->tcFilter  = XRCCTRL(* this->toolbar, "tcFilter", wxTextCtrl);\r
150 \r
151         // 設定を読み込み。\r
152         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
153         wxTheMimeTypesManager->Initialize(wxMAILCAP_ALL);\r
154 \r
155         // 初期値設定。\r
156         {\r
157                 wxIcon icon;\r
158                 icon.CopyFromBitmap(wxBitmap(L_DIR_S_ICO wxT("app.png"), wxBITMAP_TYPE_ANY));\r
159                 this->SetIcon(icon);\r
160         }\r
161         wxCommandEvent e;\r
162         this->OnArcClose(e);\r
163         this->SetDropTarget(new myFileDropTarget(this));\r
164 \r
165         // スプリッター設定。\r
166         this->window_splitter->SetSashPosition(this->conf.ReadId(CONF_WINDOW_SPLITTER_POS, 200l));\r
167 \r
168         // リストビュー設定。\r
169         int nIconMode = this->conf.ReadId(CONF_LISTVIEW_SHOWMODE, 0l);\r
170         e.SetId(nIconMode == 1 ? XRCID("Exe_View_Icons") : (nIconMode == 2 ? XRCID("Exe_View_List") : XRCID("Exe_View_Details")));\r
171         this->OnViewMode(e);\r
172         // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。\r
173         this->list_ctrl->SetSingleStyle(wxLC_VIRTUAL);\r
174         this->list_ctrl->InsertColumn(0, _("Filename"),      wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_FILENAME, 140l));\r
175         this->list_ctrl->InsertColumn(1, _("Unpacked"),      wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_UNPACKED,  80l));\r
176         this->list_ctrl->InsertColumn(2, _("Packed"),        wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_PACKED,    80l));\r
177         this->list_ctrl->InsertColumn(3, _("Ratio"),         wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_RATIO,     50l));\r
178         this->list_ctrl->InsertColumn(4, _("Method"),        wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_METHOD,    60l));\r
179         this->list_ctrl->InsertColumn(5, _("Attr"),          wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_ATTR,      50l));\r
180         this->list_ctrl->InsertColumn(6, _("Last modified"), wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_LASTMOD,  150l));\r
181         this->list_ctrl->InsertColumn(7, _("Path"),          wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_PATH,     100l));\r
182         this->list_ctrl->InsertColumn(8, _("Type"),          wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_TYPE,     100l));\r
183         this->list_ctrl->InsertColumn(9, _("No."),           wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_NO,        35l));\r
184         this->list_ctrl->InsertColumn(10,_("Comment"),       wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_COMMENT,   35l));\r
185         g_nSortColumn = this->conf.ReadId(CONF_LISTVIEW_S_COLUMN, 9l);\r
186         g_fSortAscend = this->conf.ReadId(CONF_LISTVIEW_S_ASCEND, true);\r
187 \r
188         // ツールバー/ステータスバー設定。\r
189         int nStatusBarParts[] = {70, 70, 180, 50, -1};\r
190         this->statusbar->SetFieldsCount(5, nStatusBarParts);\r
191         this->SetStatusBarPane(-1);\r
192         bool fShow = this->conf.ReadId(CONF_WINDOW_STATUSBAR, true);\r
193         this->menubar->Check(XRCID("Exe_View_StatusBar"), fShow);\r
194         this->statusbar->Show(fShow);\r
195         fShow = this->conf.ReadId(CONF_WINDOW_TOOLBAR, true);\r
196         this->menubar->Check(XRCID("Exe_View_ToolBar"), fShow);\r
197         this->toolbar->Show(fShow);\r
198 }\r
199 \r
200 // MenuBar\r
201 \r
202 void MainFrame::OnExit(wxCommandEvent&)\r
203 {\r
204         this->Close(true);\r
205 }\r
206 \r
207 void MainFrame::OnArcCreate(wxCommandEvent& e)\r
208 {\r
209         TPI_SWITCHES swInfo;\r
210         swInfo.pCustomSwitches = NULL;\r
211 \r
212         // 作成ダイアログを設定。\r
213         MakeDialog mkDlg(this, TPI_COMMAND_CREATE);\r
214         if (e.GetClientData() == NULL)\r
215         {\r
216                 // 処理対象のファイルを選択。\r
217                 wxFileDialog fd(this, _("Choose files to compress"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);\r
218                 if (fd.ShowModal() == wxID_CANCEL)\r
219                 {\r
220                         return;\r
221                 }\r
222                 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
223                 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
224                 fd.GetFilenames(mkDlg.files);\r
225         }\r
226         else\r
227         {\r
228                 mkDlg.files = * (wxArrayString *) e.GetClientData();\r
229                 swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());\r
230                 // 相対パスに変換。\r
231                 for (size_t n = 0; n < mkDlg.files.GetCount(); n++)\r
232                 {\r
233                         wxFileName fn(mkDlg.files[n]);\r
234                         fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());\r
235                         mkDlg.files[n] = fn.GetFullPath();\r
236                 }\r
237         }\r
238 \r
239         this->OnArcClose(e);\r
240         // 書庫名はファイル名の拡張子より前、もしくはディレクトリ名。\r
241         this->fnArchive = wxFileName(mkDlg.files[0]);\r
242         this->fnArchive.SetName(mkDlg.files.GetCount() == 1 ? (this->fnArchive.GetName().IsEmpty() ? this->fnArchive.GetDirs().Last() : this->fnArchive.GetName()) : swInfo.fnDestinationDirectory.GetDirs().Last());\r
243         this->fnArchive.SetEmptyExt();\r
244         this->fnArchive.SetPath(swInfo.fnDestinationDirectory.GetPath());\r
245 \r
246         // ダイアログを表示。\r
247         if (mkDlg.ShowModal() == wxID_CANCEL)\r
248         {\r
249                 return;\r
250         }\r
251 \r
252         // 各種設定。\r
253         int nSelected = mkDlg.chType->GetSelection();\r
254         swInfo.nArchiveType         = mkDlg.afInfo[nSelected].nTypeId;\r
255         swInfo.fStoreDirectoryPathes= ! mkDlg.cbIgnorePath->IsChecked();\r
256         swInfo.fMakeSFX                     = mkDlg.cbMakeSFX->IsChecked();\r
257         swInfo.fSolid               = mkDlg.cbSolid->IsChecked();\r
258         swInfo.fMMOptimize          = mkDlg.cbMMOptimize->IsChecked();\r
259         swInfo.fEncryptHeader       = mkDlg.cbEncryptHeader->IsChecked();\r
260         swInfo.fCompressHeader      = mkDlg.cbCompressHeader->IsChecked();\r
261         swInfo.nCompressLevel       = mkDlg.scLevel->GetValue();\r
262         swInfo.nRecoveryRecord      = mkDlg.scRR->GetValue();\r
263         swInfo.szPassword           = mkDlg.tcPassword->GetValue();\r
264         swInfo.szKeyFile            = mkDlg.tcKeyfile->GetValue();\r
265         swInfo.szComment            = mkDlg.tcComment->GetValue();\r
266         mkDlg.cbSplitSize->GetValue().ToULongLong(& swInfo.nSplitSize);\r
267 \r
268         // TPIを読み込み。\r
269         this->fnArchive = wxFileName(mkDlg.cbDir->GetValue(), mkDlg.cbFileName->GetValue());\r
270         if (! tpi.InitLibrary(mkDlg.afInfo[nSelected].szTPIName, this->fnArchive.GetFullPath(), TPICallbackProc, mkDlg.afInfo[nSelected].nTypeId))\r
271         {\r
272                 this->ErrorCheck(tpi.nErrorCode, wxT("InitLibrary"));\r
273                 return;\r
274         }\r
275 \r
276         // 処理を行う。\r
277         {\r
278                 ProcessDialog procDlg(this, mkDlg.files.GetCount());\r
279                 procDlg.Show(true);\r
280 \r
281                 tpi.Command(TPI_COMMAND_CREATE, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
282                 this->ErrorCheck(tpi.nErrorCode);\r
283                 procDlg.Show(false);\r
284         }\r
285         tpi.FreeLibrary();\r
286 \r
287         if (mkDlg.cbOpenAfter->IsChecked())\r
288         {\r
289                 // 作成先を開く。\r
290                 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
291         }\r
292 \r
293         if (mkDlg.cbExitAfter->IsChecked())\r
294         {\r
295                 // 終了。\r
296                 this->Close(true);\r
297         }\r
298 \r
299         // 終了しない場合は書庫を開く。\r
300         this->OnArcOpen(e);\r
301 }\r
302 \r
303 void MainFrame::OnArcOpen(wxCommandEvent& e)\r
304 {\r
305         // モード取得。通常は0, それ以外で開く場合は1, ファイルDnDなら2。\r
306         int nMode = e.GetInt() == 2 ? 2 : e.GetId() == XRCID("Arc_Open") ? 0 : 1;\r
307 \r
308         // 書庫を選択。\r
309         if (nMode == 0)\r
310         {\r
311                 wxFileDialog fd(this, _("Choose an archive"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
312                 if (fd.ShowModal() == wxID_CANCEL)\r
313                 {\r
314                         return;\r
315                 }\r
316                 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
317                 this->fnArchive = wxFileName(fd.GetPath());\r
318         }\r
319 \r
320         // 進捗ダイアログ表示。\r
321         ProcessDialog procDlg(this);\r
322         procDlg.Show(true);\r
323 \r
324         // DnD以外で書庫を開く場合、TPIを読み込み。\r
325         TPI_PROCESSINFO piInfo;\r
326         piInfo.fiInfo.nUnpackedSize = 0;\r
327         if (! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))\r
328         {\r
329                 procDlg.Show(false);\r
330                 if (nMode == 2)\r
331                 {\r
332                         // DnDの場合は書庫を作成する。\r
333                         this->OnArcCreate(e);\r
334                 }\r
335                 else if (this->IsShown())\r
336                 {\r
337                         wxBell();\r
338                         this->statusbar->SetStatusText(_("No plug-in supporting this archive was found!"), 4);\r
339                 }\r
340                 else\r
341                 {\r
342                         wxLogError(_("No plug-in supporting this archive was found!"));\r
343                         this->Close(true);\r
344                 }\r
345                 return;\r
346         }\r
347 \r
348         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
349         piInfo.eStatus = 0x1001;\r
350         if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo), wxT("Callback")) == TPI_CALLBACK_CANCEL)\r
351         {\r
352                 procDlg.Show(false);\r
353                 tpi.CloseArchive();\r
354                 wxCommandEvent e;\r
355                 this->OnArcClose(e);\r
356                 return;\r
357         }\r
358 \r
359         // 配列のサイズを確保。\r
360         this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);\r
361 \r
362         // 履歴に追加。\r
363         this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());\r
364         this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());\r
365         this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());\r
366 \r
367         // 書庫のアイコンを取得し、書庫ルートを作成。\r
368         g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));\r
369         g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));\r
370         this->tree_ctrl->SetImageList(& g_hIconT);\r
371         wxTreeItemId\r
372                 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),\r
373 #ifdef __WINDOWS__\r
374                 idArchive = this->tree_ctrl->AppendItem(idRoot, this->fnArchive.GetFullName(), g_hIconT.Add(GetFileTypeIcon(this->fnArchive))),\r
375 #else\r
376                 idArchive = this->tree_ctrl->AppendItem(idRoot, this->fnArchive.GetFullName(), g_hIconT.Add(GetFileTypeIcon(this->fnArchive).ConvertToImage().Rescale(16, 16))),\r
377 #endif\r
378                 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);\r
379 \r
380         // 巨大書庫のときにファイル名検査を省略するか。\r
381         bool bDTVCheck = piInfo.fiInfo.nUnpackedSize < 10000 || ::AskDlg(_("This archive contains so many files that it takes long to check Directory Traversal Vulnerability(DTV) problem. If you are sure this archive is safe, you can skip this scanning process. Do you want to scan for DTV problem?"), this) == wxNO;\r
382 \r
383         // ファイル情報をロード。\r
384         if (tpi.GetFileInformation(& piInfo.fiInfo, true))\r
385         {\r
386                 piInfo.eStatus = 0x1002;\r
387                 piInfo.nProcessedSize = 0;\r
388                 do\r
389                 {\r
390                         piInfo.nProcessedSize++;\r
391                         if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo), wxT("Callback")) == TPI_CALLBACK_CANCEL)\r
392                         {\r
393                                 procDlg.Show(false);\r
394                                 tpi.CloseArchive();\r
395                                 wxCommandEvent e;\r
396                                 this->OnArcClose(e);\r
397                                 return;\r
398                         }\r
399 \r
400                         // 拡張子のみ設定されている場合。\r
401                         if (piInfo.fiInfo.szStoredName.IsEmpty())\r
402                         {\r
403                                 piInfo.fiInfo.szStoredName = this->fnArchive.GetName();\r
404                                 if (piInfo.fiInfo.fnFileName.HasExt())\r
405                                 {\r
406                                         piInfo.fiInfo.szStoredName += wxT('.') + piInfo.fiInfo.fnFileName.GetExt();\r
407                                 }\r
408                                 piInfo.fiInfo.fnFileName = wxFileName(piInfo.fiInfo.szStoredName);\r
409                         }\r
410 \r
411                         // セキュリティチェック。\r
412                         // ルート記号を削除。\r
413                         wxString szPath = piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX);\r
414                         if (szPath.StartsWith(wxT("/")) || szPath.StartsWith(wxT("./")))\r
415                         {\r
416                                 piInfo.fiInfo.fnFileName = wxFileName(szPath.AfterFirst(wxT('/')), piInfo.fiInfo.fnFileName.GetFullName(), wxPATH_DOS);\r
417                         }\r
418                         // ルートメンバの情報は無視する。\r
419                         if (piInfo.fiInfo.fnFileName.GetFullPath().IsEmpty() || piInfo.fiInfo.fnFileName.GetFullPath() == wxT("."))\r
420                         {\r
421                                 continue;\r
422                         }\r
423 \r
424                         // 改行文字/タブ文字などを削除。\r
425                         if (piInfo.fiInfo.szStoredName.Find(wxT('\r')) != wxNOT_FOUND\r
426                         ||  piInfo.fiInfo.szStoredName.Find(wxT('\n')) != wxNOT_FOUND\r
427                         ||  piInfo.fiInfo.szStoredName.Find(wxT('\t')) != wxNOT_FOUND)\r
428                         {\r
429                                 wxString sz = piInfo.fiInfo.fnFileName.GetFullPath();\r
430                                 sz.Replace(wxT("\r"), wxT(" "));\r
431                                 sz.Replace(wxT("\n"), wxT(" "));\r
432                                 sz.Replace(wxT("\t"), wxT(" "));\r
433                                 piInfo.fiInfo.eDanger = TRUE;\r
434                                 piInfo.fiInfo.fnFileName = wxFileName(sz);\r
435                                 wxLogWarning(_("This archive may contain files whose name contains some special characters like CR(\\r), LF(\\n), Tab(\\t) and some problem would be happen if you extract these files. Don\'t extract these files carelessly.\nDanger file is:\n%s"), piInfo.fiInfo.fnFileName.GetFullPath().c_str());\r
436                         }\r
437 \r
438                         if (bDTVCheck)\r
439                         {\r
440                                 // DTV検査。\r
441                                 if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)\r
442                                 {\r
443                                         piInfo.fiInfo.eDanger = TRUE;\r
444                                         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
445                                 }\r
446                                 // 空白の連続による拡張子偽装を検査。\r
447                                 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT("        ")) != wxNOT_FOUND)\r
448                                 {\r
449                                         piInfo.fiInfo.eDanger = TRUE;\r
450                                         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
451                                 }\r
452                                 // Unicode制御文字を検査。\r
453                                 for (wxChar c = 0x200c; c <= 0x206f; c++)\r
454                                 {\r
455                                         if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)\r
456                                         {\r
457                                                 piInfo.fiInfo.eDanger = TRUE;\r
458                                                 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
459                                         }\r
460                                         switch (c)\r
461                                         {\r
462                                         case 0x200f: c = 0x2027; break;\r
463                                         case 0x202e: c = 0x2060; break;\r
464                                         }\r
465                                 }\r
466                         }\r
467 \r
468                         // ツリービューに反映。\r
469                         bool fDir = piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? true : false;\r
470                         TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, fDir ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetPath(), true);\r
471 \r
472                         // ディレクトリ属性を含むものについては情報を保存しない。\r
473                         if (fDir)\r
474                         {\r
475                                 continue;\r
476                         }\r
477 \r
478                         // 情報を保存してカウントアップ。\r
479                         this->fileinfo.Add(piInfo.fiInfo);\r
480                 }\r
481                 while (tpi.GetFileInformation(& piInfo.fiInfo));\r
482         }\r
483 \r
484         // GetFileInformationがエラー終了した場合。\r
485         this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));\r
486 \r
487         // 書庫の情報を取得。\r
488         tpi.GetArchiveInformation(& this->aiArchive);\r
489         this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));\r
490         this->szPassword = procDlg.szPassword;\r
491 \r
492         // 書庫を閉じる。\r
493         tpi.CloseArchive();\r
494         this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));\r
495 \r
496         // 以下、UI処理。\r
497         this->fileinfo.Shrink();\r
498         this->tree_ctrl->Freeze();\r
499         if (this->fileinfo.Count() < 10000)\r
500         {\r
501                 this->tree_ctrl->ExpandAll();\r
502                 this->tree_ctrl->SelectItem(idArchive);\r
503         }\r
504         else\r
505         {\r
506                 // ファイル数が多いとソートに時間がかかるので、書庫のルートを表示させる。\r
507                 this->tree_ctrl->Expand(idArcRoot);\r
508                 this->tree_ctrl->SelectItem(idArcRoot);\r
509         }\r
510         // ツリービューの位置合わせ。\r
511         this->tree_ctrl->ScrollTo(idArchive);\r
512         this->tree_ctrl->SetScrollPos(wxHORIZONTAL, 0);\r
513         this->tree_ctrl->Thaw();\r
514         this->list_ctrl->atDangerItem.SetTextColour(* wxRED);\r
515         this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));\r
516 \r
517         // ステータスバー設定。\r
518         this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);\r
519         this->statusbar->SetStatusText(wxString::Format(_("%u file(s)"), this->fileinfo.GetCount()), 1);\r
520         this->statusbar->SetStatusText(wxString::Format(wxString("%" wxLongLongFmtSpec "uB -> %" wxLongLongFmtSpec "uB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);\r
521         this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);\r
522         this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);\r
523         this->statusbar->SetToolTip(\r
524                 wxString::Format(\r
525                         _("%s(%s)\nTPI: %s(%s)\nAccess: %s\nModify: %s\nCreate: %s\nComment:\n%s"),\r
526                         this->fnArchive.GetFullName().c_str(), this->aiArchive.fiInfo.szTypeName.c_str(),\r
527                         this->aiArchive.fiInfo.szTPIName.c_str(), this->aiArchive.fiInfo.szEngineName.c_str(),\r
528                         this->aiArchive.tmAccess.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
529                         this->aiArchive.tmModify.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
530                         this->aiArchive.tmCreate.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
531                         this->aiArchive.szComment.c_str()\r
532                 )\r
533         );\r
534 \r
535         // ツールバー・メニューバー設定。ファイル選択時しか動作しない削除などは別に設定。\r
536         SetMenuToolState("Arc_Close",   true);\r
537         SetMenuToolState("Arc_Add",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD)   == TPI_COMMAND_ADD   && this->aiArchive.fiInfo.fArchive);\r
538         SetMenuToolState("Arc_SFX",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX)    == TPI_COMMAND_SFX   && ! this->aiArchive.fSFX);\r
539         SetMenuToolState("Arc_UnSFX",   (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX)  == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);\r
540         SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);\r
541         SetMenuToolState("Arc_Test",    (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST)   == TPI_COMMAND_TEST);\r
542         SetMenuToolState("Arc_Repair",  (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);\r
543         this->menubar->Enable(XRCID("Arc_Clone"), true);\r
544 \r
545         procDlg.Show(false);\r
546         this->Raise();\r
547 }\r
548 \r
549 void MainFrame::OnArcClose(wxCommandEvent& e)\r
550 {\r
551         // ツリービュー・リストビュー設定。\r
552         this->tree_ctrl->DeleteAllItems();\r
553         this->list_ctrl->DeleteAllItems();\r
554         this->list_ctrl->apShowFile.Clear();\r
555 \r
556         // ツールバー・メニューバー設定。\r
557         SetMenuToolState("Arc_Close",   false);\r
558         SetMenuToolState("Arc_Add",     false);\r
559         SetMenuToolState("Arc_SFX",     false);\r
560         SetMenuToolState("Arc_UnSFX",   false);\r
561         SetMenuToolState("Arc_Extract", false);\r
562         SetMenuToolState("Arc_Delete",  false);\r
563         SetMenuToolState("Arc_Test",    false);\r
564         SetMenuToolState("Arc_Repair",  false);\r
565         this->menubar->Enable(XRCID("Arc_Clone"), false);\r
566 \r
567         for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)\r
568         {\r
569                 this->statusbar->SetStatusText(wxEmptyString, i);\r
570         }\r
571         this->statusbar->SetToolTip(wxEmptyString);\r
572         this->fileinfo.Clear();\r
573         this->szPassword.Empty();\r
574         this->aiArchive.szComment.Empty();\r
575         this->aiArchive.fnArchive.Clear();\r
576         this->aiArchive.fiInfo.szTypeName.Empty();\r
577         this->aiArchive.fiInfo.szSuffix.Empty();\r
578         this->aiArchive.fiInfo.szEngineName.Empty();\r
579         this->aiArchive.fiInfo.szTPIName.Empty();\r
580 \r
581         g_hIconT.RemoveAll();\r
582         g_hIconLL.RemoveAll();\r
583         g_hIconLS.RemoveAll();\r
584 \r
585         // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。\r
586         if (e.GetExtraLong() == 0)\r
587         {\r
588                 tpi.FreeLibrary();\r
589         }\r
590 }\r
591 \r
592 void MainFrame::OnArcClone(wxCommandEvent&)\r
593 {\r
594         // 保存先を尋ねる。\r
595         wxFileDialog fd(this, _("Clone archive"), this->fnArchive.GetPath(), this->fnArchive.GetFullName(), wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
596         if (fd.ShowModal() == wxID_CANCEL)\r
597         {\r
598                 return;\r
599         }\r
600         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
601 \r
602         // コピー。\r
603         ::wxCopyFile(this->fnArchive.GetFullPath(), fd.GetPath());\r
604         wxFileName fn(fd.GetPath());\r
605         wxDateTime dtAccess, dtModify, dtCreate;\r
606         this->fnArchive.GetTimes(& dtAccess, & dtModify, & dtCreate);\r
607         fn.SetTimes(& dtAccess, & dtModify, & dtCreate);\r
608 }\r
609 \r
610 void MainFrame::OnArcAdd(wxCommandEvent& e)\r
611 {\r
612         // 作成ダイアログを設定。\r
613         MakeDialog mkDlg(this, TPI_COMMAND_ADD);\r
614 \r
615         TPI_SWITCHES swInfo;\r
616         swInfo.pCustomSwitches       = NULL;\r
617 \r
618         if (e.GetClientData() == NULL)\r
619         {\r
620                 if (::wxGetKeyState(WXK_SHIFT))\r
621                 {\r
622                         // 処理対象のフォルダを選択。\r
623                         wxDirDialog dd(this, _("Choose dir to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxDD_DIR_MUST_EXIST);\r
624                         if (dd.ShowModal() == wxID_CANCEL)\r
625                         {\r
626                                 return;\r
627                         }\r
628                         swInfo.fnDestinationDirectory = wxFileName(dd.GetPath());\r
629                         this->conf.WriteHistory(CONF_HISTORY_PATH, swInfo.fnDestinationDirectory.GetPath());\r
630                         mkDlg.files.Add(swInfo.fnDestinationDirectory.GetFullName());\r
631                 }\r
632                 else\r
633                 {\r
634                         // 処理対象のファイルを選択。\r
635                         wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);\r
636                         if (fd.ShowModal() == wxID_CANCEL)\r
637                         {\r
638                                 return;\r
639                         }\r
640                         fd.GetFilenames(mkDlg.files);\r
641                         swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
642                         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
643                 }\r
644         }\r
645         else\r
646         {\r
647                 mkDlg.files = * (wxArrayString *) e.GetClientData();\r
648                 swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());\r
649                 // 相対パスに変換。\r
650                 for (size_t n = 0; n < mkDlg.files.GetCount(); n++)\r
651                 {\r
652                         wxFileName fn(mkDlg.files[n]);\r
653                         fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());\r
654                         mkDlg.files[n] = fn.GetFullPath();\r
655                 }\r
656         }\r
657 \r
658         // ダイアログを表示。\r
659         if (mkDlg.ShowModal() == wxID_CANCEL)\r
660         {\r
661                 return;\r
662         }\r
663 \r
664         // 各種設定。\r
665         swInfo.fMakeSFX              = false;\r
666         swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();\r
667         swInfo.fSolid               = mkDlg.cbSolid->IsChecked();\r
668         swInfo.fMMOptimize          = mkDlg.cbMMOptimize->IsChecked();\r
669         swInfo.fEncryptHeader       = mkDlg.cbEncryptHeader->IsChecked();\r
670         swInfo.nCompressLevel       = mkDlg.scLevel->GetValue();\r
671         swInfo.nRecoveryRecord      = mkDlg.scRR->GetValue();\r
672         swInfo.szPassword           = mkDlg.tcPassword->GetValue();\r
673         swInfo.szKeyFile            = mkDlg.tcKeyfile->GetValue();\r
674         swInfo.szComment            = mkDlg.tcComment->GetValue();\r
675 \r
676         // 処理を行う。\r
677         {\r
678                 ProcessDialog procDlg(this, mkDlg.files.GetCount(), this->szPassword);\r
679                 procDlg.Show(true);\r
680 \r
681                 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
682                 this->ErrorCheck(tpi.nErrorCode);\r
683                 procDlg.Show(false);\r
684         }\r
685 \r
686         if (mkDlg.cbOpenAfter->IsChecked())\r
687         {\r
688                 // 作成先を開く。\r
689                 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
690         }\r
691 \r
692         if (mkDlg.cbExitAfter->IsChecked())\r
693         {\r
694                 // 終了。\r
695                 this->Close(true);\r
696         }\r
697 \r
698         // 終了しない場合は書庫を再読み込み。\r
699         this->OnArcOpen(e);\r
700 }\r
701 \r
702 void MainFrame::OnArcConvert(wxCommandEvent& e)\r
703 {\r
704         TPI_SWITCHES swInfo;\r
705         swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");\r
706 \r
707         // 保存先を尋ねる。\r
708         wxFileDialog fd(this, swInfo.fMakeSFX ? _("Save as SFX") : _("Save as normal archive"), this->fnArchive.GetPath(), this->fnArchive.GetName() + (swInfo.fMakeSFX ? EXE_EXT : (wxString) wxEmptyString), wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
709         if (fd.ShowModal() == wxID_CANCEL)\r
710         {\r
711                 return;\r
712         }\r
713         swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
714         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
715 \r
716         wxArrayString files;\r
717         files.Add(fd.GetPath());\r
718 \r
719         ProcessDialog procDlg(this);\r
720         procDlg.Show(true);\r
721         tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);\r
722         this->ErrorCheck(tpi.nErrorCode);\r
723         procDlg.Show(false);\r
724 }\r
725 \r
726 void MainFrame::OnArcExtract(wxCommandEvent& e)\r
727 {\r
728         TPI_SWITCHES swInfo;\r
729         swInfo.pCustomSwitches = NULL;\r
730         swInfo.szPassword = this->szPassword;\r
731 \r
732         // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3、クリップボードなら4、コンテキストメニューからなら8。\r
733         int nMode = e.GetInt();\r
734         if (e.GetInt() == 8)\r
735         {\r
736                 nMode = 0;\r
737         }\r
738         // 実行時のみ使用。\r
739         wxFileType * ftFile = NULL;\r
740 \r
741         // 展開ダイアログを作成。DnDまたは実行時は表示しない。\r
742         MakeDialog mkDlg(this, TPI_COMMAND_EXTRACT);\r
743         mkDlg.files    = MakeTargetFileList(this, nMode == 1, nMode == 0);\r
744 \r
745         bool bMakeDir = false;\r
746         if (nMode != 0)\r
747         {\r
748                 // 作業ディレクトリ作成。\r
749                 swInfo.fStoreDirectoryPathes = false;\r
750                 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");\r
751                 if (szDestDirBase == wxT("-----"))\r
752                 {\r
753                         // 書庫ルートのときは書庫名にしておく。\r
754                         szDestDirBase = this->fnArchive.GetName();\r
755                 }\r
756                 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(wxStandardPaths::Get().GetTempDir()), szDestDirBase, true);\r
757                 if (! swInfo.fnDestinationDirectory.IsOk())\r
758                 {\r
759                         wxLogError(_("Unable to make the temporary directory!"));\r
760                         return;\r
761                 }\r
762         }\r
763         else\r
764         {\r
765                 if (mkDlg.ShowModal() == wxID_CANCEL)\r
766                 {\r
767                         return;\r
768                 }\r
769 \r
770                 // 各種設定。\r
771                 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();\r
772                 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());\r
773                 swInfo.szPassword = mkDlg.tcPassword->GetValue();\r
774                 swInfo.szKeyFile  = mkDlg.tcKeyfile->GetValue();\r
775 \r
776                 // 必要なら書庫名でディレクトリを作成する。\r
777                 bMakeDir = WillMakeDirByArcName(this, & mkDlg);\r
778                 if (bMakeDir)\r
779                 {\r
780                         swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);\r
781                         if (! swInfo.fnDestinationDirectory.IsOk())\r
782                         {\r
783                                 wxLogError(_("Unable to make the destination directory!"));\r
784                                 return;\r
785                         }\r
786                 }\r
787         }\r
788 \r
789         // 処理を行う。\r
790         {\r
791                 ProcessDialog procDlg(this, mkDlg.files.GetCount(), this->szPassword);\r
792                 procDlg.Show(true);\r
793 \r
794                 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
795                 this->ErrorCheck(tpi.nErrorCode);\r
796                 procDlg.Show(false);\r
797         }\r
798 \r
799         if (nMode == 0)\r
800         {\r
801                 if (mkDlg.cbOpenAfter->IsChecked())\r
802                 {\r
803                         // 展開先を開く。\r
804                         if (mkDlg.chDirMake->GetSelection() == 2 && ! bMakeDir)\r
805                         {\r
806                                 wxTreeItemId tiArcSub = this->tree_ctrl->GetLastChild(this->tree_ctrl->GetLastChild(this->tree_ctrl->GetRootItem()));\r
807                                 if (tiArcSub.IsOk())\r
808                                 {\r
809                                         swInfo.fnDestinationDirectory.SetFullName(this->tree_ctrl->GetItemText(tiArcSub));\r
810                                 }\r
811                         }\r
812                         ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
813                 }\r
814 \r
815                 if (mkDlg.cbExitAfter->IsChecked())\r
816                 {\r
817                         // 終了。\r
818                         this->Close(true);\r
819                 }\r
820         }\r
821         else\r
822         {\r
823                 if (nMode == 1)\r
824                 {\r
825                         // コマンドを取得。\r
826                         ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());\r
827                         if (! ftFile || ftFile->GetOpenCommand(wxEmptyString).IsEmpty())\r
828                         {\r
829                                 // 種類が取得できないときはテキストとみなす。\r
830                                 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));\r
831                         }\r
832 \r
833                         // コマンドを実行。\r
834                         wxString szTempFile = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName();\r
835                         bool fSuccess = tpi.nErrorCode == TPI_ERROR_SUCCESS && ftFile != NULL;\r
836                         myProcess * pCallback = new myProcess(szTempFile, swInfo.fnDestinationDirectory.GetPath());\r
837                         if (fSuccess)\r
838                         {\r
839 #ifdef __LINUX__\r
840                                 // Linuxでは引用符で囲む必要がある。\r
841                                 fSuccess = ::wxExecute(ftFile->GetOpenCommand(QuoteString(szTempFile)), wxEXEC_ASYNC, pCallback) > 0;\r
842 #else\r
843                                 fSuccess = ::wxExecute(ftFile->GetOpenCommand(szTempFile), wxEXEC_ASYNC, pCallback) > 0;\r
844 #endif\r
845                         }\r
846                         if (! fSuccess)\r
847                         {\r
848                                 pCallback->OnTerminate(0, 0);\r
849                         }\r
850                 }\r
851                 else\r
852                 {\r
853                         // 展開対象を決定。\r
854                         wxArrayString asFiles;\r
855                         myFileDataObject * objFile = new myFileDataObject();\r
856                         objFile->szTempDir = nMode == 3 ? swInfo.fnDestinationDirectory.GetPath() : swInfo.fnDestinationDirectory.GetFullPath();\r
857                         for (size_t i = 0; i < mkDlg.files.GetCount(); i++)\r
858                         {\r
859                                 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();\r
860                                 if (nMode == 3)\r
861                                 {\r
862                                         asFiles.Add(szFileName);\r
863                                 }\r
864                                 else\r
865                                 {\r
866                                         // リストに追加。\r
867                                         objFile->AddFile(szFileName);\r
868                                 }\r
869                         }\r
870                         if (nMode == 3)\r
871                         {\r
872                                 objFile->AddFile(objFile->szTempDir);\r
873                         }\r
874 \r
875                         if (nMode == 4)\r
876                         {\r
877                                 wxTheClipboard->SetData(objFile);\r
878                         }\r
879                         else\r
880                         {\r
881                                 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。\r
882                                 this->SetDropTarget(NULL);\r
883 \r
884                                 // DnD開始。\r
885                                 wxDropSource dropSource(* objFile, this);\r
886                                 wxDragResult drResult = dropSource.DoDragDrop();\r
887                                 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)\r
888                                 {\r
889 #ifdef __LINUX__\r
890                                         // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。\r
891                                         sleep(3);\r
892 #endif\r
893                                 }\r
894                                 this->SetDropTarget(new myFileDropTarget(this));\r
895 \r
896                                 // ディレクトリDnDのときは、先にディレクトリの中のファイルを消しておく。\r
897                                 if (nMode == 3)\r
898                                 {\r
899                                         for (size_t i = 0; i < asFiles.GetCount(); i++)\r
900                                         {\r
901                                                 chmod(asFiles[i].ToUTF8(), 0600);\r
902                                                 ::wxRemoveFile(asFiles[i]);\r
903                                         }\r
904                                 }\r
905 \r
906                                 delete objFile;\r
907                         }\r
908                 }\r
909         }\r
910 }\r
911 \r
912 void MainFrame::OnArcDelete(wxCommandEvent& e)\r
913 {\r
914         // 全ファイル削除は危険ではないかと。\r
915         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
916         {\r
917                 // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
918                 SetMenuToolState("Arc_Delete", false);\r
919                 return;\r
920         }\r
921 \r
922         if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)\r
923         {\r
924                 return;\r
925         }\r
926 \r
927         // 処理を行う。\r
928         {\r
929                 wxArrayString asFiles = MakeTargetFileList(this);\r
930                 ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
931                 procDlg.Show(true);\r
932 \r
933                 TPI_SWITCHES swInfo;\r
934                 swInfo.szPassword = this->szPassword;\r
935                 tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
936                 this->ErrorCheck(tpi.nErrorCode);\r
937                 procDlg.Show(false);\r
938         }\r
939 \r
940         // 書庫を再読み込みする。\r
941         this->OnArcOpen(e);\r
942 }\r
943 \r
944 void MainFrame::OnArcTest(wxCommandEvent&)\r
945 {\r
946         // 処理を行う。\r
947         wxArrayString asFiles = MakeTargetFileList(this);\r
948         ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
949         procDlg.Show(true);\r
950 \r
951         TPI_SWITCHES swInfo;\r
952         swInfo.szPassword = this->szPassword;\r
953         tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
954         this->ErrorCheck(tpi.nErrorCode);\r
955         procDlg.Show(false);\r
956 }\r
957 \r
958 void MainFrame::OnArcRepair(wxCommandEvent&)\r
959 {\r
960         // 処理を行う。\r
961         wxArrayString asFiles = MakeTargetFileList(this);\r
962         ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
963         procDlg.Show(true);\r
964 \r
965         TPI_SWITCHES swInfo;\r
966         swInfo.szPassword = this->szPassword;\r
967         tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
968         this->ErrorCheck(tpi.nErrorCode);\r
969         procDlg.Show(false);    \r
970 }\r
971 \r
972 void MainFrame::OnExeCopy(wxCommandEvent & e)\r
973 {\r
974         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
975         {\r
976                 // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
977                 this->menubar->Enable(XRCID("Exe_Copy"), false);\r
978                 return;\r
979         }\r
980 \r
981         if (! wxTheClipboard->Open())\r
982         {\r
983                 return;\r
984         }\r
985 \r
986         e.SetInt(4);\r
987         this->OnArcExtract(e);\r
988         wxTheClipboard->Close();\r
989 }\r
990 \r
991 void MainFrame::OnViewMode(wxCommandEvent & e)\r
992 {\r
993         int n = e.GetId();\r
994         this->menubar->Check(n, true);\r
995         this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));\r
996         this->list_ctrl->SetSingleStyle(wxLC_ICON,   n == XRCID("Exe_View_Icons"));\r
997         this->list_ctrl->SetSingleStyle(wxLC_LIST,   n == XRCID("Exe_View_List"));\r
998 }\r
999 \r
1000 void MainFrame::OnShowToolBar(wxCommandEvent & e)\r
1001 {\r
1002         this->toolbar->Show(e.IsChecked());\r
1003 }\r
1004 \r
1005 void MainFrame::OnShowStatusBar(wxCommandEvent & e)\r
1006 {\r
1007         this->statusbar->Show(e.IsChecked());\r
1008 }\r
1009 \r
1010 void MainFrame::OnSelectAll(wxCommandEvent &)\r
1011 {\r
1012         for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)\r
1013         {\r
1014                 this->list_ctrl->Select(i, true);\r
1015         }\r
1016 }\r
1017 \r
1018 // TreeView\r
1019 \r
1020 void MainFrame::OnTreeChanged(wxTreeEvent& e)\r
1021 {\r
1022         // ツリービューからパスを取得。\r
1023         wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());\r
1024         // リストビューを初期化。\r
1025         this->list_ctrl->apShowFile.Clear();\r
1026         this->list_ctrl->DeleteAllItems();\r
1027         g_hIconLL.RemoveAll();\r
1028         g_hIconLS.RemoveAll();\r
1029 \r
1030         // 現在のアイテムの選択状態を無効にしておく。\r
1031         long nSelected = this->list_ctrl->GetFirstSelected();\r
1032         while (nSelected != -1)\r
1033         {\r
1034                 this->list_ctrl->Select(nSelected, false);\r
1035                 nSelected = this->list_ctrl->GetNextSelected(nSelected);\r
1036         }\r
1037 \r
1038         // アイコン設定。\r
1039         this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);\r
1040         this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);\r
1041 \r
1042         // 配列と比較し、パスが一致しなければ消す。\r
1043         for (size_t i = 0; i < this->fileinfo.GetCount(); i++)\r
1044         {\r
1045                 // パスを比較。\r
1046                 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())\r
1047                 {\r
1048                         // 項目がフォルダであるなら無視。\r
1049                         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
1050                         {\r
1051                                 continue;\r
1052                         }\r
1053 \r
1054                         // フィルタにかからなければ無視。\r
1055                         if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)\r
1056                         {\r
1057                                 continue;\r
1058                         }\r
1059 \r
1060                         this->list_ctrl->apShowFile.Add(& this->fileinfo[i]);\r
1061                 }\r
1062         }\r
1063 \r
1064         // ソートして表示。\r
1065         this->list_ctrl->apShowFile.Sort(& ListCtrlCompareProc);\r
1066         this->list_ctrl->SetItemCount(this->list_ctrl->apShowFile.GetCount());\r
1067 }\r
1068 \r
1069 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)\r
1070 {\r
1071         // TODO : アイテムが子階層を持っていても展開できない。\r
1072         this->tree_ctrl->SelectItem(e.GetItem());\r
1073 \r
1074         wxCommandEvent e1;\r
1075         e1.SetInt(3);\r
1076         this->OnArcExtract(e1);\r
1077 }\r
1078 \r
1079 void MainFrame::OnContextMenu(wxContextMenuEvent& e)\r
1080 {\r
1081         wxPoint p = e.GetPosition();\r
1082         this->list_ctrl->PopupMenu(this->menubar->GetMenu(1), p == wxDefaultPosition ? this->list_ctrl->GetPosition() : this->list_ctrl->ScreenToClient(p));\r
1083 }\r
1084 \r
1085 // ListView\r
1086 \r
1087 void MainFrame::OnListItemSelect(wxListEvent&)\r
1088 {\r
1089         // ファイルに対する動作の設定。但し、選択解除時はwxのバグで呼び出されない。\r
1090         bool fEnable = this->list_ctrl->GetSelectedItemCount() > 0;\r
1091         SetMenuToolState("Arc_Delete", fEnable && (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);\r
1092         this->menubar->Enable(XRCID("Exe_Copy"), fEnable);\r
1093 }\r
1094 \r
1095 void MainFrame::OnListItemDClick(wxListEvent&)\r
1096 {\r
1097         wxCommandEvent e;\r
1098         e.SetInt(1);\r
1099         this->OnArcExtract(e);\r
1100 }\r
1101 \r
1102 void MainFrame::OnListBeginDrag(wxListEvent&)\r
1103 {\r
1104         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
1105         {\r
1106                 // アイテムを選択せずドラッグしようとした場合。\r
1107                 return;\r
1108         }\r
1109 \r
1110         wxCommandEvent e;\r
1111         e.SetInt(2);\r
1112         this->OnArcExtract(e);\r
1113 }\r
1114 \r
1115 // Filter\r
1116 \r
1117 void MainFrame::OnFilter(wxCommandEvent&)\r
1118 {\r
1119         wxTreeEvent e;\r
1120         e.SetItem(this->tree_ctrl->GetSelection());\r
1121         this->OnTreeChanged(e);\r
1122 }\r
1123 \r
1124 // イベントハンドラ以外。\r
1125 \r
1126 bool MainFrame::LoadTPI(const wxString & szFileName, wxULongLong_t * llFileCount)\r
1127 {\r
1128         // 書庫を開いていれば閉じておく。\r
1129         wxCommandEvent e;\r
1130         this->OnArcClose(e);\r
1131 \r
1132         // TPIを読み込み。\r
1133         wxDir fs(L_DIR_B_LIB);\r
1134         wxString szTPIName;\r
1135         if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))\r
1136         {\r
1137                 do\r
1138                 {\r
1139                         // 初期化。\r
1140                         if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName, TPICallbackProc))\r
1141                         {\r
1142                                 tpi.FreeLibrary();\r
1143                                 continue;\r
1144                         }\r
1145 \r
1146                         // 対応確認。\r
1147                         if (! tpi.OpenArchive(szFileName, llFileCount))\r
1148                         {\r
1149                                 tpi.FreeLibrary();\r
1150                                 * llFileCount = 0;\r
1151                                 continue;\r
1152                         }\r
1153                         return true;\r
1154                 }\r
1155                 while (fs.GetNext(& szTPIName));\r
1156         }\r
1157         return false;\r
1158 }\r
1159 \r
1160 int MainFrame::ErrorCheck(int nErrorCode, const wxString & szAPIName)\r
1161 {\r
1162         switch (nErrorCode)\r
1163         {\r
1164         case TPI_ERROR_SUCCESS:\r
1165         case TPI_ERROR_S_ENDOFDATA:\r
1166         case TPI_CALLBACK_CONTINUE:\r
1167                 break;\r
1168         case TPI_ERROR_D_UNSUPPORTED:\r
1169                 wxLogError(_("Sorry, this function is not supported yet."));\r
1170                 break;\r
1171         case TPI_ERROR_D_SKIPPED:\r
1172         case TPI_CALLBACK_CANCEL:\r
1173                 break;\r
1174         default:\r
1175                 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);\r
1176         }\r
1177         return nErrorCode;\r
1178 }\r