⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 articleview.cpp.svn-base

📁 wince c++ 下 开发的 rss 阅读器源代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/**
 *  ArticleView.cpp
 *
 *  Copyright (C) 2008  David Andrs <pda@jasnapaka.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"
#include "prssr.h"
#include "../share/UIHelper.h"
#include "ArticleView.h"

#include "../share/date.h"
#include "../share/fs.h"
#include "../share/str.h"
#include "misc.h"
#include "Config.h"
#include "Feed.h"
#include "MainFrm.h"
#include "Appearance.h"
#include "Errors.h"

#ifdef MYDEBUG
#undef THIS_FILE
static TCHAR THIS_FILE[] = _T(__FILE__);
#include "debug\crtdbg.h"
#define new MYDEBUG_NEW
#endif

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


static DWORD MakeRGBVal(COLORREF clr) {
	return (GetRValue(clr) << 16) | (GetGValue(clr) << 8) | GetBValue(clr);
}

///

void OpenOnlineMessage(const CString &link, CSiteItem *si) {
	LOG1(1, "OpenOnlineMessage('%S')", link);

	CString url = SanitizeUrl(link);
	if (IsHTMLCached(url, TRUE)) {
		CString fileName = UrlToFileName(MakeAbsoluteUrl(url, _T(""), _T("")), TRUE);
		CString path = GetCachePath(FILE_TYPE_HTML, Config.CacheLocation);
		url = MakeOfflineUrl(path, fileName);
	}
	else {
		// first try to rewrite the URL
		if (Config.UseHtmlOptimizer && Config.OpenMsgWithHtmlOptimizer) url = MakeHtmlOptimizerUrl(url, Config.HtmlOptimizerURL);
		else url = RewriteUrl(url, Config.RewriteRules);
	}

	OpenUrlExt(url);
}

///////

/////////////////////////////////////////////////////////////////////////////
// CArticleView dialog

CArticleView::CArticleView() {
	//{{AFX_DATA_INIT(CArticleView)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	HotSpot = FALSE;

	m_pArticle = NULL;

	InFullScreen = FALSE;
}

CArticleView::~CArticleView() {
	delete m_pArticle;
}

BEGIN_MESSAGE_MAP(CArticleView, CHTMLCtrl)
	//{{AFX_MSG_MAP(CArticleView)
	ON_WM_INITMENUPOPUP()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_HOTKEY, OnHotKey)

	ON_COMMAND(ID_ITEM_FLAG, OnItemFlag)
	ON_UPDATE_COMMAND_UI(ID_ITEM_FLAG, OnUpdateItemFlag)
	ON_COMMAND(ID_ITEM_OPEN, OnItemOpen)
	ON_COMMAND(ID_REFRESH, OnRefresh)
	ON_COMMAND(ID_COPY_URL, OnCopyUrl)
	ON_COMMAND(ID_EDIT_COPY, OnCopy)
	ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateCopy)

	ON_COMMAND(ID_ENCLOSURE_OPEN, OnEnclosureOpen)
	ON_UPDATE_COMMAND_UI(ID_ENCLOSURE_OPEN, OnUpdateEnclosureOpen)
	ON_COMMAND(ID_ENCLOSURE_GET, OnEnclosureGet)
	ON_UPDATE_COMMAND_UI(ID_ENCLOSURE_GET, OnUpdateEnclosureGet)
	ON_COMMAND(ID_ENCLOSURE_DELETE, OnEnclosureDelete)
	ON_UPDATE_COMMAND_UI(ID_ENCLOSURE_DELETE, OnUpdateEnclosureDelete)

	ON_COMMAND(ID_OPEN_LINK, OnLinkOpen)
	ON_COMMAND(ID_DOWNLOAD_LINK, OnLinkDownload)

	ON_COMMAND_RANGE(ID_SOCIAL_BOOKMARK_BASE, ID_SOCIAL_BOOKMARK_BASE + 100, OnBookmarkLink)
	ON_COMMAND(ID_SEND_BY_EMAIL, OnSendByEmail)
	ON_COMMAND(ID_FULLSCREEN, OnFullscreen)
	ON_UPDATE_COMMAND_UI(ID_FULLSCREEN, OnUpdateFullscreen)

	ON_COMMAND(ID_VIEW_IMAGE, OnViewImage)
	ON_COMMAND(ID_COPY_IMAGE_LOCATION, OnCopyImageLocation)
END_MESSAGE_MAP()

void CArticleView::SetFeedItem(CFeedItem *fi) {
	delete m_pArticle;
	m_pArticle = new CFeedItem(*fi);
}

void CArticleView::ShowArticle() {
	LOG0(1, "CArticleView::ShowFeedItem()");

//	// reposition controls before displaying the article (enclosure bar may get hidden or visible)
//	ResizeControls();

	CString sText, sTemp;

	::SendMessage(GetSafeHwnd(), WM_SETTEXT, 0, (LPARAM) (LPCTSTR) _T(""));
	Clear();
	EnableContextMenu(TRUE);

	EnableClearType(Appearance.ClearType);
	EnableScripting(FALSE);
	ZoomLevel(1);

	AddText(L"<html>");
	AddText(L"<head>");
	CString strCSS;
	strCSS.Format(
		L"<style type=\"text/css\"><!-- "
		L"body { font-family: \"%s\"; font-size: %dpt; } "
		L"--></style>",
		Appearance.ArticleFontCfg.FontFace, Appearance.ArticleFontCfg.Size
	);
	AddText(strCSS);

	AddText(L"</head>");

	sText.Format(_T("<body bgcolor=#%x text=#%x>"),
		MakeRGBVal(Appearance.ClrArticleBg), MakeRGBVal(Appearance.ClrArticleFg));
	AddText(sText);

	sText.Format(_T("<font face=\"%s\">"), Appearance.ArticleFontCfg.FontFace);
	AddText(sText);

	// FIXME: critical section
	if (m_pArticle != NULL) {
		AddText(L"<p><strong>");
		AddText(m_pArticle->Title);
		AddText(L"</strong></p>");

		BOOL cached = IsHTMLCached(m_pArticle->Link, TRUE);

		if (cached && Config.AdvancedHtmlOptimizer) {
			HANDLE file;
			CString fileName = GetCacheFile(FILE_TYPE_HTML, Config.CacheLocation, m_pArticle->Link);
			if ((file = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) {
				do {
					char buffer[1024] = { 0 };
					DWORD read;
					BOOL res = ReadFile(file, buffer, 1023, &read, NULL);
					if (res && (read == 0)) break;

					CString text = CharToWChar(buffer, CP_UTF8);
					AddText(text);
				} while (TRUE);

				CloseHandle(file);
			}
			else {
				CString text;
				text.Format(_T("Could not open the cached HTML file: %s"), fileName);
				AddText(text);
			}
		}
		else {
			// translate
			CString description;
			description.Format(_T("<div>%s</div>"), m_pArticle->Description);		// workaround for libsgml
			AddText(L"<p>");
			AddText(description);
			AddText(L"</p>");

			// author
			sText.Empty();
			if (!m_pArticle->Author.IsEmpty())
				sText += m_pArticle->Author + _T(" | ");
			// date/time
			CString sDateTime;
			SYSTEMTIME st = TimeToTimeZone(&m_pArticle->PubDate);		// convert to local time zone
			FormatDateTime(sDateTime, st, Config.ShowRelativeDates);
			sText += sDateTime;

			// keywords
			if (m_pArticle->HasKeywordMatch()) {
				AddText(L"<p>Keywords: ");
				for (int i = 0; i < m_pArticle->KeywordPos.GetSize(); i++) {
					if (i > 0) AddText(L", ");
					AddText(Config.Keywords.GetAt(i));
				}
				AddText(L"</p>");
			}

			AddText(L"<p><font color=\"#aaa\">");
			AddText(sText);
			AddText(L"</font></p>");

			// horz divider
			AddText(L"<hr/>");

			sTemp.LoadString(IDS_LINK_TO_ARTICLE);
			if (cached)
				sText.Format(_T("<a href=\"%s\"><strong>%s</strong></a>"), m_pArticle->Link, sTemp);
			else
				sText.Format(_T("<a href=\"%s\">%s</a>"), m_pArticle->Link, sTemp);

			AddText(L"<p>");
			AddText(sText);
			AddText(L"</p>");
		}
	}
	else {
		sTemp.Format(IDS_NOTHING_TO_DISPLAY);
		AddText(L"<p>");
		AddText(sTemp);
		AddText(L"</p>");
	}
	AddText(L"</font>");

	AddText(L"</body>");
	AddText(L"</html>");

	EndOfSource();
}

void CArticleView::CreateMenu(HWND hwndCmdBar) {
	// create menu for the right Softkey
	TBBUTTON tb;
	::SendMessage(hwndCmdBar, TB_GETBUTTON, 1, (LPARAM) &tb);

	CMenu mnu;
	mnu.Attach((HMENU) tb.dwData);
	while (mnu.GetMenuItemCount() > 0)
		mnu.DeleteMenu(0, MF_BYPOSITION);

	AppendMenuFromResource(&mnu, IDR_OPEN);
	if (m_pArticle != NULL && m_pArticle->HasEnclosure()) {
		AppendMenuFromResource(&mnu, IDR_ENCLOSURES);
	}
	mnu.AppendMenu(MF_SEPARATOR);
	AppendMenuFromResource(&mnu, IDR_ITEM_FLAG);
	AppendMenuFromResource(&mnu, IDR_COPY_URL);
	// bookmark
	AppendBookmarkMenu(&mnu);
	AppendMenuFromResource(&mnu, IDR_SEND_BY_EMAIL);
	AppendMenuFromResource(&mnu, IDR_FULLSCREEN);
	mnu.AppendMenu(MF_SEPARATOR);
//	AppendMenuFromResource(&mnu, IDR_REFRESH);
	AppendMenuFromResource(&mnu, IDR_EXIT);

	mnu.Detach();
}

void CArticleView::OnScrollUp() {
	LOG0(1, "CArticleView::OnScrollUp()");

	SCROLLINFO si;
	HWND hSB = ::GetWindow(GetSafeHwnd(), GW_CHILD);
	if (hSB == NULL)
		hSB = GetSafeHwnd();

	si.cbSize = sizeof(SCROLLINFO);
	si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
	::GetScrollInfo(hSB, SB_VERT, &si);

	if (si.nPos == 0) {
		// at the top of the message move to the previous one
		OnItemPrev();
	}
	else {
		// scroll the message up
		::SendMessage(hSB, WM_VSCROLL, SB_LINEUP, NULL);
	}
}

void CArticleView::OnScrollDown() {
	LOG0(1, "CArticleView::OnScrollDown()");

	SCROLLINFO si;
	HWND hSB = ::GetWindow(GetSafeHwnd(), GW_CHILD);
	if (hSB == NULL)
		hSB = GetSafeHwnd();

	si.cbSize = sizeof(SCROLLINFO);
	si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
	::GetScrollInfo(hSB, SB_VERT, &si);

	if (si.nPos + (int) si.nPage > si.nMax) {
		// at the top of the message move to the previous one
		OnItemNext();
	}
	else {
		// scroll the message up
		::SendMessage(hSB, WM_VSCROLL, SB_LINEDOWN, NULL);
	}
}

BOOL CArticleView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) {
	LOG0(5, "CArticleView::OnNotify()");

	NMHDR *pnmh = (LPNMHDR) lParam;
	if (pnmh != NULL) {
		NM_HTMLVIEW *pnmHTML = (NM_HTMLVIEW *) lParam;

		if (pnmh->code == NM_HOTSPOT) {
			HotSpot = TRUE;
			OpenOnlineMessage(pnmHTML->szTarget, m_pArticle->SiteItem);

			*pResult = 1;
			return 1;
		}
		else if (pnmh->code == NM_CONTEXTMENU) {
			OnContextMenu((NM_HTMLCONTEXT *) lParam);
			*pResult = 1;
			return 1;
		}
		else if (pnmh->code == NM_INLINE_IMAGE) {
			if (IsHTMLCached(pnmHTML->szTarget, FALSE)) {
				// rewrite the source of the image to the cache
				m_strImageLoc = MakeOfflineUrl(GetCacheFile(FILE_TYPE_IMAGE, Config.CacheLocation, pnmHTML->szTarget));
				pnmHTML->szTarget = m_strImageLoc;

				*pResult = 0;	// use default handling of an image
				return 0;
			}
			else {
				// not cached -> show empty box
				CSiteItem *si= m_pArticle->SiteItem;

				BOOL cacheImgs;
				if (si->Info->UseGlobalCacheOptions)
					cacheImgs = Config.CacheImages;
				else
					cacheImgs = si->Info->CacheItemImages;

				if (Config.WorkOffline || !cacheImgs) {
					::SendMessage(GetSafeHwnd(), DTM_IMAGEFAIL, 0, (LPARAM) (INLINEIMAGEINFO*) pnmHTML->dwCookie);
					*pResult = 1;
					return 1;
				}
				else {
					*pResult = 0;	// use default handling of an image
					return 0;
				}
			}
		}
	}

	return CWnd::OnNotify(wParam, lParam, pResult);
}

void CArticleView::AppendBookmarkMenu(CMenu *menu) {
	// bookmarking
	if (Config.SocialBookmarkSites.GetSize() > 1) {
		// create popup menu
		HMENU hSubMenu = CreatePopupMenu();

		for (int i = 0; i < Config.SocialBookmarkSites.GetSize(); i++) {
			CSocialBookmarkSite *sbs = Config.SocialBookmarkSites[i];
			::AppendMenu(hSubMenu, MF_STRING | MF_ENABLED, ID_SOCIAL_BOOKMARK_BASE + i, sbs->Name);
		}

		CString sText;
		sText.Format(IDS_BOOKMARK_AT, _T(""));
		menu->AppendMenu(MF_POPUP, (UINT) hSubMenu, sText);
	}
	else {
		CSocialBookmarkSite *sbs = Config.SocialBookmarkSites[0];

		CString sText;
		sText.Format(IDS_BOOKMARK_AT, sbs->Name);
		menu->AppendMenu(MF_STRING, ID_SOCIAL_BOOKMARK_BASE, sText);
	}
}

void CArticleView::ContextMenu(CPoint point) {
	LOG0(3, "CArticleView::ContextMenu()");

	CMenu popup;
	popup.CreatePopupMenu();

	m_strContextMnuUrl.Empty();
	m_strContextMenuLinkName.Empty();

	AppendMenuFromResource(&popup, IDR_OPEN);
	if (m_pArticle->HasEnclosure()) {
		AppendMenuFromResource(&popup, IDR_ENCLOSURES);
	}
	popup.AppendMenu(MF_SEPARATOR);
	AppendBookmarkMenu(&popup);
	AppendMenuFromResource(&popup, IDR_SEND_BY_EMAIL);
	AppendMenuFromResource(&popup, IDR_COPY_URL);

	popup.AppendMenu(MF_SEPARATOR);
	AppendMenuFromResource(&popup, IDR_ITEM_FLAG);
	AppendMenuFromResource(&popup, IDR_COPY);
	AppendMenuFromResource(&popup, IDR_FULLSCREEN);

	popup.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, GetParent());
}

void CArticleView::OnContextMenu(NM_HTMLCONTEXT *pnmhc) {
	LOG0(3, "CArticleView::OnContextMenu()");

	CMenu popup;
	popup.CreatePopupMenu();

	if (pnmhc->uTypeFlags & HTMLCONTEXT_LINK) {
		m_strContextMnuUrl = pnmhc->szLinkHREF;
		m_strContextMenuLinkName = pnmhc->szLinkName;

		AppendMenuFromResource(&popup, IDR_LINK_CTX);
		popup.InsertMenu(1, MF_SEPARATOR | MF_BYPOSITION);
		AppendBookmarkMenu(&popup);
		AppendMenuFromResource(&popup, IDR_SEND_BY_EMAIL);
		AppendMenuFromResource(&popup, IDR_COPY_LINK_URL);
	}
	else if (pnmhc->uTypeFlags & (HTMLCONTEXT_IMAGE | HTMLCONTEXT_IMAGENOTLOADED)) {
		m_strContextMnuUrl = pnmhc->szLinkHREF;
		m_strContextMenuLinkName = pnmhc->szLinkName;

		AppendMenuFromResource(&popup, IDR_ARTICLE_IMAGE);
		AppendMenuFromResource(&popup, IDR_SEND_BY_EMAIL);
	}
	else {
		m_strContextMnuUrl.Empty();
		m_strContextMenuLinkName.Empty();

		AppendMenuFromResource(&popup, IDR_OPEN);
		if (m_pArticle->HasEnclosure()) {
			AppendMenuFromResource(&popup, IDR_ENCLOSURES);
		}
		popup.AppendMenu(MF_SEPARATOR);
		AppendBookmarkMenu(&popup);
		AppendMenuFromResource(&popup, IDR_SEND_BY_EMAIL);
		AppendMenuFromResource(&popup, IDR_COPY_URL);
	}

	popup.AppendMenu(MF_SEPARATOR);
	AppendMenuFromResource(&popup, IDR_ITEM_FLAG);
	AppendMenuFromResource(&popup, IDR_COPY);
	AppendMenuFromResource(&popup, IDR_FULLSCREEN);

	//
	CPoint point = pnmhc->pt;
	popup.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, GetParent());
}

LRESULT CArticleView::OnHotKey(WPARAM wParam, LPARAM lParam) {
	LOG0(3, "CArticleView::OnHotKey()");

	return 0;
}

void CArticleView::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu) {
	LOG0(3, "CArticleView::OnInitMenuPopup()");

	if (bSysMenu)
		return; // don't support system menu

	ASSERT(pMenu != NULL); // check the enabled state of various menu items
	CCmdUI state;
	state.m_pMenu = pMenu;
	ASSERT(state.m_pOther == NULL);
	ASSERT(state.m_pParentMenu == NULL);

	// determine if menu is popup in top-level menu and set m_pOther to
	// it if so (m_pParentMenu == NULL indicates that it is secondary popup)
	HMENU hParentMenu;
	if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
		state.m_pParentMenu = pMenu; // parent == child for tracking popup
	else if ((hParentMenu = ::WCE_FCTN(GetMenu)(m_hWnd)) != NULL) {
		CWnd *pParent = GetTopLevelParent(); // child windows don't have menus -- need to go to the top!

		if (pParent != NULL &&
			(hParentMenu = ::WCE_FCTN(GetMenu)(pParent->m_hWnd)) != NULL)
		{
			int nIndexMax = ::WCE_FCTN(GetMenuItemCount)(hParentMenu);
			for (int nIndex = 0; nIndex < nIndexMax; nIndex++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -