]> git.saurik.com Git - wxWidgets.git/blame - src/html/htmlwin.cpp
fix for animated GIFs with frames of different dimensions
[wxWidgets.git] / src / html / htmlwin.cpp
CommitLineData
5526e819
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: htmlwin.cpp
3// Purpose: wxHtmlWindow class for parsing & displaying HTML (implementation)
4// Author: Vaclav Slavik
69941f05 5// RCS-ID: $Id$
5526e819
VS
6// Copyright: (c) 1999 Vaclav Slavik
7// Licence: wxWindows Licence
8/////////////////////////////////////////////////////////////////////////////
9
10
11#ifdef __GNUG__
892aeafc
VS
12#pragma implementation "htmlwin.h"
13#pragma implementation "htmlproc.h"
5526e819
VS
14#endif
15
3096bd2f 16#include "wx/wxprec.h"
5526e819
VS
17
18#include "wx/defs.h"
f6bcfd97 19#if wxUSE_HTML && wxUSE_STREAMS
5526e819
VS
20
21#ifdef __BORDLANDC__
22#pragma hdrstop
23#endif
24
25#ifndef WXPRECOMP
04dbb646
VZ
26 #include "wx/log.h"
27 #include "wx/intl.h"
28 #include "wx/dcclient.h"
29 #include "wx/frame.h"
5526e819
VS
30#endif
31
69941f05 32#include "wx/html/htmlwin.h"
892aeafc 33#include "wx/html/htmlproc.h"
892aeafc 34#include "wx/list.h"
04dbb646
VZ
35
36#include "wx/arrimpl.cpp"
892aeafc
VS
37#include "wx/listimpl.cpp"
38
39//-----------------------------------------------------------------------------
40// wxHtmlHistoryItem
41//-----------------------------------------------------------------------------
42
43// item of history list
44class WXDLLEXPORT wxHtmlHistoryItem : public wxObject
45{
46public:
47 wxHtmlHistoryItem(const wxString& p, const wxString& a) {m_Page = p, m_Anchor = a, m_Pos = 0;}
48 int GetPos() const {return m_Pos;}
49 void SetPos(int p) {m_Pos = p;}
50 const wxString& GetPage() const {return m_Page;}
51 const wxString& GetAnchor() const {return m_Anchor;}
52
53private:
54 wxString m_Page;
55 wxString m_Anchor;
56 int m_Pos;
57};
5526e819 58
5526e819
VS
59
60//-----------------------------------------------------------------------------
892aeafc 61// our private arrays:
5526e819
VS
62//-----------------------------------------------------------------------------
63
892aeafc
VS
64WX_DECLARE_OBJARRAY(wxHtmlHistoryItem, wxHtmlHistoryArray);
65WX_DEFINE_OBJARRAY(wxHtmlHistoryArray);
5526e819 66
892aeafc
VS
67WX_DECLARE_LIST(wxHtmlProcessor, wxHtmlProcessorList);
68WX_DEFINE_LIST(wxHtmlProcessorList);
5526e819 69
892aeafc
VS
70//-----------------------------------------------------------------------------
71// wxHtmlWindow
72//-----------------------------------------------------------------------------
5526e819
VS
73
74
269e8200 75wxHtmlWindow::wxHtmlWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
f6bcfd97 76 long style, const wxString& name) : wxScrolledWindow(parent, id, pos, size, style | wxVSCROLL | wxHSCROLL, name)
5526e819
VS
77{
78 m_tmpMouseMoved = FALSE;
846914d1 79 m_tmpLastLink = NULL;
f6010d8f 80 m_tmpLastCell = NULL;
89de9af3 81 m_tmpCanDrawLocks = 0;
5526e819
VS
82 m_FS = new wxFileSystem();
83 m_RelatedStatusBar = -1;
84 m_RelatedFrame = NULL;
892aeafc 85 m_TitleFormat = wxT("%s");
d5db80c2 86 m_OpenedPage = m_OpenedAnchor = m_OpenedPageTitle = wxEmptyString;
5526e819
VS
87 m_Cell = NULL;
88 m_Parser = new wxHtmlWinParser(this);
4f9297b0 89 m_Parser->SetFS(m_FS);
5526e819
VS
90 SetBorders(10);
91 m_HistoryPos = -1;
92 m_HistoryOn = TRUE;
892aeafc
VS
93 m_History = new wxHtmlHistoryArray;
94 m_Processors = NULL;
a547ebff 95 m_Style = style;
4f9297b0 96 SetPage(wxT("<html><body></body></html>"));
5526e819
VS
97}
98
99
100
101wxHtmlWindow::~wxHtmlWindow()
102{
103 HistoryClear();
104
105 if (m_Cell) delete m_Cell;
106
5526e819
VS
107 delete m_Parser;
108 delete m_FS;
892aeafc
VS
109 delete m_History;
110 delete m_Processors;
5526e819
VS
111}
112
113
114
115void wxHtmlWindow::SetRelatedFrame(wxFrame* frame, const wxString& format)
116{
117 m_RelatedFrame = frame;
118 m_TitleFormat = format;
119}
120
121
122
123void wxHtmlWindow::SetRelatedStatusBar(int bar)
124{
125 m_RelatedStatusBar = bar;
126}
269e8200
RD
127
128
129
8eb2940f 130void wxHtmlWindow::SetFonts(wxString normal_face, wxString fixed_face, const int *sizes)
5526e819 131{
d5db80c2
VS
132 wxString op = m_OpenedPage;
133
4f9297b0 134 m_Parser->SetFonts(normal_face, fixed_face, sizes);
892aeafc 135 // fonts changed => contents invalid, so reload the page:
bfb9ee96 136 SetPage(wxT("<html><body></body></html>"));
d5db80c2 137 if (!op.IsEmpty()) LoadPage(op);
5526e819
VS
138}
139
140
141
142bool wxHtmlWindow::SetPage(const wxString& source)
143{
892aeafc
VS
144 wxString newsrc(source);
145
146 // pass HTML through registered processors:
960ba969 147 if (m_Processors || m_GlobalProcessors)
892aeafc 148 {
960ba969
VS
149 wxHtmlProcessorList::Node *nodeL, *nodeG;
150 int prL, prG;
892aeafc
VS
151
152 nodeL = (m_Processors) ? m_Processors->GetFirst() : NULL;
960ba969
VS
153 nodeG = (m_GlobalProcessors) ? m_GlobalProcessors->GetFirst() : NULL;
154
155 // VS: there are two lists, global and local, both of them sorted by
e421922f 156 // priority. Since we have to go through _both_ lists with
960ba969
VS
157 // decreasing priority, we "merge-sort" the lists on-line by
158 // processing that one of the two heads that has higher priority
159 // in every iteration
160 while (nodeL || nodeG)
892aeafc
VS
161 {
162 prL = (nodeL) ? nodeL->GetData()->GetPriority() : -1;
960ba969
VS
163 prG = (nodeG) ? nodeG->GetData()->GetPriority() : -1;
164 if (prL > prG)
892aeafc 165 {
73348d09
VS
166 if (nodeL->GetData()->IsEnabled())
167 newsrc = nodeL->GetData()->Process(newsrc);
892aeafc
VS
168 nodeL = nodeL->GetNext();
169 }
960ba969 170 else // prL <= prG
892aeafc 171 {
73348d09
VS
172 if (nodeG->GetData()->IsEnabled())
173 newsrc = nodeG->GetData()->Process(newsrc);
960ba969 174 nodeG = nodeG->GetNext();
892aeafc
VS
175 }
176 }
177 }
5526e819 178
892aeafc
VS
179 // ...and run the parser on it:
180 wxClientDC *dc = new wxClientDC(this);
4f9297b0 181 dc->SetMapMode(wxMM_TEXT);
5526e819 182 SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF));
d5db80c2 183 m_OpenedPage = m_OpenedAnchor = m_OpenedPageTitle = wxEmptyString;
4f9297b0 184 m_Parser->SetDC(dc);
33ac7e6f 185 if (m_Cell)
4f9297b0 186 {
89de9af3
VS
187 delete m_Cell;
188 m_Cell = NULL;
f61815af 189 }
892aeafc 190 m_Cell = (wxHtmlContainerCell*) m_Parser->Parse(newsrc);
5526e819 191 delete dc;
4f9297b0
VS
192 m_Cell->SetIndent(m_Borders, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
193 m_Cell->SetAlignHor(wxHTML_ALIGN_CENTER);
5526e819 194 CreateLayout();
bfb9ee96 195 if (m_tmpCanDrawLocks == 0)
892aeafc 196 Refresh();
5526e819
VS
197 return TRUE;
198}
199
39029898
VS
200bool wxHtmlWindow::AppendToPage(const wxString& source)
201{
202 return SetPage(*(GetParser()->GetSource()) + source);
203}
5526e819
VS
204
205bool wxHtmlWindow::LoadPage(const wxString& location)
206{
207 wxFSFile *f;
208 bool rt_val;
fc7dfaf8 209 bool needs_refresh = FALSE;
33ac7e6f 210
169ee06c 211 SetCursor(*wxHOURGLASS_CURSOR);
fc7dfaf8 212 wxYield(); Refresh(FALSE);
5526e819 213
89de9af3 214 m_tmpCanDrawLocks++;
e421922f 215 if (m_HistoryOn && (m_HistoryPos != -1))
4f9297b0 216 {
960ba969 217 // store scroll position into history item:
5526e819 218 int x, y;
e421922f 219 GetViewStart(&x, &y);
892aeafc 220 (*m_History)[m_HistoryPos].SetPos(y);
5526e819
VS
221 }
222
e421922f 223 if (location[0] == wxT('#'))
4f9297b0 224 {
960ba969 225 // local anchor:
5526e819 226 wxString anch = location.Mid(1) /*1 to end*/;
89de9af3 227 m_tmpCanDrawLocks--;
5526e819 228 rt_val = ScrollToAnchor(anch);
fc7dfaf8
VS
229 m_tmpCanDrawLocks++;
230 }
33ac7e6f 231 else if (location.Find(wxT('#')) != wxNOT_FOUND && location.BeforeFirst(wxT('#')) == m_OpenedPage)
4f9297b0 232 {
fc7dfaf8
VS
233 wxString anch = location.AfterFirst(wxT('#'));
234 m_tmpCanDrawLocks--;
235 rt_val = ScrollToAnchor(anch);
236 m_tmpCanDrawLocks++;
237 }
33ac7e6f
KB
238 else if (location.Find(wxT('#')) != wxNOT_FOUND &&
239 (m_FS->GetPath() + location.BeforeFirst(wxT('#'))) == m_OpenedPage)
e421922f 240 {
fc7dfaf8
VS
241 wxString anch = location.AfterFirst(wxT('#'));
242 m_tmpCanDrawLocks--;
243 rt_val = ScrollToAnchor(anch);
244 m_tmpCanDrawLocks++;
5526e819
VS
245 }
246
33ac7e6f 247 else
4f9297b0 248 {
fc7dfaf8 249 needs_refresh = TRUE;
5526e819 250 // load&display it:
33ac7e6f 251 if (m_RelatedStatusBar != -1)
e421922f 252 {
4f9297b0 253 m_RelatedFrame->SetStatusText(_("Connecting..."), m_RelatedStatusBar);
fc7dfaf8 254 Refresh(FALSE);
5526e819
VS
255 }
256
4f9297b0 257 f = m_FS->OpenFile(location);
33ac7e6f
KB
258
259 if (f == NULL)
e421922f 260 {
f6bcfd97 261 wxLogError(_("Unable to open requested HTML document: %s"), location.c_str());
89de9af3 262 m_tmpCanDrawLocks--;
169ee06c
VS
263
264 SetCursor(*wxSTANDARD_CURSOR);
5526e819
VS
265 return FALSE;
266 }
267
33ac7e6f 268 else
e421922f 269 {
5526e819
VS
270 wxNode *node;
271 wxString src = wxEmptyString;
272
33ac7e6f 273 if (m_RelatedStatusBar != -1)
e421922f 274 {
5526e819 275 wxString msg = _("Loading : ") + location;
4f9297b0 276 m_RelatedFrame->SetStatusText(msg, m_RelatedStatusBar);
fc7dfaf8 277 Refresh(FALSE);
5526e819
VS
278 }
279
280 node = m_Filters.GetFirst();
4f9297b0 281 while (node)
e421922f 282 {
4f9297b0
VS
283 wxHtmlFilter *h = (wxHtmlFilter*) node->GetData();
284 if (h->CanRead(*f))
e421922f 285 {
4f9297b0 286 src = h->ReadFile(*f);
5526e819
VS
287 break;
288 }
4f9297b0 289 node = node->GetNext();
5526e819 290 }
33ac7e6f 291 if (src == wxEmptyString)
e421922f 292 {
89de9af3 293 if (m_DefaultFilter == NULL) m_DefaultFilter = GetDefaultFilter();
4f9297b0 294 src = m_DefaultFilter->ReadFile(*f);
89de9af3 295 }
5526e819 296
4f9297b0 297 m_FS->ChangePathTo(f->GetLocation());
5526e819 298 rt_val = SetPage(src);
4f9297b0 299 m_OpenedPage = f->GetLocation();
33ac7e6f 300 if (f->GetAnchor() != wxEmptyString)
e421922f 301 {
fc7dfaf8 302 wxYield();
4f9297b0 303 ScrollToAnchor(f->GetAnchor());
5526e819
VS
304 }
305
306 delete f;
307
4f9297b0 308 if (m_RelatedStatusBar != -1) m_RelatedFrame->SetStatusText(_("Done"), m_RelatedStatusBar);
5526e819
VS
309 }
310 }
311
4f9297b0
VS
312 if (m_HistoryOn) // add this page to history there:
313 {
892aeafc 314 int c = m_History->GetCount() - (m_HistoryPos + 1);
5526e819 315
0cb9cfb2 316 if (m_HistoryPos < 0 ||
ee19c324
VS
317 (*m_History)[m_HistoryPos].GetPage() != m_OpenedPage ||
318 (*m_History)[m_HistoryPos].GetAnchor() != m_OpenedAnchor)
319 {
320 m_HistoryPos++;
321 for (int i = 0; i < c; i++)
b54e41c5 322 m_History->RemoveAt(m_HistoryPos);
ee19c324
VS
323 m_History->Add(new wxHtmlHistoryItem(m_OpenedPage, m_OpenedAnchor));
324 }
5526e819
VS
325 }
326
096824d7
VS
327 if (m_OpenedPageTitle == wxEmptyString)
328 OnSetTitle(wxFileNameFromPath(m_OpenedPage));
169ee06c 329 SetCursor(*wxSTANDARD_CURSOR);
fc7dfaf8 330
33ac7e6f 331 if (needs_refresh)
4f9297b0 332 {
fc7dfaf8
VS
333 wxYield();
334 m_tmpCanDrawLocks--;
335 Refresh();
336 }
337 else
338 m_tmpCanDrawLocks--;
339
5526e819
VS
340 return rt_val;
341}
342
343
344
345bool wxHtmlWindow::ScrollToAnchor(const wxString& anchor)
346{
4f9297b0 347 const wxHtmlCell *c = m_Cell->Find(wxHTML_COND_ISANCHOR, &anchor);
f3c82859
VS
348 if (!c)
349 {
f6bcfd97 350 wxLogWarning(_("HTML anchor %s does not exist."), anchor.c_str());
f3c82859
VS
351 return FALSE;
352 }
33ac7e6f 353 else
4f9297b0 354 {
5526e819 355 int y;
269e8200 356
4f9297b0 357 for (y = 0; c != NULL; c = c->GetParent()) y += c->GetPosY();
efba2b89 358 Scroll(-1, y / wxHTML_SCROLL_STEP);
5526e819
VS
359 m_OpenedAnchor = anchor;
360 return TRUE;
361 }
362}
363
364
d5db80c2 365void wxHtmlWindow::OnSetTitle(const wxString& title)
5526e819 366{
33ac7e6f 367 if (m_RelatedFrame)
4f9297b0 368 {
5526e819
VS
369 wxString tit;
370 tit.Printf(m_TitleFormat, title.c_str());
4f9297b0 371 m_RelatedFrame->SetTitle(tit);
5526e819 372 }
d5db80c2 373 m_OpenedPageTitle = title;
5526e819
VS
374}
375
376
377
378
379
380void wxHtmlWindow::CreateLayout()
381{
382 int ClientWidth, ClientHeight;
383
384 if (!m_Cell) return;
a547ebff 385
33ac7e6f 386 if (m_Style & wxHW_SCROLLBAR_NEVER)
4f9297b0
VS
387 {
388 SetScrollbars(wxHTML_SCROLL_STEP, 1, m_Cell->GetWidth() / wxHTML_SCROLL_STEP, 0); // always off
a547ebff 389 GetClientSize(&ClientWidth, &ClientHeight);
4f9297b0 390 m_Cell->Layout(ClientWidth);
a547ebff
VS
391 }
392
393 else {
394 GetClientSize(&ClientWidth, &ClientHeight);
4f9297b0 395 m_Cell->Layout(ClientWidth);
33ac7e6f 396 if (ClientHeight < m_Cell->GetHeight() + GetCharHeight())
e421922f 397 {
f3bcfd9b
VS
398 SetScrollbars(
399 wxHTML_SCROLL_STEP, wxHTML_SCROLL_STEP,
4f9297b0
VS
400 m_Cell->GetWidth() / wxHTML_SCROLL_STEP,
401 (m_Cell->GetHeight() + GetCharHeight()) / wxHTML_SCROLL_STEP
f3bcfd9b 402 /*cheat: top-level frag is always container*/);
a547ebff 403 }
4f9297b0 404 else /* we fit into window, no need for scrollbars */
e421922f 405 {
4f9297b0 406 SetScrollbars(wxHTML_SCROLL_STEP, 1, m_Cell->GetWidth() / wxHTML_SCROLL_STEP, 0); // disable...
89de9af3 407 GetClientSize(&ClientWidth, &ClientHeight);
4f9297b0 408 m_Cell->Layout(ClientWidth); // ...and relayout
89de9af3 409 }
a547ebff 410 }
5526e819
VS
411}
412
269e8200 413
5526e819
VS
414
415void wxHtmlWindow::ReadCustomization(wxConfigBase *cfg, wxString path)
416{
417 wxString oldpath;
418 wxString tmp;
d5db80c2
VS
419 int p_fontsizes[7];
420 wxString p_fff, p_ffn;
5526e819 421
33ac7e6f 422 if (path != wxEmptyString)
4f9297b0
VS
423 {
424 oldpath = cfg->GetPath();
425 cfg->SetPath(path);
5526e819
VS
426 }
427
892aeafc
VS
428 m_Borders = cfg->Read(wxT("wxHtmlWindow/Borders"), m_Borders);
429 p_fff = cfg->Read(wxT("wxHtmlWindow/FontFaceFixed"), m_Parser->m_FontFaceFixed);
430 p_ffn = cfg->Read(wxT("wxHtmlWindow/FontFaceNormal"), m_Parser->m_FontFaceNormal);
bfb9ee96 431 for (int i = 0; i < 7; i++)
4f9297b0 432 {
66a77a74 433 tmp.Printf(wxT("wxHtmlWindow/FontsSize%i"), i);
4f9297b0 434 p_fontsizes[i] = cfg->Read(tmp, m_Parser->m_FontsSizes[i]);
5526e819 435 }
8eb2940f 436 SetFonts(p_ffn, p_fff, p_fontsizes);
5526e819
VS
437
438 if (path != wxEmptyString)
4f9297b0 439 cfg->SetPath(oldpath);
5526e819
VS
440}
441
442
443
444void wxHtmlWindow::WriteCustomization(wxConfigBase *cfg, wxString path)
445{
446 wxString oldpath;
447 wxString tmp;
448
33ac7e6f 449 if (path != wxEmptyString)
4f9297b0
VS
450 {
451 oldpath = cfg->GetPath();
452 cfg->SetPath(path);
5526e819
VS
453 }
454
892aeafc
VS
455 cfg->Write(wxT("wxHtmlWindow/Borders"), (long) m_Borders);
456 cfg->Write(wxT("wxHtmlWindow/FontFaceFixed"), m_Parser->m_FontFaceFixed);
457 cfg->Write(wxT("wxHtmlWindow/FontFaceNormal"), m_Parser->m_FontFaceNormal);
bfb9ee96 458 for (int i = 0; i < 7; i++)
4f9297b0 459 {
66a77a74 460 tmp.Printf(wxT("wxHtmlWindow/FontsSize%i"), i);
4f9297b0 461 cfg->Write(tmp, (long) m_Parser->m_FontsSizes[i]);
5526e819
VS
462 }
463
464 if (path != wxEmptyString)
4f9297b0 465 cfg->SetPath(oldpath);
5526e819
VS
466}
467
468
469
470bool wxHtmlWindow::HistoryBack()
471{
472 wxString a, l;
473
474 if (m_HistoryPos < 1) return FALSE;
475
bbda1088
VS
476 // store scroll position into history item:
477 int x, y;
e421922f 478 GetViewStart(&x, &y);
892aeafc 479 (*m_History)[m_HistoryPos].SetPos(y);
bbda1088
VS
480
481 // go to previous position:
5526e819
VS
482 m_HistoryPos--;
483
892aeafc
VS
484 l = (*m_History)[m_HistoryPos].GetPage();
485 a = (*m_History)[m_HistoryPos].GetAnchor();
5526e819 486 m_HistoryOn = FALSE;
89de9af3 487 m_tmpCanDrawLocks++;
5526e819 488 if (a == wxEmptyString) LoadPage(l);
fc7dfaf8 489 else LoadPage(l + wxT("#") + a);
5526e819 490 m_HistoryOn = TRUE;
c88293a4 491 wxYield();
89de9af3 492 m_tmpCanDrawLocks--;
892aeafc 493 Scroll(0, (*m_History)[m_HistoryPos].GetPos());
5526e819
VS
494 Refresh();
495 return TRUE;
496}
497
1b113a81
VS
498bool wxHtmlWindow::HistoryCanBack()
499{
500 if (m_HistoryPos < 1) return FALSE;
501 return TRUE ;
502}
5526e819
VS
503
504
505bool wxHtmlWindow::HistoryForward()
506{
507 wxString a, l;
508
509 if (m_HistoryPos == -1) return FALSE;
892aeafc 510 if (m_HistoryPos >= (int)m_History->GetCount() - 1)return FALSE;
5526e819
VS
511
512 m_OpenedPage = wxEmptyString; // this will disable adding new entry into history in LoadPage()
513
514 m_HistoryPos++;
892aeafc
VS
515 l = (*m_History)[m_HistoryPos].GetPage();
516 a = (*m_History)[m_HistoryPos].GetAnchor();
5526e819 517 m_HistoryOn = FALSE;
89de9af3 518 m_tmpCanDrawLocks++;
5526e819 519 if (a == wxEmptyString) LoadPage(l);
fc7dfaf8 520 else LoadPage(l + wxT("#") + a);
5526e819 521 m_HistoryOn = TRUE;
c88293a4 522 wxYield();
89de9af3 523 m_tmpCanDrawLocks--;
892aeafc 524 Scroll(0, (*m_History)[m_HistoryPos].GetPos());
5526e819
VS
525 Refresh();
526 return TRUE;
527}
528
1b113a81
VS
529bool wxHtmlWindow::HistoryCanForward()
530{
531 if (m_HistoryPos == -1) return FALSE;
892aeafc 532 if (m_HistoryPos >= (int)m_History->GetCount() - 1)return FALSE;
1b113a81
VS
533 return TRUE ;
534}
5526e819
VS
535
536
537void wxHtmlWindow::HistoryClear()
538{
892aeafc 539 m_History->Empty();
5526e819
VS
540 m_HistoryPos = -1;
541}
542
892aeafc
VS
543void wxHtmlWindow::AddProcessor(wxHtmlProcessor *processor)
544{
545 if (!m_Processors)
546 {
547 m_Processors = new wxHtmlProcessorList;
548 m_Processors->DeleteContents(TRUE);
549 }
550 wxHtmlProcessorList::Node *node;
bfb9ee96 551
892aeafc
VS
552 for (node = m_Processors->GetFirst(); node; node = node->GetNext())
553 {
bfb9ee96 554 if (processor->GetPriority() > node->GetData()->GetPriority())
892aeafc
VS
555 {
556 m_Processors->Insert(node, processor);
960ba969 557 return;
892aeafc
VS
558 }
559 }
960ba969 560 m_Processors->Append(processor);
892aeafc
VS
561}
562
960ba969 563/*static */ void wxHtmlWindow::AddGlobalProcessor(wxHtmlProcessor *processor)
892aeafc 564{
960ba969 565 if (!m_GlobalProcessors)
892aeafc 566 {
960ba969
VS
567 m_GlobalProcessors = new wxHtmlProcessorList;
568 m_GlobalProcessors->DeleteContents(TRUE);
892aeafc
VS
569 }
570 wxHtmlProcessorList::Node *node;
e421922f 571
960ba969 572 for (node = m_GlobalProcessors->GetFirst(); node; node = node->GetNext())
892aeafc 573 {
bfb9ee96 574 if (processor->GetPriority() > node->GetData()->GetPriority())
892aeafc 575 {
960ba969
VS
576 m_GlobalProcessors->Insert(node, processor);
577 return;
892aeafc
VS
578 }
579 }
960ba969 580 m_GlobalProcessors->Append(processor);
892aeafc
VS
581}
582
5526e819
VS
583
584
585wxList wxHtmlWindow::m_Filters;
a76015e6 586wxHtmlFilter *wxHtmlWindow::m_DefaultFilter = NULL;
66806a0b
VS
587wxCursor *wxHtmlWindow::s_cur_hand = NULL;
588wxCursor *wxHtmlWindow::s_cur_arrow = NULL;
960ba969 589wxHtmlProcessorList *wxHtmlWindow::m_GlobalProcessors = NULL;
a76015e6
VS
590
591void wxHtmlWindow::CleanUpStatics()
592{
892aeafc 593 delete m_DefaultFilter;
a76015e6 594 m_DefaultFilter = NULL;
269e8200
RD
595 m_Filters.DeleteContents(TRUE);
596 m_Filters.Clear();
960ba969
VS
597 delete m_GlobalProcessors;
598 m_GlobalProcessors = NULL;
892aeafc
VS
599 delete s_cur_hand;
600 delete s_cur_arrow;
a76015e6
VS
601}
602
603
5526e819
VS
604
605void wxHtmlWindow::AddFilter(wxHtmlFilter *filter)
606{
5526e819
VS
607 m_Filters.Append(filter);
608}
609
610
611
612
0b2dadd3 613void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
5526e819 614{
0b2dadd3 615 LoadPage(link.GetHref());
5526e819
VS
616}
617
f6010d8f
VZ
618void wxHtmlWindow::OnCellClicked(wxHtmlCell *cell,
619 wxCoord x, wxCoord y,
620 const wxMouseEvent& event)
19193a2c 621{
f6010d8f 622 wxCHECK_RET( cell, _T("can't be called with NULL cell") );
5526e819 623
f6010d8f
VZ
624 cell->OnMouseClick(this, x, y, event);
625}
626
627void wxHtmlWindow::OnCellMouseHover(wxHtmlCell * WXUNUSED(cell),
628 wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
629{
630 // do nothing here
631}
5526e819
VS
632
633void wxHtmlWindow::OnDraw(wxDC& dc)
634{
635 int x, y;
636 wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
637 int v_y, v_h;
638
89de9af3 639 if (m_tmpCanDrawLocks > 0) return;
33ac7e6f 640
5526e819 641 dc.SetMapMode(wxMM_TEXT);
5526e819 642 dc.SetBackgroundMode(wxTRANSPARENT);
e421922f 643 GetViewStart(&x, &y);
5526e819 644
33ac7e6f 645 while (upd)
4f9297b0 646 {
5526e819
VS
647 v_y = upd.GetY();
648 v_h = upd.GetH();
4f9297b0 649 if (m_Cell) m_Cell->Draw(dc, 0, 0, y * wxHTML_SCROLL_STEP + v_y, y * wxHTML_SCROLL_STEP + v_h + v_y);
5526e819
VS
650 upd++;
651 }
652}
653
654
655
656
657void wxHtmlWindow::OnSize(wxSizeEvent& event)
658{
659 wxScrolledWindow::OnSize(event);
660 CreateLayout();
f6bcfd97 661 Refresh();
5526e819
VS
662}
663
664
5526e819
VS
665void wxHtmlWindow::OnMouseEvent(wxMouseEvent& event)
666{
667 m_tmpMouseMoved = TRUE;
668
33ac7e6f 669 if (event.ButtonDown())
4f9297b0 670 {
f6010d8f
VZ
671 if ( m_Cell )
672 {
673 int sx, sy;
674 GetViewStart(&sx, &sy);
675 sx *= wxHTML_SCROLL_STEP;
676 sy *= wxHTML_SCROLL_STEP;
5526e819 677
f6010d8f
VZ
678 wxPoint pos = event.GetPosition();
679 pos.x += sx;
680 pos.y += sy;
5526e819 681
f6010d8f
VZ
682 wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
683
684 // VZ: is it possible that we don't find anything at all?
d168485f
VS
685 // VS: yes. FindCellByPos returns terminal cell and
686 // containers may have empty borders
f6010d8f
VZ
687 if ( cell )
688 OnCellClicked(cell, pos.x, pos.y, event);
689 }
5526e819
VS
690 }
691}
692
693
694
33ac7e6f 695void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
5526e819 696{
33ac7e6f 697 if (s_cur_hand == NULL)
66806a0b
VS
698 {
699 s_cur_hand = new wxCursor(wxCURSOR_HAND);
700 s_cur_arrow = new wxCursor(wxCURSOR_ARROW);
701 }
5526e819 702
33ac7e6f 703 if (m_tmpMouseMoved && (m_Cell != NULL))
4f9297b0 704 {
5526e819 705 int sx, sy;
0cb9cfb2
VZ
706 GetViewStart(&sx, &sy);
707 sx *= wxHTML_SCROLL_STEP;
708 sy *= wxHTML_SCROLL_STEP;
5526e819 709
0cb9cfb2 710 int x, y;
5526e819
VS
711 wxGetMousePosition(&x, &y);
712 ScreenToClient(&x, &y);
f6010d8f
VZ
713 x += sx;
714 y += sy;
0cb9cfb2 715
f6010d8f
VZ
716 wxHtmlCell *cell = m_Cell->FindCellByPos(x, y);
717 if ( cell != m_tmpLastCell )
e421922f 718 {
f6010d8f
VZ
719 wxHtmlLinkInfo *lnk = cell ? cell->GetLink(x, y) : NULL;
720
721 if (lnk != m_tmpLastLink)
e421922f 722 {
f6010d8f
VZ
723 if (lnk == NULL)
724 {
725 SetCursor(*s_cur_arrow);
726 if (m_RelatedStatusBar != -1)
727 m_RelatedFrame->SetStatusText(wxEmptyString, m_RelatedStatusBar);
728 }
729 else
730 {
731 SetCursor(*s_cur_hand);
732 if (m_RelatedStatusBar != -1)
733 m_RelatedFrame->SetStatusText(lnk->GetHref(), m_RelatedStatusBar);
734 }
735 m_tmpLastLink = lnk;
622ea783 736 }
f6010d8f
VZ
737
738 m_tmpLastCell = cell;
5526e819 739 }
f6010d8f
VZ
740 else // mouse moved but stayed in the same cell
741 {
742 if ( cell )
743 OnCellMouseHover(cell, x, y);
744 }
745
5526e819
VS
746 m_tmpMouseMoved = FALSE;
747 }
748}
749
750
bfb9ee96 751IMPLEMENT_ABSTRACT_CLASS(wxHtmlProcessor,wxObject)
5526e819
VS
752
753IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow)
754
755BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
756 EVT_SIZE(wxHtmlWindow::OnSize)
757 EVT_LEFT_DOWN(wxHtmlWindow::OnMouseEvent)
0cb9cfb2 758 EVT_RIGHT_DOWN(wxHtmlWindow::OnMouseEvent)
5526e819
VS
759 EVT_MOTION(wxHtmlWindow::OnMouseEvent)
760 EVT_IDLE(wxHtmlWindow::OnIdle)
5526e819
VS
761END_EVENT_TABLE()
762
763
764
765
766
a76015e6
VS
767// A module to allow initialization/cleanup
768// without calling these functions from app.cpp or from
769// the user's application.
770
771class wxHtmlWinModule: public wxModule
772{
773DECLARE_DYNAMIC_CLASS(wxHtmlWinModule)
774public:
775 wxHtmlWinModule() : wxModule() {}
776 bool OnInit() { return TRUE; }
777 void OnExit() { wxHtmlWindow::CleanUpStatics(); }
778};
779
780IMPLEMENT_DYNAMIC_CLASS(wxHtmlWinModule, wxModule)
781
5526e819 782
0cecad31
VS
783// This hack forces the linker to always link in m_* files
784// (wxHTML doesn't work without handlers from these files)
785#include "wx/html/forcelnk.h"
786FORCE_WXHTML_MODULES()
5526e819 787
19193a2c 788#endif