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