OSDN Git Service

微修正。
[tpi/lychee.git] / src / lychee / frm_main.cpp
index 6c02750..52134ce 100644 (file)
@@ -45,51 +45,57 @@ bool g_fSortAscend;
 // MainFrame\r
 //******************************************************************************\r
 \r
-MainFrame::MainFrame(): wxFrame()\r
+MainFrame::MainFrame(): wxFrame(), gFrame(NULL)\r
 {\r
 }\r
 \r
 MainFrame::~MainFrame()\r
 {\r
-       wxCommandEvent e;\r
-       this->OnArcClose(e);\r
-\r
        // 設定を記録。\r
        if (! this->IsIconized() && ! this->IsMaximized())\r
        {\r
                int a, b;\r
                this->GetSize(& a, & b);\r
-               this->conf.WriteId(CONF_WINDOW_WIDTH, (long) a);\r
-               this->conf.WriteId(CONF_WINDOW_HEIGHT,(long) b);\r
+               this->conf.WriteId(CONF_WINDOW_WIDTH,  a);\r
+               this->conf.WriteId(CONF_WINDOW_HEIGHT, b);\r
                this->GetPosition(& a, & b);\r
-               this->conf.WriteId(CONF_WINDOW_X, (long) a);\r
-               this->conf.WriteId(CONF_WINDOW_Y, (long) b);\r
+               this->conf.WriteId(CONF_WINDOW_X, a);\r
+               this->conf.WriteId(CONF_WINDOW_Y, b);\r
+       }\r
+\r
+       // ウインドウが表示されていないときは、GetSashPosition()が不正な値を返す。\r
+       if (this->IsShown())\r
+       {\r
+               this->conf.WriteId(CONF_WINDOW_SPLITTER_POS, this->window_splitter->GetSashPosition());\r
        }\r
-       this->conf.WriteId(CONF_WINDOW_SPLITTER_POS, (long) this->window_splitter->GetSashPosition());\r
 \r
        // ツールバー/ステータスバー関連。\r
        this->conf.WriteId(CONF_WINDOW_STATUSBAR, this->statusbar->IsShown());\r
        this->conf.WriteId(CONF_WINDOW_TOOLBAR,   this->toolbar->IsShown());\r
 \r
        // ListView関連。\r
-       this->conf.WriteId(CONF_LISTVIEW_SHOWMODE, (long) (this->menubar->IsChecked(XRCID("Exe_View_Icons")) ? 1 : this->menubar->IsChecked(XRCID("Exe_View_List")) ? 2 : 0));\r
+       this->conf.WriteId(CONF_LISTVIEW_SHOWMODE, this->menubar->IsChecked(XRCID("Exe_View_Icons")) ? 1 : this->menubar->IsChecked(XRCID("Exe_View_List")) ? 2 : 0);\r
        if (this->menubar->IsChecked(XRCID("Exe_View_Details")))\r
        {\r
-               this->conf.WriteId(CONF_LISTVIEW_C_FILENAME,(long) this->list_ctrl->GetColumnWidth(0));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_UNPACKED,(long) this->list_ctrl->GetColumnWidth(1));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_PACKED,  (long) this->list_ctrl->GetColumnWidth(2));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_RATIO,   (long) this->list_ctrl->GetColumnWidth(3));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_METHOD,  (long) this->list_ctrl->GetColumnWidth(4));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_ATTR,        (long) this->list_ctrl->GetColumnWidth(5));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_LASTMOD, (long) this->list_ctrl->GetColumnWidth(6));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_PATH,    (long) this->list_ctrl->GetColumnWidth(7));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_TYPE,    (long) this->list_ctrl->GetColumnWidth(8));\r
-               this->conf.WriteId(CONF_LISTVIEW_C_NO,      (long) this->list_ctrl->GetColumnWidth(9));\r
-               this->conf.WriteId(CONF_LISTVIEW_S_COLUMN,  (long) g_nSortColumn);\r
-               this->conf.WriteId(CONF_LISTVIEW_S_ASCEND,  g_fSortAscend);\r
+               this->conf.WriteId(CONF_LISTVIEW_C_FILENAME, this->list_ctrl->GetColumnWidth(0));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_UNPACKED, this->list_ctrl->GetColumnWidth(1));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_PACKED,   this->list_ctrl->GetColumnWidth(2));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_RATIO,    this->list_ctrl->GetColumnWidth(3));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_METHOD,   this->list_ctrl->GetColumnWidth(4));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_ATTR,         this->list_ctrl->GetColumnWidth(5));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_LASTMOD,  this->list_ctrl->GetColumnWidth(6));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_PATH,     this->list_ctrl->GetColumnWidth(7));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_TYPE,     this->list_ctrl->GetColumnWidth(8));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_NO,       this->list_ctrl->GetColumnWidth(9));\r
+               this->conf.WriteId(CONF_LISTVIEW_C_COMMENT,  this->list_ctrl->GetColumnWidth(10));\r
+               this->conf.WriteId(CONF_LISTVIEW_S_COLUMN,   g_nSortColumn);\r
+               this->conf.WriteId(CONF_LISTVIEW_S_ASCEND,   g_fSortAscend);\r
        }\r
 \r
-       this->Close(true);\r
+       wxCommandEvent e;\r
+       delete this->gFrame;\r
+       this->Show(false);\r
+       this->OnArcClose(e);\r
 }\r
 \r
 //******************************************************************************\r
@@ -97,11 +103,14 @@ MainFrame::~MainFrame()
 //******************************************************************************\r
 \r
 BEGIN_EVENT_TABLE(MainFrame, wxFrame)\r
-       EVT_INIT_DIALOG(      MainFrame::OnInit)\r
+       EVT_INIT_DIALOG(MainFrame::OnInit)\r
+       EVT_SIZE(       MainFrame::OnSize)\r
+       EVT_CLOSE(      MainFrame::OnClose)\r
        // Menu\r
        EVT_MENU(XRCID("Arc_Create"),  MainFrame::OnArcCreate)\r
        EVT_MENU(XRCID("Arc_Open"),    MainFrame::OnArcOpen)\r
        EVT_MENU(XRCID("Arc_Close"),   MainFrame::OnArcClose)\r
+       EVT_MENU(XRCID("Arc_Clone"),   MainFrame::OnArcClone)\r
        EVT_MENU(XRCID("Arc_Add"),     MainFrame::OnArcAdd)\r
        EVT_MENU(XRCID("Arc_SFX"),     MainFrame::OnArcConvert)\r
        EVT_MENU(XRCID("Arc_UnSFX"),   MainFrame::OnArcConvert)\r
@@ -110,6 +119,7 @@ BEGIN_EVENT_TABLE(MainFrame, wxFrame)
        EVT_MENU(XRCID("Arc_Delete"),  MainFrame::OnArcDelete)\r
        EVT_MENU(XRCID("Arc_Test"),    MainFrame::OnArcTest)\r
        EVT_MENU(XRCID("Arc_Repair"),  MainFrame::OnArcRepair)\r
+       EVT_MENU(XRCID("Exe_Copy"),    MainFrame::OnExeCopy)\r
        EVT_MENU(XRCID("Exe_View_Icons"),  MainFrame::OnViewMode)\r
        EVT_MENU(XRCID("Exe_View_Details"),MainFrame::OnViewMode)\r
        EVT_MENU(XRCID("Exe_View_List"),   MainFrame::OnViewMode)\r
@@ -119,9 +129,13 @@ BEGIN_EVENT_TABLE(MainFrame, wxFrame)
        // TreeView\r
        EVT_TREE_SEL_CHANGED(XRCID("TreeView"), MainFrame::OnTreeChanged)\r
        EVT_TREE_BEGIN_DRAG( XRCID("TreeView"), MainFrame::OnTreeBeginDrag)\r
+       EVT_COMMAND_CONTEXT_MENU(XRCID("TreeView"), MainFrame::OnContextMenu)\r
        // ListView\r
