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