OSDN Git Service

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