root/FolderView.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. IMPLEMENT_DYNCREATE
  2. CFolderView
  3. BEGIN_MESSAGE_MAP
  4. AssertValid
  5. Dump
  6. OnInitialUpdate
  7. ConstructTree
  8. OnSelchanged
  9. AddSubItem
  10. OnItemexpanded
  11. GetItemPath
  12. GetTopItemName
  13. OnChar
  14. OnSelchanging
  15. RefreshTree
  16. AddUser
  17. RemoveUser
  18. RenameUser
  19. GetSelectedItemName
  20. OnKeyDown
  21. OnSetFocus
  22. CopyItem
  23. OnItemCopied
  24. CopyBranch
  25. OnBegindrag
  26. OnMouseMove
  27. OnLButtonUp
  28. WhatKind
  29. GetSelectedItemKind
  30. DeleteFolder
  31. OnRclick
  32. OnPopupDel
  33. AddFolder
  34. OnEndlabeledit
  35. OnPopupRename
  36. OnPopupAdd
  37. OnBeginlabeledit
  38. OnPopupRebuild
  39. OnSize
  40. OnPopupClearTrash

/*
 * Copyright (C) 2002-2003 chik, s.hiranaka
 * For license terms, see the file COPYING in this directory.
 */

// FolderView.cpp : インプリメンテーション ファイル
//

#include "stdafx.h"
#include "Pochy.h"
#include "MainFrm.h"
#include "SummaryView.h"
#include "FolderView.h"
#include "PochyDoc.h"
#include "Retrieve.h"
#include "SortStringArray.h"
#include "lib.h"
#include "direct.h"                     // _mkdir

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CFolderView

IMPLEMENT_DYNCREATE(CFolderView, CTreeView)

CFolderView::CFolderView()
{
        this->m_bLDragging = FALSE;
}

CFolderView::~CFolderView()
{
}

BEGIN_MESSAGE_MAP(CFolderView, CTreeView)
        //{{AFX_MSG_MAP(CFolderView)
        ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
        ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded)
        ON_WM_CHAR()
        ON_NOTIFY_REFLECT(TVN_SELCHANGING, OnSelchanging)
        ON_WM_KEYDOWN()
        ON_WM_SETFOCUS()
        ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
        ON_WM_MOUSEMOVE()
        ON_WM_LBUTTONUP()
        ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
        ON_COMMAND(ID_FOLDERVIEW_DEL, OnPopupDel)
        ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndlabeledit)
        ON_COMMAND(ID_FOLDERVIEW_RENAME, OnPopupRename)
        ON_COMMAND(ID_FOLDERVIEW_ADD, OnPopupAdd)
        ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginlabeledit)
        ON_COMMAND(ID_FOLDERVIEW_RESTRUCT, OnPopupRebuild)
        ON_WM_SIZE()
        ON_COMMAND(ID_FOLDERVIEW_CLEAR_TRASH, OnPopupClearTrash)
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFolderView 描画

void CFolderView::OnDraw(CDC* pDC)
{
        CDocument* pDoc = GetDocument();
}

/////////////////////////////////////////////////////////////////////////////
// CFolderView 診断

#ifdef _DEBUG
void CFolderView::AssertValid() const
{
        CTreeView::AssertValid();
}

