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

📄 chmhtmlwindow.cpp

📁 一个CHM在LINUX下的使用工具
💻 CPP
字号:
/*  Copyright (C) 2003  Razvan Cojocaru <razvanco@gmx.net>  Mac OS specific patches contributed by Chanler White   <cawhite@nwrails.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, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <chmhtmlwindow.h>#include <contenttaghandler.h>#include <chminputstream.h>#include <chmframe.h>#include <wx/wx.h>#include <wx/log.h>#include <wx/clipbrd.h>CHMHtmlWindow::CHMHtmlWindow(wxWindow *parent, wxTreeCtrl *tc,			     CHMFrame *frame)	: wxHtmlWindow(parent, -1, wxDefaultPosition, wxSize(200,200)),	  _tcl(tc), _syncTree(true), _found(false), _menu(NULL), 	  _absolute(false), _frame(frame), _link(NULL), _fdlg(NULL){	_menu = new wxMenu;	_menu->Append(ID_PopupForward, _("For&ward"));	_menu->Append(ID_PopupBack, _("&Back"));	_menu->Append(ID_CopyLink, _("Copy &link location"));	_menu->AppendSeparator();	_menu->Append(ID_CopySel, _("&Copy selection"));	_menu->AppendSeparator();	_menu->Append(ID_PopupFind, _("&Find in page.."));}CHMHtmlWindow::~CHMHtmlWindow(){	delete _menu;	delete _fdlg;}bool CHMHtmlWindow::LoadPage(const wxString& location){	//wxLogNull log;	wxString tmp = location;	// Path is already absolute.	if(_absolute) {		FixRelativePath(tmp, wxEmptyString);		_absolute = false;	} else		FixRelativePath(tmp, GetPrefix(GetOpenedPage()));	if(!tmp.Left(19).CmpNoCase(wxT("javascript:fullsize"))) 		tmp = tmp.AfterFirst(wxT('\'')).BeforeLast(wxT('\''));	_prefix = GetPrefix(tmp);	if(_syncTree && 	   // We should be looking for a valid page, not / (home).	   !location.AfterLast(wxT('/')).IsEmpty() && 	   _tcl->GetCount() > 1) {		wxString srch;		if(tmp.StartsWith(wxT("/")) || tmp.StartsWith(wxT("file:")))			srch = tmp.AfterLast(wxT(':')).AfterFirst(				wxT('/')).BeforeFirst(wxT('#'));		else			srch = tmp.BeforeFirst(wxT('#'));				// Sync will call SelectItem() on the tree item		// if it finds one, and that in turn will call		// LoadPage() with _syncTree set to false.		Sync(_tcl->GetRootItem(), srch);		if(_found)			_found = false;	}	return wxHtmlWindow::LoadPage(tmp);}void CHMHtmlWindow::Sync(wxTreeItemId root, const wxString& page){	if(_found)		return;	URLTreeItem *data = reinterpret_cast<URLTreeItem *>(		_tcl->GetItemData(root));	wxString url;	if(data)		url = (data->_url).BeforeFirst(wxT('#'));	if(data && (!url.CmpNoCase(page) || 		    !url.CmpNoCase(GetPrefix(GetOpenedPage()) + wxT("/") 				   + page))) {		// Order counts!		_found = true;		_tcl->SelectItem(root);		return;	}	wxTreeItemIdValue cookie;	wxTreeItemId child = _tcl->GetFirstChild(root, cookie);	for(size_t i = 0; i < _tcl->GetChildrenCount(root, FALSE); ++i) {		Sync(child, page);		child = _tcl->GetNextChild(root, cookie);	}}inline wxString CHMHtmlWindow::GetPrefix(const wxString& location) const{	return location.AfterLast(wxT(':')).AfterFirst(		wxT('/')).BeforeLast(wxT('/'));}bool CHMHtmlWindow::FixRelativePath(wxString &location,				    const wxString& prefix) const{	if(!location.Left(5).CmpNoCase(wxT("file:")) || 	   !location.Left(5).CmpNoCase(wxT("http:")) ||	   !location.Left(6).CmpNoCase(wxT("https:")) ||	   !location.Left(4).CmpNoCase(wxT("ftp:")) ||	   !location.Left(7).CmpNoCase(wxT("mailto:")) ||	   !location.Left(7).CmpNoCase(wxT("ms-its:")) ||	   !location.Left(10).CmpNoCase(wxT("javascript")) ||	   location.StartsWith(wxT("#")))		return false;	  	CHMFile *chmf = CHMInputStream::GetCache();	if(!chmf)		return false;	bool result = location.StartsWith(wxT(".."));	wxString prf = prefix;	while(location.StartsWith(wxT(".."))) {		location = location.AfterFirst(wxT('/'));		prf = prf.BeforeLast(wxT('/'));	}	if(location.StartsWith(wxT("./")))		location = location.AfterFirst(wxT('/'));			if(!prf.IsEmpty())		prf = wxString(wxT("/")) + prf;	// Handle absolute paths too (that start with /)	if(!location.StartsWith(wxT("/")))		location = wxString(wxT("file:")) + chmf->ArchiveName() + 			wxT("#xchm:") + prf + wxT("/") + location;	else		location = wxString(wxT("file:")) + chmf->ArchiveName() + 			wxT("#xchm:") + location;	// Don't redirect for simple relative paths that wxHTML can	// handle by itself.	return result;}wxHtmlOpeningStatus CHMHtmlWindow::OnOpeningURL(wxHtmlURLType type,						const wxString& url, 						wxString *redirect) const{	if(type == wxHTML_URL_PAGE)		return wxHTML_OPEN;	wxString tmp = url;	if(FixRelativePath(tmp, _prefix)) {		*redirect = tmp;		return wxHTML_REDIRECT;	}	return wxHTML_OPEN;}void CHMHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link){	wxString url = link.GetHref();	LoadPage(url);	if(!url.Left(7).CmpNoCase(wxT("MS-ITS:")))		_frame->UpdateCHMInfo();}wxHtmlCell* CHMHtmlWindow::FindFirst(wxHtmlCell *parent, const wxString& word,				     bool wholeWords, bool caseSensitive){	wxString tmp = word;		if(!parent)		return NULL; 	if(!caseSensitive)		tmp.MakeLower();	// If this cell is not a container, the for body will never happen	// (GetFirstChild() will return NULL).	for(wxHtmlCell *cell = parent->GetFirstChild(); cell; 	    cell = cell->GetNext()) {				wxHtmlCell *result;		if((result = FindFirst(cell, word, wholeWords, caseSensitive)))			return result;	}	wxHtmlSelection ws;	ws.Set(parent, parent);	wxString text = parent->ConvertToText(&ws);	if(text.IsEmpty())		return NULL;	if(!caseSensitive)		text.MakeLower();	text.Trim(TRUE);	text.Trim(FALSE);	bool found = false;	if(wholeWords && text == tmp) {		found = true;	} else if(!wholeWords && text.Find(tmp.c_str()) != -1) {		found = true;	}	if(found) {		// What is all this wxWidgets protected member crap?		delete m_selection;		m_selection = new wxHtmlSelection();		// !! Must see if this works now. !!		m_selection->Set(parent, parent);				int y;		wxHtmlCell *cell = parent;		for (y = 0; cell != NULL; cell = cell->GetParent()) 			y += cell->GetPosY();		Scroll(-1, y / wxHTML_SCROLL_STEP);		Refresh();				return parent;	}	return NULL;}wxHtmlCell* CHMHtmlWindow::FindNext(wxHtmlCell *start, const wxString& word, 				    bool wholeWords, bool caseSensitive){	wxHtmlCell *cell;	if(!start)		return NULL;	for(cell = start; cell; cell = cell->GetNext()) {		wxHtmlCell *result;		if((result = FindFirst(cell, word, wholeWords, caseSensitive)))			return result;	}	cell = start->GetParent();		while(cell && !cell->GetNext())		cell = cell->GetParent();	if(!cell)		return NULL;	return FindNext(cell->GetNext(), word, wholeWords, caseSensitive);}void CHMHtmlWindow::ClearSelection(){	delete m_selection;	m_selection = NULL;	Refresh();}void CHMHtmlWindow::OnCopy(wxCommandEvent& WXUNUSED(event)){	CopySelection();}void CHMHtmlWindow::OnFind(wxCommandEvent& WXUNUSED(event)){	if(!_fdlg) {		wxWindow* p = GetParent();		while(p->GetParent())			p = p->GetParent();		_fdlg = new CHMFindDialog(p, this);	}	_fdlg->CentreOnParent();	_fdlg->ShowModal();	_fdlg->SetFocusToTextBox();	_fdlg->Reset();}void CHMHtmlWindow::OnForward(wxCommandEvent& WXUNUSED(event)){	HistoryForward();}void CHMHtmlWindow::OnBack(wxCommandEvent& WXUNUSED(event)){	HistoryBack();}void CHMHtmlWindow::OnCopyLink(wxCommandEvent& WXUNUSED(event)){	if(wxTheClipboard->Open()) {		wxTheClipboard->SetData(			new wxTextDataObject(_link->GetHref()));		wxTheClipboard->Close();	}}void CHMHtmlWindow::OnRightClick(wxMouseEvent& event){	if(IsSelectionEnabled())		_menu->Enable(ID_CopySel, m_selection != NULL);	_menu->Enable(ID_PopupForward, HistoryCanForward());	_menu->Enable(ID_PopupBack, HistoryCanBack());	_menu->Enable(ID_CopyLink, false);	wxHtmlCell *cell = 		m_Cell->FindCellByPos(event.m_x, event.m_y);	if(cell) {		_link = cell->GetLink();		if(_link) {			_menu->Enable(ID_CopyLink, true);		}	}	PopupMenu(_menu, event.GetPosition());}#ifdef __WXMAC__/* This is a hack, consisting of copying the relevent event handler from   the wxWidgets src/generic/scrlwing.cpp file to make up for the fact that for   some reason, compiling wxWidgets with scroll wheel support is exposing a    crashing bug on OS X.   When this gets fixed in wxWidgets, this should prob be just removed.. */void CHMHtmlWindow::HandleOnMouseWheel(wxMouseEvent& event){	int m_wheelRotation = 0;	m_wheelRotation += event.GetWheelRotation();	int lines = m_wheelRotation / event.GetWheelDelta();	m_wheelRotation -= lines * event.GetWheelDelta();	if (lines != 0)	{		wxScrollWinEvent newEvent;		newEvent.SetPosition(0);		newEvent.SetOrientation(wxVERTICAL);		newEvent.m_eventObject = m_win;		if (event.IsPageScroll())		{			if (lines > 0)				newEvent.m_eventType = 					wxEVT_SCROLLWIN_PAGEUP;			else				newEvent.m_eventType = 					wxEVT_SCROLLWIN_PAGEDOWN;			m_win->GetEventHandler()->ProcessEvent(newEvent);		} else {			lines *= event.GetLinesPerAction();			if (lines > 0)				newEvent.m_eventType = 					wxEVT_SCROLLWIN_LINEUP;			else				newEvent.m_eventType = 					wxEVT_SCROLLWIN_LINEDOWN;			int times = abs(lines);			for (; times > 0; times--)				m_win->GetEventHandler()					->ProcessEvent(newEvent);		}	}}#endifBEGIN_EVENT_TABLE(CHMHtmlWindow, wxHtmlWindow)	EVT_MENU(ID_CopySel, CHMHtmlWindow::OnCopy)	EVT_MENU(ID_PopupFind, CHMHtmlWindow::OnFind)	EVT_MENU(ID_PopupForward, CHMHtmlWindow::OnForward)	EVT_MENU(ID_PopupBack, CHMHtmlWindow::OnBack)	EVT_MENU(ID_CopyLink, CHMHtmlWindow::OnCopyLink)	EVT_RIGHT_DOWN(CHMHtmlWindow::OnRightClick)#ifdef __WXMAC__	EVT_MOUSEWHEEL(CHMHtmlWindow::HandleOnMouseWheel)#endifEND_EVENT_TABLE()

⌨️ 快捷键说明

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