-       EVT_LIST_ITEM_ACTIVATED(XRCID("ListView"), MainFrame::OnListItemDClick)\r
-       EVT_LIST_BEGIN_DRAG(    XRCID("ListView"), MainFrame::OnListBeginDrag)\r
+       EVT_LIST_ITEM_SELECTED(  XRCID("ListView"), MainFrame::OnListItemSelect)\r
+       EVT_LIST_ITEM_DESELECTED(XRCID("ListView"), MainFrame::OnListItemSelect)\r
+       EVT_LIST_ITEM_ACTIVATED( XRCID("ListView"), MainFrame::OnListItemDClick)\r
+       EVT_LIST_BEGIN_DRAG(     XRCID("ListView"), MainFrame::OnListBeginDrag)\r
+       EVT_COMMAND_CONTEXT_MENU(XRCID("ListView"), MainFrame::OnContextMenu)\r
        // Filter\r
        EVT_TEXT(XRCID("tcFilter"), MainFrame::OnFilter)\r
 END_EVENT_TABLE()\r
@@ -142,7 +156,7 @@ void MainFrame::OnInit(wxInitDialogEvent&)
        this->tcFilter  = XRCCTRL(* this->toolbar, "tcFilter", wxTextCtrl);\r
 \r
        // 設定を読み込み。\r
-       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));\r
+       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
        wxTheMimeTypesManager->Initialize(wxMAILCAP_ALL);\r
 \r
        // 初期値設定。\r
@@ -153,6 +167,7 @@ void MainFrame::OnInit(wxInitDialogEvent&)
        }\r
        wxCommandEvent e;\r
        this->OnArcClose(e);\r
+       this->SetDropTarget(new myFileDropTarget(this));\r
 \r
        // スプリッター設定。\r
        this->window_splitter->SetSashPosition(this->conf.ReadId(CONF_WINDOW_SPLITTER_POS, 200l));\r
@@ -173,9 +188,9 @@ void MainFrame::OnInit(wxInitDialogEvent&)
        this->list_ctrl->InsertColumn(7, _("Path"),          wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_PATH,     100l));\r
        this->list_ctrl->InsertColumn(8, _("Type"),          wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_TYPE,     100l));\r
        this->list_ctrl->InsertColumn(9, _("No."),           wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_NO,        35l));\r
+       this->list_ctrl->InsertColumn(10,_("Comment"),       wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_COMMENT,   35l));\r
        g_nSortColumn = this->conf.ReadId(CONF_LISTVIEW_S_COLUMN, 9l);\r
        g_fSortAscend = this->conf.ReadId(CONF_LISTVIEW_S_ASCEND, true);\r
-       this->list_ctrl->SetDropTarget(new myFileDropTarget(this));\r
 \r
        // ツールバー/ステータスバー設定。\r
        int nStatusBarParts[] = {70, 70, 180, 50, -1};\r
@@ -187,6 +202,33 @@ void MainFrame::OnInit(wxInitDialogEvent&)
        fShow = this->conf.ReadId(CONF_WINDOW_TOOLBAR, true);\r
        this->menubar->Check(XRCID("Exe_View_ToolBar"), fShow);\r
        this->toolbar->Show(fShow);\r
+\r
+       // ステータスバー上にプログレスバーを作成。\r
+       this->gFrame = new wxGauge(this->statusbar, -1, 0, wxPoint(0, 0), wxSize(200, 10));\r
+       this->gFrame->Show(false);\r
+}\r
+\r
+void MainFrame::OnClose(wxCloseEvent& e)\r
+{\r
+       if (e.CanVeto() && g_procDlg != NULL)\r
+       {\r
+               g_procDlg->OnClose(e);\r
+               e.Veto();\r
+       }\r
+       else\r
+       {\r
+               this->Destroy();\r
+       }\r
+}\r
+\r
+void MainFrame::OnSize(wxSizeEvent& e)\r
+{\r
+       // プログレスバーの位置を変更。\r
+       if (this->gFrame != NULL)\r
+       {\r
+               this->gFrame->SetPosition(wxPoint(this->statusbar->GetSize().GetWidth() - 230, 10));\r
+       }\r
+       e.Skip();\r
 }\r
 \r
 // MenuBar\r
@@ -202,22 +244,33 @@ void MainFrame::OnArcCreate(wxCommandEvent& e)
        swInfo.pCustomSwitches = NULL;\r
 \r
        // 作成ダイアログを設定。\r
-       MakeDialog mkDlg;\r
-       ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));\r
-       ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));\r
-\r
+       MakeDialog mkDlg(this, TPI_COMMAND_CREATE);\r
        if (e.GetClientData() == NULL)\r
        {\r
-               // 処理対象のファイルを選択。\r
-               wxFileDialog fd(this, _("Choose files to compress"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));\r
-               fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);\r
-               if (fd.ShowModal() == wxID_CANCEL)\r
+               if (::wxGetKeyState(WXK_SHIFT))\r
                {\r
-                       return;\r
+                       // 処理対象のフォルダを選択。\r
+                       wxDirDialog dd(this, _("Choose dir to compress"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxDD_DIR_MUST_EXIST);\r
+                       if (dd.ShowModal() == wxID_CANCEL)\r
+                       {\r
+                               return;\r
+                       }\r
+                       swInfo.fnDestinationDirectory = wxFileName(dd.GetPath());\r
+                       this->conf.WriteHistory(CONF_HISTORY_PATH, swInfo.fnDestinationDirectory.GetPath());\r
+                       mkDlg.files.Add(swInfo.fnDestinationDirectory.GetFullName());\r
+               }\r
+               else\r
+               {\r
+                       // 処理対象のファイルを選択。\r
+                       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
+                       if (fd.ShowModal() == wxID_CANCEL)\r
+                       {\r
+                               return;\r
+                       }\r
+                       fd.GetFilenames(mkDlg.files);\r
+                       swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
+                       this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
                }\r
-               swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
-               this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
-               fd.GetFilenames(mkDlg.files);\r
        }\r
        else\r
        {\r
@@ -240,62 +293,53 @@ void MainFrame::OnArcCreate(wxCommandEvent& e)
        this->fnArchive.SetPath(swInfo.fnDestinationDirectory.GetPath());\r
 \r
        // ダイアログを表示。\r
-       mkDlg.InitDialog();\r
        if (mkDlg.ShowModal() == wxID_CANCEL)\r
        {\r
                return;\r
        }\r
 \r
        // 各種設定。\r
+       int nSelected = mkDlg.chType->GetSelection();\r
+       swInfo.nArchiveType         = mkDlg.afInfo[nSelected].nTypeId;\r
        swInfo.fStoreDirectoryPathes= ! mkDlg.cbIgnorePath->IsChecked();\r
-       swInfo.fMakeSFX                     = mkDlg.cbMakeSFX->IsChecked();\r
+       swInfo.fMakeSFX             = mkDlg.cbMakeSFX->IsChecked();\r
        swInfo.fSolid               = mkDlg.cbSolid->IsChecked();\r
        swInfo.fMMOptimize          = mkDlg.cbMMOptimize->IsChecked();\r
        swInfo.fEncryptHeader       = mkDlg.cbEncryptHeader->IsChecked();\r
-       swInfo.sCompressLevel       = mkDlg.scLevel->GetValue();\r
-       swInfo.sRecoveryRecord      = mkDlg.scRR->GetValue();\r
+       swInfo.fCompressHeader      = mkDlg.cbCompressHeader->IsChecked();\r
+       swInfo.nCompressLevel       = mkDlg.scLevel->GetValue();\r
+       swInfo.nRecoveryRecord      = mkDlg.scRR->GetValue();\r
        swInfo.szPassword           = mkDlg.tcPassword->GetValue();\r
        swInfo.szKeyFile            = mkDlg.tcKeyfile->GetValue();\r
        swInfo.szComment            = mkDlg.tcComment->GetValue();\r
-       {\r
-               wxULongLong_t ll;\r
-               mkDlg.cbSplitSize->GetValue().ToULongLong(& ll);\r
-               swInfo.llSplitSize      = ll;\r
-       }\r
+       mkDlg.cbSplitSize->GetValue().ToULongLong(& swInfo.nSplitSize);\r
 \r
        // TPIを読み込み。\r
-       int nSelected = mkDlg.chType->GetSelection();\r
        this->fnArchive = wxFileName(mkDlg.cbDir->GetValue(), mkDlg.cbFileName->GetValue());\r
-       if (! tpi.InitLibrary(mkDlg.afInfo[nSelected].szTPIName, this->fnArchive.GetFullPath(), mkDlg.afInfo[nSelected].llTypeId))\r
+       swInfo.szArcName            = this->fnArchive.GetFullPath();\r
+       if (! tpi.InitLibrary(mkDlg.afInfo[nSelected].szTPIName, this->fnArchive.GetFullPath(), TPICallbackProc, mkDlg.afInfo[nSelected].nTypeId))\r
        {\r
-               ::wxLogError(_("Error: %s!"), wxT("InitLibrary()!"));\r
+               this->ErrorCheck(tpi.nErrorCode, wxT("InitLibrary"));\r
                return;\r
        }\r
 \r
-       // コールバック関数を設定。\r
-       if (! tpi.SetCallbackProc(TPICallbackProc))\r
-       {\r
-               ::wxLogError(_("Error: %s!"), wxT("SetCallbackProc()!"));\r
-       }\r
-\r
        // 処理を行う。\r
-       ProcessDialog procDlg;\r
-       procDlg.InitDialog();\r
-       procDlg.Show(true);\r
-       if (! tpi.Command(TPI_COMMAND_CREATE, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files))\r
        {\r
-               this->ErrorCheck(tpi.nErrorCode);\r
-               return;\r
+               ProcessDialog procDlg(this, mkDlg.files.GetCount());\r
+               tpi.Command(TPI_COMMAND_CREATE, & swInfo, mkDlg.files);\r
+               procDlg.Show(false);\r
+               if (this->ErrorCheck(tpi.nErrorCode) != TPI_ERROR_SUCCESS)\r
+               {\r
+                       tpi.FreeLibrary();\r
+                       return;\r
+               }\r
        }\r
-       procDlg.Show(false);\r
        tpi.FreeLibrary();\r
 \r
        if (mkDlg.cbOpenAfter->IsChecked())\r
        {\r
                // 作成先を開く。\r
-#ifdef __WINDOWS__\r
-               ::wxExecute(wxT("explorer ") + swInfo.fnDestinationDirectory.GetFullPath());\r
-#endif\r
+               ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
        }\r
 \r
        if (mkDlg.cbExitAfter->IsChecked())\r
@@ -305,17 +349,22 @@ void MainFrame::OnArcCreate(wxCommandEvent& e)
        }\r
 \r
        // 終了しない場合は書庫を開く。\r