void CFolderView::Dump(CDumpContext& dc) const
{
        CTreeView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CFolderView メッセージ ハンドラ

void CFolderView::OnInitialUpdate() 
{
        CTreeView::OnInitialUpdate();
        DWORD dwStyle;                          // スタイル取得用
        HWND hWnd;
        CTreeCtrl& tc = GetTreeCtrl();
        CPochyApp *app = (CPochyApp *)AfxGetApp();

        // setting image for drag
        if(this->m_drag_image.Create(15, 15, ILC_COLOR8|ILC_MASK, 0, 2)){
                CBitmap bmp;
                if(bmp.LoadBitmap(IDB_DRAG)){
                        this->m_drag_image.Add(&bmp, RGB(255,255,255));
                }
                bmp.DeleteObject();
        }

        // iconの設定
        if(this->m_image.Create(17, 16, ILC_COLOR8|ILC_MASK, 0, 7)){
                CBitmap bmp;
                if(bmp.LoadBitmap(IDB_TREEVIEW)){
                        this->m_image.Add(&bmp, RGB(255,255,255));
                }
                bmp.DeleteObject();
        }
        tc.SetImageList(&m_image, TVSIL_NORMAL);

        // ツリーコントロールのすべてのアイテムを削除し初期化する
        tc.DeleteAllItems();    // もしかしたらいらないかも?

        // 現在のビューのスタイルを取得
        hWnd = tc.GetSafeHwnd();
        dwStyle = GetWindowLong(hWnd, GWL_STYLE);

        // ビューのスタイルを変更
        SetWindowLong(hWnd, GWL_STYLE,
                dwStyle|TVS_HASLINES/*|TVS_LINESATROOT*/|TVS_HASBUTTONS|TVS_EDITLABELS|TVS_SHOWSELALWAYS);

        // 色の設定
        COLORREF m_colorEdit;

        m_colorEdit = RGB(
                app->GetProfileInt("FolderViewColor", "BkColorR", DEF_BKG_COLOR_R),
                app->GetProfileInt("FolderViewColor", "BkColorG", DEF_BKG_COLOR_G),
                app->GetProfileInt("FolderViewColor", "BkColorB", DEF_BKG_COLOR_B));
        tc.SetBkColor(m_colorEdit);

        m_colorEdit = RGB(
                app->GetProfileInt("FolderViewColor", "TxtColorR", DEF_TXT_COLOR_R),
                app->GetProfileInt("FolderViewColor", "TxtColorG", DEF_TXT_COLOR_G),
                app->GetProfileInt("FolderViewColor", "TxtColorB", DEF_TXT_COLOR_B));
        tc.SetTextColor(m_colorEdit);

        CMainFrame *mf = (CMainFrame*)this->GetParentFrame(); // ここではapp->m_pMainWnd2は使えない
        CString def_account = app->GetProfileString("DefaultMailBox", "BoxName", "");
        if(!def_account.IsEmpty()){
                ConstructTree(def_account);
        }else{
                mf->m_pAcntV->m_combo_account.GetLBText(0, def_account);
                ConstructTree(def_account);
        }

        // ツリーの最初のアイテムを選択
        HTREEITEM ti = tc.GetChildItem(tc.GetRootItem());
        tc.SelectItem(ti);
}

void CFolderView::ConstructTree(CString account)
{
        CFileFind ff;
        CStringArray DirArray;
        CTreeCtrl& tc = GetTreeCtrl();
        CPochyApp* app = (CPochyApp*)AfxGetApp();

        tc.DeleteAllItems();
        if(account.IsEmpty())
                return;

        if(!g_is_there(app->m_app_path+"\\"+account+"\\account.ini"))
                return;

        AddUser(app->m_app_path + "\\" + account, account);
        tc.Expand(tc.GetRootItem(), TVE_EXPAND);
}

void CFolderView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) 
{
        NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
        CTreeCtrl& tc = GetTreeCtrl();
        CPochyApp* app = (CPochyApp*)AfxGetApp();
        CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
        CSummaryView *sv = mf->m_pListV;
        CTextView *tv = mf->m_pTextV;

        HTREEITEM ti = tc.GetSelectedItem();
        CString current_account;

        // toolbarのreply、transfer、header表示ボタンを無効にする 
        mf->m_button_reply = FALSE;
        mf->m_button_transfer = FALSE;
        mf->m_button_info = FALSE;

        // toolbarのgpgボタンを無効にする
        mf->m_button_gpg_dec = FALSE;

        CWaitCursor wait_cursor; // カーソルを砂時計にする。
        // listviewに表示させる
        sv->SetItem(app->m_app_path + this->GetItemPath(ti));

        // multipartviewが隠れていなければ隠す
        mf->HideMultiPartView(TRUE);

        // display empty on textview
        tv->Clear();

        // 左上隅のドキュメント名をカレントメールボックス名にする
//      GetDocument()->SetTitle(mf->m_pAcntV->GetCurrentAccountName());
    CString title;
    CString account = mf->m_pAcntV->GetCurrentAccountName();
    title.Format("%s - %s", account, "pochy");
    mf->SetWindowText(title);


        *pResult = 0;
}

