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