-       this->OnArcOpen(e);\r
+       if (this->fnArchive.FileExists())\r
+       {\r
+               e.SetInt(1);\r
+               this->OnArcOpen(e);\r
+       }\r
 }\r
 \r
 void MainFrame::OnArcOpen(wxCommandEvent& e)\r
 {\r
+       // モード取得。通常は0, それ以外で開く場合は1, ファイルDnDなら2。\r
+       int nMode = e.GetInt();\r
+\r
        // 書庫を選択。\r
-       if (e.GetId() == XRCID("Arc_Open"))\r
+       if (nMode == 0)\r
        {\r
-               wxFileDialog fd(this);\r
-               fd.SetDirectory(this->conf.ReadHistory(CONF_HISTORY_PATH, 0));\r
-               fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
+               wxFileDialog fd(this, _("Choose an archive"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
                if (fd.ShowModal() == wxID_CANCEL)\r
                {\r
                        return;\r
@@ -323,41 +372,51 @@ void MainFrame::OnArcOpen(wxCommandEvent& e)
                this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
                this->fnArchive = wxFileName(fd.GetPath());\r
        }\r
-       this->OnArcClose(e);\r
 \r
-       // 進捗ダイアログ表示。\r
-       ProcessDialog procDlg;\r
-       procDlg.InitDialog();\r
-       procDlg.Show(true);\r
-\r
-       // TPIを読み込み、最初のコールバックを送信。\r
+       // TPIを読み込み。\r
+       ProcessDialog procDlg(this);\r
        TPI_PROCESSINFO piInfo;\r
-       piInfo.uMessage = TPI_MESSAGE_STATUS;\r
-       piInfo.uStatus = 0x1000;\r
-       piInfo.llProcessedSize = 0;\r
-       piInfo.fiInfo.fnFileName = this->fnArchive;\r
-       piInfo.fiInfo.llUnpackedSize = this->LoadTPI(this->fnArchive.GetFullPath());\r
-       if (piInfo.fiInfo.llUnpackedSize.ToULong() == 0)\r
+       piInfo.fiInfo.nUnpackedSize = 0;\r
+       if (! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))\r
        {\r
-               procDlg.Show(false);\r
-               tpi.FreeLibrary();\r
-               ::wxLogError(_("No plug-in supporting this archive was found!"));\r
+               if (nMode == 2)\r
+               {\r
+                       // DnDの場合は書庫を作成する。\r
+                       this->OnArcCreate(e);\r
+               }\r
+               else if (this->IsShown())\r
+               {\r
+                       wxBell();\r
+                       this->statusbar->SetStatusText(_("No plug-in supporting this archive was found!"), 4);\r
+               }\r
+               else\r
+               {\r
+                       wxLogError(_("No plug-in supporting this archive was found!"));\r
+                       this->Close(true);\r
+               }\r
                return;\r
        }\r
-       TPICallbackProc(TPI_NOTIFY_COMMON, & piInfo);\r
 \r
-       // 配列のサイズを確保。\r
-       this->fileinfo.Alloc(piInfo.fiInfo.llUnpackedSize.ToULong());\r
+       // コマンドラインから書庫を開く場合にはウインドウが表示されていないので表示。\r
+       if (! this->IsShown())\r
+       {\r
+               this->Show();\r
+       }\r
 \r
-       // 書庫を開く。\r
-       if (! tpi.OpenArchive(this->fnArchive.GetFullPath()))\r
+       piInfo.eMessage = TPI_MESSAGE_STATUS;\r
+       piInfo.eStatus = 0x1001;\r
+       if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo), wxT("Callback")) == TPI_CALLBACK_CANCEL)\r
        {\r
                procDlg.Show(false);\r
-               tpi.FreeLibrary();\r
-               ::wxLogError(_("Error: %s!"), wxT("OpenArchive()"));\r
+               tpi.CloseArchive();\r
+               // OnArcClose処理はProcessDialogのデストラクタで行う。\r
+               // this->OnArcClose(e);\r
                return;\r
        }\r
 \r
+       // 配列のサイズを確保。\r
+       this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);\r
+\r
        // 履歴に追加。\r
        this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());\r
        this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());\r
@@ -368,125 +427,194 @@ void MainFrame::OnArcOpen(wxCommandEvent& e)
        g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));\r
        this->tree_ctrl->SetImageList(& g_hIconT);\r
        wxTreeItemId\r
-               idRoot = this->tree_ctrl->AddRoot(wxEmptyString),\r
-#ifdef __WINDOWS__\r
-               idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName))),\r
-#else\r
-               idArchive = this->tree_ctrl->AppendItem(idRoot, piInfo.fiInfo.fnFileName.GetFullName(), g_hIconT.Add(GetFileTypeIcon(piInfo.fiInfo.fnFileName).ConvertToImage().Rescale(16, 16))),\r
-#endif\r
+               idRoot    = this->tree_ctrl->AddRoot(wxEmptyString),\r
+               idArchive = this->tree_ctrl->AppendItem(idRoot, this->fnArchive.GetFullName(), g_hIconT.Add(myRescaleIcon(GetFileTypeIcon(this->fnArchive)))),\r
                idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);\r
 \r
+       // 巨大書庫のときにファイル名検査を省略するか。\r
+       bool bDTVCheck = piInfo.fiInfo.nUnpackedSize < 10000 || AskDlg(_("This archive contains so many files that it takes long to check Directory Traversal Vulnerability(DTV) problem. If you are sure this archive is safe, you can skip this scanning process. Do you want to scan for DTV problem?"), this) == wxNO;\r
+\r
        // ファイル情報をロード。\r
        if (tpi.GetFileInformation(& piInfo.fiInfo, true))\r
        {\r
-               piInfo.uStatus = 0x1001;\r
+               piInfo.eStatus = 0x1002;\r
+               piInfo.nProcessedSize = 0;\r
                do\r
                {\r
-                       piInfo.llProcessedSize++;\r
-                       if (this->ErrorCheck(TPICallbackProc(TPI_NOTIFY_COMMON, & piInfo)) == TPI_CALLBACK_CANCEL)\r
+                       piInfo.nProcessedSize++;\r
+                       if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo), wxT("Callback")) == TPI_CALLBACK_CANCEL)\r
                        {\r
                                procDlg.Show(false);\r
                                tpi.CloseArchive();\r
-                               wxCommandEvent e;\r
-                               this->OnArcClose(e);\r
+                               // OnArcClose処理はProcessDialogのデストラクタで行う。\r
+                               // this->OnArcClose(e);\r
                                return;\r
                        }\r
 \r
