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