OSDN Git Service

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