-                       // ツリービューに反映。\r
-                       TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, piInfo.fiInfo.fnFileName.GetPath(), true);\r
-\r
-                       // ディレクトリ属性を含むものについては除去。\r
-                       if (piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY)\r
+                       // 拡張子のみ設定されている場合。\r
+                       if (piInfo.fiInfo.szStoredName.IsEmpty())\r
                        {\r
-                               continue;\r
+                               piInfo.fiInfo.szStoredName = this->fnArchive.GetName();\r
+                               if (piInfo.fiInfo.fnFileName.HasExt())\r
+                               {\r
+                                       piInfo.fiInfo.szStoredName += wxT('.') + piInfo.fiInfo.fnFileName.GetExt();\r
+                               }\r
+                               piInfo.fiInfo.fnFileName = wxFileName(piInfo.fiInfo.szStoredName);\r
                        }\r
 \r
                        // セキュリティチェック。\r
-                       // DTV検査。\r
-                       if (piInfo.fiInfo.fnFileName.GetPathWithSep().Find(wxT("..")) != wxNOT_FOUND)\r
+                       // ルート記号を削除。\r
+                       wxString szPath = piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX);\r
+                       if (szPath.StartsWith(wxT("/")) || szPath.StartsWith(wxT("./")))\r
+                       {\r
+                               piInfo.fiInfo.fnFileName = wxFileName(szPath.AfterFirst(wxT('/')), piInfo.fiInfo.fnFileName.GetFullName(), wxPATH_DOS);\r
+                       }\r
+                       // ルートメンバの情報は無視する。\r
+                       if (piInfo.fiInfo.fnFileName.GetFullPath().IsEmpty() || piInfo.fiInfo.fnFileName.GetFullPath() == wxT("."))\r
                        {\r
-                               piInfo.fiInfo.uDanger = TRUE;\r
-                               ::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
+                               continue;\r
                        }\r
-                       // 空白の連続による拡張子偽装を検査。\r
-                       if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT("        ")) != wxNOT_FOUND)\r
+\r
+                       // 改行文字/タブ文字などを削除。\r
+                       if (piInfo.fiInfo.szStoredName.Find(wxT('\r')) != wxNOT_FOUND\r
+                       ||  piInfo.fiInfo.szStoredName.Find(wxT('\n')) != wxNOT_FOUND\r
+                       ||  piInfo.fiInfo.szStoredName.Find(wxT('\t')) != wxNOT_FOUND)\r
                        {\r
-                               piInfo.fiInfo.uDanger = TRUE;\r
-                               ::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
+                               wxString sz = piInfo.fiInfo.fnFileName.GetFullPath();\r
+                               sz.Replace(wxT("\r"), wxT(" "));\r
+                               sz.Replace(wxT("\n"), wxT(" "));\r
+                               sz.Replace(wxT("\t"), wxT(" "));\r
+                               piInfo.fiInfo.eDanger = TRUE;\r
+                               piInfo.fiInfo.fnFileName = wxFileName(sz);\r
+                               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
                        }\r
-                       // Unicode制御文字を検査。\r
-                       for (wxChar c = 0x200c; c <= 0x206f; c++)\r
+\r
+                       if (bDTVCheck)\r
                        {\r
-                               if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)\r
+                               // DTV検査。\r
+                               if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)\r
                                {\r
-                                       piInfo.fiInfo.uDanger = TRUE;\r
-                                       ::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
+                                       piInfo.fiInfo.eDanger = TRUE;\r
+                                       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
                                }\r
-                               switch (c)\r
+                               // 空白の連続による拡張子偽装を検査。\r
+                               if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT("        ")) != wxNOT_FOUND)\r
                                {\r
-                               case 0x200f: c = 0x2027; break;\r
-                               case 0x202e: c = 0x2060; break;\r
+                                       piInfo.fiInfo.eDanger = TRUE;\r
+                                       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
                                }\r
+                               // Unicode制御文字を検査。\r
+                               for (wxChar c = 0x200c; c <= 0x206f; c++)\r
+                               {\r
+                                       if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)\r
+                                       {\r
+                                               piInfo.fiInfo.eDanger = TRUE;\r
+                                               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
+                                       }\r
+                                       switch (c)\r
+                                       {\r
+                                       case 0x200f: c = 0x2027; break;\r
+                                       case 0x202e: c = 0x2060; break;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       // ツリービューに反映。\r
+                       bool fDir = piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? true : false;\r
+                       TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, fDir ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetPath(), true);\r
+\r
+                       // ディレクトリ属性を含むものについては情報を保存しない。\r
+                       if (fDir)\r
+                       {\r
+                               continue;\r
                        }\r
 \r
                        // 情報を保存してカウントアップ。\r
                        this->fileinfo.Add(piInfo.fiInfo);\r
                }\r
-               while (tpi.GetFileInformation(& piInfo.fiInfo, false));\r
+               while (tpi.GetFileInformation(& piInfo.fiInfo));\r
        }\r
 \r
        // GetFileInformationがエラー終了した場合。\r
-       if (tpi.nErrorCode != TPI_ERROR_S_ENDOFDATA)\r
-       {\r
-               ::wxLogError(_("Error: %s!"), wxT("GetFileInformation()"));\r
-       }\r
+       this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));\r
 \r
        // 書庫の情報を取得。\r
-       if (! tpi.GetArchiveInformation(& this->aiArchive))\r
-       {\r
-               ::wxLogError(_("Error: %s!"), wxT("GetArchiveInformation()"));\r
-       }\r
+       tpi.GetArchiveInformation(& this->aiArchive);\r
+       this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));\r
+       this->szPassword = procDlg.szPassword;\r
 \r
-       // 書庫を閉じる。\r
-       if (! tpi.CloseArchive())\r
+       // Command()でハンドルを用いない場合は、ここで書庫を閉じる。\r
+       if (! tpi.bHandleOnCommand)\r
        {\r
-               ::wxLogError(_("Error: %s!"), wxT("CloseArchive()"));\r
+               tpi.CloseArchive();\r
+               this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));\r
        }\r
 \r
        // 以下、UI処理。\r
        this->fileinfo.Shrink();\r
-       this->tree_ctrl->ExpandAll();\r
+       if (this->fileinfo.Count() < 10000)\r
+       {\r
+               this->tree_ctrl->ExpandAll();\r
+               this->tree_ctrl->SelectItem(idArchive);\r
+       }\r
+       else\r
+       {\r
+               // ファイル数が多いとソートに時間がかかるので、書庫のルートを表示させる。\r
+               this->tree_ctrl->Expand(idArcRoot);\r
+               this->tree_ctrl->SelectItem(idArcRoot);\r
+       }\r
+       // ツリービューの位置合わせ。\r
        this->tree_ctrl->ScrollTo(idArchive);\r
-       this->tree_ctrl->SelectItem(idArchive);\r
+       this->tree_ctrl->SetScrollPos(wxHORIZONTAL, 0);\r
        this->list_ctrl->atDangerItem.SetTextColour(* wxRED);\r
        this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));\r
 \r
        // ステータスバー設定。\r
        this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);\r
