]> git.saurik.com Git - wxWidgets.git/blame - src/html/htmlwin.cpp
blind fix for wxGIFDecoder::ReadGIF
[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{
b835e9bf 635 if (m_tmpCanDrawLocks > 0 || m_Cell == NULL) return;
5526e819 636
b835e9bf
VS
637 int x, y;
638 wxRect rect = GetUpdateRegion().GetBox();
33ac7e6f 639
5526e819 640 dc.SetMapMode(wxMM_TEXT);
5526e819 641 dc.SetBackgroundMode(wxTRANSPARENT);
e421922f 642 GetViewStart(&x, &y);
5526e819 643
b835e9bf
VS
644 m_Cell->Draw(dc, 0, 0,
645 y * wxHTML_SCROLL_STEP + rect.GetTop(),
646 y * wxHTML_SCROLL_STEP + rect.GetBottom());
5526e819
VS
647}
648
649
650
651
652void wxHtmlWindow::OnSize(wxSizeEvent& event)
653{
654 wxScrolledWindow::OnSize(event);
655 CreateLayout();
f6bcfd97 656 Refresh();
5526e819
VS
657}
658
659
5526e819
VS
660void wxHtmlWindow::OnMouseEvent(wxMouseEvent& event)
661{
662 m_tmpMouseMoved = TRUE;
663
33ac7e6f 664 if (event.ButtonDown())
4f9297b0 665 {
f6010d8f
VZ
666 if ( m_Cell )
667 {
668 int sx, sy;
669 GetViewStart(&sx, &sy);
670 sx *= wxHTML_SCROLL_STEP;
671 sy *= wxHTML_SCROLL_STEP;
5526e819 672
f6010d8f
VZ
673 wxPoint pos = event.GetPosition();
674 pos.x += sx;
675 pos.y += sy;
5526e819 676
f6010d8f
VZ
677 wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
678
679 // VZ: is it possible that we don't find anything at all?
d168485f
VS
680 // VS: yes. FindCellByPos returns terminal cell and
681 // containers may have empty borders
f6010d8f
VZ
682 if ( cell )
683 OnCellClicked(cell, pos.x, pos.y, event);
684 }
5526e819
VS
685 }
686}
687
688
689
33ac7e6f 690void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
5526e819 691{
33ac7e6f 692 if (s_cur_hand == NULL)
66806a0b
VS
693 {
694 s_cur_hand = new wxCursor(wxCURSOR_HAND);
695 s_cur_arrow = new wxCursor(wxCURSOR_ARROW);
696 }
5526e819 697
33ac7e6f 698 if (m_tmpMouseMoved && (m_Cell != NULL))
4f9297b0 699 {
5526e819 700 int sx, sy;
0cb9cfb2
VZ
701 GetViewStart(&sx, &sy);
702 sx *= wxHTML_SCROLL_STEP;
703 sy *= wxHTML_SCROLL_STEP;
5526e819 704
0cb9cfb2 705 int x, y;
5526e819
VS
706 wxGetMousePosition(&x, &y);
707 ScreenToClient(&x, &y);
f6010d8f
VZ
708 x += sx;
709 y += sy;
0cb9cfb2 710
f6010d8f
VZ
711 wxHtmlCell *cell = m_Cell->FindCellByPos(x, y);
712 if ( cell != m_tmpLastCell )
e421922f 713 {
f6010d8f
VZ
714 wxHtmlLinkInfo *lnk = cell ? cell->GetLink(x, y) : NULL;
715
716 if (lnk != m_tmpLastLink)
e421922f 717 {
f6010d8f
VZ
718 if (lnk == NULL)
719 {
720 SetCursor(*s_cur_arrow);
721 if (m_RelatedStatusBar != -1)
722 m_RelatedFrame->SetStatusText(wxEmptyString, m_RelatedStatusBar);
723 }
724 else
725 {
726 SetCursor(*s_cur_hand);
727 if (m_RelatedStatusBar != -1)
728 m_RelatedFrame->SetStatusText(lnk->GetHref(), m_RelatedStatusBar);
729 }
730 m_tmpLastLink = lnk;
622ea783 731 }
f6010d8f
VZ
732
733 m_tmpLastCell = cell;
5526e819 734 }
f6010d8f
VZ
735 else // mouse moved but stayed in the same cell
736 {
737 if ( cell )
738 OnCellMouseHover(cell, x, y);
739 }
740
5526e819
VS
741 m_tmpMouseMoved = FALSE;
742 }
743}
744
745
bfb9ee96 746IMPLEMENT_ABSTRACT_CLASS(wxHtmlProcessor,wxObject)
5526e819
VS
747
748IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow)
749
750BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
751 EVT_SIZE(wxHtmlWindow::OnSize)
752 EVT_LEFT_DOWN(wxHtmlWindow::OnMouseEvent)
0cb9cfb2 753 EVT_RIGHT_DOWN(wxHtmlWindow::OnMouseEvent)
5526e819
VS
754 EVT_MOTION(wxHtmlWindow::OnMouseEvent)
755 EVT_IDLE(wxHtmlWindow::OnIdle)
5526e819
VS
756END_EVENT_TABLE()
757
758
759
760
761
a76015e6
VS
762// A module to allow initialization/cleanup
763// without calling these functions from app.cpp or from
764// the user's application.
765
766class wxHtmlWinModule: public wxModule
767{
768DECLARE_DYNAMIC_CLASS(wxHtmlWinModule)
769public:
770 wxHtmlWinModule() : wxModule() {}
771 bool OnInit() { return TRUE; }
772 void OnExit() { wxHtmlWindow::CleanUpStatics(); }
773};
774
775IMPLEMENT_DYNAMIC_CLASS(wxHtmlWinModule, wxModule)
776
5526e819 777
0cecad31
VS
778// This hack forces the linker to always link in m_* files
779// (wxHTML doesn't work without handlers from these files)
780#include "wx/html/forcelnk.h"
781FORCE_WXHTML_MODULES()
5526e819 782
b835e9bf 783#endif