root/MultiPartView.cpp

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

DEFINITIONS

This source file includes following definitions.
  1. IMPLEMENT_DYNCREATE
  2. CMultiPartView
  3. BEGIN_MESSAGE_MAP
  4. AssertValid
  5. Dump
  6. OnInitialUpdate
  7. OnItemchanged
  8. OnRclick
  9. OnChar
  10. ReArrange
  11. OnSize
  12. ExecuteFile
  13. OnDblclk
  14. PreCreateWindow
  15. OnMultipartSave2file

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

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

#include "stdafx.h"
#include "pochy.h"
#include "MultiPartView.h"
#include "TextView.h"
#include "MainFrm.h"
#include "lib.h"
#include "CodeConvert.h"
#include "direct.h" // for _mkdir
#include "quoted-printable.h"
#include "base64.h"

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

/////////////////////////////////////////////////////////////////////////////
// CMultiPartView

IMPLEMENT_DYNCREATE(CMultiPartView, CListView)

CMultiPartView::CMultiPartView()
{
}

CMultiPartView::~CMultiPartView()
{
/*      m_image->Detach();
        delete m_image;*/
}


BEGIN_MESSAGE_MAP(CMultiPartView, CListView)
        //{{AFX_MSG_MAP(CMultiPartView)
        ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemchanged)
        ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
        ON_WM_CHAR()
        ON_WM_SIZE()
        ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
        ON_COMMAND(ID_MULTIPART_SAVE2FILE, OnMultipartSave2file)
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMultiPartView 描画

void CMultiPartView::OnDraw(CDC* pDC)
{
        CDocument* pDoc = GetDocument();
        // TODO: この位置に描画用のコードを追加してください
}

/////////////////////////////////////////////////////////////////////////////
// CMultiPartView 診断

#ifdef _DEBUG
void CMultiPartView::AssertValid() const
{
        CListView::AssertValid();
}

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

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

void CMultiPartView::OnInitialUpdate() 
{
        CListView::OnInitialUpdate();
        
        CListCtrl& lc = GetListCtrl();
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        CString num;
        char* Column[] = { "mime/type", "encoding", "ファイル名" };
        LV_COLUMN lvc;
        DWORD dwStyle;
        HWND hWnd;

        // 現在のスタイルから、レポートスタイルへ変更
        hWnd = lc.GetSafeHwnd();
        dwStyle = GetWindowLong(hWnd, GWL_STYLE);
        SetWindowLong(hWnd, GWL_STYLE, (dwStyle &~ LVS_TYPEMASK) | LVS_REPORT);
        lc.SetExtendedStyle(LVS_EX_FULLROWSELECT);

        // 色の設定
        COLORREF m_colorEdit;
        // 背景色
        m_colorEdit = RGB(
                app->GetProfileInt("TextViewColor", "BkColorR", 0),
                app->GetProfileInt("TextViewColor", "BkColorG", 0),
                app->GetProfileInt("TextViewColor", "BkColorB", 0));
        lc.SetBkColor(m_colorEdit);
        // テキストの背景色
        m_colorEdit = RGB(
                app->GetProfileInt("TextViewColor", "BkColorR", DEF_BKG_COLOR_R),
                app->GetProfileInt("TextViewColor", "BkColorG", DEF_BKG_COLOR_G),
                app->GetProfileInt("TextViewColor", "BkColorB", DEF_BKG_COLOR_B));
        lc.SetTextBkColor(m_colorEdit);
        // 文字の色
        m_colorEdit = RGB(
                app->GetProfileInt("TextViewColor", "TxtColorR", DEF_TXT_COLOR_R),
                app->GetProfileInt("TextViewColor", "TxtColorG", DEF_TXT_COLOR_G),
                app->GetProfileInt("TextViewColor", "TxtColorB", DEF_TXT_COLOR_B));
        lc.SetTextColor(m_colorEdit);

        // リストビューへカラムを設定
        lvc.mask = LVCF_FMT|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;
        lvc.fmt = LVCFMT_LEFT;
        for(int i = 0; i < 3; i++){
                lvc.pszText = Column[i];
                num.Format("%d", i);
                lvc.cx = app->GetProfileInt("MultiPartViewColumn", num.GetBuffer(0), 150);
                if(lvc.cx > 1000 || lvc.cx < 1){
                        lvc.cx = 150;
                }
                lc.InsertColumn(i, &lvc);
        }

        // setting system icon image.
        m_image.Create(16, 16, ILC_COLORDDB | ILC_MASK, 1, 100);
//      lc.SetImageList(&m_image, LVSIL_SMALL);
//      m_image.Add(NULL);
}