-       this->statusbar->SetStatusText(wxString::Format(_("%d file(s)"), this->fileinfo.GetCount()), 1);\r
-       this->statusbar->SetStatusText(this->aiArchive.llUnpackedSize.ToString() + _(" B -> ") + this->aiArchive.llPackedSize.ToString() + _(" B"), 2);\r
+       this->statusbar->SetStatusText(wxString::Format(_("%u file(s)"), this->fileinfo.GetCount()), 1);\r
+       this->statusbar->SetStatusText(wxString::Format(wxString("%" wxLongLongFmtSpec "uB -> %" wxLongLongFmtSpec "uB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);\r
        this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);\r
        this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);\r
-\r
-       // ツールバー・メニューバー設定。\r
+       this->statusbar->SetToolTip(\r
+               wxString::Format(\r
+                       _("%s(%s)\nTPI: %s(%s)\nAccess: %s\nModify: %s\nCreate: %s\nComment:\n%s"),\r
+                       this->fnArchive.GetFullName().c_str(), this->aiArchive.fiInfo.szTypeName.c_str(),\r
+                       this->aiArchive.fiInfo.szTPIName.c_str(), this->aiArchive.fiInfo.szEngineName.c_str(),\r
+                       this->aiArchive.tmAccess.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
+                       this->aiArchive.tmModify.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
+                       this->aiArchive.tmCreate.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
+                       this->aiArchive.szComment.c_str()\r
+               )\r
+       );\r
+\r
+       // ツールバー・メニューバー設定。ファイル選択時しか動作しない削除などは別に設定。\r
        SetMenuToolState("Arc_Close",   true);\r
-       SetMenuToolState("Arc_Add",     (this->aiArchive.fiInfo.llSupportedCommand & TPI_COMMAND_ADD)   == TPI_COMMAND_ADD   && this->aiArchive.fiInfo.fArchive);\r
-       SetMenuToolState("Arc_SFX",     (this->aiArchive.fiInfo.llSupportedCommand & TPI_COMMAND_SFX)    == TPI_COMMAND_SFX   && this->aiArchive.nSFXType == 0);\r
-       SetMenuToolState("Arc_UnSFX",   (this->aiArchive.fiInfo.llSupportedCommand & TPI_COMMAND_UNSFX)  == TPI_COMMAND_UNSFX && this->aiArchive.nSFXType != 0);\r
-       SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.llSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);\r
-       SetMenuToolState("Arc_Delete",  (this->aiArchive.fiInfo.llSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);\r
-       SetMenuToolState("Arc_Test",    (this->aiArchive.fiInfo.llSupportedCommand & TPI_COMMAND_TEST)   == TPI_COMMAND_TEST);\r
-       SetMenuToolState("Arc_Repair",  (this->aiArchive.fiInfo.llSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);\r
+       SetMenuToolState("Arc_Add",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD)    == TPI_COMMAND_ADD   &&   this->aiArchive.fiInfo.fArchive);\r
+       SetMenuToolState("Arc_SFX",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX)    == TPI_COMMAND_SFX   && ! this->aiArchive.fSFX);\r
+       SetMenuToolState("Arc_UnSFX",   (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX)  == TPI_COMMAND_UNSFX &&   this->aiArchive.fSFX);\r
+       SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);\r
+       SetMenuToolState("Arc_Test",    (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST)   == TPI_COMMAND_TEST);\r
+       SetMenuToolState("Arc_Repair",  (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);\r
+       this->menubar->Enable(XRCID("Arc_Clone"), true);\r
+\r
+       // タイトルバー設定。\r
+       this->SetTitle(this->fnArchive.GetFullName() + wxT(" - Lychee"));\r
 \r
        procDlg.Show(false);\r
+       this->Raise();\r
 }\r
 \r
-void MainFrame::OnArcClose(wxCommandEvent&)\r
+void MainFrame::OnArcClose(wxCommandEvent& e)\r
 {\r
+       if (tpi.bHandleOnCommand)\r
+       {\r
+               tpi.CloseArchive();\r
+       }\r
+\r
        // ツリービュー・リストビュー設定。\r
        this->tree_ctrl->DeleteAllItems();\r
        this->list_ctrl->DeleteAllItems();\r
-       this->list_ctrl->showFileInfo.Clear();\r
+       this->list_ctrl->apShowFile.Clear();\r
 \r
        // ツールバー・メニューバー設定。\r
        SetMenuToolState("Arc_Close",   false);\r
@@ -497,80 +625,133 @@ void MainFrame::OnArcClose(wxCommandEvent&)
        SetMenuToolState("Arc_Delete",  false);\r
        SetMenuToolState("Arc_Test",    false);\r
        SetMenuToolState("Arc_Repair",  false);\r
+       this->menubar->Enable(XRCID("Arc_Clone"), false);\r
 \r
        for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)\r
        {\r
                this->statusbar->SetStatusText(wxEmptyString, i);\r
        }\r
+       this->statusbar->SetToolTip(wxEmptyString);\r
        this->fileinfo.Clear();\r
-       this->aiArchive.szComment.Clear();\r
+       this->szPassword.Empty();\r
+       this->aiArchive.szComment.Empty();\r
        this->aiArchive.fnArchive.Clear();\r
-       this->aiArchive.fiInfo.szTypeName.Clear();\r
-       this->aiArchive.fiInfo.szSuffix.Clear();\r
-       this->aiArchive.fiInfo.szEngineName.Clear();\r
-       this->aiArchive.fiInfo.szTPIName.Clear();\r
+       this->aiArchive.fiInfo.szTypeName.Empty();\r
+       this->aiArchive.fiInfo.szSuffix.Empty();\r
+       this->aiArchive.fiInfo.szEngineName.Empty();\r
+       this->aiArchive.fiInfo.szTPIName.Empty();\r
 \r
        g_hIconT.RemoveAll();\r
        g_hIconLL.RemoveAll();\r
        g_hIconLS.RemoveAll();\r
-       this->tpi.FreeLibrary();\r
+\r
+       // タイトルバー設定。\r
+       this->SetTitle(wxT("Lychee"));\r
+\r
+       // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。\r
+       if (e.GetExtraLong() == 0)\r
+       {\r
+               tpi.FreeLibrary();\r
+       }\r
 }\r
 \r