void CFolderView::AddSubItem(HTREEITEM Item)
{
        CString path;
        CFileFind ff;
        BOOL b_Find;
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        HTREEITEM subItem;
        CPochyApp *app = (CPochyApp *)AfxGetApp();

        subItem = treeCtrl.GetChildItem(Item);
        do{
                if(NULL == treeCtrl.GetChildItem(subItem)){
                        path = app->m_app_path + GetItemPath(subItem) + "\\*.*";
                        b_Find = ff.FindFile(path);
                        path.Empty();
                        while(b_Find){
                                b_Find = ff.FindNextFile();
                                if(ff.IsDirectory() && !ff.IsDots())
                                        treeCtrl.SetItemData(treeCtrl.InsertItem(ff.GetFileName().GetBuffer(0), 0, 0, subItem, TVI_LAST), FV_OTHER);
                        }
                }
                subItem = treeCtrl.GetNextSiblingItem(subItem);
        }while(subItem);
}

void CFolderView::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) 
{
        HTREEITEM ti;
        CString path;
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

        CWaitCursor wait_cursor; // カーソルを砂時計にする。

        ti = pNMTreeView->itemNew.hItem;
        path = app->m_app_path + GetItemPath(ti);
        AddSubItem(pNMTreeView->itemNew.hItem);
        *pResult = 0;
}

CString CFolderView::GetItemPath(HTREEITEM ti)
{
        CString item_name;
        CString path;
        CTreeCtrl& treeCtrl = GetTreeCtrl();

        while(ti){
                switch(WhatKind(ti)){
                case FV_INBOX:
                        item_name = "inbox";
                        break;
                case FV_OUTBOX:
                        item_name = "outbox";
                        break;
                case FV_DRAFT:
                        item_name = "draft";
                        break;
                case FV_TRASH:
                        item_name = "trash";
                        break;
                default:
                        item_name = treeCtrl.GetItemText(ti);
                        break;
                }
                item_name.Insert(0, "\\");
                path.Insert(0, item_name);
                ti = treeCtrl.GetParentItem(ti);
        }
        return path;
}

CString CFolderView::GetTopItemName(HTREEITEM ti)
{
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        CString name;

        while(ti){
                name = treeCtrl.GetItemText(ti);
                ti = treeCtrl.GetParentItem(ti);
        }

        return name;
}

void CFolderView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
//      CMainFrame *pMF = (CMainFrame*)GetParentFrame();
        CPochyApp* app = (CPochyApp*)AfxGetApp();
        CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        HTREEITEM ti;

        if(mf->Char(nChar))
                return;

        switch(nChar){
        case 'n':
                ti = treeCtrl.GetNextItem(treeCtrl.GetSelectedItem(), TVGN_NEXTVISIBLE);
                if(ti != NULL) treeCtrl.SelectItem(ti);
                break;
        case 'p':
                ti = treeCtrl.GetNextItem(treeCtrl.GetSelectedItem(), TVGN_PREVIOUSVISIBLE);
                if(ti != NULL) treeCtrl.SelectItem(ti);
                break;
        default:
                break;
        }
}

void CFolderView::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult) 
{

        NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
        // リストビューのカラムの幅をiniファイルへ保存
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
        CSummaryView *listView = mf->m_pListV;

        CString num;
        int i;

        for(i = 0; i < 4; i++){
                num.Format("%d", i);
                app->WriteProfileInt("SummaryViewColumn", num.GetBuffer(0), listView->GetListCtrl().GetColumnWidth(i));
        }
        *pResult = 0;
}

void CFolderView::RefreshTree()
{
        CPochyApp* app=(CPochyApp*)AfxGetApp();
        ConstructTree(app->m_app_path);
}

