OSDN Git Service

「必要ならディレクトリを作成」と「処理後に出力先を開く」を選択して展開し、ディレクトリを作成しなかった場合、展開後により適切なパスを開くよう変更。
[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;\r
214         mkDlg.SetParent(this);\r
215         if (e.GetClientData() == NULL)\r
216         {\r
217                 // 処理対象のファイルを選択。\r
218                 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
219                 if (fd.ShowModal() == wxID_CANCEL)\r
220                 {\r
221                         return;\r
222                 }\r
223                 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
224                 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
225                 fd.GetFilenames(mkDlg.files);\r
226         }\r
227         else\r
228         {\r
229                 mkDlg.files = * (wxArrayString *) e.GetClientData();\r
230                 swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());\r
231                 // 相対パスに変換。\r
232                 for (size_t n = 0; n < mkDlg.files.GetCount(); n++)\r
233                 {\r
234                         wxFileName fn(mkDlg.files[n]);\r
235                         fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());\r
236                         mkDlg.files[n] = fn.GetFullPath();\r
237                 }\r
238         }\r
239 \r
240         this->OnArcClose(e);\r
241         // 書庫名はファイル名の拡張子より前、もしくはディレクトリ名。\r
242         this->fnArchive = wxFileName(mkDlg.files[0]);\r
243         this->fnArchive.SetName(mkDlg.files.GetCount() == 1 ? (this->fnArchive.GetName().IsEmpty() ? this->fnArchive.GetDirs().Last() : this->fnArchive.GetName()) : swInfo.fnDestinationDirectory.GetDirs().Last());\r
244         this->fnArchive.SetEmptyExt();\r
245         this->fnArchive.SetPath(swInfo.fnDestinationDirectory.GetPath());\r
246 \r
247         // ダイアログを表示。\r
248         if (mkDlg.ShowModal() == wxID_CANCEL)\r
249         {\r
250                 return;\r
251         }\r
252 \r
253         // 各種設定。\r
254         int nSelected = mkDlg.chType->GetSelection();\r
255         swInfo.nArchiveType         = mkDlg.afInfo[nSelected].nTypeId;\r
256         swInfo.fStoreDirectoryPathes= ! mkDlg.cbIgnorePath->IsChecked();\r
257         swInfo.fMakeSFX                     = mkDlg.cbMakeSFX->IsChecked();\r
258         swInfo.fSolid               = mkDlg.cbSolid->IsChecked();\r
259         swInfo.fMMOptimize          = mkDlg.cbMMOptimize->IsChecked();\r
260         swInfo.fEncryptHeader       = mkDlg.cbEncryptHeader->IsChecked();\r
261         swInfo.fCompressHeader      = mkDlg.cbCompressHeader->IsChecked();\r
262         swInfo.nCompressLevel       = mkDlg.scLevel->GetValue();\r
263         swInfo.nRecoveryRecord      = mkDlg.scRR->GetValue();\r
264         swInfo.szPassword           = mkDlg.tcPassword->GetValue();\r
265         swInfo.szKeyFile            = mkDlg.tcKeyfile->GetValue();\r
266         swInfo.szComment            = mkDlg.tcComment->GetValue();\r
267         mkDlg.cbSplitSize->GetValue().ToULongLong(& swInfo.nSplitSize);\r
268 \r
269         // TPIを読み込み。\r
270         this->fnArchive = wxFileName(mkDlg.cbDir->GetValue(), mkDlg.cbFileName->GetValue());\r
271         if (! tpi.InitLibrary(mkDlg.afInfo[nSelected].szTPIName, this->fnArchive.GetFullPath(), mkDlg.afInfo[nSelected].nTypeId))\r
272         {\r
273                 this->ErrorCheck(tpi.nErrorCode, wxT("InitLibrary"));\r
274                 return;\r
275         }\r
276 \r
277         // コールバック関数を設定。\r
278         tpi.SetCallbackProc(TPICallbackProc);\r
279         this->ErrorCheck(tpi.nErrorCode, wxT("SetCallbackProc"));\r
280 \r
281         // 処理を行う。\r
282         {\r
283                 ProcessDialog procDlg;\r
284                 procDlg.fnArchive  = & this->fnArchive;\r
285                 procDlg.nFileCount = mkDlg.files.GetCount();\r
286                 procDlg.Show(true);\r
287 \r
288                 tpi.Command(TPI_COMMAND_CREATE, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
289                 this->ErrorCheck(tpi.nErrorCode);\r
290                 procDlg.Show(false);\r
291         }\r
292         tpi.FreeLibrary();\r
293 \r
294         if (mkDlg.cbOpenAfter->IsChecked())\r
295         {\r
296                 // 作成先を開く。\r
297                 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
298         }\r
299 \r
300         if (mkDlg.cbExitAfter->IsChecked())\r
301         {\r
302                 // 終了。\r
303                 this->Close(true);\r
304         }\r
305 \r
306         // 終了しない場合は書庫を開く。\r
307         this->OnArcOpen(e);\r
308 }\r
309 \r
310 void MainFrame::OnArcOpen(wxCommandEvent& e)\r
311 {\r
312         // モード取得。通常は0, それ以外で開く場合は1, ファイルDnDなら2。\r
313         int nMode = e.GetInt() == 2 ? 2 : e.GetId() == XRCID("Arc_Open") ? 0 : 1;\r
314 \r
315         // 書庫を選択。\r
316         if (nMode == 0)\r
317         {\r
318                 wxFileDialog fd(this, _("Choose an archive"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
319                 if (fd.ShowModal() == wxID_CANCEL)\r
320                 {\r
321                         return;\r
322                 }\r
323                 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
324                 this->fnArchive = wxFileName(fd.GetPath());\r
325         }\r
326 \r
327         // 進捗ダイアログ表示。\r
328         ProcessDialog procDlg;\r
329         procDlg.fnArchive  = & this->fnArchive;\r
330         procDlg.Show(true);\r
331 \r
332         // DnD以外で書庫を開く場合、TPIを読み込み。\r
333         TPI_PROCESSINFO piInfo;\r
334         if (! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))\r
335         {\r
336                 procDlg.Show(false);\r
337                 if (nMode == 2)\r
338                 {\r
339                         // DnDの場合は書庫を作成する。\r
340                         this->OnArcCreate(e);\r
341                 }\r
342                 else if (this->IsShown())\r
343                 {\r
344                         wxBell();\r
345                         this->statusbar->SetStatusText(_("No plug-in supporting this archive was found!"), 4);\r
346                 }\r
347                 else\r
348                 {\r
349                         wxLogError(_("No plug-in supporting this archive was found!"));\r
350                         this->Close(true);\r
351                 }\r
352                 return;\r
353         }\r
354 \r
355         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
356         piInfo.eStatus = 0x1001;\r
357         if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo), wxT("Callback")) == TPI_CALLBACK_CANCEL)\r
358         {\r
359                 procDlg.Show(false);\r
360                 tpi.CloseArchive();\r
361                 wxCommandEvent e;\r
362                 this->OnArcClose(e);\r
363                 return;\r
364         }\r
365 \r
366         // 配列のサイズを確保。\r
367         this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);\r
368 \r
369         // 履歴に追加。\r
370         this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());\r
371         this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());\r
372         this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());\r
373 \r
374         // 書庫のアイコンを取得し、書庫ルートを作成。\r
375         g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));\r
376         g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));\r
377         this->tree_ctrl->SetImageList(& g_hIconT);\r
378         wxTreeItemId\r
379                 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),\r
380 #ifdef __WINDOWS__\r
381                 idArchive = this->tree_ctrl->AppendItem(idRoot, this->fnArchive.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName))),\r
382 #else\r
383                 idArchive = this->tree_ctrl->AppendItem(idRoot, this->fnArchive.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName).ConvertToImage().Rescale(16, 16))),\r
384 #endif\r
385                 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);\r
386 \r
387         // ファイル情報をロード。\r
388         if (tpi.GetFileInformation(& piInfo.fiInfo, true))\r
389         {\r
390                 piInfo.eStatus = 0x1002;\r
391                 piInfo.nProcessedSize = 0;\r
392                 do\r
393                 {\r
394                         piInfo.nProcessedSize++;\r
395                         if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo), wxT("Callback")) == TPI_CALLBACK_CANCEL)\r
396                         {\r
397                                 procDlg.Show(false);\r
398                                 tpi.CloseArchive();\r
399                                 wxCommandEvent e;\r
400                                 this->OnArcClose(e);\r
401                                 return;\r
402                         }\r
403 \r
404                         // 拡張子のみ設定されている場合。\r
405                         if (piInfo.fiInfo.szStoredName.IsEmpty())\r
406                         {\r
407                                 piInfo.fiInfo.szStoredName = this->fnArchive.GetName();\r
408                                 if (piInfo.fiInfo.fnFileName.HasExt())\r
409                                 {\r
410                                         piInfo.fiInfo.szStoredName += wxT('.') + piInfo.fiInfo.fnFileName.GetExt();\r
411                                 }\r
412                                 piInfo.fiInfo.fnFileName = wxFileName(piInfo.fiInfo.szStoredName);\r
413                         }\r
414 \r
415                         // セキュリティチェック。\r
416                         // ルート記号を削除。\r
417                         wxString szPath = piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX);\r
418                         if (szPath.StartsWith(wxT("/")) || szPath.StartsWith(wxT("./")))\r
419                         {\r
420                                 piInfo.fiInfo.fnFileName = wxFileName(szPath.AfterFirst(wxT('/')), piInfo.fiInfo.fnFileName.GetFullName(), wxPATH_DOS);\r
421                         }\r
422                         // ルートメンバの情報は無視する。\r
423                         if (piInfo.fiInfo.fnFileName.GetFullPath().IsEmpty() || piInfo.fiInfo.fnFileName.GetFullPath() == wxT("."))\r
424                         {\r
425                                 continue;\r
426                         }\r
427 \r
428                         // 改行文字/タブ文字などを削除。\r
429                         if (piInfo.fiInfo.szStoredName.Find(wxT('\r')) != wxNOT_FOUND\r
430                         ||  piInfo.fiInfo.szStoredName.Find(wxT('\n')) != wxNOT_FOUND\r
431                         ||  piInfo.fiInfo.szStoredName.Find(wxT('\t')) != wxNOT_FOUND)\r
432                         {\r
433                                 wxString sz = piInfo.fiInfo.fnFileName.GetFullPath();\r
434                                 sz.Replace(wxT("\r"), wxT(" "));\r
435                                 sz.Replace(wxT("\n"), wxT(" "));\r
436                                 sz.Replace(wxT("\t"), wxT(" "));\r
437                                 piInfo.fiInfo.eDanger = TRUE;\r
438                                 piInfo.fiInfo.fnFileName = wxFileName(sz);\r
439                                 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
440                         }\r
441 \r
442                         // DTV検査。\r
443                         if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)\r
444                         {\r
445                                 piInfo.fiInfo.eDanger = TRUE;\r
446                                 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
447                         }\r
448                         // 空白の連続による拡張子偽装を検査。\r
449                         if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT("        ")) != wxNOT_FOUND)\r
450                         {\r
451                                 piInfo.fiInfo.eDanger = TRUE;\r
452                                 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
453                         }\r
454                         // Unicode制御文字を検査。\r
455                         for (wxChar c = 0x200c; c <= 0x206f; c++)\r
456                         {\r
457                                 if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)\r
458                                 {\r
459                                         piInfo.fiInfo.eDanger = TRUE;\r
460                                         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
461                                 }\r
462                                 switch (c)\r
463                                 {\r
464                                 case 0x200f: c = 0x2027; break;\r
465                                 case 0x202e: c = 0x2060; break;\r
466                                 }\r
467                         }\r
468 \r
469                         // ツリービューに反映。\r
470                         bool fDir = piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? true : false;\r
471                         TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, fDir ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetPath(), true);\r
472 \r
473                         // ディレクトリ属性を含むものについては情報を保存しない。\r
474                         if (fDir)\r
475                         {\r
476                                 continue;\r
477                         }\r
478 \r
479                         // 情報を保存してカウントアップ。\r
480                         this->fileinfo.Add(piInfo.fiInfo);\r
481                 }\r
482                 while (tpi.GetFileInformation(& piInfo.fiInfo));\r
483         }\r
484 \r
485         // GetFileInformationがエラー終了した場合。\r
486         this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));\r
487 \r
488         // 書庫の情報を取得。\r
489         tpi.GetArchiveInformation(& this->aiArchive);\r
490         this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));\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->ExpandAll();\r
499         this->tree_ctrl->ScrollTo(idArchive);\r
500         this->tree_ctrl->SelectItem(idArchive);\r
501         this->tree_ctrl->SetScrollPos(wxHORIZONTAL, 0);\r
502         this->list_ctrl->atDangerItem.SetTextColour(* wxRED);\r
503         this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));\r
504 \r
505         // ステータスバー設定。\r
506         this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);\r
507         this->statusbar->SetStatusText(wxString::Format(_("%u file(s)"), this->fileinfo.GetCount()), 1);\r
508         this->statusbar->SetStatusText(wxString::Format(wxString("%" wxLongLongFmtSpec "uB -> %" wxLongLongFmtSpec "uB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);\r
509         this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);\r
510         this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);\r
511         this->statusbar->SetToolTip(\r
512                 wxString::Format(\r
513                         _("%s(%s)\nModify: %s\nCreate: %s\nTPI: %s(%s)"),\r
514                         this->fnArchive.GetFullName().c_str(), this->aiArchive.fiInfo.szTypeName.c_str(),\r
515                         this->aiArchive.tmModify.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
516                         this->aiArchive.tmCreate.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
517                         this->aiArchive.fiInfo.szTPIName.c_str(), this->aiArchive.fiInfo.szEngineName.c_str()\r
518                 )\r
519         );\r
520 \r
521         // ツールバー・メニューバー設定。ファイル選択時しか動作しない削除などは別に設定。\r
522         SetMenuToolState("Arc_Close",   true);\r
523         SetMenuToolState("Arc_Add",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD)   == TPI_COMMAND_ADD   && this->aiArchive.fiInfo.fArchive);\r
524         SetMenuToolState("Arc_SFX",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX)    == TPI_COMMAND_SFX   && ! this->aiArchive.fSFX);\r
525         SetMenuToolState("Arc_UnSFX",   (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX)  == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);\r
526         SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);\r
527         SetMenuToolState("Arc_Test",    (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST)   == TPI_COMMAND_TEST);\r
528         SetMenuToolState("Arc_Repair",  (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);\r
529         this->menubar->Enable(XRCID("Arc_Clone"), true);\r
530 \r
531         procDlg.Show(false);\r
532         this->Raise();\r
533 }\r
534 \r
535 void MainFrame::OnArcClose(wxCommandEvent& e)\r
536 {\r
537         // ツリービュー・リストビュー設定。\r
538         this->tree_ctrl->DeleteAllItems();\r
539         this->list_ctrl->DeleteAllItems();\r
540         this->list_ctrl->apShowFile.Clear();\r
541 \r
542         // ツールバー・メニューバー設定。\r
543         SetMenuToolState("Arc_Close",   false);\r
544         SetMenuToolState("Arc_Add",     false);\r
545         SetMenuToolState("Arc_SFX",     false);\r
546         SetMenuToolState("Arc_UnSFX",   false);\r
547         SetMenuToolState("Arc_Extract", false);\r
548         SetMenuToolState("Arc_Delete",  false);\r
549         SetMenuToolState("Arc_Test",    false);\r
550         SetMenuToolState("Arc_Repair",  false);\r
551         this->menubar->Enable(XRCID("Arc_Clone"), false);\r
552 \r
553         for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)\r
554         {\r
555                 this->statusbar->SetStatusText(wxEmptyString, i);\r
556         }\r
557         this->statusbar->SetToolTip(wxEmptyString);\r
558         this->fileinfo.Clear();\r
559         this->aiArchive.szComment.Empty();\r
560         this->aiArchive.fnArchive.Clear();\r
561         this->aiArchive.fiInfo.szTypeName.Empty();\r
562         this->aiArchive.fiInfo.szSuffix.Empty();\r
563         this->aiArchive.fiInfo.szEngineName.Empty();\r
564         this->aiArchive.fiInfo.szTPIName.Empty();\r
565 \r
566         g_hIconT.RemoveAll();\r
567         g_hIconLL.RemoveAll();\r
568         g_hIconLS.RemoveAll();\r
569 \r
570         // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。\r
571         if (e.GetExtraLong() == 0)\r
572         {\r
573                 tpi.FreeLibrary();\r
574         }\r
575 }\r
576 \r
577 void MainFrame::OnArcClone(wxCommandEvent&)\r
578 {\r
579         // 保存先を尋ねる。\r
580         wxFileDialog fd(this, _("Clone archive"), this->fnArchive.GetPath(), this->fnArchive.GetFullName(), wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
581         if (fd.ShowModal() == wxID_CANCEL)\r
582         {\r
583                 return;\r
584         }\r
585         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
586 \r
587         // コピー。\r
588         ::wxCopyFile(this->fnArchive.GetFullPath(), fd.GetPath());\r
589         wxFileName fn(fd.GetPath());\r
590         wxDateTime dtAccess, dtModify, dtCreate;\r
591         this->fnArchive.GetTimes(& dtAccess, & dtModify, & dtCreate);\r
592         fn.SetTimes(& dtAccess, & dtModify, & dtCreate);\r
593 }\r
594 \r
595 void MainFrame::OnArcAdd(wxCommandEvent& e)\r
596 {\r
597         // 作成ダイアログを設定。\r
598         MakeDialog mkDlg;\r
599         mkDlg.SetParent(this);\r
600         mkDlg.uCommand = TPI_COMMAND_ADD;\r
601 \r
602         // 処理対象のファイルを選択。\r
603         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
604         if (fd.ShowModal() == wxID_CANCEL)\r
605         {\r
606                 return;\r
607         }\r
608         fd.GetFilenames(mkDlg.files);\r
609         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
610 \r
611         // ダイアログを表示。\r
612         if (mkDlg.ShowModal() == wxID_CANCEL)\r
613         {\r
614                 return;\r
615         }\r
616 \r
617         // 各種設定。\r
618         TPI_SWITCHES swInfo;\r
619         swInfo.pCustomSwitches       = NULL;\r
620         swInfo.fMakeSFX              = false;\r
621         swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());\r
622         swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();\r
623         swInfo.fSolid               = mkDlg.cbSolid->IsChecked();\r
624         swInfo.fMMOptimize          = mkDlg.cbMMOptimize->IsChecked();\r
625         swInfo.fEncryptHeader       = mkDlg.cbEncryptHeader->IsChecked();\r
626         swInfo.nCompressLevel       = mkDlg.scLevel->GetValue();\r
627         swInfo.nRecoveryRecord      = mkDlg.scRR->GetValue();\r
628         swInfo.szPassword           = mkDlg.tcPassword->GetValue();\r
629         swInfo.szKeyFile            = mkDlg.tcKeyfile->GetValue();\r
630         swInfo.szComment            = mkDlg.tcComment->GetValue();\r
631 \r
632         // 処理を行う。\r
633         {\r
634                 ProcessDialog procDlg;\r
635                 procDlg.fnArchive  = & this->fnArchive;\r
636                 procDlg.nFileCount = mkDlg.files.GetCount();\r
637                 procDlg.Show(true);\r
638 \r
639                 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
640                 this->ErrorCheck(tpi.nErrorCode);\r
641                 procDlg.Show(false);\r
642         }\r
643 \r
644         if (mkDlg.cbOpenAfter->IsChecked())\r
645         {\r
646                 // 作成先を開く。\r
647                 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
648         }\r
649 \r
650         if (mkDlg.cbExitAfter->IsChecked())\r
651         {\r
652                 // 終了。\r
653                 this->Close(true);\r
654         }\r
655 \r
656         // 終了しない場合は書庫を再読み込み。\r
657         this->OnArcOpen(e);\r
658 }\r
659 \r
660 void MainFrame::OnArcConvert(wxCommandEvent& e)\r
661 {\r
662         TPI_SWITCHES swInfo;\r
663         swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");\r
664 \r
665         // 保存先を尋ねる。\r
666         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
667         if (fd.ShowModal() == wxID_CANCEL)\r
668         {\r
669                 return;\r
670         }\r
671         swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
672         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
673 \r
674         wxArrayString files;\r
675         files.Add(fd.GetPath());\r
676 \r
677         ProcessDialog procDlg;\r
678         procDlg.Show(true);\r
679         tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);\r
680         this->ErrorCheck(tpi.nErrorCode);\r
681         procDlg.Show(false);\r
682 }\r
683 \r
684 void MainFrame::OnArcExtract(wxCommandEvent& e)\r
685 {\r
686         TPI_SWITCHES swInfo;\r
687         swInfo.pCustomSwitches = NULL;\r
688 \r
689         // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3、クリップボードなら4、コンテキストメニューからなら8。\r
690         int nMode = e.GetInt();\r
691         if (e.GetInt() == 8)\r
692         {\r
693                 nMode = 0;\r
694         }\r
695         // 実行時のみ使用。\r
696         wxFileType * ftFile = NULL;\r
697 \r
698         // 展開ダイアログを作成。DnDまたは実行時は表示しない。\r
699         MakeDialog mkDlg;\r
700         mkDlg.SetParent(this);\r
701         mkDlg.uCommand = TPI_COMMAND_EXTRACT;\r
702         mkDlg.files    = MakeTargetFileList(this, nMode == 1);\r
703 \r
704         bool bMakeDir = false;\r
705         if (nMode != 0)\r
706         {\r
707                 // 作業ディレクトリ作成。\r
708                 swInfo.fStoreDirectoryPathes = false;\r
709                 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");\r
710                 wxStandardPaths p;\r
711                 if (szDestDirBase == wxT("-----"))\r
712                 {\r
713                         // 書庫ルートのときは書庫名にしておく。\r
714                         szDestDirBase = this->fnArchive.GetName();\r
715                 }\r
716                 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(p.GetTempDir()), szDestDirBase, true);\r
717                 if (! swInfo.fnDestinationDirectory.IsOk())\r
718                 {\r
719                         wxLogError(_("Unable to make the temporary directory!"));\r
720                         return;\r
721                 }\r
722         }\r
723         else\r
724         {\r
725                 if (mkDlg.ShowModal() == wxID_CANCEL)\r
726                 {\r
727                         return;\r
728                 }\r
729 \r
730                 // 各種設定。\r
731                 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();\r
732                 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());\r
733                 swInfo.szPassword = mkDlg.tcPassword->GetValue();\r
734                 swInfo.szKeyFile  = mkDlg.tcKeyfile->GetValue();\r
735 \r
736                 // 必要なら書庫名でディレクトリを作成する。\r
737                 bMakeDir = WillMakeDirByArcName(this, & mkDlg);\r
738                 if (bMakeDir)\r
739                 {\r
740                         swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);\r
741                         if (! swInfo.fnDestinationDirectory.IsOk())\r
742                         {\r
743                                 wxLogError(_("Unable to make the destination directory!"));\r
744                                 return;\r
745                         }\r
746                 }\r
747         }\r
748 \r
749         // 処理を行う。\r
750         {\r
751                 ProcessDialog procDlg;\r
752                 procDlg.fnArchive  = & this->fnArchive;\r
753                 procDlg.nFileCount = mkDlg.files.GetCount();\r
754                 procDlg.Show(true);\r
755 \r
756                 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
757                 this->ErrorCheck(tpi.nErrorCode);\r
758                 procDlg.Show(false);\r
759         }\r
760 \r
761         if (nMode == 0)\r
762         {\r
763                 if (mkDlg.cbOpenAfter->IsChecked())\r
764                 {\r
765                         // 展開先を開く。\r
766                         if (mkDlg.chDirMake->GetSelection() == 2 && ! bMakeDir)\r
767                         {\r
768                                 wxTreeItemId tiArcSub = this->tree_ctrl->GetLastChild(this->tree_ctrl->GetLastChild(this->tree_ctrl->GetRootItem()));\r
769                                 if (tiArcSub.IsOk())\r
770                                 {\r
771                                         swInfo.fnDestinationDirectory.SetFullName(this->tree_ctrl->GetItemText(tiArcSub));\r
772                                 }\r
773                         }\r
774                         ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
775                 }\r
776 \r
777                 if (mkDlg.cbExitAfter->IsChecked())\r
778                 {\r
779                         // 終了。\r
780                         this->Close(true);\r
781                 }\r
782         }\r
783         else\r
784         {\r
785                 if (nMode == 1)\r
786                 {\r
787                         // コマンドを取得。\r
788                         ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());\r
789                         if (! ftFile || ftFile->GetOpenCommand(wxEmptyString).IsEmpty())\r
790                         {\r
791                                 // 種類が取得できないときはテキストとみなす。\r
792                                 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));\r
793                         }\r
794 \r
795                         // コマンドを実行。\r
796                         wxString szTempFile = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName();\r
797                         bool fSuccess = tpi.nErrorCode == TPI_ERROR_SUCCESS && ftFile != NULL;\r
798                         myProcess * pCallback = new myProcess(szTempFile, swInfo.fnDestinationDirectory.GetPath());\r
799                         if (fSuccess)\r
800                         {\r
801 #ifdef __LINUX__\r
802                                 // Linuxでは引用符で囲む必要がある。\r
803                                 fSuccess = ::wxExecute(ftFile->GetOpenCommand(QuoteString(szTempFile)), wxEXEC_ASYNC, pCallback) > 0;\r
804 #else\r
805                                 fSuccess = ::wxExecute(ftFile->GetOpenCommand(szTempFile), wxEXEC_ASYNC, pCallback) > 0;\r
806 #endif\r
807                         }\r
808                         if (! fSuccess)\r
809                         {\r
810                                 pCallback->OnTerminate(0, 0);\r
811                         }\r
812                 }\r
813                 else\r
814                 {\r
815                         // 展開対象を決定。\r
816                         wxArrayString asFiles;\r
817                         myFileDataObject * objFile = new myFileDataObject();\r
818                         objFile->szTempDir = nMode == 3 ? swInfo.fnDestinationDirectory.GetPath() : swInfo.fnDestinationDirectory.GetFullPath();\r
819                         for (size_t i = 0; i < mkDlg.files.GetCount(); i++)\r
820                         {\r
821                                 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();\r
822                                 if (nMode == 3)\r
823                                 {\r
824                                         asFiles.Add(szFileName);\r
825                                 }\r
826                                 else\r
827                                 {\r
828                                         // リストに追加。\r
829                                         objFile->AddFile(szFileName);\r
830                                 }\r
831                         }\r
832                         if (nMode == 3)\r
833                         {\r
834                                 objFile->AddFile(objFile->szTempDir);\r
835                         }\r
836 \r
837                         if (nMode == 4)\r
838                         {\r
839                                 wxTheClipboard->SetData(objFile);\r
840                         }\r
841                         else\r
842                         {\r
843                                 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。\r
844                                 this->SetDropTarget(NULL);\r
845 \r
846                                 // DnD開始。\r
847                                 wxDropSource dropSource(* objFile, this);\r
848                                 wxDragResult drResult = dropSource.DoDragDrop();\r
849                                 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)\r
850                                 {\r
851 #ifdef __LINUX__\r
852                                         // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。\r
853                                         sleep(3);\r
854 #endif\r
855                                 }\r
856                                 this->SetDropTarget(new myFileDropTarget(this));\r
857 \r
858                                 // ディレクトリDnDのときは、先にディレクトリの中のファイルを消しておく。\r
859                                 if (nMode == 3)\r
860                                 {\r
861                                         for (size_t i = 0; i < asFiles.GetCount(); i++)\r
862                                         {\r
863                                                 chmod(asFiles[i].ToUTF8(), 0600);\r
864                                                 ::wxRemoveFile(asFiles[i]);\r
865                                         }\r
866                                 }\r
867 \r
868                                 delete objFile;\r
869                         }\r
870                 }\r
871         }\r
872 }\r
873 \r
874 void MainFrame::OnArcDelete(wxCommandEvent& e)\r
875 {\r
876         // 全ファイル削除は危険ではないかと。\r
877         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
878         {\r
879                 // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
880                 SetMenuToolState("Arc_Delete", false);\r
881                 return;\r
882         }\r
883 \r
884         if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)\r
885         {\r
886                 return;\r
887         }\r
888 \r
889         // 処理を行う。\r
890         {\r
891                 wxArrayString asFiles = MakeTargetFileList(this, false);\r
892                 ProcessDialog procDlg;\r
893                 procDlg.fnArchive  = & this->fnArchive;\r
894                 procDlg.nFileCount = asFiles.GetCount();\r
895                 procDlg.Show(true);\r
896 \r
897                 TPI_SWITCHES swInfo;\r
898                 tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
899                 this->ErrorCheck(tpi.nErrorCode);\r
900                 procDlg.Show(false);\r
901         }\r
902 \r
903         // 書庫を再読み込みする。\r
904         this->OnArcOpen(e);\r
905 }\r
906 \r
907 void MainFrame::OnArcTest(wxCommandEvent&)\r
908 {\r
909         // 処理を行う。\r
910         wxArrayString asFiles = MakeTargetFileList(this, false);\r
911         ProcessDialog procDlg;\r
912         procDlg.fnArchive  = & this->fnArchive;\r
913         procDlg.nFileCount = asFiles.GetCount();\r
914         procDlg.Show(true);\r
915 \r
916         TPI_SWITCHES swInfo;\r
917         bool bIsCorrect = tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
918         procDlg.Show(false);\r
919 \r
920         if (bIsCorrect)\r
921         {\r
922                 wxLogMessage(_("This is a correct archive."));\r
923         }\r
924         else\r
925         {\r
926                 this->ErrorCheck(tpi.nErrorCode);\r
927         }\r
928 }\r
929 \r
930 void MainFrame::OnArcRepair(wxCommandEvent&)\r
931 {\r
932         // 処理を行う。\r
933         wxArrayString asFiles = MakeTargetFileList(this, false);\r
934         ProcessDialog procDlg;\r
935         procDlg.fnArchive  = & this->fnArchive;\r
936         procDlg.nFileCount = asFiles.GetCount();\r
937         procDlg.Show(true);\r
938 \r
939         TPI_SWITCHES swInfo;\r
940         tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
941         this->ErrorCheck(tpi.nErrorCode);\r
942         procDlg.Show(false);    \r
943 }\r
944 \r
945 void MainFrame::OnExeCopy(wxCommandEvent & e)\r
946 {\r
947         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
948         {\r
949                 // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
950                 this->menubar->Enable(XRCID("Exe_Copy"), false);\r
951                 return;\r
952         }\r
953 \r
954         if (! wxTheClipboard->Open())\r
955         {\r
956                 return;\r
957         }\r
958 \r
959         e.SetInt(4);\r
960         this->OnArcExtract(e);\r
961         wxTheClipboard->Close();\r
962 }\r
963 \r
964 void MainFrame::OnViewMode(wxCommandEvent & e)\r
965 {\r
966         int n = e.GetId();\r
967         this->menubar->Check(n, true);\r
968         this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));\r
969         this->list_ctrl->SetSingleStyle(wxLC_ICON,   n == XRCID("Exe_View_Icons"));\r
970         this->list_ctrl->SetSingleStyle(wxLC_LIST,   n == XRCID("Exe_View_List"));\r
971 }\r
972 \r
973 void MainFrame::OnShowToolBar(wxCommandEvent & e)\r
974 {\r
975         this->toolbar->Show(e.IsChecked());\r
976 }\r
977 \r
978 void MainFrame::OnShowStatusBar(wxCommandEvent & e)\r
979 {\r
980         this->statusbar->Show(e.IsChecked());\r
981 }\r
982 \r
983 void MainFrame::OnSelectAll(wxCommandEvent &)\r
984 {\r
985         for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)\r
986         {\r
987                 this->list_ctrl->Select(i, true);\r
988         }\r
989 }\r
990 \r
991 // TreeView\r
992 \r
993 void MainFrame::OnTreeChanged(wxTreeEvent& e)\r
994 {\r
995         // ツリービューからパスを取得。\r
996         wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());\r
997         // リストビューを初期化。\r
998         this->list_ctrl->apShowFile.Clear();\r
999         this->list_ctrl->DeleteAllItems();\r
1000         g_hIconLL.RemoveAll();\r
1001         g_hIconLS.RemoveAll();\r
1002 \r
1003         // 現在のアイテムの選択状態を無効にしておく。\r
1004         long nSelected = this->list_ctrl->GetFirstSelected();\r
1005         while (nSelected != -1)\r
1006         {\r
1007                 this->list_ctrl->Select(nSelected, false);\r
1008                 nSelected = this->list_ctrl->GetNextSelected(nSelected);\r
1009         }\r
1010 \r
1011         // アイコン設定。\r
1012         this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);\r
1013         this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);\r
1014 \r
1015         // 配列と比較し、パスが一致しなければ消す。\r
1016         for (size_t i = 0; i < this->fileinfo.GetCount(); i++)\r
1017         {\r
1018                 // パスを比較。\r
1019                 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())\r
1020                 {\r
1021                         // 項目がフォルダであるなら無視。\r
1022                         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
1023                         {\r
1024                                 continue;\r
1025                         }\r
1026 \r
1027                         // フィルタにかからなければ無視。\r
1028                         if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)\r
1029                         {\r
1030                                 continue;\r
1031                         }\r
1032 \r
1033                         this->list_ctrl->apShowFile.Add(& this->fileinfo[i]);\r
1034                 }\r
1035         }\r
1036 \r
1037         // ソートして表示。\r
1038         this->list_ctrl->apShowFile.Sort(& ListCtrlCompareProc);\r
1039         this->list_ctrl->SetItemCount(this->list_ctrl->apShowFile.GetCount());\r
1040 }\r
1041 \r
1042 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)\r
1043 {\r
1044         // TODO : アイテムが子階層を持っていても展開できない。\r
1045         this->tree_ctrl->SelectItem(e.GetItem());\r
1046 \r
1047         wxCommandEvent e1;\r
1048         e1.SetInt(3);\r
1049         this->OnArcExtract(e1);\r
1050 }\r
1051 \r
1052 void MainFrame::OnContextMenu(wxContextMenuEvent& e)\r
1053 {\r
1054         wxPoint p = e.GetPosition();\r
1055         this->list_ctrl->PopupMenu(this->menubar->GetMenu(1), p == wxDefaultPosition ? this->list_ctrl->GetPosition() : this->list_ctrl->ScreenToClient(p));\r
1056 }\r
1057 \r
1058 // ListView\r
1059 \r
1060 void MainFrame::OnListItemSelect(wxListEvent&)\r
1061 {\r
1062         // ファイルに対する動作の設定。但し、選択解除時はwxのバグで呼び出されない。\r
1063         bool fEnable = this->list_ctrl->GetSelectedItemCount() > 0;\r
1064         SetMenuToolState("Arc_Delete", fEnable && (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);\r
1065         this->menubar->Enable(XRCID("Exe_Copy"), fEnable);\r
1066 }\r
1067 \r
1068 void MainFrame::OnListItemDClick(wxListEvent&)\r
1069 {\r
1070         wxCommandEvent e;\r
1071         e.SetInt(1);\r
1072         this->OnArcExtract(e);\r
1073 }\r
1074 \r
1075 void MainFrame::OnListBeginDrag(wxListEvent&)\r
1076 {\r
1077         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
1078         {\r
1079                 // アイテムを選択せずドラッグしようとした場合。\r
1080                 return;\r
1081         }\r
1082 \r
1083         wxCommandEvent e;\r
1084         e.SetInt(2);\r
1085         this->OnArcExtract(e);\r
1086 }\r
1087 \r
1088 // Filter\r
1089 \r
1090 void MainFrame::OnFilter(wxCommandEvent&)\r
1091 {\r
1092         wxTreeEvent e;\r
1093         e.SetItem(this->tree_ctrl->GetSelection());\r
1094         this->OnTreeChanged(e);\r
1095 }\r
1096 \r
1097 // イベントハンドラ以外。\r
1098 \r
1099 bool MainFrame::LoadTPI(const wxString & szFileName, wxULongLong_t * llFileCount)\r
1100 {\r
1101         // 書庫を開いていれば閉じておく。\r
1102         wxCommandEvent e;\r
1103         this->OnArcClose(e);\r
1104 \r
1105         // TPIを読み込み。\r
1106         wxDir fs(L_DIR_B_LIB);\r
1107         wxString szTPIName;\r
1108         if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))\r
1109         {\r
1110                 do\r
1111                 {\r
1112                         // 初期化。\r
1113                         if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName))\r
1114                         {\r
1115                                 tpi.FreeLibrary();\r
1116                                 continue;\r
1117                         }\r
1118 \r
1119                         // コールバック関数を設定。\r
1120                         tpi.SetCallbackProc(TPICallbackProc);\r
1121 \r
1122                         // 対応確認。\r
1123                         if (! tpi.OpenArchive(szFileName, llFileCount))\r
1124                         {\r
1125                                 tpi.FreeLibrary();\r
1126                                 * llFileCount = 0;\r
1127                                 continue;\r
1128                         }\r
1129                         return true;\r
1130                 }\r
1131                 while (fs.GetNext(& szTPIName));\r
1132         }\r
1133         return false;\r
1134 }\r
1135 \r
1136 int MainFrame::ErrorCheck(int nErrorCode, const wxString & szAPIName)\r
1137 {\r
1138         switch (nErrorCode)\r
1139         {\r
1140         case TPI_ERROR_SUCCESS:\r
1141         case TPI_ERROR_S_ENDOFDATA:\r
1142         case TPI_CALLBACK_CONTINUE:\r
1143                 break;\r
1144         case TPI_ERROR_D_UNSUPPORTED:\r
1145                 wxLogError(_("Sorry, this function is not supported yet."));\r
1146                 break;\r
1147         case TPI_ERROR_D_SKIPPED:\r
1148         case TPI_CALLBACK_CANCEL:\r
1149                 wxLogError(_("This operation is canceled by the user."));\r
1150                 break;\r
1151         default:\r
1152                 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);\r
1153         }\r
1154         return nErrorCode;\r
1155 }\r