root/TextView.cpp
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- IMPLEMENT_DYNCREATE
- CTextView
- BEGIN_MESSAGE_MAP
- AssertValid
- Dump
- OnInitialUpdate
- Font
- OnChar
- GetCurrentPath
- GetCurrentRawHeader
- GetCurrentSubject
- GetCurrentFrom
- GetCurrentTo
- GetCurrentCc
- GetCurrentDate
- GetCurrentMsgID
- GetCurrentBody
- GetCurrentHeader
- GetCurrentCT
- GetCurrentCTE
- GetCurrentReplyTo
- GetCurrentText
- IsPgpMime
- OnLink
- DisplayPart
- Update
- Update2
- OnRButtonDown
- OnPopupCopy
- OnPopupSelall
- OnPopupBrowser
- OnPopupEditor
- OnSetFocus
- SetFontEx
- SetFontColorAndLink
- ReDisplay
- GetFontEx
- Clear
/*
* Copyright (C) 2002-2003 chik, s.hiranaka
* For license terms, see the file COPYING in this directory.
*/
// TextView.cpp : インプリメンテーション ファイル
//
#include "stdafx.h"
#include "Pochy.h"
#include "TextView.h"
#include "FetchMail.h"
#include "CodeConvert.h"
#include "mainfrm.h"
#include "sendmail.h"
#include "PassPhraseDlg.h"
#include "HeaderInfo.h"
#include <Shlwapi.h> // StrStrI プロジェクトの設定のリンクに"Shlwapi.lib"を追加
#include "quoted-printable.h"
#include "base64.h"
//#include "_regex.h"
#include "lib.h"
#include "direct.h" // _mkdir
#include "Gpg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTextView
IMPLEMENT_DYNCREATE(CTextView, CRichEditView)
CTextView::CTextView()
{
m_current_part = -1;
}
CTextView::~CTextView()
{
}
BEGIN_MESSAGE_MAP(CTextView, CRichEditView)
//{{AFX_MSG_MAP(CTextView)
ON_WM_CHAR()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_TEXTVIEW_COPY, OnPopupCopy)
ON_COMMAND(ID_TEXTVIEW_SELALL, OnPopupSelall)
ON_COMMAND(ID_TEXTVIEW_BROWSER, OnPopupBrowser)
ON_COMMAND(ID_TEXTVIEW_EDITOR, OnPopupEditor)
ON_WM_SETFOCUS()
//}}AFX_MSG_MAP
ON_NOTIFY_REFLECT_EX(EN_LINK, OnLink)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTextView 描画
void CTextView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
}
/////////////////////////////////////////////////////////////////////////////
// CTextView 診断
#ifdef _DEBUG
void CTextView::AssertValid() const
{
CRichEditView::AssertValid();
}
void CTextView::Dump(CDumpContext& dc) const
{
CRichEditView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTextView メッセージ ハンドラ
void CTextView::OnInitialUpdate()
{
CRichEditView::OnInitialUpdate();
CPochyApp *app = (CPochyApp *)AfxGetApp();
CRichEditCtrl& r = GetRichEditCtrl();
/* HWND hwnd = r.m_hWnd;
int x = ::SendMessage (hwnd, EM_GETLANGOPTIONS, 0, 0);
x &= ~(IMF_AUTOFONT);
::SendMessage(hwnd, EM_SETLANGOPTIONS, 0, x);*/
LOGFONT lf;
LPBYTE pData;
UINT nSize;
if(app->GetProfileBinary("TextViewFont", "LogFont", &pData, &nSize)){
ASSERT(nSize == sizeof(LOGFONT));
::CopyMemory(&lf, pData, sizeof(LOGFONT));
delete [] pData;
}else{
// ::GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
lf.lfHeight = -16;
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = 400;
lf.lfItalic = 0;
lf.lfUnderline = 0;
lf.lfStrikeOut = 0;
lf.lfCharSet = 128;
lf.lfOutPrecision = 3;
lf.lfClipPrecision = 2;
lf.lfQuality = 1;
lf.lfPitchAndFamily = 49;
strcpy(lf.lfFaceName, "MS ゴシック");
}
this->SetFontEx(lf);
r.SetBackgroundColor(FALSE, 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)));
r.SetReadOnly(TRUE);
this->SetFontColorAndLink();
// if(設定で折り返しなしになっていたら以下を実行)
// m_nWordWrap = WrapNone;
// WrapChanged(); // 折り返しなし
// r.SetOptions(ECOOP_OR,ECO_AUTOHSCROLL);
}
void CTextView::Font()
{
CRichEditCtrl& r = GetRichEditCtrl();
CHARFORMAT cf;
DWORD dwMask = r.GetDefaultCharFormat(cf);
LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "\0"};
if(cf.dwEffects & CFE_STRIKEOUT)
lf.lfStrikeOut = 1;
if(cf.dwEffects & CFE_UNDERLINE)
lf.lfUnderline = 1;
if(cf.dwEffects & CFE_ITALIC)
lf.lfItalic |= 1;
if(cf.dwEffects & CFE_BOLD)
lf.lfWeight = FW_BOLD;
else
lf.lfWeight = FW_NORMAL;
strcpy(lf.lfFaceName, cf.szFaceName);
lf.lfPitchAndFamily = cf.bPitchAndFamily;
lf.lfCharSet = cf.bCharSet;
lf.lfHeight = cf.yHeight * 4/3 * 1/20;
CFontDialog fd(&lf, CF_EFFECTS | CF_SCREENFONTS | CF_BOTH, NULL, this);
fd.m_cf.rgbColors = cf.crTextColor;
if(fd.DoModal() == IDOK){
int minilen = min(strlen(lf.lfFaceName), LF_FACESIZE);
strncpy(cf.szFaceName, lf.lfFaceName, minilen);
cf.bPitchAndFamily = lf.lfPitchAndFamily;
cf.bCharSet = lf.lfCharSet;
cf.yHeight = fd.m_cf.iPointSize * 2;
cf.crTextColor = fd.m_cf.rgbColors;
cf.dwEffects &= ~CFE_AUTOCOLOR;
cf.dwMask = CFM_BOLD | CFM_CHARSET | CFM_COLOR | CFM_FACE | CFM_ITALIC | CFM_SIZE | CFM_OFFSET | CFM_STRIKEOUT | CFM_UNDERLINE;
if(lf.lfStrikeOut)
cf.dwEffects |= CFE_STRIKEOUT;
else
cf.dwEffects &= ~CFE_STRIKEOUT;
if(lf.lfUnderline)
cf.dwEffects |= CFE_UNDERLINE;
else
cf.dwEffects &= ~CFE_UNDERLINE;
if(lf.lfItalic)
cf.dwEffects |= CFE_ITALIC;
else
cf.dwEffects &= ~CFE_ITALIC;
if(lf.lfWeight > FW_NORMAL)
cf.dwEffects |= CFE_BOLD;
else
cf.dwEffects &= ~CFE_BOLD;
r.SetDefaultCharFormat(cf);
Invalidate(TRUE);
}
TRACE("height=%d\n",cf.yHeight);
}
void CTextView::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 '<': // 実装予定
break;
case '>': // 実装予定
break;
default:
break;
}
}
CString CTextView::GetCurrentPath()
{
return m_path;
}
CString CTextView::GetCurrentRawHeader()
{
return m_md.m_hi.GetAllDecoded();
}
CString CTextView::GetCurrentSubject()
{
return m_md.m_hi.GetSubject();
}
CString CTextView::GetCurrentFrom()
{
return m_md.m_hi.GetFrom();
}
CString CTextView::GetCurrentTo()
{
return m_md.m_hi.GetTo();
}
CString CTextView::GetCurrentCc()
{
return m_md.m_hi.GetCc();
}
CString CTextView::GetCurrentDate()
{
return m_md.m_hi.GetDate();
}
CString CTextView::GetCurrentMsgID()
{
return m_md.m_hi.GetMsgID();
}
CString CTextView::GetCurrentBody()
{
return m_body;
}
CString CTextView::GetCurrentHeader()
{
return m_header;
}
CString CTextView::GetCurrentCT()
{
return m_md.GetContentType(m_current_part);
}
int CTextView::GetCurrentCTE()
{
return m_md.GetEncodingType(m_current_part);
}
CString CTextView::GetCurrentReplyTo()
{
return m_md.m_hi.GetReplyTo();
}
CString CTextView::GetCurrentText()
{
return m_text;
}
BOOL CTextView::IsPgpMime()
{
return g_cstr_compare(m_md.m_hi.GetProtocol(), "application/pgp-encrypted");
}
void CTextView::OnLink(NMHDR* in_pNotifyHeader, LRESULT* out_pResult)
{
*out_pResult = 0;
CPochyApp *app = (CPochyApp *)AfxGetApp();
CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
CString current_account = mf->m_pAcntV->GetCurrentAccountName();
ENLINK * pLink = (ENLINK*)in_pNotifyHeader;
if(pLink->msg == WM_LBUTTONDBLCLK && m_onlink != pLink->lParam){
// 二重起動を防ぐために現在のマウスのクリックされたポイントを保存しておく
m_onlink = pLink->lParam; // 苦肉の策
// クリックされたリンクの文字列を取得
GetRichEditCtrl().SetSel(pLink->chrg);
CString link = GetRichEditCtrl().GetSelText();
if(link.Find("mailto:") == 0||link.Find("Mailto:") == 0){
// initialization.
app->m_me.Initialize();
// setting To
if(link.Find("?", 7) != -1) // mailto:hoge@hoge.com?subject=PGP%20Key&Body=Please%20send%20keyとか
// subject, body is not implemented.
app->m_me.SetTo(link.Mid(7, link.Find("?", 7)-7));
else
app->m_me.SetTo(link.Mid(7));
// setting From
CString path = app->m_app_path+"\\"+current_account+"\\account.ini";
CString address;
GetPrivateProfileString("mailbox", "address", "", address.GetBuffer(BUF_LENGTH), BUF_LENGTH, path);
address.ReleaseBuffer();
app->m_me.SetFrom(address);
// getting signature.
CString signature;
g_file2cstring(app->m_app_path+"\\"+current_account+"\\signature", signature);
// set main text.
app->m_me.AddText(signature);
// draftframe
app->CreateDraftFrame(mf->m_pAcntV->GetCurrentAccountName());
}else{
ShellExecute(this->GetSafeHwnd(), _T( "open" ), link, NULL, NULL, SW_NORMAL);
}
}
}
void CTextView::DisplayPart(int part)
{
CPochyApp *app = (CPochyApp *)AfxGetApp();
CStringArray body;
CString message;
CString header;
m_current_part = part;
m_md.GetBody(part, body);
g_cstra2cstr(body, message, g_cstra_getsize(body));
if(m_md.GetFileName(part).IsEmpty()){
// in case of base64 in text/plain or text/html.
if(m_md.GetEncodingType(part) == BASE64){
message.Remove('\r');
message.Remove('\n');
char* in_base64 = message.GetBuffer(0);
char* out_base64 = new char[message.GetLength()];
int len = from64tobits(out_base64, in_base64, strlen(in_base64));
out_base64[len] = 0;
message.Empty();
message = out_base64;
delete out_base64;
}
// in case of quoted-printable in text/plain or text/html
if(m_md.GetEncodingType(part) == QUOTED_PRINTABLE){
// fromQPtobitsの実装があやしい
// implementation of fromQPtobits is weird.
char* in_qp = message.GetBuffer(0);
char* out_qp = new char[message.GetLength()+10]; // これではbufferの容量が足りないみたいで時々これが原因でお亡くなりになることが。。。
// ↑の+10はfromQPtobitsの最後で挿入されるNULL文字文
// +10 mean fromQPtobits insert NULL last.
// CString の GetBuffer はNULL文字は含まないのか????
// not clear that CString::GetBuffer not include NULL ?????
int len = fromQPtobits(out_qp, in_qp, strlen(in_qp));
out_qp[len] = 0;
message.Empty();
message = out_qp;
delete out_qp;
}
CCodeConvert cc(message);
message = cc.ToSjis();
}else{ // in case of attachment file.
if(GetCurrentCTE() == SEVEN_BIT){
CCodeConvert cc(message);
message = cc.ToSjis();
}
else if(GetCurrentCTE() == EIGHT_BIT){
CCodeConvert cc(message);
message = cc.ToSjis();
}else{
message.Format("添付ファイル\r\n%s", m_md.GetFileName(part));
}
}
m_body = message;
// 表示用ヘッダの準備
// prepare for heaer info displayed on textview.
if(!m_md.m_hi.GetTo().IsEmpty())
header += "To: "+m_md.m_hi.GetTo()+"\r\n";
if(!m_md.m_hi.GetCc().IsEmpty())
header += "Cc: "+m_md.m_hi.GetCc()+"\r\n";
if(!m_md.m_hi.GetBcc().IsEmpty())
header += "Bcc: "+m_md.m_hi.GetBcc()+"\r\n";
if(!m_md.m_hi.GetFrom().IsEmpty())
header += "From: "+m_md.m_hi.GetFrom()+"\r\n";
if(!m_md.m_hi.GetSubject().IsEmpty())
header += "Subject: "+m_md.m_hi.GetSubject()+"\r\n";
if(!m_md.m_hi.GetDate().IsEmpty())
header += "Date: "+m_md.m_hi.GetDate()+"\r\n";
if(!m_md.m_hi.GetReplyTo().IsEmpty())
header += "Reply-To: "+m_md.m_hi.GetReplyTo()+"\r\n";
if(!m_md.m_hi.GetXmailer().IsEmpty())
header += "X-Mailer: "+m_md.m_hi.GetXmailer()+"\r\n";
m_header = header;
message = header+"\r\n"+message;
m_text = message;
this->SetWindowText("");
this->SetWindowText(message);
/* CHARFORMAT cf;
GetRichEditCtrl().SetSel(0, header.GetLength());
GetRichEditCtrl().GetSelectionCharFormat(cf);
cf.dwMask = CFM_COLOR|CFM_BACKCOLOR;
cf.crTextColor = RGB(
app->GetProfileInt("TextViewHdColor", "TxtColorR", DEF_HEADER_INFO_COLOR_R),
app->GetProfileInt("TextViewHdColor", "TxtColorG", DEF_HEADER_INFO_COLOR_G),
app->GetProfileInt("TextViewHdColor", "TxtColorB", DEF_HEADER_INFO_COLOR_B));
GetRichEditCtrl().SetSelectionCharFormat(cf);
GetRichEditCtrl().HideSelection(TRUE, FALSE);
GetRichEditCtrl().SetSel(0, 0);*/
this->SetFontColorAndLink();
}
void CTextView::Update(CString path)
{
CPochyApp *app = (CPochyApp *)AfxGetApp();
CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
CListCtrl &lc = mf->m_pMultiV->GetListCtrl();
m_path = path;
// after getting 0st element of MULTIPARTSTRUCT in mimedecode class, and display.
if(path.IsEmpty()){ // if empty, not display.
this->Clear();
}else{
if(!m_md.DoIt(path)){ // analyze mime structure of mail.
this->Clear();
return;
}
DisplayPart(0); // anyway, 0st element of MULTIPARTSTRUCT is on display.
// pgp/mime or not
if(IsPgpMime()&&app->m_gpg_enable)
mf->m_button_gpg_dec = TRUE;
// in case of being not compatible to pgp/mime
else if((-1 != GetCurrentBody().Find("-----BEGIN PGP MESSAGE-----"))&&app->m_gpg_enable)
mf->m_button_gpg_dec = TRUE;
else
mf->m_button_gpg_dec = FALSE;
// setting multipartview
lc.DeleteAllItems();
int n;
if(1 < m_md.HowManyPart()){ // in case of two or more than tree multipart.
n = 0;
CString enc_type;
while(n < m_md.HowManyPart()){
lc.InsertItem(n, m_md.GetContentType(n));
switch(m_md.GetEncodingType(n)){
case BASE64:
enc_type = "base64";
break;
case QUOTED_PRINTABLE:
enc_type = "quoted-printable";
break;
case SEVEN_BIT:
enc_type = "7bit";
break;
}
lc.SetItemText(n, 1, enc_type);
if(!m_md.GetFileName(n).IsEmpty()){
lc.SetItemText(n, 2, m_md.GetFileName(n));
}
n++;
}
mf->HideMultiPartView(FALSE);
// 0番目のアイテムを選択状態にする
// setting 0th item selected.
lc.SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
}
else if(!m_md.GetFileName(0).IsEmpty()){ // in case of only one attachment file.
lc.InsertItem(0, m_md.GetFileName(0));
mf->HideMultiPartView(FALSE);
// setting item of 0 selected.
// 0番目のアイテムを選択状態にする
lc.SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
}
else{ // in case of not multipart, nor number of multipart is one, text/html
// multipartでない、もしくはmultipartの数が1、もしくはtext/htmlのみの場合
mf->HideMultiPartView(TRUE);
}
mf->m_pMultiV->ReArrange();
mf->ReArrangeSplit();
}
}
void CTextView::Update2(CString mail)
{
CPochyApp *app = (CPochyApp *)AfxGetApp();
CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
CListCtrl &lc = mf->m_pMultiV->GetListCtrl();
// 以下mimedecodeのMULTIPARTSTRUCTの0番目の要素を取得して表示
if(mail.IsEmpty()){ // 空の場合は何も表示しない
this->Clear();
}else{
if(!m_md.DoIt2(mail)){ // メールのmime構造を分析する
// メールが壊れていた場合はそのまま表示する。
this->Clear();
return;
}
DisplayPart(0); // 取りあえず、MULTIPARTSTRUCTの0番目の要素を表示
// pgp/mimeかどうか
if(IsPgpMime()&&app->m_gpg_enable)
mf->m_button_gpg_dec = TRUE;
// pgp/mime非対応のpgpメール
else if(-1 != GetCurrentBody().Find("-----BEGIN PGP MESSAGE-----")&&app->m_gpg_enable)
mf->m_button_gpg_dec = TRUE;
else
mf->m_button_gpg_dec = FALSE;
// multipartview の設定
lc.DeleteAllItems();
int n;
if(1 < m_md.HowManyPart()){ // multipart2個以上の場合
n = 0;
CString enc_type;
while(n < m_md.HowManyPart()){
lc.InsertItem(n, m_md.GetContentType(n));
switch(m_md.GetEncodingType(n)){
case BASE64:
enc_type = "base64";
break;
case QUOTED_PRINTABLE:
enc_type = "quoted-printable";
break;
case SEVEN_BIT:
enc_type = "7bit";
break;
}
lc.SetItemText(n, 1, enc_type);
lc.SetItemText(n, 2, m_md.GetFileName(n));
n++;
}
mf->HideMultiPartView(FALSE);
// 0番目のアイテムを選択状態にする
lc.SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
}
else if(!m_md.GetFileName(0).IsEmpty()){ // 添付ファイル1個だけの場合
lc.InsertItem(0, m_md.GetFileName(0));
mf->HideMultiPartView(FALSE);
// 0番目のアイテムを選択状態にする
lc.SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
}
else{ // multipartでない、もしくはmultipartの数が1、もしくはtext/htmlのみの場合
mf->HideMultiPartView(TRUE);
}
mf->m_pMultiV->ReArrange();
mf->ReArrangeSplit();
}
}
void CTextView::OnRButtonDown(UINT nFlags, CPoint point)
{
POINT pt;
PostMessage(WM_NULL, 0, 0); // this is point
GetCursorPos(&pt);
CMenu menu;
menu.LoadMenu(IDR_TEXTVIEW_POPUP);
// 文字列が選択されているかどうか確認
CRichEditCtrl &r = GetRichEditCtrl();
if(r.GetSelText().IsEmpty())
menu.EnableMenuItem(ID_TEXTVIEW_COPY, MF_GRAYED /* 無効 */);
else
menu.EnableMenuItem(ID_TEXTVIEW_COPY, MF_ENABLED /* 有効 */);
// htmlかtextかbinaryか判断する
CMenu *pPopup = menu.GetSubMenu(0);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, (int)pt.x, (int)pt.y, this);
CRichEditView::OnRButtonDown(nFlags, point);
}
void CTextView::OnPopupCopy()
{
// 選択されている文字列をクリップボードにコピーする
CRichEditCtrl &r = GetRichEditCtrl();
r.Copy();
}
void CTextView::OnPopupSelall()
{
// select all
CRichEditCtrl &r = GetRichEditCtrl();
r.SetSel(0, -1);
}
void CTextView::OnPopupBrowser()
{
CPochyApp *app = (CPochyApp *)AfxGetApp();
CStringArray body;
this->m_md.GetBody(this->m_current_part, body);
CString buf;
g_cstra2cstr(body, buf, g_cstra_getsize(body));
if(this->m_md.GetEncodingType(this->m_current_part) == BASE64){
buf.Remove('\r');
buf.Remove('\n');
char* in_base64 = buf.GetBuffer(0);
char* out_base64 = new char[buf.GetLength()];
int len = from64tobits(out_base64, in_base64, strlen(in_base64));
out_base64[len] = 0;
buf.Empty();
buf = out_base64;
delete out_base64;
}
// in case of quoted-printable in text/plain or text/html
else if(this->m_md.GetEncodingType(this->m_current_part) == QUOTED_PRINTABLE){
// fromQPtobitsの実装があやしい
// implementation of fromQPtobits is weird.
char* in_qp = buf.GetBuffer(0);
char* out_qp = new char[buf.GetLength()+10]; // これではbufferの容量が足りないみたいで時々これが原因でお亡くなりになることが。。。
// ↑の+10はfromQPtobitsの最後で挿入されるNULL文字文
// +10 mean fromQPtobits insert NULL last.
// CString の GetBuffer はNULL文字は含まないのか????
// not clear that CString::GetBuffer not include NULL ?????
int len = fromQPtobits(out_qp, in_qp, strlen(in_qp));
out_qp[len] = 0;
buf.Empty();
buf = out_qp;
delete out_qp;
}
CString msg_id;
// use Message-ID for file name
msg_id = m_md.m_hi.GetMsgID();
msg_id = g_ma(msg_id);
msg_id.Replace(".", "_");
if(!g_is_there(app->m_app_path+"\\temp")) // if temp directory not exist, create
_mkdir(app->m_app_path+"\\temp");
g_cstring2file(buf, app->m_app_path+"\\temp\\"+msg_id+".html");
ShellExecute(NULL, "open", app->m_app_path+"\\temp\\"+msg_id+".html", NULL, NULL, SW_SHOW);
}
void CTextView::OnPopupEditor()
{
CPochyApp *app = (CPochyApp *)AfxGetApp();
CString body = GetCurrentHeader()+"\r\n"+GetCurrentBody();
CString msg_id;
// user Message-ID for file name
msg_id = m_md.m_hi.GetMsgID();
msg_id = g_ma(msg_id);
msg_id.Replace(".", "_");
if(!g_is_there(app->m_app_path+"\\temp")) // if temp directory not exist, create
_mkdir(app->m_app_path+"\\temp");
FILE* file = fopen(app->m_app_path+"\\temp\\"+msg_id+".txt", "wb");
fwrite(body.GetBuffer(0), sizeof(char), body.GetLength(), file);
fclose(file);
CString file_path = app->m_app_path+"\\temp\\"+msg_id+".txt";
CString editor_path = app->GetProfileString("Editor", "Path", "notepad");
if(editor_path.IsEmpty())
editor_path = "notepad";
file_path = "\""+file_path+"\"";
// ファイルpathをsetting.iniで指定されたeditorで開く
ShellExecute(NULL, NULL, editor_path, file_path, NULL, SW_SHOWNORMAL);
}
void CTextView::OnSetFocus(CWnd* pOldWnd)
{
CRichEditView::OnSetFocus(pOldWnd);
}
void CTextView::SetFontEx(LOGFONT &lf)
{
CRichEditCtrl &r = GetRichEditCtrl();
m_font.DeleteObject();
if(m_font.CreateFontIndirect(&lf))
r.SetFont(&m_font);
this->SetFontColorAndLink();
}
void CTextView::SetFontColorAndLink()
{
CRichEditCtrl &r = GetRichEditCtrl();
CPochyApp* app = (CPochyApp*)AfxGetApp();
// clickable url を有効にする
long lENM = r.GetEventMask();
lENM |= ENM_LINK;
r.SetEventMask(lENM);
BOOL bEnable = 1;
::SendMessage(m_hWnd, EM_AUTOURLDETECT, bEnable, 0);
// 文字の属性を設定
CHARFORMAT2 cf;
r.GetDefaultCharFormat(cf);
cf.dwMask = CFM_COLOR | CFM_PROTECTED | CFM_FACE | CFM_SIZE | CFM_CHARSET | CFM_SUBSCRIPT;
cf.crTextColor = 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));
cf.dwEffects = CFE_PROTECTED | CFE_SUBSCRIPT;
// cf.bCharSet = CHINESEBIG5_CHARSET;
// strcpy(cf.szFaceName, "MingLiU");//cf.szFaceName
// r.SendMessage(EM_SETCHARFORMAT,(WPARAM)SCF_ALL,(LPARAM)&cf);
r.SetSel(0, -1);
r.SetSelectionCharFormat(cf);
CString mail;
r.GetWindowText(mail);
r.SetSel(0, mail.Find("\r\n\r\n")+2);
r.GetSelectionCharFormat(cf);
cf.dwMask = CFM_COLOR | CFM_BACKCOLOR;
cf.crTextColor = RGB(
app->GetProfileInt("TextViewHdColor", "TxtColorR", DEF_HEADER_INFO_COLOR_R),
app->GetProfileInt("TextViewHdColor", "TxtColorG", DEF_HEADER_INFO_COLOR_G),
app->GetProfileInt("TextViewHdColor", "TxtColorB", DEF_HEADER_INFO_COLOR_B));
r.SetSelectionCharFormat(cf);
r.HideSelection(TRUE, FALSE);
r.SetSel(0, 0);
// 行間を調整する
// PARAFORMAT2 pf;
// pf.cbSize = sizeof(pf);
// pf.dwMask = PFM_LINESPACING | PFM_SPACEAFTER;
// pf.dySpaceAfter = 0;
// pf.bLineSpacingRule = 4;
// pf.dyLineSpacing = 210;
// r.SetSel(0,-1);
// r.SendMessage(EM_SETPARAFORMAT,0,(LPARAM)&pf);
// r.SetSel(0,0);
}
void CTextView::ReDisplay()
{
if(m_current_part != -1)
DisplayPart(m_current_part);
}
CFont *CTextView::GetFontEx()
{
return &m_font;
}
void CTextView::Clear()
{
CPochyApp* app = (CPochyApp*)AfxGetApp();
CMainFrame *mf = (CMainFrame*)app->m_pMainWnd;
this->SetWindowText("");
this->m_current_part = 0;
this->m_body.Empty();
this->m_current_part = -1;
this->m_display_header.Empty();
this->m_header.Empty();
this->m_mail.Empty();
this->m_multipart_header.Empty();
this->m_path.Empty();
mf->HideMultiPartView(TRUE);
}