void CFolderView::AddUser(CString path, CString user)
{
        CFileFind ff;
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        CSortStringArray DirArray;
        CTreeCtrl& tc = GetTreeCtrl();
        HTREEITEM hItem = tc.InsertItem(user, 3, 3, TVI_ROOT, TVI_FIRST);
        tc.SetItemData(hItem, FV_TOP);

        BOOL b = ff.FindFile(path + "\\*.*");

        // フォルダの中身を捜査して、ディレクトリ名をDirArrayに格納する
        while(b){
                b = ff.FindNextFile();
                if(     ff.IsDirectory() &&
                        !ff.IsDots() &&
                        ff.GetFileName() != "inbox" &&
                        ff.GetFileName() != "outbox" &&
                        ff.GetFileName() != "draft" &&
                        ff.GetFileName() != "trash")
                {
                           DirArray.Add(ff.GetFileName());
                }
        }
        DirArray.Sort();

        // treeviewへitemを追加
        CString inbox;
        CString outbox;
        CString draft;
        CString trash;

        GetPrivateProfileString("mailbox", "inbox", DEF_BOXNAME_INBOX, inbox.GetBuffer(BUF_LENGTH), BUF_LENGTH, path+"\\account.ini");
        GetPrivateProfileString("mailbox", "outbox", DEF_BOXNAME_OUTBOX, outbox.GetBuffer(BUF_LENGTH), BUF_LENGTH, path+"\\account.ini");
        GetPrivateProfileString("mailbox", "draft", DEF_BOXNAME_DRAFT, draft.GetBuffer(BUF_LENGTH), BUF_LENGTH, path+"\\account.ini");
        GetPrivateProfileString("mailbox", "trash", DEF_BOXNAME_TRASH, trash.GetBuffer(BUF_LENGTH), BUF_LENGTH, path+"\\account.ini");

        inbox.ReleaseBuffer();
        outbox.ReleaseBuffer();
        draft.ReleaseBuffer();
        trash.ReleaseBuffer();

        tc.SetItemData(tc.InsertItem(inbox, 4, 5, hItem, TVI_LAST), FV_INBOX);
        tc.SetItemData(tc.InsertItem(outbox, 4, 5, hItem, TVI_LAST), FV_OUTBOX);
        tc.SetItemData(tc.InsertItem(draft, 4, 5, hItem, TVI_LAST), FV_DRAFT);
        tc.SetItemData(tc.InsertItem(trash, 2, 2, hItem, TVI_LAST), FV_TRASH);

        for(int i=0; i <= DirArray.GetUpperBound(); i++)
                tc.SetItemData(tc.InsertItem(DirArray.GetAt(i).GetBuffer(0), 0, 1, hItem, TVI_LAST), FV_OTHER);
}

void CFolderView::RemoveUser(CString user)
{
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        HTREEITEM hti = treeCtrl.GetChildItem(TVI_ROOT);
        while(hti){
                if(treeCtrl.GetItemText(hti) == user){
                        treeCtrl.DeleteItem(hti);
                        break;
                }else{
                        hti = treeCtrl.GetNextSiblingItem(hti);
                }
        }
}

void CFolderView::RenameUser(CString oldname, CString newname)
{
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        HTREEITEM hti = treeCtrl.GetChildItem(TVI_ROOT);
        while(hti){
                if(treeCtrl.GetItemText(hti) == oldname){
                        treeCtrl.SetItemText(hti, newname);
                        break;
                }else{
                        hti = treeCtrl.GetNextSiblingItem(hti);
                }
        }
}

CString CFolderView::GetSelectedItemName()
{
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        HTREEITEM hti = treeCtrl.GetSelectedItem();

        return treeCtrl.GetItemText(hti);
}