-void MainFrame::OnArcAdd(wxCommandEvent& e)\r
+void MainFrame::OnArcClone(wxCommandEvent&)\r
 {\r
-       // 作成ダイアログを設定。\r
-       MakeDialog mkDlg;\r
-       ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));\r
-       ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));\r
-       mkDlg.uCommand = TPI_COMMAND_ADD;\r
-\r
-       // 処理対象のファイルを選択。\r
-       wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));\r
-       fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);\r
+       // 保存先を尋ねる。\r
+       wxFileDialog fd(this, _("Clone archive"), this->fnArchive.GetPath(), this->fnArchive.GetFullName(), wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
        if (fd.ShowModal() == wxID_CANCEL)\r
        {\r
                return;\r
        }\r
-       fd.GetFilenames(mkDlg.files);\r
        this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
 \r
+       // コピー。\r
+       ::wxCopyFile(this->fnArchive.GetFullPath(), fd.GetPath());\r
+       wxFileName fn(fd.GetPath());\r
+       wxDateTime dtAccess, dtModify, dtCreate;\r
+       this->fnArchive.GetTimes(& dtAccess, & dtModify, & dtCreate);\r
+       fn.SetTimes(& dtAccess, & dtModify, & dtCreate);\r
+}\r
+\r
+void MainFrame::OnArcAdd(wxCommandEvent& e)\r
+{\r
+       // 作成ダイアログを設定。\r
+       MakeDialog mkDlg(this, TPI_COMMAND_ADD);\r
+\r
+       TPI_SWITCHES swInfo;\r
+       swInfo.pCustomSwitches       = NULL;\r
+\r
+       if (e.GetClientData() == NULL)\r
+       {\r
+               if (::wxGetKeyState(WXK_SHIFT))\r
+               {\r
+                       // 処理対象のフォルダを選択。\r
+                       wxDirDialog dd(this, _("Choose dir to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxDD_DIR_MUST_EXIST);\r
+                       if (dd.ShowModal() == wxID_CANCEL)\r
+                       {\r
+                               return;\r
+                       }\r
+                       swInfo.fnDestinationDirectory = wxFileName(dd.GetPath());\r
+                       this->conf.WriteHistory(CONF_HISTORY_PATH, swInfo.fnDestinationDirectory.GetPath());\r
+                       mkDlg.files.Add(swInfo.fnDestinationDirectory.GetFullName());\r
+               }\r
+               else\r
+               {\r
+                       // 処理対象のファイルを選択。\r
+                       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
+                       if (fd.ShowModal() == wxID_CANCEL)\r
+                       {\r
+                               return;\r
+                       }\r
+                       fd.GetFilenames(mkDlg.files);\r
+                       swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
+                       this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
+               }\r
+       }\r
+       else\r
+       {\r
+               mkDlg.files = * (wxArrayString *) e.GetClientData();\r
+               swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());\r
+               // 相対パスに変換。\r
+               for (size_t n = 0; n < mkDlg.files.GetCount(); n++)\r
+               {\r
+                       wxFileName fn(mkDlg.files[n]);\r
+                       fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());\r
+                       mkDlg.files[n] = fn.GetFullPath();\r
+               }\r
+       }\r
+\r
        // ダイアログを表示。\r
-       mkDlg.InitDialog();\r
        if (mkDlg.ShowModal() == wxID_CANCEL)\r
        {\r
                return;\r
        }\r
 \r
        // 各種設定。\r
-       TPI_SWITCHES swInfo;\r
-       swInfo.pCustomSwitches       = NULL;\r
-       swInfo.fMakeSFX              = false;\r
-       swInfo.fnDestinationDirectory= wxFileName::DirName(fd.GetDirectory());\r
-       swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();\r
+       swInfo.szArcName            = this->fnArchive.GetFullPath();\r
+       swInfo.fMakeSFX             = false;\r
+       swInfo.fStoreDirectoryPathes= ! mkDlg.cbIgnorePath->IsChecked();\r
        swInfo.fSolid               = mkDlg.cbSolid->IsChecked();\r
        swInfo.fMMOptimize          = mkDlg.cbMMOptimize->IsChecked();\r
        swInfo.fEncryptHeader       = mkDlg.cbEncryptHeader->IsChecked();\r
-       swInfo.sCompressLevel       = mkDlg.scLevel->GetValue();\r
-       swInfo.sRecoveryRecord      = mkDlg.scRR->GetValue();\r
+       swInfo.nCompressLevel       = mkDlg.scLevel->GetValue();\r
+       swInfo.nRecoveryRecord      = mkDlg.scRR->GetValue();\r
        swInfo.szPassword           = mkDlg.tcPassword->GetValue();\r
        swInfo.szKeyFile            = mkDlg.tcKeyfile->GetValue();\r
        swInfo.szComment            = mkDlg.tcComment->GetValue();\r
 \r
-       ProcessDialog procDlg;\r
-       procDlg.InitDialog();\r
-       procDlg.Show(true);\r
-       if (! this->tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files))\r
+       // 処理を行う。\r
        {\r
+               ProcessDialog procDlg(this, mkDlg.files.GetCount(), this->szPassword);\r
+               tpi.Command(TPI_COMMAND_ADD, & swInfo, mkDlg.files);\r
                this->ErrorCheck(tpi.nErrorCode);\r
+               procDlg.Show(false);\r
        }\r
-       procDlg.Show(false);\r
 \r
        if (mkDlg.cbOpenAfter->IsChecked())\r
        {\r
                // 作成先を開く。\r
-#ifdef __WINDOWS__\r
-               ::wxExecute(wxT("explorer ") + swInfo.fnDestinationDirectory.GetFullPath());\r
-#endif\r
+               ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
        }\r
 \r
        if (mkDlg.cbExitAfter->IsChecked())\r
@@ -580,17 +761,18 @@ void MainFrame::OnArcAdd(wxCommandEvent& e)
        }\r
 \r
        // 終了しない場合は書庫を再読み込み。\r
+       e.SetInt(1);\r
        this->OnArcOpen(e);\r
 }\r
 \r
 void MainFrame::OnArcConvert(wxCommandEvent& e)\r
 {\r
        TPI_SWITCHES swInfo;\r
-       swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");\r
+       swInfo.szArcName            = this->fnArchive.GetFullPath();\r
+       swInfo.fMakeSFX             = e.GetId() == XRCID("Arc_SFX");\r
 \r
        // 保存先を尋ねる。\r
-       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
-       fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
+       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
        if (fd.ShowModal() == wxID_CANCEL)\r
        {\r
                return;\r
@@ -601,51 +783,35 @@ void MainFrame::OnArcConvert(wxCommandEvent& e)
        wxArrayString files;\r
        files.Add(fd.GetPath());\r
 \r
-       ProcessDialog procDlg;\r
-       procDlg.InitDialog();\r
-       procDlg.Show(true);\r
-       if (! this->tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files))\r
-       {\r
-               this->ErrorCheck(tpi.nErrorCode);\r
-       }\r
+       ProcessDialog procDlg(this);\r
+       tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, files);\r
+       this->ErrorCheck(tpi.nErrorCode);\r
        procDlg.Show(false);\r
 }\r
 \r
 void MainFrame::OnArcExtract(wxCommandEvent& e)\r
 {\r
        TPI_SWITCHES swInfo;\r
-       swInfo.pCustomSwitches = NULL;\r
+       swInfo.szArcName            = this->fnArchive.GetFullPath();\r
+       swInfo.pCustomSwitches      = NULL;\r
+       swInfo.szPassword           = this->szPassword;\r
 \r
-       // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3。\r
+       // ã\83¢ã\83¼ã\83\89å\8f\96å¾\97ã\80\82é\80\9a常ã\81¯0, å®\9fè¡\8cã\81ªã\82\891, ã\83\95ã\82¡ã\82¤ã\83«DnDã\81ªã\82\89\80\81ã\83\87ã\82£ã\83¬ã\82¯ã\83\88ã\83ªDnDã\81ªã\82\89\80\81ã\82¯ã\83ªã\83\83ã\83\97ã\83\9cã\83¼ã\83\89ã\81ªã\82\89\80\81ã\82³ã\83³ã\83\86ã\82­ã\82¹ã\83\88ã\83¡ã\83\8bã\83¥ã\83¼ã\81\8bã\82\89ã\81ªã\82\89\80\82\r
        int nMode = e.GetInt();\r
+       if (e.GetInt() == 8)\r
+       {\r
+               nMode = 0;\r
+       }\r
        // 実行時のみ使用。\r
        wxFileType * ftFile = NULL;\r
 \r
        // 展開ダイアログを作成。DnDまたは実行時は表示しない。\r
-       MakeDialog mkDlg;\r
-       ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_make.xrc"));\r
-       ::wxXmlResource::Get()->LoadDialog(& mkDlg, this, wxT("dlg_make"));\r
-       mkDlg.uCommand = TPI_COMMAND_EXTRACT;\r
-       mkDlg.files    = MakeTargetFileList(this, nMode == 1);\r
+       MakeDialog mkDlg(this, TPI_COMMAND_EXTRACT);\r
+       mkDlg.files    = MakeTargetFileList(this, nMode == 1, nMode == 0);\r
 \r
+       bool bMakeDir = false;\r
        if (nMode != 0)\r
        {\r
-               if (nMode == 1)\r
-               {\r
-                       // コマンドを取得。\r
-                       ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0]).GetExt());\r
-                       if (! ftFile)\r
-                       {\r
-                               // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。\r
-                               ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));\r
-                               if (! ftFile)\r
-                               {\r
-                                       ::wxLogError(_("Unable to get the file type!"));\r
-                                       return;\r
-                               }\r
-                       }\r
-               }\r
-\r
                // 作業ディレクトリ作成。\r
                swInfo.fStoreDirectoryPathes = false;\r
                wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");\r
@@ -654,16 +820,15 @@ void MainFrame::OnArcExtract(wxCommandEvent& e)
                        // 書庫ルートのときは書庫名にしておく。\r
                        szDestDirBase = this->fnArchive.GetName();\r
                }\r
-               swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(::wxGetCwd()), szDestDirBase, true);\r
+               swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(wxStandardPaths::Get().GetTempDir()), szDestDirBase, true);\r
                if (! swInfo.fnDestinationDirectory.IsOk())\r
                {\r
-                       ::wxLogError(_("Unable to make the temporary directory!"));\r
+                       wxLogError(_("Unable to make the temporary directory!"));\r
                        return;\r
                }\r
        }\r
        else\r
        {\r
-               mkDlg.InitDialog();\r
                if (mkDlg.ShowModal() == wxID_CANCEL)\r
                {\r
                        return;\r
@@ -676,34 +841,40 @@ void MainFrame::OnArcExtract(wxCommandEvent& e)
                swInfo.szKeyFile  = mkDlg.tcKeyfile->GetValue();\r
 \r
                // 必要なら書庫名でディレクトリを作成する。\r
-               if (WillMakeDirByArcName(this, & mkDlg))\r
+               bMakeDir = WillMakeDirByArcName(this, & mkDlg);\r
+               if (bMakeDir)\r
                {\r
                        swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);\r
                        if (! swInfo.fnDestinationDirectory.IsOk())\r
                        {\r
-                               ::wxLogError(_("Unable to make the destination directory!"));\r
+                               wxLogError(_("Unable to make the destination directory!"));\r
                                return;\r
                        }\r
                }\r
        }\r
 \r
