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