OSDN Git Service

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