void CFolderView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
        CTreeCtrl& tc = GetTreeCtrl();
        switch(nChar){
                case 46: // delキーが押された場合、現在選択状態にあるフォルダを削除する
                        DeleteFolder(tc.GetSelectedItem());
                        break;
                default:
                        break;
        }
        CTreeView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CFolderView::OnSetFocus(CWnd* pOldWnd) 
{
        CTreeView::OnSetFocus(pOldWnd);

//      CPochyApp *app = (CPochyApp *)AfxGetApp();
//      CMainFrame* mf = (CMainFrame*)app->m_pMainWnd;
//      mf->SetStatusBarText(2, "アカウントとフォルダ");
}

HTREEITEM CFolderView::CopyItem( HTREEITEM hItem, HTREEITEM htiNewParent, HTREEITEM htiAfter)
{
        TV_INSERTSTRUCT tvstruct;
        HTREEITEM hNewItem;
        CString sText;

        // get information of the source item
        tvstruct.item.hItem = hItem;
        tvstruct.item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
        GetTreeCtrl().GetItem(&tvstruct.item);  
        sText = GetTreeCtrl().GetItemText( hItem );

        tvstruct.item.cchTextMax = sText.GetLength();
        tvstruct.item.pszText = sText.LockBuffer();

        // Insert the item at proper location
        tvstruct.hParent = htiNewParent;
        tvstruct.hInsertAfter = htiAfter;
        tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
        hNewItem = GetTreeCtrl().InsertItem(&tvstruct);
        sText.ReleaseBuffer();

        // Now copy item data and item state.
        GetTreeCtrl().SetItemData( hNewItem, GetTreeCtrl().GetItemData( hItem ));
        GetTreeCtrl().SetItemState( hNewItem, GetTreeCtrl().GetItemState( hItem, TVIS_STATEIMAGEMASK ), TVIS_STATEIMAGEMASK);

        // Call virtual function to allow further processing in derived class
        OnItemCopied( hItem, hNewItem );

        return hNewItem;
}

void CFolderView::OnItemCopied(HTREEITEM /*hItem*/, HTREEITEM /*hNewItem*/)
{
        // Virtual function 
}

HTREEITEM CFolderView::CopyBranch(HTREEITEM htiBranch, HTREEITEM htiNewParent, HTREEITEM htiAfter)
{

        HTREEITEM hChild;

        HTREEITEM hNewItem = CopyItem( htiBranch, htiNewParent, htiAfter );
        hChild = GetTreeCtrl().GetChildItem(htiBranch);
        while( hChild != NULL)
                {
                        // recursively transfer all the items
                        CopyBranch(hChild, hNewItem);  
                        hChild = GetTreeCtrl().GetNextSiblingItem( hChild );
                }
        return hNewItem;
}

void CFolderView::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
        NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
        *pResult = 0;

        m_hitemDrag = pNMTreeView->itemNew.hItem;
        m_hitemDrop = NULL;

        m_pDragImage = GetTreeCtrl().CreateDragImage(m_hitemDrag);  // get the image list for dragging
        // CreateDragImage() returns NULL if no image list
        // associated with the tree view control
        if( !m_pDragImage )
                return;

        m_bLDragging = TRUE;
        m_hitemDrop = NULL;
        m_pDragImage->BeginDrag(0, CPoint(-15,-15));
        POINT pt = pNMTreeView->ptDrag;
        ClientToScreen( &pt );
        m_pDragImage->DragEnter(NULL, pt);
        SetCapture();
}

