OSDN Git Service

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