OSDN Git Service

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