void CMultiPartView::OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult) 
{
        NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
        m_index = pNMListView->iItem; // 現在選択されているItemを保存しておく
        CPochyApp* app = (CPochyApp*)AfxGetApp();
        CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
        CTextView *tv = (CTextView*)mf->m_pTextV;
        tv->DisplayPart(m_index);
        *pResult = 0;
}

void CMultiPartView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
        POINT pt;

        if(m_index != -1){
                PostMessage(WM_NULL, 0, 0); // this is point
                GetCursorPos(&pt);
                CMenu menu;
                menu.LoadMenu(IDR_MULTIPART_POPUP);
                CMenu *pPopup = menu.GetSubMenu(0);
                pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, (int)pt.x, (int)pt.y, this);
        }       
        *pResult = 0;
}

void CMultiPartView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
        CPochyApp* app = (CPochyApp*)AfxGetApp();
        CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;

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

        switch(nChar){
                case VK_RETURN: // 添付ファイルの場合起動
//                      ExecuteFile();
                        break;
                case 'n':
//                      SelectNext();
                        break;
                case 'p':
//                      SelectPrev();
                        break;
                default:
                        break;
        }       
        CListView::OnChar(nChar, nRepCnt, nFlags);
}

void CMultiPartView::ReArrange()
{
        int i,width;
        CPoint p;
        CRect rect;
        CListCtrl& lc = GetListCtrl();
        p.x = 0;
        p.y = 0;
        GetClientRect(rect);
        width = rect.right;
        for(i=0;i<lc.GetItemCount();i++){
                lc.SetItemPosition(i,p);
                lc.GetItemRect(i,rect,LVIR_BOUNDS);
                if(width <= rect.right && i){
                        p.x = 0;
                        p.y = rect.bottom;
                        lc.SetItemPosition(i,p);
                        lc.GetItemRect(i,rect,LVIR_BOUNDS);
                }
                p.x = rect.right + 20;
        }
}

void CMultiPartView::OnSize(UINT nType, int cx, int cy) 
{
        CListView::OnSize(nType, cx, cy);
}