-       ProcessDialog procDlg;\r
-       procDlg.InitDialog();\r
-       procDlg.Show(true);\r
-       if (! this->tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files))\r
+       // 処理を行う。\r
        {\r
+               ProcessDialog procDlg(this, mkDlg.files.GetCount(), this->szPassword);\r
+               tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, mkDlg.files);\r
                this->ErrorCheck(tpi.nErrorCode);\r
+               procDlg.Show(false);\r
        }\r
-       procDlg.Show(false);\r
 \r
        if (nMode == 0)\r
        {\r
                if (mkDlg.cbOpenAfter->IsChecked())\r
                {\r
                        // 展開先を開く。\r
-#ifdef __WINDOWS__\r
-                       ::wxExecute(wxT("explorer ") + swInfo.fnDestinationDirectory.GetFullPath());\r
-#endif\r
+                       if (mkDlg.chDirMake->GetSelection() == 2 && ! bMakeDir)\r
+                       {\r
+                               wxTreeItemId tiArcSub = this->tree_ctrl->GetLastChild(this->tree_ctrl->GetLastChild(this->tree_ctrl->GetRootItem()));\r
+                               if (tiArcSub.IsOk())\r
+                               {\r
+                                       swInfo.fnDestinationDirectory.SetFullName(this->tree_ctrl->GetItemText(tiArcSub));\r
+                               }\r
+                       }\r
+                       ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
                }\r
 \r
                if (mkDlg.cbExitAfter->IsChecked())\r
@@ -714,57 +885,92 @@ void MainFrame::OnArcExtract(wxCommandEvent& e)
        }\r
        else\r
        {\r
-               wxArrayString asFiles;\r
                if (nMode == 1)\r
                {\r
+                       // コマンドを取得。\r
+                       ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());\r
+                       if (! ftFile || ftFile->GetOpenCommand(wxEmptyString).IsEmpty())\r
+                       {\r
+                               // 種類が取得できないときはテキストとみなす。\r
+                               ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));\r
+                       }\r
+\r
                        // コマンドを実行。\r
-                       asFiles.Add(swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0]).GetFullName());\r
-                       if (tpi.nErrorCode == TPI_ERROR_SUCCESS)\r
+                       wxString szTempFile = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName();\r
+                       bool fSuccess = tpi.nErrorCode == TPI_ERROR_SUCCESS && ftFile != NULL;\r
+                       myProcess * pCallback = new myProcess(szTempFile, swInfo.fnDestinationDirectory.GetPath());\r
+                       if (fSuccess)\r
                        {\r
 #ifdef __LINUX__\r
                                // Linuxでは引用符で囲む必要がある。\r
-                               ::wxExecute(ftFile->GetOpenCommand(wxT('"') + asFiles[0] + wxT('"')), wxEXEC_SYNC);\r
+                               fSuccess = ::wxExecute(ftFile->GetOpenCommand(QuoteString(szTempFile)), wxEXEC_ASYNC, pCallback) > 0;\r
 #else\r
-                               ::wxExecute(ftFile->GetOpenCommand(asFiles[0]), wxEXEC_SYNC);\r
+                               fSuccess = ::wxExecute(ftFile->GetOpenCommand(szTempFile), wxEXEC_ASYNC, pCallback) > 0;\r
 #endif\r
                        }\r
+                       if (! fSuccess)\r
+                       {\r
+                               pCallback->OnTerminate(0, 0);\r
+                       }\r
                }\r
                else\r
                {\r
                        // 展開対象を決定。\r
-                       wxFileDataObject objFile;\r
+                       wxArrayString asFiles;\r
+                       myFileDataObject * objFile = new myFileDataObject();\r
+                       objFile->szTempDir = nMode == 3 ? swInfo.fnDestinationDirectory.GetPath() : swInfo.fnDestinationDirectory.GetFullPath();\r
                        for (size_t i = 0; i < mkDlg.files.GetCount(); i++)\r
                        {\r
-                               wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i]).GetFullName();\r
-                               if (nMode == 2)\r
+                               wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();\r
+                               if (nMode == 3)\r
+                               {\r
+                                       asFiles.Add(szFileName);\r
+                               }\r
+                               else\r
                                {\r
                                        // リストに追加。\r
-                                       objFile.AddFile(szFileName);\r
+                                       objFile->AddFile(szFileName);\r
                                }\r
-                               asFiles.Add(szFileName);\r
                        }\r
                        if (nMode == 3)\r
                        {\r
-                               objFile.AddFile(swInfo.fnDestinationDirectory.GetPath());\r
+                               objFile->AddFile(objFile->szTempDir);\r
                        }\r
 \r
-                       // DnD開始。\r
-                       wxDropSource dropSource(objFile, this);\r
-                       if (dropSource.DoDragDrop() != wxDragMove)\r
+                       if (nMode == 4)\r
+                       {\r
+                               wxTheClipboard->SetData(objFile);\r
+                       }\r
+                       else\r
                        {\r
+                               // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。\r
+                               this->SetDropTarget(NULL);\r
+\r
+                               // DnD開始。\r
+                               wxDropSource dropSource(* objFile, this);\r
+                               wxDragResult drResult = dropSource.DoDragDrop();\r
+                               if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)\r
+                               {\r
 #ifdef __LINUX__\r
-                               // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。\r
-                               sleep(3);\r
+                                       // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。\r
+                                       sleep(3);\r
 #endif\r
-                       }\r
-               }\r
+                               }\r
+                               this->SetDropTarget(new myFileDropTarget(this));\r
 \r
-               // ファイルと一時ディレクトリを削除。\r
-               for (size_t i = 0; i < asFiles.GetCount(); i++)\r
-               {\r
-                       ::wxRemoveFile(asFiles[i]);\r
+                               // ディレクトリDnDのときは、先にディレクトリの中のファイルを消しておく。\r
+                               if (nMode == 3)\r
+                               {\r
+                                       for (size_t i = 0; i < asFiles.GetCount(); i++)\r
+                                       {\r
+                                               chmod(asFiles[i].ToUTF8(), 0600);\r
+                                               ::wxRemoveFile(asFiles[i]);\r
+                                       }\r
+                               }\r
+\r
+                               delete objFile;\r
+                       }\r
                }\r
-               ::wxRmdir(swInfo.fnDestinationDirectory.GetFullPath());\r
        }\r
 }\r
 \r
@@ -773,58 +979,76 @@ void MainFrame::OnArcDelete(wxCommandEvent& e)
        // 全ファイル削除は危険ではないかと。\r
        if (this->list_ctrl->GetSelectedItemCount() == 0)\r
        {\r
+               // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
+               SetMenuToolState("Arc_Delete", false);\r
                return;\r
        }\r
 \r
-       if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)\r
+       if (AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)\r
        {\r
                return;\r
        }\r
 \r
-       // 各種設定。\r
-       TPI_SWITCHES swInfo;\r
-       ProcessDialog procDlg;\r
-       procDlg.InitDialog();\r
-       procDlg.Show(true);\r
-       if (! this->tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), MakeTargetFileList(this, false)))\r
+       // 処理を行う。\r
        {\r
+               wxArrayString asFiles = MakeTargetFileList(this);\r
+               ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
+               TPI_SWITCHES swInfo;\r
+               swInfo.szArcName  = this->fnArchive.GetFullPath();\r
+               swInfo.szPassword = this->szPassword;\r
+               tpi.Command(TPI_COMMAND_DELETE, & swInfo, asFiles);\r
                this->ErrorCheck(tpi.nErrorCode);\r
+               procDlg.Show(false);\r
        }\r
-       procDlg.Show(false);    \r
 \r
        // 書庫を再読み込みする。\r
