]> git.saurik.com Git - wxWidgets.git/blame - src/html/htmlwin.cpp
fixed the bug with the order of 2 size events when the scrollbar[s] (dis)appear in...
[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
200
201bool wxHtmlWindow::LoadPage(const wxString& location)
202{
203 wxFSFile *f;
204 bool rt_val;
fc7dfaf8 205 bool needs_refresh = FALSE;
33ac7e6f 206
169ee06c 207 SetCursor(*wxHOURGLASS_CURSOR);
fc7dfaf8 208 wxYield(); Refresh(FALSE);
5526e819 209
89de9af3 210 m_tmpCanDrawLocks++;
e421922f 211 if (m_HistoryOn && (m_HistoryPos != -1))
4f9297b0 212 {
960ba969 213 // store scroll position into history item:
5526e819 214 int x, y;
e421922f 215 GetViewStart(&x, &y);
892aeafc 216 (*m_History)[m_HistoryPos].SetPos(y);
5526e819
VS
217 }
218
e421922f 219 if (location[0] == wxT('#'))
4f9297b0 220 {
960ba969 221 // local anchor:
5526e819 222 wxString anch = location.Mid(1) /*1 to end*/;
89de9af3 223 m_tmpCanDrawLocks--;
5526e819 224 rt_val = ScrollToAnchor(anch);
fc7dfaf8
VS
225 m_tmpCanDrawLocks++;
226 }
33ac7e6f 227 else if (location.Find(wxT('#')) != wxNOT_FOUND && location.BeforeFirst(wxT('#')) == m_OpenedPage)
4f9297b0 228 {
fc7dfaf8
VS
229 wxString anch = location.AfterFirst(wxT('#'));
230 m_tmpCanDrawLocks--;
231 rt_val = ScrollToAnchor(anch);
232 m_tmpCanDrawLocks++;
233 }
33ac7e6f
KB
234 else if (location.Find(wxT('#')) != wxNOT_FOUND &&
235 (m_FS->GetPath() + location.BeforeFirst(wxT('#'))) == m_OpenedPage)
e421922f 236 {
fc7dfaf8
VS
237 wxString anch = location.AfterFirst(wxT('#'));
238 m_tmpCanDrawLocks--;
239 rt_val = ScrollToAnchor(anch);
240 m_tmpCanDrawLocks++;
5526e819
VS
241 }
242
33ac7e6f 243 else
4f9297b0 244 {
fc7dfaf8 245 needs_refresh = TRUE;
5526e819 246 // load&display it:
33ac7e6f 247 if (m_RelatedStatusBar != -1)
e421922f 248 {
4f9297b0 249 m_RelatedFrame->SetStatusText(_("Connecting..."), m_RelatedStatusBar);
fc7dfaf8 250 Refresh(FALSE);
5526e819
VS
251 }
252
4f9297b0 253 f = m_FS->OpenFile(location);
33ac7e6f
KB
254
255 if (f == NULL)
e421922f 256 {
f6bcfd97 257 wxLogError(_("Unable to open requested HTML document: %s"), location.c_str());
89de9af3 258 m_tmpCanDrawLocks--;
169ee06c
VS
259
260 SetCursor(*wxSTANDARD_CURSOR);
5526e819
VS
261 return FALSE;
262 }
263
33ac7e6f 264 else
e421922f 265 {
5526e819
VS
266 wxNode *node;
267 wxString src = wxEmptyString;
268
33ac7e6f 269 if (m_RelatedStatusBar != -1)
e421922f 270 {
5526e819 271 wxString msg = _("Loading : ") + location;
4f9297b0 272 m_RelatedFrame->SetStatusText(msg, m_RelatedStatusBar);
fc7dfaf8 273 Refresh(FALSE);
5526e819
VS
274 }
275
276 node = m_Filters.GetFirst();
4f9297b0 277 while (node)
e421922f 278 {
4f9297b0
VS
279 wxHtmlFilter *h = (wxHtmlFilter*) node->GetData();
280 if (h->CanRead(*f))
e421922f 281 {
4f9297b0 282 src = h->ReadFile(*f);
5526e819
VS
283 break;
284 }
4f9297b0 285 node = node->GetNext();
5526e819 286 }
33ac7e6f 287 if (src == wxEmptyString)
e421922f 288 {
89de9af3 289 if (m_DefaultFilter == NULL) m_DefaultFilter = GetDefaultFilter();
4f9297b0 290 src = m_DefaultFilter->ReadFile(*f);
89de9af3 291 }
5526e819 292
4f9297b0 293 m_FS->ChangePathTo(f->GetLocation());
5526e819 294 rt_val = SetPage(src);
4f9297b0 295 m_OpenedPage = f->GetLocation();
33ac7e6f 296 if (f->GetAnchor() != wxEmptyString)
e421922f 297 {
fc7dfaf8 298 wxYield();
4f9297b0 299 ScrollToAnchor(f->GetAnchor());
5526e819
VS
300 }
301
302 delete f;
303
4f9297b0 304 if (m_RelatedStatusBar != -1) m_RelatedFrame->SetStatusText(_("Done"), m_RelatedStatusBar);
5526e819
VS
305 }
306 }
307
4f9297b0
VS
308 if (m_HistoryOn) // add this page to history there:
309 {
892aeafc 310 int c = m_History->GetCount() - (m_HistoryPos + 1);
5526e819 311
0cb9cfb2 312 if (m_HistoryPos < 0 ||
ee19c324
VS
313 (*m_History)[m_HistoryPos].GetPage() != m_OpenedPage ||
314 (*m_History)[m_HistoryPos].GetAnchor() != m_OpenedAnchor)
315 {
316 m_HistoryPos++;
317 for (int i = 0; i < c; i++)
b54e41c5 318 m_History->RemoveAt(m_HistoryPos);
ee19c324
VS
319 m_History->Add(new wxHtmlHistoryItem(m_OpenedPage, m_OpenedAnchor));
320 }
5526e819
VS
321 }
322
096824d7
VS
323 if (m_OpenedPageTitle == wxEmptyString)
324 OnSetTitle(wxFileNameFromPath(m_OpenedPage));
169ee06c 325 SetCursor(*wxSTANDARD_CURSOR);
fc7dfaf8 326
33ac7e6f 327 if (needs_refresh)
4f9297b0 328 {
fc7dfaf8
VS
329 wxYield();
330 m_tmpCanDrawLocks--;
331 Refresh();
332 }
333 else
334 m_tmpCanDrawLocks--;
335
5526e819
VS
336 return rt_val;
337}
338
339
340
341bool wxHtmlWindow::ScrollToAnchor(const wxString& anchor)
342{
4f9297b0 343 const wxHtmlCell *c = m_Cell->Find(wxHTML_COND_ISANCHOR, &anchor);
f3c82859
VS
344 if (!c)
345 {
f6bcfd97 346 wxLogWarning(_("HTML anchor %s does not exist."), anchor.c_str());
f3c82859
VS
347 return FALSE;
348 }
33ac7e6f 349 else
4f9297b0 350 {
5526e819 351 int y;
269e8200 352
4f9297b0 353 for (y = 0; c != NULL; c = c->GetParent()) y += c->GetPosY();
efba2b89 354 Scroll(-1, y / wxHTML_SCROLL_STEP);
5526e819
VS
355 m_OpenedAnchor = anchor;
356 return TRUE;
357 }
358}
359
360
d5db80c2 361void wxHtmlWindow::OnSetTitle(const wxString& title)
5526e819 362{
33ac7e6f 363 if (m_RelatedFrame)
4f9297b0 364 {
5526e819
VS
365 wxString tit;
366 tit.Printf(m_TitleFormat, title.c_str());
4f9297b0 367 m_RelatedFrame->SetTitle(tit);
5526e819 368 }
d5db80c2 369 m_OpenedPageTitle = title;
5526e819
VS
370}
371
372
373
374
375
376void wxHtmlWindow::CreateLayout()
377{
378 int ClientWidth, ClientHeight;
379
380 if (!m_Cell) return;
a547ebff 381
33ac7e6f 382 if (m_Style & wxHW_SCROLLBAR_NEVER)
4f9297b0
VS
383 {
384 SetScrollbars(wxHTML_SCROLL_STEP, 1, m_Cell->GetWidth() / wxHTML_SCROLL_STEP, 0); // always off
a547ebff 385 GetClientSize(&ClientWidth, &ClientHeight);
4f9297b0 386 m_Cell->Layout(ClientWidth);
a547ebff
VS
387 }
388
389 else {
390 GetClientSize(&ClientWidth, &ClientHeight);
4f9297b0 391 m_Cell->Layout(ClientWidth);
33ac7e6f 392 if (ClientHeight < m_Cell->GetHeight() + GetCharHeight())
e421922f 393 {
f3bcfd9b
VS
394 SetScrollbars(
395 wxHTML_SCROLL_STEP, wxHTML_SCROLL_STEP,
4f9297b0
VS
396 m_Cell->GetWidth() / wxHTML_SCROLL_STEP,
397 (m_Cell->GetHeight() + GetCharHeight()) / wxHTML_SCROLL_STEP
f3bcfd9b 398 /*cheat: top-level frag is always container*/);
a547ebff 399 }
4f9297b0 400 else /* we fit into window, no need for scrollbars */
e421922f 401 {
4f9297b0 402 SetScrollbars(wxHTML_SCROLL_STEP, 1, m_Cell->GetWidth() / wxHTML_SCROLL_STEP, 0); // disable...
89de9af3 403 GetClientSize(&ClientWidth, &ClientHeight);
4f9297b0 404 m_Cell->Layout(ClientWidth); // ...and relayout
89de9af3 405 }
a547ebff 406 }
5526e819
VS
407}
408
269e8200 409
5526e819
VS
410
411void wxHtmlWindow::ReadCustomization(wxConfigBase *cfg, wxString path)
412{
413 wxString oldpath;
414 wxString tmp;
d5db80c2
VS
415 int p_fontsizes[7];
416 wxString p_fff, p_ffn;
5526e819 417
33ac7e6f 418 if (path != wxEmptyString)
4f9297b0
VS
419 {
420 oldpath = cfg->GetPath();
421 cfg->SetPath(path);
5526e819
VS
422 }
423
892aeafc
VS
424 m_Borders = cfg->Read(wxT("wxHtmlWindow/Borders"), m_Borders);
425 p_fff = cfg->Read(wxT("wxHtmlWindow/FontFaceFixed"), m_Parser->m_FontFaceFixed);
426 p_ffn = cfg->Read(wxT("wxHtmlWindow/FontFaceNormal"), m_Parser->m_FontFaceNormal);
bfb9ee96 427 for (int i = 0; i < 7; i++)
4f9297b0 428 {
66a77a74 429 tmp.Printf(wxT("wxHtmlWindow/FontsSize%i"), i);
4f9297b0 430 p_fontsizes[i] = cfg->Read(tmp, m_Parser->m_FontsSizes[i]);
5526e819 431 }
8eb2940f 432 SetFonts(p_ffn, p_fff, p_fontsizes);
5526e819
VS
433
434 if (path != wxEmptyString)
4f9297b0 435 cfg->SetPath(oldpath);
5526e819
VS
436}
437
438
439
440void wxHtmlWindow::WriteCustomization(wxConfigBase *cfg, wxString path)
441{
442 wxString oldpath;
443 wxString tmp;
444
33ac7e6f 445 if (path != wxEmptyString)
4f9297b0
VS
446 {
447 oldpath = cfg->GetPath();
448 cfg->SetPath(path);
5526e819
VS
449 }
450
892aeafc
VS
451 cfg->Write(wxT("wxHtmlWindow/Borders"), (long) m_Borders);
452 cfg->Write(wxT("wxHtmlWindow/FontFaceFixed"), m_Parser->m_FontFaceFixed);
453 cfg->Write(wxT("wxHtmlWindow/FontFaceNormal"), m_Parser->m_FontFaceNormal);
bfb9ee96 454 for (int i = 0; i < 7; i++)
4f9297b0 455 {
66a77a74 456 tmp.Printf(wxT("wxHtmlWindow/FontsSize%i"), i);
4f9297b0 457 cfg->Write(tmp, (long) m_Parser->m_FontsSizes[i]);
5526e819
VS
458 }
459
460 if (path != wxEmptyString)
4f9297b0 461 cfg->SetPath(oldpath);
5526e819
VS
462}
463
464
465
466bool wxHtmlWindow::HistoryBack()
467{
468 wxString a, l;
469
470 if (m_HistoryPos < 1) return FALSE;
471
bbda1088
VS
472 // store scroll position into history item:
473 int x, y;
e421922f 474 GetViewStart(&x, &y);
892aeafc 475 (*m_History)[m_HistoryPos].SetPos(y);
bbda1088
VS
476
477 // go to previous position:
5526e819
VS
478 m_HistoryPos--;
479
892aeafc
VS
480 l = (*m_History)[m_HistoryPos].GetPage();
481 a = (*m_History)[m_HistoryPos].GetAnchor();
5526e819 482 m_HistoryOn = FALSE;
89de9af3 483 m_tmpCanDrawLocks++;
5526e819 484 if (a == wxEmptyString) LoadPage(l);
fc7dfaf8 485 else LoadPage(l + wxT("#") + a);
5526e819 486 m_HistoryOn = TRUE;
c88293a4 487 wxYield();
89de9af3 488 m_tmpCanDrawLocks--;
892aeafc 489 Scroll(0, (*m_History)[m_HistoryPos].GetPos());
5526e819
VS
490 Refresh();
491 return TRUE;
492}
493
1b113a81
VS
494bool wxHtmlWindow::HistoryCanBack()
495{
496 if (m_HistoryPos < 1) return FALSE;
497 return TRUE ;
498}
5526e819
VS
499
500
501bool wxHtmlWindow::HistoryForward()
502{
503 wxString a, l;
504
505 if (m_HistoryPos == -1) return FALSE;
892aeafc 506 if (m_HistoryPos >= (int)m_History->GetCount() - 1)return FALSE;
5526e819
VS
507
508 m_OpenedPage = wxEmptyString; // this will disable adding new entry into history in LoadPage()
509
510 m_HistoryPos++;
892aeafc
VS
511 l = (*m_History)[m_HistoryPos].GetPage();
512 a = (*m_History)[m_HistoryPos].GetAnchor();
5526e819 513 m_HistoryOn = FALSE;
89de9af3 514 m_tmpCanDrawLocks++;
5526e819 515 if (a == wxEmptyString) LoadPage(l);
fc7dfaf8 516 else LoadPage(l + wxT("#") + a);
5526e819 517 m_HistoryOn = TRUE;
c88293a4 518 wxYield();
89de9af3 519 m_tmpCanDrawLocks--;
892aeafc 520 Scroll(0, (*m_History)[m_HistoryPos].GetPos());
5526e819
VS
521 Refresh();
522 return TRUE;
523}
524
1b113a81
VS
525bool wxHtmlWindow::HistoryCanForward()
526{
527 if (m_HistoryPos == -1) return FALSE;
892aeafc 528 if (m_HistoryPos >= (int)m_History->GetCount() - 1)return FALSE;
1b113a81
VS
529 return TRUE ;
530}
5526e819
VS
531
532
533void wxHtmlWindow::HistoryClear()
534{
892aeafc 535 m_History->Empty();
5526e819
VS
536 m_HistoryPos = -1;
537}
538
892aeafc
VS
539void wxHtmlWindow::AddProcessor(wxHtmlProcessor *processor)
540{
541 if (!m_Processors)
542 {
543 m_Processors = new wxHtmlProcessorList;
544 m_Processors->DeleteContents(TRUE);
545 }
546 wxHtmlProcessorList::Node *node;
bfb9ee96 547
892aeafc
VS
548 for (node = m_Processors->GetFirst(); node; node = node->GetNext())
549 {
bfb9ee96 550 if (processor->GetPriority() > node->GetData()->GetPriority())
892aeafc
VS
551 {
552 m_Processors->Insert(node, processor);
960ba969 553 return;
892aeafc
VS
554 }
555 }
960ba969 556 m_Processors->Append(processor);
892aeafc
VS
557}
558
960ba969 559/*static */ void wxHtmlWindow::AddGlobalProcessor(wxHtmlProcessor *processor)
892aeafc 560{
960ba969 561 if (!m_GlobalProcessors)
892aeafc 562 {
960ba969
VS
563 m_GlobalProcessors = new wxHtmlProcessorList;
564 m_GlobalProcessors->DeleteContents(TRUE);
892aeafc
VS
565 }
566 wxHtmlProcessorList::Node *node;
e421922f 567
960ba969 568 for (node = m_GlobalProcessors->GetFirst(); node; node = node->GetNext())
892aeafc 569 {
bfb9ee96 570 if (processor->GetPriority() > node->GetData()->GetPriority())
892aeafc 571 {
960ba969
VS
572 m_GlobalProcessors->Insert(node, processor);
573 return;
892aeafc
VS
574 }
575 }
960ba969 576 m_GlobalProcessors->Append(processor);
892aeafc
VS
577}
578
5526e819
VS
579
580
581wxList wxHtmlWindow::m_Filters;
a76015e6 582wxHtmlFilter *wxHtmlWindow::m_DefaultFilter = NULL;
66806a0b
VS
583wxCursor *wxHtmlWindow::s_cur_hand = NULL;
584wxCursor *wxHtmlWindow::s_cur_arrow = NULL;
960ba969 585wxHtmlProcessorList *wxHtmlWindow::m_GlobalProcessors = NULL;
a76015e6
VS
586
587void wxHtmlWindow::CleanUpStatics()
588{
892aeafc 589 delete m_DefaultFilter;
a76015e6 590 m_DefaultFilter = NULL;
269e8200
RD
591 m_Filters.DeleteContents(TRUE);
592 m_Filters.Clear();
960ba969
VS
593 delete m_GlobalProcessors;
594 m_GlobalProcessors = NULL;
892aeafc
VS
595 delete s_cur_hand;
596 delete s_cur_arrow;
a76015e6
VS
597}
598
599
5526e819
VS
600
601void wxHtmlWindow::AddFilter(wxHtmlFilter *filter)
602{
5526e819
VS
603 m_Filters.Append(filter);
604}
605
606
607
608
0b2dadd3 609void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
5526e819 610{
0b2dadd3 611 LoadPage(link.GetHref());
5526e819
VS
612}
613
f6010d8f
VZ
614void wxHtmlWindow::OnCellClicked(wxHtmlCell *cell,
615 wxCoord x, wxCoord y,
616 const wxMouseEvent& event)
617{
618 wxCHECK_RET( cell, _T("can't be called with NULL cell") );
5526e819 619
f6010d8f
VZ
620 cell->OnMouseClick(this, x, y, event);
621}
622
623void wxHtmlWindow::OnCellMouseHover(wxHtmlCell * WXUNUSED(cell),
624 wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
625{
626 // do nothing here
627}
5526e819
VS
628
629void wxHtmlWindow::OnDraw(wxDC& dc)
630{
631 int x, y;
632 wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
633 int v_y, v_h;
634
89de9af3 635 if (m_tmpCanDrawLocks > 0) return;
33ac7e6f 636
5526e819 637 dc.SetMapMode(wxMM_TEXT);
5526e819 638 dc.SetBackgroundMode(wxTRANSPARENT);
e421922f 639 GetViewStart(&x, &y);
5526e819 640
33ac7e6f 641 while (upd)
4f9297b0 642 {
5526e819
VS
643 v_y = upd.GetY();
644 v_h = upd.GetH();
4f9297b0 645 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
646 upd++;
647 }
648}
649
650
651
652
653void wxHtmlWindow::OnSize(wxSizeEvent& event)
654{
655 wxScrolledWindow::OnSize(event);
656 CreateLayout();
f6bcfd97 657 Refresh();
5526e819
VS
658}
659
660
5526e819
VS
661void wxHtmlWindow::OnMouseEvent(wxMouseEvent& event)
662{
663 m_tmpMouseMoved = TRUE;
664
33ac7e6f 665 if (event.ButtonDown())
4f9297b0 666 {
f6010d8f
VZ
667 if ( m_Cell )
668 {
669 int sx, sy;
670 GetViewStart(&sx, &sy);
671 sx *= wxHTML_SCROLL_STEP;
672 sy *= wxHTML_SCROLL_STEP;
5526e819 673
f6010d8f
VZ
674 wxPoint pos = event.GetPosition();
675 pos.x += sx;
676 pos.y += sy;
5526e819 677
f6010d8f
VZ
678 wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
679
680 // VZ: is it possible that we don't find anything at all?
d168485f
VS
681 // VS: yes. FindCellByPos returns terminal cell and
682 // containers may have empty borders
f6010d8f
VZ
683 if ( cell )
684 OnCellClicked(cell, pos.x, pos.y, event);
685 }
5526e819
VS
686 }
687}
688
689
690
33ac7e6f 691void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
5526e819 692{
33ac7e6f 693 if (s_cur_hand == NULL)
66806a0b
VS
694 {
695 s_cur_hand = new wxCursor(wxCURSOR_HAND);
696 s_cur_arrow = new wxCursor(wxCURSOR_ARROW);
697 }
5526e819 698
33ac7e6f 699 if (m_tmpMouseMoved && (m_Cell != NULL))
4f9297b0 700 {
5526e819 701 int sx, sy;
0cb9cfb2
VZ
702 GetViewStart(&sx, &sy);
703 sx *= wxHTML_SCROLL_STEP;
704 sy *= wxHTML_SCROLL_STEP;
5526e819 705
0cb9cfb2 706 int x, y;
5526e819
VS
707 wxGetMousePosition(&x, &y);
708 ScreenToClient(&x, &y);
f6010d8f
VZ
709 x += sx;
710 y += sy;
0cb9cfb2 711
f6010d8f
VZ
712 wxHtmlCell *cell = m_Cell->FindCellByPos(x, y);
713 if ( cell != m_tmpLastCell )
e421922f 714 {
f6010d8f
VZ
715 wxHtmlLinkInfo *lnk = cell ? cell->GetLink(x, y) : NULL;
716
717 if (lnk != m_tmpLastLink)
e421922f 718 {
f6010d8f
VZ
719 if (lnk == NULL)
720 {
721 SetCursor(*s_cur_arrow);
722 if (m_RelatedStatusBar != -1)
723 m_RelatedFrame->SetStatusText(wxEmptyString, m_RelatedStatusBar);
724 }
725 else
726 {
727 SetCursor(*s_cur_hand);
728 if (m_RelatedStatusBar != -1)
729 m_RelatedFrame->SetStatusText(lnk->GetHref(), m_RelatedStatusBar);
730 }
731 m_tmpLastLink = lnk;
622ea783 732 }
f6010d8f
VZ
733
734 m_tmpLastCell = cell;
5526e819 735 }
f6010d8f
VZ
736 else // mouse moved but stayed in the same cell
737 {
738 if ( cell )
739 OnCellMouseHover(cell, x, y);
740 }
741
5526e819
VS
742 m_tmpMouseMoved = FALSE;
743 }
744}
745
746
bfb9ee96 747IMPLEMENT_ABSTRACT_CLASS(wxHtmlProcessor,wxObject)
5526e819
VS
748
749IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow)
750
751BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
752 EVT_SIZE(wxHtmlWindow::OnSize)
753 EVT_LEFT_DOWN(wxHtmlWindow::OnMouseEvent)
0cb9cfb2 754 EVT_RIGHT_DOWN(wxHtmlWindow::OnMouseEvent)
5526e819
VS
755 EVT_MOTION(wxHtmlWindow::OnMouseEvent)
756 EVT_IDLE(wxHtmlWindow::OnIdle)
5526e819
VS
757END_EVENT_TABLE()
758
759
760
761
762
a76015e6
VS
763// A module to allow initialization/cleanup
764// without calling these functions from app.cpp or from
765// the user's application.
766
767class wxHtmlWinModule: public wxModule
768{
769DECLARE_DYNAMIC_CLASS(wxHtmlWinModule)
770public:
771 wxHtmlWinModule() : wxModule() {}
772 bool OnInit() { return TRUE; }
773 void OnExit() { wxHtmlWindow::CleanUpStatics(); }
774};
775
776IMPLEMENT_DYNAMIC_CLASS(wxHtmlWinModule, wxModule)
777
5526e819 778
0cecad31
VS
779// This hack forces the linker to always link in m_* files
780// (wxHTML doesn't work without handlers from these files)
781#include "wx/html/forcelnk.h"
782FORCE_WXHTML_MODULES()
5526e819 783
483ff5a5 784#endif