void CMultiPartView::ExecuteFile()
{
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        CMainFrame *mf = (CMainFrame *)app->m_pMainWnd;
        CTextView *tv = (CTextView *)mf->m_pTextV;

        CString file_name;
        CString body;
        CStringArray buf;
        CString msg_id;

        tv->m_md.GetBody(m_index, buf);
        g_cstra2cstr(buf, body, g_cstra_getsize(buf));

        if(m_index != -1){
                // 添付ファイルの場合
                if(!tv->m_md.GetFileName(m_index).IsEmpty()){
                        if(!g_is_there(app->m_app_path+"\\attached")) // attachedフォルダがない場合は作る
                                _mkdir(app->m_app_path+"\\attached");
                        file_name = tv->m_md.GetFileName(m_index);
                        FILE* file = fopen(app->m_app_path+"\\attached\\"+file_name, "wb");
                        // base64の処理
                        if(tv->GetCurrentCTE() == BASE64){
                                body.Remove('\r');
                                body.Remove('\n');
                                char* in = body.GetBuffer(0);
                                char* out = new char[body.GetLength()];
                                int len = from64tobits(out, in, strlen(in));
                                if(tv->GetCurrentCTE() == SEVEN_BIT || tv->GetCurrentCTE() == EIGHT_BIT){
                                        CString cstr_out = out;
                                        CCodeConvert cc(cstr_out);
                                        cstr_out = cc.ToSjis();
                                        out = cstr_out.GetBuffer(0);
                                }
                                fwrite(out, sizeof(char), len, file);
                                fclose(file);
                                delete out;
                        }
                        // quoted-pritableの処理
                        else if(tv->GetCurrentCTE() == QUOTED_PRINTABLE){
                                char* in2 = body.GetBuffer(0);
                                char* out2 = new char[body.GetLength()+10];
                                int len = fromQPtobits(out2, in2, strlen(in2));
                                if(tv->GetCurrentCTE() == SEVEN_BIT || tv->GetCurrentCTE() == EIGHT_BIT){
                                        CString cstr_out = out2;
                                        CCodeConvert cc(cstr_out);
                                        cstr_out = cc.ToSjis();
                                        out2 = cstr_out.GetBuffer(0);
                                }
                                fwrite(out2, sizeof(char), len, file);
                                fclose(file);
                                delete out2;
                        }else{
                                if(tv->GetCurrentCTE() == SEVEN_BIT || tv->GetCurrentCTE() == EIGHT_BIT){
                                        CCodeConvert cc(body);
                                        body = cc.ToSjis();
                                }
                                fwrite(body.GetBuffer(0), sizeof(char), body.GetLength(), file);
                                fclose(file);
                        }
                        // ファイルを開いちゃう
                        ShellExecute(NULL, "open", app->m_app_path+"\\attached\\"+file_name, NULL, NULL, SW_SHOW);
                }
                // text/htmlの場合(text/htmlでbase64 quoted-printableの処理が必要)
                else if(g_cstr_compare(tv->m_md.GetContentType(m_index), "Text/Html")){
                        if(BASE64 == tv->GetCurrentCTE()){
                                char* in_base64 = body.GetBuffer(0);
                                char* out_base64 = new char[body.GetLength()];
                                int len = from64tobits(out_base64, in_base64, strlen(in_base64));
                                body.Empty();
                                body = out_base64;
                                delete out_base64;
                        }
                        else if(QUOTED_PRINTABLE == tv->GetCurrentCTE()){
                                char* in_qp = body.GetBuffer(0);
                                char* out_qp = new char[body.GetLength()];
                                int len = fromQPtobits(out_qp, in_qp, strlen(in_qp));
                                body.Empty();
                                body = out_qp;
                                delete out_qp;
                        }
                        msg_id = tv->m_md.m_hi.GetMsgID();
                        msg_id = g_ma(msg_id);
                        msg_id.Replace(".", "_");
                        file_name = msg_id + ".html";

                        if(!g_is_there(app->m_app_path+"\\temp")) // tempフォルダがない場合は作る
                                _mkdir(app->m_app_path+"\\temp");
                        
                        FILE* file = fopen(app->m_app_path+"\\temp\\"+file_name, "wb");
                        // sjis変換
                        CCodeConvert cc(body);
                        body = cc.ToSjis();
                        fwrite(body.GetBuffer(0), sizeof(char), body.GetLength(), file);
                        fclose(file);
                        // ファイルを開いちゃう
                        ShellExecute(NULL, "open", app->m_app_path+"\\temp\\"+file_name, NULL, NULL, SW_SHOW);
                }
                // text/plainの場合(text/plainでbase64 quoted-printableの処理が必要)
                else if(g_cstr_compare(tv->m_md.GetContentType(m_index), "Text/Plain")){
                        if(BASE64 == tv->GetCurrentCTE()){
                                char* in_base64 = body.GetBuffer(0);
                                char* out_base64 = new char[body.GetLength()];
                                int len = from64tobits(out_base64, in_base64, strlen(in_base64));
                                body.Empty();
                                body = out_base64;
                                delete out_base64;
                        }
                        else if(QUOTED_PRINTABLE == tv->GetCurrentCTE()){
                                char* in_qp = body.GetBuffer(0);
                                char* out_qp = new char[body.GetLength()];
                                int len = fromQPtobits(out_qp, in_qp, strlen(in_qp));
                                body.Empty();
                                body = out_qp;
                                delete out_qp;
                        }
                        msg_id = tv->m_md.m_hi.GetMsgID();
                        msg_id = g_ma(msg_id);
                        msg_id.Replace(".", "_");
                        file_name = msg_id + ".txt";

                        if(!g_is_there(app->m_app_path+"\\temp")) /* tempフォルダがない場合は作る */
                                _mkdir(app->m_app_path+"\\temp");
                        
                        FILE* file = fopen(app->m_app_path+"\\temp\\"+file_name, "wb");
                        // sjis変換
                        CCodeConvert cc(body);
                        body = cc.ToSjis();
                        fwrite(body.GetBuffer(0), sizeof(char), body.GetLength(), file);
                        fclose(file);
                        // ファイルを開いちゃう
                        CString editor_path = app->GetProfileString("Editor", "Path", "notepad");
                        if(editor_path.IsEmpty())
                                editor_path = "notepad";
                        // ファイルpathをsetting.iniで指定されたeditorで開く
                        ShellExecute(NULL,NULL, editor_path, "\""+app->m_app_path+"\\temp\\"+file_name+"\"", NULL, SW_SHOWNORMAL);
                }
                // message/rfc822の場合
                else if(g_cstr_compare(tv->m_md.GetContentType(m_index), "message/rfc822")){
                        if(BASE64 == tv->GetCurrentCTE()){
                                char* in_base64 = body.GetBuffer(0);
                                char* out_base64 = new char[body.GetLength()];
                                int len = from64tobits(out_base64, in_base64, strlen(in_base64));
                                body.Empty();
                                body = out_base64;
                                delete out_base64;
                        }
                        else if(QUOTED_PRINTABLE == tv->GetCurrentCTE()){
                                char* in_qp = body.GetBuffer(0);
                                char* out_qp = new char[body.GetLength()];
                                int len = fromQPtobits(out_qp, in_qp, strlen(in_qp));
                                body.Empty();
                                body = out_qp;
                                delete out_qp;
                        }
                        msg_id = tv->m_md.m_hi.GetMsgID();
                        msg_id = g_ma(msg_id);
                        msg_id.Replace(".", "_");
                        file_name = msg_id + ".txt";

                        if(!g_is_there(app->m_app_path+"\\temp")) /* tempフォルダがない場合は作る */
                                _mkdir(app->m_app_path+"\\temp");

                        FILE* file = fopen(app->m_app_path+"\\temp\\"+file_name, "wb");
                        // sjis変換
                        CCodeConvert cc(body);
                        body = cc.ToSjis();
                        fwrite(body.GetBuffer(0), sizeof(char), body.GetLength(), file);
                        fclose(file);
                        // ファイルを開いちゃう
                        CString editor_path = app->GetProfileString("Editor", "Path", "notepad");
                        if(editor_path.IsEmpty())
                                editor_path = "notepad";
                        // ファイルpathをsetting.iniで指定されたeditorで開く
                        ShellExecute(NULL,NULL, editor_path, "\""+app->m_app_path+"\\temp\\"+file_name+"\"", NULL, SW_SHOWNORMAL);
                }
        }
}

