htmlwin.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,495 行 · 第 1/3 页
CPP
1,495 行
/////////////////////////////////////////////////////////////////////////////
// Name: htmlwin.cpp
// Purpose: wxHtmlWindow class for parsing & displaying HTML (implementation)
// Author: Vaclav Slavik
// RCS-ID: $Id: htmlwin.cpp,v 1.109.2.1 2006/01/18 16:48:40 VZ Exp $
// Copyright: (c) 1999 Vaclav Slavik
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "htmlwin.h"
#pragma implementation "htmlproc.h"
#endif
#include "wx/wxprec.h"
#include "wx/defs.h"
#if wxUSE_HTML && wxUSE_STREAMS
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WXPRECOMP
#include "wx/log.h"
#include "wx/intl.h"
#include "wx/dcclient.h"
#include "wx/frame.h"
#endif
#include "wx/html/htmlwin.h"
#include "wx/html/htmlproc.h"
#include "wx/list.h"
#include "wx/clipbrd.h"
#include "wx/dataobj.h"
#include "wx/timer.h"
#include "wx/dcmemory.h"
#include "wx/settings.h"
#include "wx/arrimpl.cpp"
#include "wx/listimpl.cpp"
#if wxUSE_CLIPBOARD
// ----------------------------------------------------------------------------
// wxHtmlWinAutoScrollTimer: the timer used to generate a stream of scroll
// events when a captured mouse is held outside the window
// ----------------------------------------------------------------------------
class wxHtmlWinAutoScrollTimer : public wxTimer
{
public:
wxHtmlWinAutoScrollTimer(wxScrolledWindow *win,
wxEventType eventTypeToSend,
int pos, int orient)
{
m_win = win;
m_eventType = eventTypeToSend;
m_pos = pos;
m_orient = orient;
}
virtual void Notify();
private:
wxScrolledWindow *m_win;
wxEventType m_eventType;
int m_pos,
m_orient;
DECLARE_NO_COPY_CLASS(wxHtmlWinAutoScrollTimer)
};
void wxHtmlWinAutoScrollTimer::Notify()
{
// only do all this as long as the window is capturing the mouse
if ( wxWindow::GetCapture() != m_win )
{
Stop();
}
else // we still capture the mouse, continue generating events
{
// first scroll the window if we are allowed to do it
wxScrollWinEvent event1(m_eventType, m_pos, m_orient);
event1.SetEventObject(m_win);
if ( m_win->GetEventHandler()->ProcessEvent(event1) )
{
// and then send a pseudo mouse-move event to refresh the selection
wxMouseEvent event2(wxEVT_MOTION);
wxGetMousePosition(&event2.m_x, &event2.m_y);
// the mouse event coordinates should be client, not screen as
// returned by wxGetMousePosition
wxWindow *parentTop = m_win;
while ( parentTop->GetParent() )
parentTop = parentTop->GetParent();
wxPoint ptOrig = parentTop->GetPosition();
event2.m_x -= ptOrig.x;
event2.m_y -= ptOrig.y;
event2.SetEventObject(m_win);
// FIXME: we don't fill in the other members - ok?
m_win->GetEventHandler()->ProcessEvent(event2);
}
else // can't scroll further, stop
{
Stop();
}
}
}
#endif // wxUSE_CLIPBOARD
//-----------------------------------------------------------------------------
// wxHtmlHistoryItem
//-----------------------------------------------------------------------------
// item of history list
class WXDLLIMPEXP_HTML wxHtmlHistoryItem
{
public:
wxHtmlHistoryItem(const wxString& p, const wxString& a) {m_Page = p, m_Anchor = a, m_Pos = 0;}
int GetPos() const {return m_Pos;}
void SetPos(int p) {m_Pos = p;}
const wxString& GetPage() const {return m_Page;}
const wxString& GetAnchor() const {return m_Anchor;}
private:
wxString m_Page;
wxString m_Anchor;
int m_Pos;
};
//-----------------------------------------------------------------------------
// our private arrays:
//-----------------------------------------------------------------------------
WX_DECLARE_OBJARRAY(wxHtmlHistoryItem, wxHtmlHistoryArray);
WX_DEFINE_OBJARRAY(wxHtmlHistoryArray);
WX_DECLARE_LIST(wxHtmlProcessor, wxHtmlProcessorList);
WX_DEFINE_LIST(wxHtmlProcessorList);
//-----------------------------------------------------------------------------
// wxHtmlWindow
//-----------------------------------------------------------------------------
void wxHtmlWindow::Init()
{
m_tmpMouseMoved = false;
m_tmpLastLink = NULL;
m_tmpLastCell = NULL;
m_tmpCanDrawLocks = 0;
m_FS = new wxFileSystem();
#if wxUSE_STATUSBAR
m_RelatedStatusBar = -1;
#endif // wxUSE_STATUSBAR
m_RelatedFrame = NULL;
m_TitleFormat = wxT("%s");
m_OpenedPage = m_OpenedAnchor = m_OpenedPageTitle = wxEmptyString;
m_Cell = NULL;
m_Parser = new wxHtmlWinParser(this);
m_Parser->SetFS(m_FS);
m_HistoryPos = -1;
m_HistoryOn = true;
m_History = new wxHtmlHistoryArray;
m_Processors = NULL;
m_Style = 0;
SetBorders(10);
m_selection = NULL;
m_makingSelection = false;
#if wxUSE_CLIPBOARD
m_timerAutoScroll = NULL;
m_lastDoubleClick = 0;
#endif // wxUSE_CLIPBOARD
m_backBuffer = NULL;
m_eraseBgInOnPaint = false;
m_tmpSelFromCell = NULL;
}
bool wxHtmlWindow::Create(wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size,
long style, const wxString& name)
{
if (!wxScrolledWindow::Create(parent, id, pos, size,
style | wxVSCROLL | wxHSCROLL,
name))
return false;
m_Style = style;
SetPage(wxT("<html><body></body></html>"));
return true;
}
wxHtmlWindow::~wxHtmlWindow()
{
#if wxUSE_CLIPBOARD
StopAutoScrolling();
#endif // wxUSE_CLIPBOARD
HistoryClear();
delete m_selection;
delete m_Cell;
if ( m_Processors )
{
WX_CLEAR_LIST(wxHtmlProcessorList, *m_Processors);
}
delete m_Parser;
delete m_FS;
delete m_History;
delete m_Processors;
delete m_backBuffer;
}
void wxHtmlWindow::SetRelatedFrame(wxFrame* frame, const wxString& format)
{
m_RelatedFrame = frame;
m_TitleFormat = format;
}
#if wxUSE_STATUSBAR
void wxHtmlWindow::SetRelatedStatusBar(int bar)
{
m_RelatedStatusBar = bar;
}
#endif // wxUSE_STATUSBAR
void wxHtmlWindow::SetFonts(wxString normal_face, wxString fixed_face, const int *sizes)
{
wxString op = m_OpenedPage;
m_Parser->SetFonts(normal_face, fixed_face, sizes);
// fonts changed => contents invalid, so reload the page:
SetPage(wxT("<html><body></body></html>"));
if (!op.empty())
LoadPage(op);
}
void wxHtmlWindow::SetStandardFonts(int size,
const wxString& normal_face,
const wxString& fixed_face)
{
wxString op = m_OpenedPage;
m_Parser->SetStandardFonts(size, normal_face, fixed_face);
// fonts changed => contents invalid, so reload the page:
SetPage(wxT("<html><body></body></html>"));
if (!op.empty())
LoadPage(op);
}
bool wxHtmlWindow::SetPage(const wxString& source)
{
wxString newsrc(source);
wxDELETE(m_selection);
// we will soon delete all the cells, so clear pointers to them:
m_tmpSelFromCell = NULL;
// pass HTML through registered processors:
if (m_Processors || m_GlobalProcessors)
{
wxHtmlProcessorList::compatibility_iterator nodeL, nodeG;
int prL, prG;
nodeL = (m_Processors) ? m_Processors->GetFirst() : wxHtmlProcessorList::compatibility_iterator();
nodeG = (m_GlobalProcessors) ? m_GlobalProcessors->GetFirst() : wxHtmlProcessorList::compatibility_iterator();
// VS: there are two lists, global and local, both of them sorted by
// priority. Since we have to go through _both_ lists with
// decreasing priority, we "merge-sort" the lists on-line by
// processing that one of the two heads that has higher priority
// in every iteration
while (nodeL || nodeG)
{
prL = (nodeL) ? nodeL->GetData()->GetPriority() : -1;
prG = (nodeG) ? nodeG->GetData()->GetPriority() : -1;
if (prL > prG)
{
if (nodeL->GetData()->IsEnabled())
newsrc = nodeL->GetData()->Process(newsrc);
nodeL = nodeL->GetNext();
}
else // prL <= prG
{
if (nodeG->GetData()->IsEnabled())
newsrc = nodeG->GetData()->Process(newsrc);
nodeG = nodeG->GetNext();
}
}
}
// ...and run the parser on it:
wxClientDC *dc = new wxClientDC(this);
dc->SetMapMode(wxMM_TEXT);
SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF));
SetBackgroundImage(wxNullBitmap);
m_OpenedPage = m_OpenedAnchor = m_OpenedPageTitle = wxEmptyString;
m_Parser->SetDC(dc);
if (m_Cell)
{
delete m_Cell;
m_Cell = NULL;
}
m_Cell = (wxHtmlContainerCell*) m_Parser->Parse(newsrc);
delete dc;
m_Cell->SetIndent(m_Borders, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
m_Cell->SetAlignHor(wxHTML_ALIGN_CENTER);
CreateLayout();
if (m_tmpCanDrawLocks == 0)
Refresh();
return true;
}
bool wxHtmlWindow::AppendToPage(const wxString& source)
{
return SetPage(*(GetParser()->GetSource()) + source);
}
bool wxHtmlWindow::LoadPage(const wxString& location)
{
wxBusyCursor busyCursor;
wxFSFile *f;
bool rt_val;
bool needs_refresh = false;
m_tmpCanDrawLocks++;
if (m_HistoryOn && (m_HistoryPos != -1))
{
// store scroll position into history item:
int x, y;
GetViewStart(&x, &y);
(*m_History)[m_HistoryPos].SetPos(y);
}
if (location[0] == wxT('#'))
{
// local anchor:
wxString anch = location.Mid(1) /*1 to end*/;
m_tmpCanDrawLocks--;
rt_val = ScrollToAnchor(anch);
m_tmpCanDrawLocks++;
}
else if (location.Find(wxT('#')) != wxNOT_FOUND && location.BeforeFirst(wxT('#')) == m_OpenedPage)
{
wxString anch = location.AfterFirst(wxT('#'));
m_tmpCanDrawLocks--;
rt_val = ScrollToAnchor(anch);
m_tmpCanDrawLocks++;
}
else if (location.Find(wxT('#')) != wxNOT_FOUND &&
(m_FS->GetPath() + location.BeforeFirst(wxT('#'))) == m_OpenedPage)
{
wxString anch = location.AfterFirst(wxT('#'));
m_tmpCanDrawLocks--;
rt_val = ScrollToAnchor(anch);
m_tmpCanDrawLocks++;
}
else
{
needs_refresh = true;
#if wxUSE_STATUSBAR
// load&display it:
if (m_RelatedStatusBar != -1)
{
m_RelatedFrame->SetStatusText(_("Connecting..."), m_RelatedStatusBar);
Refresh(false);
}
#endif // wxUSE_STATUSBAR
f = m_Parser->OpenURL(wxHTML_URL_PAGE, location);
// try to interpret 'location' as filename instead of URL:
if (f == NULL)
{
wxFileName fn(location);
wxString location2 = wxFileSystem::FileNameToURL(fn);
f = m_Parser->OpenURL(wxHTML_URL_PAGE, location2);
}
if (f == NULL)
{
wxLogError(_("Unable to open requested HTML document: %s"), location.c_str());
m_tmpCanDrawLocks--;
return false;
}
else
{
wxList::compatibility_iterator node;
wxString src = wxEmptyString;
#if wxUSE_STATUSBAR
if (m_RelatedStatusBar != -1)
{
wxString msg = _("Loading : ") + location;
m_RelatedFrame->SetStatusText(msg, m_RelatedStatusBar);
Refresh(false);
}
#endif // wxUSE_STATUSBAR
node = m_Filters.GetFirst();
while (node)
{
wxHtmlFilter *h = (wxHtmlFilter*) node->GetData();
if (h->CanRead(*f))
{
src = h->ReadFile(*f);
break;
}
node = node->GetNext();
}
if (src == wxEmptyString)
{
if (m_DefaultFilter == NULL) m_DefaultFilter = GetDefaultFilter();
src = m_DefaultFilter->ReadFile(*f);
}
m_FS->ChangePathTo(f->GetLocation());
rt_val = SetPage(src);
m_OpenedPage = f->GetLocation();
if (f->GetAnchor() != wxEmptyString)
{
ScrollToAnchor(f->GetAnchor());
}
delete f;
#if wxUSE_STATUSBAR
if (m_RelatedStatusBar != -1)
m_RelatedFrame->SetStatusText(_("Done"), m_RelatedStatusBar);
#endif // wxUSE_STATUSBAR
}
}
if (m_HistoryOn) // add this page to history there:
{
int c = m_History->GetCount() - (m_HistoryPos + 1);
if (m_HistoryPos < 0 ||
(*m_History)[m_HistoryPos].GetPage() != m_OpenedPage ||
(*m_History)[m_HistoryPos].GetAnchor() != m_OpenedAnchor)
{
m_HistoryPos++;
for (int i = 0; i < c; i++)
m_History->RemoveAt(m_HistoryPos);
m_History->Add(new wxHtmlHistoryItem(m_OpenedPage, m_OpenedAnchor));
}
}
if (m_OpenedPageTitle == wxEmptyString)
OnSetTitle(wxFileNameFromPath(m_OpenedPage));
if (needs_refresh)
{
m_tmpCanDrawLocks--;
Refresh();
}
else
m_tmpCanDrawLocks--;
return rt_val;
}
bool wxHtmlWindow::LoadFile(const wxFileName& filename)
{
wxString url = wxFileSystem::FileNameToURL(filename);
return LoadPage(url);
}
bool wxHtmlWindow::ScrollToAnchor(const wxString& anchor)
{
const wxHtmlCell *c = m_Cell->Find(wxHTML_COND_ISANCHOR, &anchor);
if (!c)
{
wxLogWarning(_("HTML anchor %s does not exist."), anchor.c_str());
return false;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?