void CFolderView::OnMouseMove(UINT nFlags, CPoint point) 
{
        CPochyApp* app = (CPochyApp*)AfxGetApp();
        CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
        HTREEITEM       hitem;
        UINT            flags;

        if (m_bLDragging){
                POINT pt = point;
                ClientToScreen( &pt );
                CImageList::DragMove(pt);
                if ((hitem = GetTreeCtrl().HitTest(point, &flags)) != NULL){
                        CImageList::DragShowNolock(FALSE);
                        GetTreeCtrl().SelectDropTarget(hitem);
                        m_hitemDrop = hitem;
                        CImageList::DragShowNolock(TRUE);
                }else{
                        GetTreeCtrl().SelectDropTarget(NULL);
                        m_hitemDrop = NULL;
                }
#if 0 //危険なコード
                if(flags & (TVHT_ABOVE | TVHT_BELOW | TVHT_TORIGHT | TVHT_TOLEFT)){
                        m_pDragImage->EndDrag();
                        m_pDragImage->Replace(0,AfxGetApp()->LoadIcon(IDI_ICON1));
                        m_pDragImage->BeginDrag(0, CPoint(-15,-15));
                        ClientToScreen(&point);
                        m_pDragImage->DragEnter(NULL,point);
                }else{
                        m_pDragImage->EndDrag();
                        if(m_hitemDrag){
                                m_pDragImage = GetTreeCtrl().CreateDragImage(m_hitemDrag);
                        }else{
                                m_pDragImage = mf->m_pListV->GetListCtrl().CreateDragImage(m_ListItemDrag,&pt);
                        }
                        m_pDragImage->BeginDrag(0, CPoint(-15,-15));
                        ClientToScreen(&point);
                        m_pDragImage->DragEnter(NULL,point);
                }
#endif
        }

        CTreeView::OnMouseMove(nFlags, point);
}

void CFolderView::OnLButtonUp(UINT nFlags, CPoint point) 
{
        CTreeView::OnLButtonUp(nFlags, point);

        if (m_bLDragging){
                CPochyApp* app = (CPochyApp*)AfxGetApp();
                CSummaryView* sv = ((CMainFrame*)app->m_pMainWnd)->m_pListV;
                m_bLDragging = FALSE;
                CImageList::DragLeave(this);
                CImageList::EndDrag();
                ReleaseCapture();

                // Remove drop target highlighting
                GetTreeCtrl().SelectDropTarget(NULL);

                if(!m_hitemDrop)
                        return;

                if(m_hitemDrag){
                        if(m_hitemDrag == m_hitemDrop)
                                return;
                        if(!GetTreeCtrl().GetParentItem(m_hitemDrag))
                                return;
                        if(!GetTreeCtrl().GetParentItem(GetTreeCtrl().GetParentItem(m_hitemDrag))){
                                if(WhatKind(m_hitemDrag) != FV_OTHER)
                                        return;
                        }

                        HTREEITEM htiParent = m_hitemDrop;
                        while( (htiParent = GetTreeCtrl().GetParentItem( htiParent )) != NULL ){
                                if( htiParent == m_hitemDrag ) return;
                        }

                        GetTreeCtrl().Expand(m_hitemDrop, TVE_EXPAND);

                        if(g_is_there(app->m_app_path + GetItemPath(m_hitemDrop)
                                + "\\" + GetTreeCtrl().GetItemText(m_hitemDrag))){
                                AfxMessageBox(app->m_app_path + GetItemPath(m_hitemDrop) + "\\" + GetTreeCtrl().GetItemText(m_hitemDrag) + "\r\nは既に存在してます。移動できないっす。");
                                return;
                        }
                        HTREEITEM htiNew = CopyBranch(m_hitemDrag, m_hitemDrop, TVI_LAST);
                        rename(app->m_app_path + GetItemPath(m_hitemDrag),
                                app->m_app_path + GetItemPath(m_hitemDrop) + "\\" + GetTreeCtrl().GetItemText(m_hitemDrag));
                        GetTreeCtrl().DeleteItem(m_hitemDrag);
                        GetTreeCtrl().SelectItem(htiNew);
                }else{
                        if(sv->m_path == app->m_app_path + GetItemPath(m_hitemDrop))
                                return;

                        CWaitCursor wait_cursor; // turn cursor into sandglass
                        CUIntArray ia;

                        switch(WhatKind(m_hitemDrop)){
                        case FV_INBOX:
                        case FV_OTHER:
                        case FV_TRASH:
                                sv->GetSelectedMail(ia);
                                sv->MoveMail(ia, app->m_app_path+GetItemPath(m_hitemDrop), SMRY_COLUMN_FROM);
                                break;
                        case FV_OUTBOX:
                        case FV_DRAFT:
                                sv->GetSelectedMail(ia);
                                sv->MoveMail(ia, app->m_app_path+GetItemPath(m_hitemDrop), SMRY_COLUMN_TO);
                                break;
                        default:
                                break;
                        }
        }
    }
}