+       e.SetInt(1);\r
        this->OnArcOpen(e);\r
 }\r
 \r
 void MainFrame::OnArcTest(wxCommandEvent&)\r
 {\r
+       // 処理を行う。\r
+       wxArrayString asFiles = MakeTargetFileList(this);\r
+       ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
        TPI_SWITCHES swInfo;\r
-       ProcessDialog procDlg;\r
-       procDlg.InitDialog();\r
-       procDlg.Show(true);\r
-       bool bIsCorrect = this->tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), MakeTargetFileList(this, false));\r
+       swInfo.szArcName  = this->fnArchive.GetFullPath();\r
+       swInfo.szPassword = this->szPassword;\r
+       tpi.Command(TPI_COMMAND_TEST, & swInfo, asFiles);\r
+       this->ErrorCheck(tpi.nErrorCode);\r
        procDlg.Show(false);\r
-       if (bIsCorrect)\r
-       {\r
-               ::wxLogMessage(_("This is a correct archive."));\r
-       }\r
-       else\r
-       {\r
-               this->ErrorCheck(tpi.nErrorCode);\r
-       }\r
 }\r
 \r
 void MainFrame::OnArcRepair(wxCommandEvent&)\r
 {\r
+       // 処理を行う。\r
+       wxArrayString asFiles = MakeTargetFileList(this);\r
+       ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
        TPI_SWITCHES swInfo;\r
-       ProcessDialog procDlg;\r
-       procDlg.InitDialog();\r
-       procDlg.Show(true);\r
-       if (! this->tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), MakeTargetFileList(this, false)))\r
+       swInfo.szArcName  = this->fnArchive.GetFullPath();\r
+       swInfo.szPassword = this->szPassword;\r
+       tpi.Command(TPI_COMMAND_REPAIR, & swInfo, asFiles);\r
+       this->ErrorCheck(tpi.nErrorCode);\r
+       procDlg.Show(false);    \r
+}\r
+\r
+void MainFrame::OnExeCopy(wxCommandEvent & e)\r
+{\r
+       if (this->list_ctrl->GetSelectedItemCount() == 0)\r
        {\r
-               this->ErrorCheck(tpi.nErrorCode);\r
+               // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
+               this->menubar->Enable(XRCID("Exe_Copy"), false);\r
+               return;\r
        }\r
-       procDlg.Show(false);    \r
+\r
+       if (! wxTheClipboard->Open())\r
+       {\r
+               return;\r
+       }\r
+\r
+       e.SetInt(4);\r
+       this->OnArcExtract(e);\r
+       wxTheClipboard->Close();\r
 }\r
 \r
 void MainFrame::OnViewMode(wxCommandEvent & e)\r
@@ -861,7 +1085,7 @@ void MainFrame::OnTreeChanged(wxTreeEvent& e)
        // ツリービューからパスを取得。\r
        wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());\r
        // リストビューを初期化。\r
-       this->list_ctrl->showFileInfo.Clear();\r
+       this->list_ctrl->apShowFile.Clear();\r
        this->list_ctrl->DeleteAllItems();\r
        g_hIconLL.RemoveAll();\r
        g_hIconLS.RemoveAll();\r
@@ -896,13 +1120,13 @@ void MainFrame::OnTreeChanged(wxTreeEvent& e)
                                continue;\r
                        }\r
 \r
-                       this->list_ctrl->showFileInfo.Add(this->fileinfo[i]);\r
+                       this->list_ctrl->apShowFile.Add(& this->fileinfo[i]);\r
                }\r
        }\r
 \r
        // ソートして表示。\r
-       this->list_ctrl->showFileInfo.Sort(& ListCtrlCompareProc);\r
-       this->list_ctrl->SetItemCount(this->list_ctrl->showFileInfo.GetCount());\r
+       this->list_ctrl->apShowFile.Sort(& ListCtrlCompareProc);\r
+       this->list_ctrl->SetItemCount(this->list_ctrl->apShowFile.GetCount());\r
 }\r
 \r
 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)\r
@@ -915,8 +1139,22 @@ void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
        this->OnArcExtract(e1);\r
 }\r
 \r
+void MainFrame::OnContextMenu(wxContextMenuEvent& e)\r
+{\r
+       wxPoint p = e.GetPosition();\r
+       this->list_ctrl->PopupMenu(this->menubar->GetMenu(1), p == wxDefaultPosition ? this->list_ctrl->GetPosition() : this->list_ctrl->ScreenToClient(p));\r
+}\r
+\r
 // ListView\r
 \r
+void MainFrame::OnListItemSelect(wxListEvent&)\r
+{\r
+       // ファイルに対する動作の設定。但し、選択解除時はwxのバグで呼び出されない。\r
+       bool fEnable = this->list_ctrl->GetSelectedItemCount() > 0;\r
+       SetMenuToolState("Arc_Delete", fEnable && (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);\r
+       this->menubar->Enable(XRCID("Exe_Copy"), fEnable);\r
+}\r
+\r
 void MainFrame::OnListItemDClick(wxListEvent&)\r
 {\r
        wxCommandEvent e;\r
@@ -948,54 +1186,49 @@ void MainFrame::OnFilter(wxCommandEvent&)
 \r
 // イベントハンドラ以外。\r
 \r
-wxULongLong MainFrame::LoadTPI(wxString szFileName)\r
+bool MainFrame::LoadTPI(const wxString & szFileName, wxULongLong_t * llFileCount)\r
 {\r
-       // TPIを読み込み。\r
-       wxFileSystem fs;\r
-       fs.ChangePathTo(L_DIR_B_LIB, true);\r
-       wxString szTPIName = fs.FindFirst(wxT("*" TPI_EXT), wxFILE);\r
-       wxULongLong llFileCount = 0;\r
-       while (! szTPIName.IsEmpty())\r
-       {\r
-               // 初期化。\r
-               if (! tpi.InitLibrary(szTPIName, szFileName, 0))\r
-               {\r
-                       tpi.FreeLibrary();\r
-                       szTPIName = fs.FindNext();\r
-                       continue;\r
-               }\r
-\r
-               // コールバック関数を設定。\r
-               tpi.SetCallbackProc(TPICallbackProc);\r
+       // 書庫を開いていれば閉じておく。\r
+       wxCommandEvent e;\r
+       this->OnArcClose(e);\r
 \r
-               // 対応確認。\r
-               if (! tpi.CheckArchive(szFileName, & llFileCount) || llFileCount == 0)\r
+       // TPIを読み込み。\r
+       wxDir fs(L_DIR_B_LIB);\r
+       wxString szTPIName;\r
+       if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))\r
+       {\r
+               do\r
                {\r
-                       tpi.FreeLibrary();\r
-                       szTPIName = fs.FindNext();\r
-                       continue;\r
+                       // 初期化と対応確認。\r
+                       if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName, TPICallbackProc) || ! tpi.OpenArchive(szFileName, llFileCount))\r
+                       {\r
+                               tpi.FreeLibrary();\r
+                               * llFileCount = 0;\r
+                               continue;\r
+                       }\r
+                       return true;\r
                }\r
-               break;\r
+               while (fs.GetNext(& szTPIName));\r
        }\r
-       return llFileCount;\r
+       return false;\r
 }\r
 \r
-int MainFrame::ErrorCheck(int nErrorCode)\r
+int MainFrame::ErrorCheck(int nErrorCode, const wxString & szAPIName)\r
 {\r
        switch (nErrorCode)\r
        {\r
        case TPI_ERROR_SUCCESS:\r
+       case TPI_ERROR_S_ENDOFDATA:\r
        case TPI_CALLBACK_CONTINUE:\r
                break;\r
        case TPI_ERROR_D_UNSUPPORTED:\r
-               ::wxLogError(_("Sorry, this function is not supported yet."));\r
+               wxLogError(_("Sorry, this function is not supported yet."));\r
                break;\r
        case TPI_ERROR_D_SKIPPED:\r
        case TPI_CALLBACK_CANCEL:\r
-               ::wxLogError(_("This operation is canceled by the user."));\r
                break;\r
        default:\r
-               ::wxLogError(_("Error code: %d"), nErrorCode);\r
+               wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);\r
        }\r
        return nErrorCode;\r
 }\r