OSDN Git Service

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