int CFolderView::WhatKind(HTREEITEM hItem)
{
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        return treeCtrl.GetItemData(hItem);
}

int CFolderView::GetSelectedItemKind()
{
        CTreeCtrl& treeCtrl = GetTreeCtrl();
        return WhatKind(treeCtrl.GetSelectedItem());
}

BOOL CFolderView::DeleteFolder(HTREEITEM ti)
{
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        CTreeCtrl& tc = GetTreeCtrl();
        int r;

        if(WhatKind(ti) != FV_OTHER)
                return FALSE;

        CString path = app->m_app_path + GetItemPath(ti);
        if(IDYES == AfxMessageBox(path + "\r\n\r\n削除してもよいですか?", MB_YESNO)){
                if(IDYES == AfxMessageBox("くどいですがもう一回確認。全部消えまっせ。良いっすか?", MB_YESNO)){
                        r = g_delete_directory(path);
                        if(r)
                        tc.DeleteItem(ti);
                        return r;
                }
        }
        return FALSE;
}

void CFolderView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
        const MSG* msg = GetCurrentMessage();
        CPoint pt1 = msg->pt;
        CPoint pt2 = msg->pt;
        ScreenToClient(&pt1);
        UINT flag = 0;
        HTREEITEM hItem = GetTreeCtrl().HitTest(pt1, &flag);

        /*
        Value Description 
        TVHT_ABOVE Above the client area.  
        TVHT_BELOW Below the client area.  
        TVHT_NOWHERE In the client area, but below the last item.  
        TVHT_ONITEM On the bitmap or label associated with an item.  
        TVHT_ONITEMBUTTON On the button associated with an item.  
        TVHT_ONITEMICON On the bitmap associated with an item.  
        TVHT_ONITEMINDENT In the indentation associated with an item.  
        TVHT_ONITEMLABEL On the label (string) associated with an item.  
        TVHT_ONITEMRIGHT In the area to the right of an item.  
        TVHT_ONITEMSTATEICON On the state icon for a tree view item that is in a user-defined state.  
        TVHT_TOLEFT To the left of the client area.  
        TVHT_TORIGHT To the right of the client area. 
        */

        if(hItem != NULL && flag & TVHT_ONITEM)
                GetTreeCtrl().SelectItem(hItem);
        else
                return;

        CMenu menu;
        menu.LoadMenu(IDR_FOLDERVIEW_POPUP);

        if(this->WhatKind(hItem) != FV_OTHER)
                // 削除を無効にする
                menu.EnableMenuItem(ID_FOLDERVIEW_DEL, MF_GRAYED);
        else
                // 有効にする
                menu.EnableMenuItem(ID_FOLDERVIEW_DEL, MF_ENABLED);

        if(this->WhatKind(hItem) == FV_TRASH)
                menu.EnableMenuItem(ID_FOLDERVIEW_CLEAR_TRASH, MF_ENABLED);
        else
                menu.EnableMenuItem(ID_FOLDERVIEW_CLEAR_TRASH, MF_GRAYED);

        if(this->WhatKind(hItem) == FV_TOP)
                // 名前変更を無効にする
                menu.EnableMenuItem(ID_FOLDERVIEW_RENAME, MF_GRAYED);
        else
                // 有効にする
                menu.EnableMenuItem(ID_FOLDERVIEW_RENAME, MF_ENABLED);

        CMenu *pPopup = menu.GetSubMenu(0);
        pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON |TPM_LEFTBUTTON, (int)pt2.x, (int)pt2.y, this);

        PostMessage(WM_NULL, 0, 0); // this is point    
        *pResult = 0;
}

void CFolderView::OnPopupDel() 
{
        CTreeCtrl& fv = GetTreeCtrl();
        DeleteFolder(fv.GetSelectedItem());
}

BOOL CFolderView::AddFolder(HTREEITEM parent_ti)
{
        return TRUE;
}