void CMultiPartView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
{
        ExecuteFile();
        *pResult = 0;
}

BOOL CMultiPartView::PreCreateWindow(CREATESTRUCT& cs) 
{
        cs.style |= LVS_SINGLESEL;
        return CListView::PreCreateWindow(cs);
}

void CMultiPartView::OnMultipartSave2file() 
{
        CString path;
        CString b_cstr;
        CStringArray b_cstra;
        CString Outbuf;
        CString file_name;
        char *pOutbuf;
        int len;
        FILE *file;
        CPochyApp *app = (CPochyApp *)AfxGetApp();
        CMainFrame *mf = (CMainFrame *)app->m_pMainWnd;

        CTextView *tv = (CTextView *)mf->m_pTextV;
        CListCtrl& lc = GetListCtrl();

        file_name = tv->m_md.GetFileName(m_index);

        CFileDialog dlg( FALSE, NULL, file_name, OFN_HIDEREADONLY, NULL, this );
        if( dlg.DoModal() == IDOK ){
                path = dlg.GetPathName();
                
                if(g_is_there(path)){
                        if(IDYES != AfxMessageBox(path+"\r\n\r\nは既に存在します。上書きしてもよいですか?", MB_YESNO))
                                return;
                }
                file = fopen(path.GetBuffer(0), "wb");
                tv->m_md.GetBody(m_index, b_cstra);
                g_cstra2cstr(b_cstra, b_cstr, g_cstra_getsize(b_cstra));
                // base64でエンコードされた添付ファイルの場合
                if(tv->GetCurrentCTE() == BASE64){
                        b_cstr.Remove('\r');
                        b_cstr.Remove('\n');
                        pOutbuf = Outbuf.GetBuffer(b_cstr.GetLength());
                        len = from64tobits(pOutbuf, b_cstr.GetBuffer(0), b_cstr.GetLength());
                        fwrite(pOutbuf, sizeof(char), len, file);
                }
                // quoted-printableの場合
                else if(tv->GetCurrentCTE() == QUOTED_PRINTABLE){
                        pOutbuf = Outbuf.GetBuffer(b_cstr.GetLength()+10);
                        len = fromQPtobits(pOutbuf, b_cstr.GetBuffer(0), b_cstr.GetLength());
                        fwrite(pOutbuf, sizeof(char), len, file);
                }
                else{ // その他の場合(7bit 8bit bin
                        CCodeConvert cc(b_cstr);
                        b_cstr = cc.ToSjis();
                        fwrite(b_cstr.GetBuffer(0), sizeof(char), b_cstr.GetLength(), file);
                }
                fclose(file);
        }
}

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