OSDN Git Service

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