void CFolderView::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) 
{
        TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
        CString name;
        GetTreeCtrl().GetEditControl()->GetWindowText(name);

        HTREEITEM hItem = GetTreeCtrl().GetSelectedItem();

        CString path = app->m_app_path+"\\"+mf->m_pAcntV->GetCurrentAccountName()+"\\account.ini";

        switch(WhatKind(hItem)){
        case FV_INBOX:
                WritePrivateProfileString("mailbox", "inbox", name, path);
                break;
        case FV_OUTBOX:
                WritePrivateProfileString("mailbox", "outbox", name, path);
                break;
        case FV_DRAFT:
                WritePrivateProfileString("mailbox", "draft", name, path);
                break;
        case FV_TRASH:
                WritePrivateProfileString("mailbox", "trash", name, path);
                break;
        case FV_OTHER:
                if(name != m_current_edit_item_name){
                        if(g_is_there(app->m_app_path + GetItemPath(GetTreeCtrl().GetParentItem(hItem)) + "\\" + name)){
                                AfxMessageBox(app->m_app_path + GetItemPath(GetTreeCtrl().GetParentItem(hItem)) + "\\" + name + "\r\nは既に存在しています。");
                                *pResult = FALSE;
                                return;
                        }else{
                                rename(app->m_app_path + GetItemPath(hItem),
                                        app->m_app_path + GetItemPath(GetTreeCtrl().GetParentItem(hItem)) + "\\" + name);
                        }
                }
                break;
        }

        *pResult = TRUE;
}

void CFolderView::OnPopupRename() 
{
        GetTreeCtrl().EditLabel(GetTreeCtrl().GetSelectedItem());
}

void CFolderView::OnPopupAdd()
{
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        HTREEITEM hItem1;
        HTREEITEM hItem2;
        CString name;
        int i;

        hItem1 = GetTreeCtrl().GetSelectedItem();
        if(g_is_there(app->m_app_path+GetItemPath(hItem1)+"\\新しいフォルダ")){
                i=1;
                while(1){
                        name.Format("新しいフォルダ (%d)", i);
                        if(!g_is_there(app->m_app_path+GetItemPath(hItem1)+"\\"+name))
                                break;
                        i++;
                }
                hItem2 = GetTreeCtrl().InsertItem(name, 0, 1, hItem1, TVI_LAST);
        }else{
                hItem2 = GetTreeCtrl().InsertItem("新しいフォルダ", 0, 1, hItem1, TVI_LAST);
        }
        _mkdir(app->m_app_path + GetItemPath(hItem2));
        GetTreeCtrl().SetItemData(hItem2, FV_OTHER);
        GetTreeCtrl().SelectItem(hItem2);
}

void CFolderView::OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult) 
{
        TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;

        m_current_edit_item_name = GetTreeCtrl().GetItemText(GetTreeCtrl().GetSelectedItem());

        // in case of top-level item, editing label is prohibited
        if(WhatKind(GetTreeCtrl().GetSelectedItem()) != FV_TOP){
                *pResult = 0;
        }else{
                *pResult = TRUE;
        }
}

void CFolderView::OnPopupRebuild() 
{
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
        CTreeCtrl &tc = GetTreeCtrl();
        tc.DeleteAllItems();
        ConstructTree(mf->m_pAcntV->GetCurrentAccountName());
}

void CFolderView::OnSize(UINT nType, int cx, int cy) 
{
        CTreeView::OnSize(nType, cx, cy);
        this->Invalidate(FALSE);
}

void CFolderView::OnPopupClearTrash() 
{
        CPochyApp* app = (CPochyApp*)AfxGetApp();
        CSummaryView* sv = ((CMainFrame*)app->m_pMainWnd)->m_pListV;

        CTreeCtrl& tc = GetTreeCtrl();
        HTREEITEM ti = tc.GetSelectedItem();
        CString path = app->m_app_path + this->GetItemPath(ti);
        if(IDYES == AfxMessageBox("trashを空にしても良いですか?", MB_YESNO)){
                sv->ClearAllMail(path);
        }
}

/* [<][>][^][v][top][bottom][index][help] */