don't show the I-beam cursor over text in wxHtmlListBox
[wxWidgets.git] / src / html / htmlwin.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: htmlwin.cpp
3 // Purpose: wxHtmlWindow class for parsing & displaying HTML (implementation)
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id$
6 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #include "wx/wxprec.h"
11
12 #include "wx/defs.h"
13 #if wxUSE_HTML && wxUSE_STREAMS
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WXPRECOMP
20 #include "wx/log.h"
21 #include "wx/intl.h"
22 #include "wx/dcclient.h"
23 #include "wx/frame.h"
24 #endif
25
26 #include "wx/html/htmlwin.h"
27 #include "wx/html/htmlproc.h"
28 #include "wx/list.h"
29 #include "wx/clipbrd.h"
30 #include "wx/dataobj.h"
31 #include "wx/timer.h"
32 #include "wx/dcmemory.h"
33 #include "wx/settings.h"
34
35 #include "wx/arrimpl.cpp"
36 #include "wx/listimpl.cpp"
37
38
39 #if wxUSE_CLIPBOARD
40 // ----------------------------------------------------------------------------
41 // wxHtmlWinAutoScrollTimer: the timer used to generate a stream of scroll
42 // events when a captured mouse is held outside the window
43 // ----------------------------------------------------------------------------
44
45 class wxHtmlWinAutoScrollTimer : public wxTimer
46 {
47 public:
48 wxHtmlWinAutoScrollTimer(wxScrolledWindow *win,
49 wxEventType eventTypeToSend,
50 int pos, int orient)
51 {
52 m_win = win;
53 m_eventType = eventTypeToSend;
54 m_pos = pos;
55 m_orient = orient;
56 }
57
58 virtual void Notify();
59
60 private:
61 wxScrolledWindow *m_win;
62 wxEventType m_eventType;
63 int m_pos,
64 m_orient;
65
66 DECLARE_NO_COPY_CLASS(wxHtmlWinAutoScrollTimer)
67 };
68
69 void wxHtmlWinAutoScrollTimer::Notify()
70 {
71 // only do all this as long as the window is capturing the mouse
72 if ( wxWindow::GetCapture() != m_win )
73 {
74 Stop();
75 }
76 else // we still capture the mouse, continue generating events
77 {
78 // first scroll the window if we are allowed to do it
79 wxScrollWinEvent event1(m_eventType, m_pos, m_orient);
80 event1.SetEventObject(m_win);
81 if ( m_win->GetEventHandler()->ProcessEvent(event1) )
82 {
83 // and then send a pseudo mouse-move event to refresh the selection
84 wxMouseEvent event2(wxEVT_MOTION);
85 wxGetMousePosition(&event2.m_x, &event2.m_y);
86
87 // the mouse event coordinates should be client, not screen as
88 // returned by wxGetMousePosition
89 wxWindow *parentTop = m_win;
90 while ( parentTop->GetParent() )
91 parentTop = parentTop->GetParent();
92 wxPoint ptOrig = parentTop->GetPosition();
93 event2.m_x -= ptOrig.x;
94 event2.m_y -= ptOrig.y;
95
96 event2.SetEventObject(m_win);
97
98 // FIXME: we don't fill in the other members - ok?
99 m_win->GetEventHandler()->ProcessEvent(event2);
100 }
101 else // can't scroll further, stop
102 {
103 Stop();
104 }
105 }
106 }
107
108 #endif // wxUSE_CLIPBOARD
109
110
111
112 //-----------------------------------------------------------------------------
113 // wxHtmlHistoryItem
114 //-----------------------------------------------------------------------------
115
116 // item of history list
117 class WXDLLIMPEXP_HTML wxHtmlHistoryItem
118 {
119 public:
120 wxHtmlHistoryItem(const wxString& p, const wxString& a) {m_Page = p, m_Anchor = a, m_Pos = 0;}
121 int GetPos() const {return m_Pos;}
122 void SetPos(int p) {m_Pos = p;}
123 const wxString& GetPage() const {return m_Page;}
124 const wxString& GetAnchor() const {return m_Anchor;}
125
126 private:
127 wxString m_Page;
128 wxString m_Anchor;
129 int m_Pos;
130 };
131
132
133 //-----------------------------------------------------------------------------
134 // our private arrays:
135 //-----------------------------------------------------------------------------
136
137 WX_DECLARE_OBJARRAY(wxHtmlHistoryItem, wxHtmlHistoryArray);
138 WX_DEFINE_OBJARRAY(wxHtmlHistoryArray)
139
140 WX_DECLARE_LIST(wxHtmlProcessor, wxHtmlProcessorList);
141 WX_DEFINE_LIST(wxHtmlProcessorList)
142
143 //-----------------------------------------------------------------------------
144 // wxHtmlWindowMouseHelper
145 //-----------------------------------------------------------------------------
146
147 wxHtmlWindowMouseHelper::wxHtmlWindowMouseHelper(wxHtmlWindowInterface *iface)
148 : m_tmpMouseMoved(false),
149 m_tmpLastLink(NULL),
150 m_tmpLastCell(NULL),
151 m_interface(iface)
152 {
153 }
154
155 void wxHtmlWindowMouseHelper::HandleMouseMoved()
156 {
157 m_tmpMouseMoved = true;
158 }
159
160 bool wxHtmlWindowMouseHelper::HandleMouseClick(wxHtmlCell *rootCell,
161 const wxPoint& pos,
162 const wxMouseEvent& event)
163 {
164 if (!rootCell)
165 return false;
166
167 wxHtmlCell *cell = rootCell->FindCellByPos(pos.x, pos.y);
168 // this check is needed because FindCellByPos returns terminal cell and
169 // containers may have empty borders -- in this case NULL will be
170 // returned
171 if (!cell)
172 return false;
173
174 // adjust the coordinates to be relative to this cell:
175 wxPoint relpos = pos - cell->GetAbsPos(rootCell);
176
177 return OnCellClicked(cell, relpos.x, relpos.y, event);
178 }
179
180 void wxHtmlWindowMouseHelper::HandleIdle(wxHtmlCell *rootCell,
181 const wxPoint& pos)
182 {
183 wxHtmlCell *cell = rootCell ? rootCell->FindCellByPos(pos.x, pos.y) : NULL;
184
185 if (cell != m_tmpLastCell)
186 {
187 wxHtmlLinkInfo *lnk = NULL;
188 if (cell)
189 {
190 // adjust the coordinates to be relative to this cell:
191 wxPoint relpos = pos - cell->GetAbsPos(rootCell);
192 lnk = cell->GetLink(relpos.x, relpos.y);
193 }
194
195 wxCursor cur;
196 if (cell)
197 cur = cell->GetMouseCursor(m_interface);
198 else
199 cur = m_interface->GetHTMLCursor(
200 wxHtmlWindowInterface::HTMLCursor_Default);
201
202 m_interface->GetHTMLWindow()->SetCursor(cur);
203
204 if (lnk != m_tmpLastLink)
205 {
206 if (lnk)
207 m_interface->SetHTMLStatusText(lnk->GetHref());
208 else
209 m_interface->SetHTMLStatusText(wxEmptyString);
210
211 m_tmpLastLink = lnk;
212 }
213
214 m_tmpLastCell = cell;
215 }
216 else // mouse moved but stayed in the same cell
217 {
218 if ( cell )
219 {
220 OnCellMouseHover(cell, pos.x, pos.y);
221 }
222 }
223
224 m_tmpMouseMoved = false;
225 }
226
227 bool wxHtmlWindowMouseHelper::OnCellClicked(wxHtmlCell *cell,
228 wxCoord x, wxCoord y,
229 const wxMouseEvent& event)
230 {
231 wxCHECK_MSG( cell, false, _T("can't be called with NULL cell") );
232
233 return cell->ProcessMouseClick(m_interface, wxPoint(x, y), event);
234 }
235
236 void wxHtmlWindowMouseHelper::OnCellMouseHover(wxHtmlCell * WXUNUSED(cell),
237 wxCoord WXUNUSED(x),
238 wxCoord WXUNUSED(y))
239 {
240 // do nothing here
241 }
242
243 //-----------------------------------------------------------------------------
244 // wxHtmlWindow
245 //-----------------------------------------------------------------------------
246
247 wxList wxHtmlWindow::m_Filters;
248 wxHtmlFilter *wxHtmlWindow::m_DefaultFilter = NULL;
249 wxHtmlProcessorList *wxHtmlWindow::m_GlobalProcessors = NULL;
250 wxCursor *wxHtmlWindow::ms_cursorLink = NULL;
251 wxCursor *wxHtmlWindow::ms_cursorText = NULL;
252
253 void wxHtmlWindow::CleanUpStatics()
254 {
255 wxDELETE(m_DefaultFilter);
256 WX_CLEAR_LIST(wxList, m_Filters);
257 if (m_GlobalProcessors)
258 WX_CLEAR_LIST(wxHtmlProcessorList, *m_GlobalProcessors);
259 wxDELETE(m_GlobalProcessors);
260 wxDELETE(ms_cursorLink);
261 wxDELETE(ms_cursorText);
262 }
263
264 void wxHtmlWindow::Init()
265 {
266 m_tmpCanDrawLocks = 0;
267 m_FS = new wxFileSystem();
268 #if wxUSE_STATUSBAR
269 m_RelatedStatusBar = -1;
270 #endif // wxUSE_STATUSBAR
271 m_RelatedFrame = NULL;
272 m_TitleFormat = wxT("%s");
273 m_OpenedPage = m_OpenedAnchor = m_OpenedPageTitle = wxEmptyString;
274 m_Cell = NULL;
275 m_Parser = new wxHtmlWinParser(this);
276 m_Parser->SetFS(m_FS);
277 m_HistoryPos = -1;
278 m_HistoryOn = true;
279 m_History = new wxHtmlHistoryArray;
280 m_Processors = NULL;
281 m_Style = 0;
282 SetBorders(10);
283 m_selection = NULL;
284 m_makingSelection = false;
285 #if wxUSE_CLIPBOARD
286 m_timerAutoScroll = NULL;
287 m_lastDoubleClick = 0;
288 #endif // wxUSE_CLIPBOARD
289 m_backBuffer = NULL;
290 m_eraseBgInOnPaint = false;
291 m_tmpSelFromCell = NULL;
292 }
293
294 bool wxHtmlWindow::Create(wxWindow *parent, wxWindowID id,
295 const wxPoint& pos, const wxSize& size,
296 long style, const wxString& name)
297 {
298 if (!wxScrolledWindow::Create(parent, id, pos, size,
299 style | wxVSCROLL | wxHSCROLL,
300 name))
301 return false;
302
303 m_Style = style;
304 SetPage(wxT("<html><body></body></html>"));
305 return true;
306 }
307
308
309 wxHtmlWindow::~wxHtmlWindow()
310 {
311 #if wxUSE_CLIPBOARD
312 StopAutoScrolling();
313 #endif // wxUSE_CLIPBOARD
314 HistoryClear();
315
316 delete m_selection;
317
318 delete m_Cell;
319
320 if ( m_Processors )
321 {
322 WX_CLEAR_LIST(wxHtmlProcessorList, *m_Processors);
323 }
324
325 delete m_Parser;
326 delete m_FS;
327 delete m_History;
328 delete m_Processors;
329 delete m_backBuffer;
330 }
331
332
333
334 void wxHtmlWindow::SetRelatedFrame(wxFrame* frame, const wxString& format)
335 {
336 m_RelatedFrame = frame;
337 m_TitleFormat = format;
338 }
339
340
341
342 #if wxUSE_STATUSBAR
343 void wxHtmlWindow::SetRelatedStatusBar(int bar)
344 {
345 m_RelatedStatusBar = bar;
346 }
347 #endif // wxUSE_STATUSBAR
348
349
350
351 void wxHtmlWindow::SetFonts(const wxString& normal_face, const wxString& fixed_face, const int *sizes)
352 {
353 m_Parser->SetFonts(normal_face, fixed_face, sizes);
354
355 // re-layout the page after changing fonts:
356 DoSetPage(*(m_Parser->GetSource()));
357 }
358
359 void wxHtmlWindow::SetStandardFonts(int size,
360 const wxString& normal_face,
361 const wxString& fixed_face)
362 {
363 m_Parser->SetStandardFonts(size, normal_face, fixed_face);
364
365 // re-layout the page after changing fonts:
366 DoSetPage(*(m_Parser->GetSource()));
367 }
368
369 bool wxHtmlWindow::SetPage(const wxString& source)
370 {
371 m_OpenedPage = m_OpenedAnchor = m_OpenedPageTitle = wxEmptyString;
372 return DoSetPage(source);
373 }
374
375 bool wxHtmlWindow::DoSetPage(const wxString& source)
376 {
377 wxString newsrc(source);
378
379 wxDELETE(m_selection);
380
381 // we will soon delete all the cells, so clear pointers to them:
382 m_tmpSelFromCell = NULL;
383
384 // pass HTML through registered processors:
385 if (m_Processors || m_GlobalProcessors)
386 {
387 wxHtmlProcessorList::compatibility_iterator nodeL, nodeG;
388 int prL, prG;
389
390 if ( m_Processors )
391 nodeL = m_Processors->GetFirst();
392 if ( m_GlobalProcessors )
393 nodeG = m_GlobalProcessors->GetFirst();
394
395 // VS: there are two lists, global and local, both of them sorted by
396 // priority. Since we have to go through _both_ lists with
397 // decreasing priority, we "merge-sort" the lists on-line by
398 // processing that one of the two heads that has higher priority
399 // in every iteration
400 while (nodeL || nodeG)
401 {
402 prL = (nodeL) ? nodeL->GetData()->GetPriority() : -1;
403 prG = (nodeG) ? nodeG->GetData()->GetPriority() : -1;
404 if (prL > prG)
405 {
406 if (nodeL->GetData()->IsEnabled())
407 newsrc = nodeL->GetData()->Process(newsrc);
408 nodeL = nodeL->GetNext();
409 }
410 else // prL <= prG
411 {
412 if (nodeG->GetData()->IsEnabled())
413 newsrc = nodeG->GetData()->Process(newsrc);
414 nodeG = nodeG->GetNext();
415 }
416 }
417 }
418
419 // ...and run the parser on it:
420 wxClientDC *dc = new wxClientDC(this);
421 dc->SetMapMode(wxMM_TEXT);
422 SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF));
423 SetBackgroundImage(wxNullBitmap);
424
425 m_Parser->SetDC(dc);
426 if (m_Cell)
427 {
428 delete m_Cell;
429 m_Cell = NULL;
430 }
431 m_Cell = (wxHtmlContainerCell*) m_Parser->Parse(newsrc);
432 delete dc;
433 m_Cell->SetIndent(m_Borders, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
434 m_Cell->SetAlignHor(wxHTML_ALIGN_CENTER);
435 CreateLayout();
436 if (m_tmpCanDrawLocks == 0)
437 Refresh();
438 return true;
439 }
440
441 bool wxHtmlWindow::AppendToPage(const wxString& source)
442 {
443 return DoSetPage(*(GetParser()->GetSource()) + source);
444 }
445
446 bool wxHtmlWindow::LoadPage(const wxString& location)
447 {
448 wxBusyCursor busyCursor;
449
450 wxFSFile *f;
451 bool rt_val;
452 bool needs_refresh = false;
453
454 m_tmpCanDrawLocks++;
455 if (m_HistoryOn && (m_HistoryPos != -1))
456 {
457 // store scroll position into history item:
458 int x, y;
459 GetViewStart(&x, &y);
460 (*m_History)[m_HistoryPos].SetPos(y);
461 }
462
463 if (location[0] == wxT('#'))
464 {
465 // local anchor:
466 wxString anch = location.Mid(1) /*1 to end*/;
467 m_tmpCanDrawLocks--;
468 rt_val = ScrollToAnchor(anch);
469 m_tmpCanDrawLocks++;
470 }
471 else if (location.Find(wxT('#')) != wxNOT_FOUND && location.BeforeFirst(wxT('#')) == m_OpenedPage)
472 {
473 wxString anch = location.AfterFirst(wxT('#'));
474 m_tmpCanDrawLocks--;
475 rt_val = ScrollToAnchor(anch);
476 m_tmpCanDrawLocks++;
477 }
478 else if (location.Find(wxT('#')) != wxNOT_FOUND &&
479 (m_FS->GetPath() + location.BeforeFirst(wxT('#'))) == m_OpenedPage)
480 {
481 wxString anch = location.AfterFirst(wxT('#'));
482 m_tmpCanDrawLocks--;
483 rt_val = ScrollToAnchor(anch);
484 m_tmpCanDrawLocks++;
485 }
486
487 else
488 {
489 needs_refresh = true;
490 #if wxUSE_STATUSBAR
491 // load&display it:
492 if (m_RelatedStatusBar != -1)
493 {
494 m_RelatedFrame->SetStatusText(_("Connecting..."), m_RelatedStatusBar);
495 Refresh(false);
496 }
497 #endif // wxUSE_STATUSBAR
498
499 f = m_Parser->OpenURL(wxHTML_URL_PAGE, location);
500
501 // try to interpret 'location' as filename instead of URL:
502 if (f == NULL)
503 {
504 wxFileName fn(location);
505 wxString location2 = wxFileSystem::FileNameToURL(fn);
506 f = m_Parser->OpenURL(wxHTML_URL_PAGE, location2);
507 }
508
509 if (f == NULL)
510 {
511 wxLogError(_("Unable to open requested HTML document: %s"), location.c_str());
512 m_tmpCanDrawLocks--;
513 return false;
514 }
515
516 else
517 {
518 wxList::compatibility_iterator node;
519 wxString src = wxEmptyString;
520
521 #if wxUSE_STATUSBAR
522 if (m_RelatedStatusBar != -1)
523 {
524 wxString msg = _("Loading : ") + location;
525 m_RelatedFrame->SetStatusText(msg, m_RelatedStatusBar);
526 Refresh(false);
527 }
528 #endif // wxUSE_STATUSBAR
529
530 node = m_Filters.GetFirst();
531 while (node)
532 {
533 wxHtmlFilter *h = (wxHtmlFilter*) node->GetData();
534 if (h->CanRead(*f))
535 {
536 src = h->ReadFile(*f);
537 break;
538 }
539 node = node->GetNext();
540 }
541 if (src == wxEmptyString)
542 {
543 if (m_DefaultFilter == NULL) m_DefaultFilter = GetDefaultFilter();
544 src = m_DefaultFilter->ReadFile(*f);
545 }
546
547 m_FS->ChangePathTo(f->GetLocation());
548 rt_val = SetPage(src);
549 m_OpenedPage = f->GetLocation();
550 if (f->GetAnchor() != wxEmptyString)
551 {
552 ScrollToAnchor(f->GetAnchor());
553 }
554
555 delete f;
556
557 #if wxUSE_STATUSBAR
558 if (m_RelatedStatusBar != -1)
559 m_RelatedFrame->SetStatusText(_("Done"), m_RelatedStatusBar);
560 #endif // wxUSE_STATUSBAR
561 }
562 }
563
564 if (m_HistoryOn) // add this page to history there:
565 {
566 int c = m_History->GetCount() - (m_HistoryPos + 1);
567
568 if (m_HistoryPos < 0 ||
569 (*m_History)[m_HistoryPos].GetPage() != m_OpenedPage ||
570 (*m_History)[m_HistoryPos].GetAnchor() != m_OpenedAnchor)
571 {
572 m_HistoryPos++;
573 for (int i = 0; i < c; i++)
574 m_History->RemoveAt(m_HistoryPos);
575 m_History->Add(new wxHtmlHistoryItem(m_OpenedPage, m_OpenedAnchor));
576 }
577 }
578
579 if (m_OpenedPageTitle == wxEmptyString)
580 OnSetTitle(wxFileNameFromPath(m_OpenedPage));
581
582 if (needs_refresh)
583 {
584 m_tmpCanDrawLocks--;
585 Refresh();
586 }
587 else
588 m_tmpCanDrawLocks--;
589
590 return rt_val;
591 }
592
593
594 bool wxHtmlWindow::LoadFile(const wxFileName& filename)
595 {
596 wxString url = wxFileSystem::FileNameToURL(filename);
597 return LoadPage(url);
598 }
599
600
601 bool wxHtmlWindow::ScrollToAnchor(const wxString& anchor)
602 {
603 const wxHtmlCell *c = m_Cell->Find(wxHTML_COND_ISANCHOR, &anchor);
604 if (!c)
605 {
606 wxLogWarning(_("HTML anchor %s does not exist."), anchor.c_str());
607 return false;
608 }
609 else
610 {
611 int y;
612
613 for (y = 0; c != NULL; c = c->GetParent()) y += c->GetPosY();
614 Scroll(-1, y / wxHTML_SCROLL_STEP);
615 m_OpenedAnchor = anchor;
616 return true;
617 }
618 }
619
620
621 void wxHtmlWindow::OnSetTitle(const wxString& title)
622 {
623 if (m_RelatedFrame)
624 {
625 wxString tit;
626 tit.Printf(m_TitleFormat, title.c_str());
627 m_RelatedFrame->SetTitle(tit);
628 }
629 m_OpenedPageTitle = title;
630 }
631
632
633
634
635
636 void wxHtmlWindow::CreateLayout()
637 {
638 int ClientWidth, ClientHeight;
639
640 if (!m_Cell) return;
641
642 if (m_Style & wxHW_SCROLLBAR_NEVER)
643 {
644 SetScrollbars(wxHTML_SCROLL_STEP, 1, m_Cell->GetWidth() / wxHTML_SCROLL_STEP, 0); // always off
645 GetClientSize(&ClientWidth, &ClientHeight);
646 m_Cell->Layout(ClientWidth);
647 }
648
649 else {
650 GetClientSize(&ClientWidth, &ClientHeight);
651 m_Cell->Layout(ClientWidth);
652 if (ClientHeight < m_Cell->GetHeight() + GetCharHeight())
653 {
654 SetScrollbars(
655 wxHTML_SCROLL_STEP, wxHTML_SCROLL_STEP,
656 m_Cell->GetWidth() / wxHTML_SCROLL_STEP,
657 (m_Cell->GetHeight() + GetCharHeight()) / wxHTML_SCROLL_STEP
658 /*cheat: top-level frag is always container*/);
659 }
660 else /* we fit into window, no need for scrollbars */
661 {
662 SetScrollbars(wxHTML_SCROLL_STEP, 1, m_Cell->GetWidth() / wxHTML_SCROLL_STEP, 0); // disable...
663 GetClientSize(&ClientWidth, &ClientHeight);
664 m_Cell->Layout(ClientWidth); // ...and relayout
665 }
666 }
667 }
668
669
670
671 void wxHtmlWindow::ReadCustomization(wxConfigBase *cfg, wxString path)
672 {
673 wxString oldpath;
674 wxString tmp;
675 int p_fontsizes[7];
676 wxString p_fff, p_ffn;
677
678 if (path != wxEmptyString)
679 {
680 oldpath = cfg->GetPath();
681 cfg->SetPath(path);
682 }
683
684 m_Borders = cfg->Read(wxT("wxHtmlWindow/Borders"), m_Borders);
685 p_fff = cfg->Read(wxT("wxHtmlWindow/FontFaceFixed"), m_Parser->m_FontFaceFixed);
686 p_ffn = cfg->Read(wxT("wxHtmlWindow/FontFaceNormal"), m_Parser->m_FontFaceNormal);
687 for (int i = 0; i < 7; i++)
688 {
689 tmp.Printf(wxT("wxHtmlWindow/FontsSize%i"), i);
690 p_fontsizes[i] = cfg->Read(tmp, m_Parser->m_FontsSizes[i]);
691 }
692 SetFonts(p_ffn, p_fff, p_fontsizes);
693
694 if (path != wxEmptyString)
695 cfg->SetPath(oldpath);
696 }
697
698
699
700 void wxHtmlWindow::WriteCustomization(wxConfigBase *cfg, wxString path)
701 {
702 wxString oldpath;
703 wxString tmp;
704
705 if (path != wxEmptyString)
706 {
707 oldpath = cfg->GetPath();
708 cfg->SetPath(path);
709 }
710
711 cfg->Write(wxT("wxHtmlWindow/Borders"), (long) m_Borders);
712 cfg->Write(wxT("wxHtmlWindow/FontFaceFixed"), m_Parser->m_FontFaceFixed);
713 cfg->Write(wxT("wxHtmlWindow/FontFaceNormal"), m_Parser->m_FontFaceNormal);
714 for (int i = 0; i < 7; i++)
715 {
716 tmp.Printf(wxT("wxHtmlWindow/FontsSize%i"), i);
717 cfg->Write(tmp, (long) m_Parser->m_FontsSizes[i]);
718 }
719
720 if (path != wxEmptyString)
721 cfg->SetPath(oldpath);
722 }
723
724
725
726 bool wxHtmlWindow::HistoryBack()
727 {
728 wxString a, l;
729
730 if (m_HistoryPos < 1) return false;
731
732 // store scroll position into history item:
733 int x, y;
734 GetViewStart(&x, &y);
735 (*m_History)[m_HistoryPos].SetPos(y);
736
737 // go to previous position:
738 m_HistoryPos--;
739
740 l = (*m_History)[m_HistoryPos].GetPage();
741 a = (*m_History)[m_HistoryPos].GetAnchor();
742 m_HistoryOn = false;
743 m_tmpCanDrawLocks++;
744 if (a == wxEmptyString) LoadPage(l);
745 else LoadPage(l + wxT("#") + a);
746 m_HistoryOn = true;
747 m_tmpCanDrawLocks--;
748 Scroll(0, (*m_History)[m_HistoryPos].GetPos());
749 Refresh();
750 return true;
751 }
752
753 bool wxHtmlWindow::HistoryCanBack()
754 {
755 if (m_HistoryPos < 1) return false;
756 return true ;
757 }
758
759
760 bool wxHtmlWindow::HistoryForward()
761 {
762 wxString a, l;
763
764 if (m_HistoryPos == -1) return false;
765 if (m_HistoryPos >= (int)m_History->GetCount() - 1)return false;
766
767 m_OpenedPage = wxEmptyString; // this will disable adding new entry into history in LoadPage()
768
769 m_HistoryPos++;
770 l = (*m_History)[m_HistoryPos].GetPage();
771 a = (*m_History)[m_HistoryPos].GetAnchor();
772 m_HistoryOn = false;
773 m_tmpCanDrawLocks++;
774 if (a == wxEmptyString) LoadPage(l);
775 else LoadPage(l + wxT("#") + a);
776 m_HistoryOn = true;
777 m_tmpCanDrawLocks--;
778 Scroll(0, (*m_History)[m_HistoryPos].GetPos());
779 Refresh();
780 return true;
781 }
782
783 bool wxHtmlWindow::HistoryCanForward()
784 {
785 if (m_HistoryPos == -1) return false;
786 if (m_HistoryPos >= (int)m_History->GetCount() - 1)return false;
787 return true ;
788 }
789
790
791 void wxHtmlWindow::HistoryClear()
792 {
793 m_History->Empty();
794 m_HistoryPos = -1;
795 }
796
797 void wxHtmlWindow::AddProcessor(wxHtmlProcessor *processor)
798 {
799 if (!m_Processors)
800 {
801 m_Processors = new wxHtmlProcessorList;
802 }
803 wxHtmlProcessorList::compatibility_iterator node;
804
805 for (node = m_Processors->GetFirst(); node; node = node->GetNext())
806 {
807 if (processor->GetPriority() > node->GetData()->GetPriority())
808 {
809 m_Processors->Insert(node, processor);
810 return;
811 }
812 }
813 m_Processors->Append(processor);
814 }
815
816 /*static */ void wxHtmlWindow::AddGlobalProcessor(wxHtmlProcessor *processor)
817 {
818 if (!m_GlobalProcessors)
819 {
820 m_GlobalProcessors = new wxHtmlProcessorList;
821 }
822 wxHtmlProcessorList::compatibility_iterator node;
823
824 for (node = m_GlobalProcessors->GetFirst(); node; node = node->GetNext())
825 {
826 if (processor->GetPriority() > node->GetData()->GetPriority())
827 {
828 m_GlobalProcessors->Insert(node, processor);
829 return;
830 }
831 }
832 m_GlobalProcessors->Append(processor);
833 }
834
835
836
837 void wxHtmlWindow::AddFilter(wxHtmlFilter *filter)
838 {
839 m_Filters.Append(filter);
840 }
841
842
843 bool wxHtmlWindow::IsSelectionEnabled() const
844 {
845 #if wxUSE_CLIPBOARD
846 return !(m_Style & wxHW_NO_SELECTION);
847 #else
848 return false;
849 #endif
850 }
851
852
853 #if wxUSE_CLIPBOARD
854 wxString wxHtmlWindow::DoSelectionToText(wxHtmlSelection *sel)
855 {
856 if ( !sel )
857 return wxEmptyString;
858
859 wxClientDC dc(this);
860
861 const wxHtmlCell *end = sel->GetToCell();
862 wxString text;
863 wxHtmlTerminalCellsInterator i(sel->GetFromCell(), end);
864 if ( i )
865 {
866 text << i->ConvertToText(sel);
867 ++i;
868 }
869 const wxHtmlCell *prev = *i;
870 while ( i )
871 {
872 if ( prev->GetParent() != i->GetParent() )
873 text << _T('\n');
874 text << i->ConvertToText(*i == end ? sel : NULL);
875 prev = *i;
876 ++i;
877 }
878 return text;
879 }
880
881 wxString wxHtmlWindow::ToText()
882 {
883 if (m_Cell)
884 {
885 wxHtmlSelection sel;
886 sel.Set(m_Cell->GetFirstTerminal(), m_Cell->GetLastTerminal());
887 return DoSelectionToText(&sel);
888 }
889 else
890 return wxEmptyString;
891 }
892
893 #endif // wxUSE_CLIPBOARD
894
895 bool wxHtmlWindow::CopySelection(ClipboardType t)
896 {
897 #if wxUSE_CLIPBOARD
898 if ( m_selection )
899 {
900 #if defined(__UNIX__) && !defined(__WXMAC__)
901 wxTheClipboard->UsePrimarySelection(t == Primary);
902 #else // !__UNIX__
903 // Primary selection exists only under X11, so don't do anything under
904 // the other platforms when we try to access it
905 //
906 // TODO: this should be abstracted at wxClipboard level!
907 if ( t == Primary )
908 return false;
909 #endif // __UNIX__/!__UNIX__
910
911 if ( wxTheClipboard->Open() )
912 {
913 const wxString txt(SelectionToText());
914 wxTheClipboard->SetData(new wxTextDataObject(txt));
915 wxTheClipboard->Close();
916 wxLogTrace(_T("wxhtmlselection"),
917 _("Copied to clipboard:\"%s\""), txt.c_str());
918
919 return true;
920 }
921 }
922 #else
923 wxUnusedVar(t);
924 #endif // wxUSE_CLIPBOARD
925
926 return false;
927 }
928
929
930 void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
931 {
932 const wxMouseEvent *e = link.GetEvent();
933 if (e == NULL || e->LeftUp())
934 LoadPage(link.GetHref());
935 }
936
937 void wxHtmlWindow::OnEraseBackground(wxEraseEvent& event)
938 {
939 if ( !m_bmpBg.Ok() )
940 {
941 // don't even skip the event, if we don't have a bg bitmap we're going
942 // to overwrite background in OnPaint() below anyhow, so letting the
943 // default handling take place would only result in flicker, just set a
944 // flag to erase the background below
945 m_eraseBgInOnPaint = true;
946 return;
947 }
948
949 wxDC& dc = *event.GetDC();
950
951 // if the image is not fully opaque, we have to erase the background before
952 // drawing it, however avoid doing it for opaque images as this would just
953 // result in extra flicker without any other effect as background is
954 // completely covered anyhow
955 if ( m_bmpBg.GetMask() )
956 {
957 dc.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID));
958 dc.Clear();
959 }
960
961 const wxSize sizeWin(GetClientSize());
962 const wxSize sizeBmp(m_bmpBg.GetWidth(), m_bmpBg.GetHeight());
963 for ( wxCoord x = 0; x < sizeWin.x; x += sizeBmp.x )
964 {
965 for ( wxCoord y = 0; y < sizeWin.y; y += sizeBmp.y )
966 {
967 dc.DrawBitmap(m_bmpBg, x, y, true /* use mask */);
968 }
969 }
970 }
971
972 void wxHtmlWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
973 {
974 wxPaintDC dc(this);
975
976 if (m_tmpCanDrawLocks > 0 || m_Cell == NULL)
977 return;
978
979 int x, y;
980 GetViewStart(&x, &y);
981 wxRect rect = GetUpdateRegion().GetBox();
982 wxSize sz = GetSize();
983
984 wxMemoryDC dcm;
985 if ( !m_backBuffer )
986 m_backBuffer = new wxBitmap(sz.x, sz.y);
987 dcm.SelectObject(*m_backBuffer);
988
989 if ( m_eraseBgInOnPaint )
990 {
991 dcm.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID));
992 dcm.Clear();
993
994 m_eraseBgInOnPaint = false;
995 }
996 else // someone has already erased the background, keep it
997 {
998 // preserve the existing background, otherwise we'd erase anything the
999 // user code had drawn in its EVT_ERASE_BACKGROUND handler when we do
1000 // the Blit back below
1001 dcm.Blit(0, rect.GetTop(),
1002 sz.x, rect.GetBottom() - rect.GetTop() + 1,
1003 &dc,
1004 0, rect.GetTop());
1005 }
1006
1007 PrepareDC(dcm);
1008 dcm.SetMapMode(wxMM_TEXT);
1009 dcm.SetBackgroundMode(wxTRANSPARENT);
1010
1011 wxHtmlRenderingInfo rinfo;
1012 wxDefaultHtmlRenderingStyle rstyle;
1013 rinfo.SetSelection(m_selection);
1014 rinfo.SetStyle(&rstyle);
1015 m_Cell->Draw(dcm, 0, 0,
1016 y * wxHTML_SCROLL_STEP + rect.GetTop(),
1017 y * wxHTML_SCROLL_STEP + rect.GetBottom(),
1018 rinfo);
1019
1020 //#define DEBUG_HTML_SELECTION
1021 #ifdef DEBUG_HTML_SELECTION
1022 {
1023 int xc, yc, x, y;
1024 wxGetMousePosition(&xc, &yc);
1025 ScreenToClient(&xc, &yc);
1026 CalcUnscrolledPosition(xc, yc, &x, &y);
1027 wxHtmlCell *at = m_Cell->FindCellByPos(x, y);
1028 wxHtmlCell *before =
1029 m_Cell->FindCellByPos(x, y, wxHTML_FIND_NEAREST_BEFORE);
1030 wxHtmlCell *after =
1031 m_Cell->FindCellByPos(x, y, wxHTML_FIND_NEAREST_AFTER);
1032
1033 dcm.SetBrush(*wxTRANSPARENT_BRUSH);
1034 dcm.SetPen(*wxBLACK_PEN);
1035 if (at)
1036 dcm.DrawRectangle(at->GetAbsPos(),
1037 wxSize(at->GetWidth(),at->GetHeight()));
1038 dcm.SetPen(*wxGREEN_PEN);
1039 if (before)
1040 dcm.DrawRectangle(before->GetAbsPos().x+1, before->GetAbsPos().y+1,
1041 before->GetWidth()-2,before->GetHeight()-2);
1042 dcm.SetPen(*wxRED_PEN);
1043 if (after)
1044 dcm.DrawRectangle(after->GetAbsPos().x+2, after->GetAbsPos().y+2,
1045 after->GetWidth()-4,after->GetHeight()-4);
1046 }
1047 #endif
1048
1049 dcm.SetDeviceOrigin(0,0);
1050 dc.Blit(0, rect.GetTop(),
1051 sz.x, rect.GetBottom() - rect.GetTop() + 1,
1052 &dcm,
1053 0, rect.GetTop());
1054 }
1055
1056
1057
1058
1059 void wxHtmlWindow::OnSize(wxSizeEvent& event)
1060 {
1061 wxDELETE(m_backBuffer);
1062
1063 wxScrolledWindow::OnSize(event);
1064 CreateLayout();
1065
1066 // Recompute selection if necessary:
1067 if ( m_selection )
1068 {
1069 m_selection->Set(m_selection->GetFromCell(),
1070 m_selection->GetToCell());
1071 m_selection->ClearPrivPos();
1072 }
1073
1074 Refresh();
1075 }
1076
1077
1078 void wxHtmlWindow::OnMouseMove(wxMouseEvent& WXUNUSED(event))
1079 {
1080 wxHtmlWindowMouseHelper::HandleMouseMoved();
1081 }
1082
1083 void wxHtmlWindow::OnMouseDown(wxMouseEvent& event)
1084 {
1085 #if wxUSE_CLIPBOARD
1086 if ( event.LeftDown() && IsSelectionEnabled() )
1087 {
1088 const long TRIPLECLICK_LEN = 200; // 0.2 sec after doubleclick
1089 if ( wxGetLocalTimeMillis() - m_lastDoubleClick <= TRIPLECLICK_LEN )
1090 {
1091 SelectLine(CalcUnscrolledPosition(event.GetPosition()));
1092
1093 (void) CopySelection();
1094 }
1095 else
1096 {
1097 m_makingSelection = true;
1098
1099 if ( m_selection )
1100 {
1101 wxDELETE(m_selection);
1102 Refresh();
1103 }
1104 m_tmpSelFromPos = CalcUnscrolledPosition(event.GetPosition());
1105 m_tmpSelFromCell = NULL;
1106
1107 CaptureMouse();
1108 }
1109 }
1110 #else
1111 wxUnusedVar(event);
1112 #endif // wxUSE_CLIPBOARD
1113 }
1114
1115 void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
1116 {
1117 #if wxUSE_CLIPBOARD
1118 if ( m_makingSelection )
1119 {
1120 ReleaseMouse();
1121 m_makingSelection = false;
1122
1123 // did the user move the mouse far enough from starting point?
1124 if ( CopySelection(Primary) )
1125 {
1126 // we don't want mouse up event that ended selecting to be
1127 // handled as mouse click and e.g. follow hyperlink:
1128 return;
1129 }
1130 }
1131 #endif // wxUSE_CLIPBOARD
1132
1133 SetFocus();
1134
1135 wxPoint pos = CalcUnscrolledPosition(event.GetPosition());
1136 wxHtmlWindowMouseHelper::HandleMouseClick(m_Cell, pos, event);
1137 }
1138
1139
1140
1141 void wxHtmlWindow::OnInternalIdle()
1142 {
1143 wxWindow::OnInternalIdle();
1144
1145 if (m_Cell != NULL && DidMouseMove())
1146 {
1147 #ifdef DEBUG_HTML_SELECTION
1148 Refresh();
1149 #endif
1150 int xc, yc, x, y;
1151 wxGetMousePosition(&xc, &yc);
1152 ScreenToClient(&xc, &yc);
1153 CalcUnscrolledPosition(xc, yc, &x, &y);
1154
1155 wxHtmlCell *cell = m_Cell->FindCellByPos(x, y);
1156
1157 // handle selection update:
1158 if ( m_makingSelection )
1159 {
1160 if ( !m_tmpSelFromCell )
1161 m_tmpSelFromCell = m_Cell->FindCellByPos(
1162 m_tmpSelFromPos.x,m_tmpSelFromPos.y);
1163
1164 // NB: a trick - we adjust selFromPos to be upper left or bottom
1165 // right corner of the first cell of the selection depending
1166 // on whether the mouse is moving to the right or to the left.
1167 // This gives us more "natural" behaviour when selecting
1168 // a line (specifically, first cell of the next line is not
1169 // included if you drag selection from left to right over
1170 // entire line):
1171 wxPoint dirFromPos;
1172 if ( !m_tmpSelFromCell )
1173 {
1174 dirFromPos = m_tmpSelFromPos;
1175 }
1176 else
1177 {
1178 dirFromPos = m_tmpSelFromCell->GetAbsPos();
1179 if ( x < m_tmpSelFromPos.x )
1180 {
1181 dirFromPos.x += m_tmpSelFromCell->GetWidth();
1182 dirFromPos.y += m_tmpSelFromCell->GetHeight();
1183 }
1184 }
1185 bool goingDown = dirFromPos.y < y ||
1186 (dirFromPos.y == y && dirFromPos.x < x);
1187
1188 // determine selection span:
1189 if ( /*still*/ !m_tmpSelFromCell )
1190 {
1191 if (goingDown)
1192 {
1193 m_tmpSelFromCell = m_Cell->FindCellByPos(
1194 m_tmpSelFromPos.x,m_tmpSelFromPos.y,
1195 wxHTML_FIND_NEAREST_AFTER);
1196 if (!m_tmpSelFromCell)
1197 m_tmpSelFromCell = m_Cell->GetFirstTerminal();
1198 }
1199 else
1200 {
1201 m_tmpSelFromCell = m_Cell->FindCellByPos(
1202 m_tmpSelFromPos.x,m_tmpSelFromPos.y,
1203 wxHTML_FIND_NEAREST_BEFORE);
1204 if (!m_tmpSelFromCell)
1205 m_tmpSelFromCell = m_Cell->GetLastTerminal();
1206 }
1207 }
1208
1209 wxHtmlCell *selcell = cell;
1210 if (!selcell)
1211 {
1212 if (goingDown)
1213 {
1214 selcell = m_Cell->FindCellByPos(x, y,
1215 wxHTML_FIND_NEAREST_BEFORE);
1216 if (!selcell)
1217 selcell = m_Cell->GetLastTerminal();
1218 }
1219 else
1220 {
1221 selcell = m_Cell->FindCellByPos(x, y,
1222 wxHTML_FIND_NEAREST_AFTER);
1223 if (!selcell)
1224 selcell = m_Cell->GetFirstTerminal();
1225 }
1226 }
1227
1228 // NB: it may *rarely* happen that the code above didn't find one
1229 // of the cells, e.g. if wxHtmlWindow doesn't contain any
1230 // visible cells.
1231 if ( selcell && m_tmpSelFromCell )
1232 {
1233 if ( !m_selection )
1234 {
1235 // start selecting only if mouse movement was big enough
1236 // (otherwise it was meant as mouse click, not selection):
1237 const int PRECISION = 2;
1238 wxPoint diff = m_tmpSelFromPos - wxPoint(x,y);
1239 if (abs(diff.x) > PRECISION || abs(diff.y) > PRECISION)
1240 {
1241 m_selection = new wxHtmlSelection();
1242 }
1243 }
1244 if ( m_selection )
1245 {
1246 if ( m_tmpSelFromCell->IsBefore(selcell) )
1247 {
1248 m_selection->Set(m_tmpSelFromPos, m_tmpSelFromCell,
1249 wxPoint(x,y), selcell); }
1250 else
1251 {
1252 m_selection->Set(wxPoint(x,y), selcell,
1253 m_tmpSelFromPos, m_tmpSelFromCell);
1254 }
1255 m_selection->ClearPrivPos();
1256 Refresh();
1257 }
1258 }
1259 }
1260
1261 // handle cursor and status bar text changes:
1262
1263 // NB: because we're passing in 'cell' and not 'm_Cell' (so that the
1264 // leaf cell lookup isn't done twice), we need to adjust the
1265 // position for the new root:
1266 wxPoint posInCell(x, y);
1267 if (cell)
1268 posInCell -= cell->GetAbsPos();
1269 wxHtmlWindowMouseHelper::HandleIdle(cell, posInCell);
1270 }
1271 }
1272
1273 #if wxUSE_CLIPBOARD
1274 void wxHtmlWindow::StopAutoScrolling()
1275 {
1276 if ( m_timerAutoScroll )
1277 {
1278 wxDELETE(m_timerAutoScroll);
1279 }
1280 }
1281
1282 void wxHtmlWindow::OnMouseEnter(wxMouseEvent& event)
1283 {
1284 StopAutoScrolling();
1285 event.Skip();
1286 }
1287
1288 void wxHtmlWindow::OnMouseLeave(wxMouseEvent& event)
1289 {
1290 // don't prevent the usual processing of the event from taking place
1291 event.Skip();
1292
1293 // when a captured mouse leave a scrolled window we start generate
1294 // scrolling events to allow, for example, extending selection beyond the
1295 // visible area in some controls
1296 if ( wxWindow::GetCapture() == this )
1297 {
1298 // where is the mouse leaving?
1299 int pos, orient;
1300 wxPoint pt = event.GetPosition();
1301 if ( pt.x < 0 )
1302 {
1303 orient = wxHORIZONTAL;
1304 pos = 0;
1305 }
1306 else if ( pt.y < 0 )
1307 {
1308 orient = wxVERTICAL;
1309 pos = 0;
1310 }
1311 else // we're lower or to the right of the window
1312 {
1313 wxSize size = GetClientSize();
1314 if ( pt.x > size.x )
1315 {
1316 orient = wxHORIZONTAL;
1317 pos = GetVirtualSize().x / wxHTML_SCROLL_STEP;
1318 }
1319 else if ( pt.y > size.y )
1320 {
1321 orient = wxVERTICAL;
1322 pos = GetVirtualSize().y / wxHTML_SCROLL_STEP;
1323 }
1324 else // this should be impossible
1325 {
1326 // but seems to happen sometimes under wxMSW - maybe it's a bug
1327 // there but for now just ignore it
1328
1329 //wxFAIL_MSG( _T("can't understand where has mouse gone") );
1330
1331 return;
1332 }
1333 }
1334
1335 // only start the auto scroll timer if the window can be scrolled in
1336 // this direction
1337 if ( !HasScrollbar(orient) )
1338 return;
1339
1340 delete m_timerAutoScroll;
1341 m_timerAutoScroll = new wxHtmlWinAutoScrollTimer
1342 (
1343 this,
1344 pos == 0 ? wxEVT_SCROLLWIN_LINEUP
1345 : wxEVT_SCROLLWIN_LINEDOWN,
1346 pos,
1347 orient
1348 );
1349 m_timerAutoScroll->Start(50); // FIXME: make configurable
1350 }
1351 }
1352
1353 void wxHtmlWindow::OnKeyUp(wxKeyEvent& event)
1354 {
1355 if ( IsSelectionEnabled() && event.GetKeyCode() == 'C' && event.CmdDown() )
1356 {
1357 (void) CopySelection();
1358 }
1359 }
1360
1361 void wxHtmlWindow::OnCopy(wxCommandEvent& WXUNUSED(event))
1362 {
1363 (void) CopySelection();
1364 }
1365
1366 void wxHtmlWindow::OnDoubleClick(wxMouseEvent& event)
1367 {
1368 // select word under cursor:
1369 if ( IsSelectionEnabled() )
1370 {
1371 SelectWord(CalcUnscrolledPosition(event.GetPosition()));
1372
1373 (void) CopySelection(Primary);
1374
1375 m_lastDoubleClick = wxGetLocalTimeMillis();
1376 }
1377 else
1378 event.Skip();
1379 }
1380
1381 void wxHtmlWindow::SelectWord(const wxPoint& pos)
1382 {
1383 if ( m_Cell )
1384 {
1385 wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
1386 if ( cell )
1387 {
1388 delete m_selection;
1389 m_selection = new wxHtmlSelection();
1390 m_selection->Set(cell, cell);
1391 RefreshRect(wxRect(CalcScrolledPosition(cell->GetAbsPos()),
1392 wxSize(cell->GetWidth(), cell->GetHeight())));
1393 }
1394 }
1395 }
1396
1397 void wxHtmlWindow::SelectLine(const wxPoint& pos)
1398 {
1399 if ( m_Cell )
1400 {
1401 wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
1402 if ( cell )
1403 {
1404 // We use following heuristic to find a "line": let the line be all
1405 // cells in same container as the cell under mouse cursor that are
1406 // neither completely above nor completely bellow the clicked cell
1407 // (i.e. are likely to be words positioned on same line of text).
1408
1409 int y1 = cell->GetAbsPos().y;
1410 int y2 = y1 + cell->GetHeight();
1411 int y;
1412 const wxHtmlCell *c;
1413 const wxHtmlCell *before = NULL;
1414 const wxHtmlCell *after = NULL;
1415
1416 // find last cell of line:
1417 for ( c = cell->GetNext(); c; c = c->GetNext())
1418 {
1419 y = c->GetAbsPos().y;
1420 if ( y + c->GetHeight() > y1 && y < y2 )
1421 after = c;
1422 else
1423 break;
1424 }
1425 if ( !after )
1426 after = cell;
1427
1428 // find first cell of line:
1429 for ( c = cell->GetParent()->GetFirstChild();
1430 c && c != cell; c = c->GetNext())
1431 {
1432 y = c->GetAbsPos().y;
1433 if ( y + c->GetHeight() > y1 && y < y2 )
1434 {
1435 if ( ! before )
1436 before = c;
1437 }
1438 else
1439 before = NULL;
1440 }
1441 if ( !before )
1442 before = cell;
1443
1444 delete m_selection;
1445 m_selection = new wxHtmlSelection();
1446 m_selection->Set(before, after);
1447
1448 Refresh();
1449 }
1450 }
1451 }
1452
1453 void wxHtmlWindow::SelectAll()
1454 {
1455 if ( m_Cell )
1456 {
1457 delete m_selection;
1458 m_selection = new wxHtmlSelection();
1459 m_selection->Set(m_Cell->GetFirstTerminal(), m_Cell->GetLastTerminal());
1460 Refresh();
1461 }
1462 }
1463
1464 #endif // wxUSE_CLIPBOARD
1465
1466
1467
1468 IMPLEMENT_ABSTRACT_CLASS(wxHtmlProcessor,wxObject)
1469
1470 #if wxUSE_EXTENDED_RTTI
1471 IMPLEMENT_DYNAMIC_CLASS_XTI(wxHtmlWindow, wxScrolledWindow,"wx/html/htmlwin.h")
1472
1473 wxBEGIN_PROPERTIES_TABLE(wxHtmlWindow)
1474 /*
1475 TODO PROPERTIES
1476 style , wxHW_SCROLLBAR_AUTO
1477 borders , (dimension)
1478 url , string
1479 htmlcode , string
1480 */
1481 wxEND_PROPERTIES_TABLE()
1482
1483 wxBEGIN_HANDLERS_TABLE(wxHtmlWindow)
1484 wxEND_HANDLERS_TABLE()
1485
1486 wxCONSTRUCTOR_5( wxHtmlWindow , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
1487 #else
1488 IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow)
1489 #endif
1490
1491 BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
1492 EVT_SIZE(wxHtmlWindow::OnSize)
1493 EVT_LEFT_DOWN(wxHtmlWindow::OnMouseDown)
1494 EVT_LEFT_UP(wxHtmlWindow::OnMouseUp)
1495 EVT_RIGHT_UP(wxHtmlWindow::OnMouseUp)
1496 EVT_MOTION(wxHtmlWindow::OnMouseMove)
1497 EVT_ERASE_BACKGROUND(wxHtmlWindow::OnEraseBackground)
1498 EVT_PAINT(wxHtmlWindow::OnPaint)
1499 #if wxUSE_CLIPBOARD
1500 EVT_LEFT_DCLICK(wxHtmlWindow::OnDoubleClick)
1501 EVT_ENTER_WINDOW(wxHtmlWindow::OnMouseEnter)
1502 EVT_LEAVE_WINDOW(wxHtmlWindow::OnMouseLeave)
1503 EVT_KEY_UP(wxHtmlWindow::OnKeyUp)
1504 EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy)
1505 #endif // wxUSE_CLIPBOARD
1506 END_EVENT_TABLE()
1507
1508 //-----------------------------------------------------------------------------
1509 // wxHtmlWindowInterface implementation in wxHtmlWindow
1510 //-----------------------------------------------------------------------------
1511
1512 void wxHtmlWindow::SetHTMLWindowTitle(const wxString& title)
1513 {
1514 OnSetTitle(title);
1515 }
1516
1517 void wxHtmlWindow::OnHTMLLinkClicked(const wxHtmlLinkInfo& link)
1518 {
1519 OnLinkClicked(link);
1520 }
1521
1522 wxHtmlOpeningStatus wxHtmlWindow::OnHTMLOpeningURL(wxHtmlURLType type,
1523 const wxString& url,
1524 wxString *redirect) const
1525 {
1526 return OnOpeningURL(type, url, redirect);
1527 }
1528
1529 wxPoint wxHtmlWindow::HTMLCoordsToWindow(wxHtmlCell *WXUNUSED(cell),
1530 const wxPoint& pos) const
1531 {
1532 return CalcScrolledPosition(pos);
1533 }
1534
1535 wxWindow* wxHtmlWindow::GetHTMLWindow()
1536 {
1537 return this;
1538 }
1539
1540 wxColour wxHtmlWindow::GetHTMLBackgroundColour() const
1541 {
1542 return GetBackgroundColour();
1543 }
1544
1545 void wxHtmlWindow::SetHTMLBackgroundColour(const wxColour& clr)
1546 {
1547 SetBackgroundColour(clr);
1548 }
1549
1550 void wxHtmlWindow::SetHTMLBackgroundImage(const wxBitmap& bmpBg)
1551 {
1552 SetBackgroundImage(bmpBg);
1553 }
1554
1555 void wxHtmlWindow::SetHTMLStatusText(const wxString& text)
1556 {
1557 #if wxUSE_STATUSBAR
1558 if (m_RelatedStatusBar != -1)
1559 m_RelatedFrame->SetStatusText(text, m_RelatedStatusBar);
1560 #endif // wxUSE_STATUSBAR
1561 }
1562
1563 /*static*/
1564 wxCursor wxHtmlWindow::GetDefaultHTMLCursor(HTMLCursor type)
1565 {
1566 switch (type)
1567 {
1568 case HTMLCursor_Link:
1569 if ( !ms_cursorLink )
1570 ms_cursorLink = new wxCursor(wxCURSOR_HAND);
1571 return *ms_cursorLink;
1572
1573 case HTMLCursor_Text:
1574 if ( !ms_cursorText )
1575 ms_cursorText = new wxCursor(wxCURSOR_IBEAM);
1576 return *ms_cursorText;
1577
1578 case HTMLCursor_Default:
1579 default:
1580 return *wxSTANDARD_CURSOR;
1581 }
1582 }
1583
1584 wxCursor wxHtmlWindow::GetHTMLCursor(HTMLCursor type) const
1585 {
1586 return GetDefaultHTMLCursor(type);
1587 }
1588
1589
1590 //-----------------------------------------------------------------------------
1591 // wxHtmlWinModule
1592 //-----------------------------------------------------------------------------
1593
1594 // A module to allow initialization/cleanup
1595 // without calling these functions from app.cpp or from
1596 // the user's application.
1597
1598 class wxHtmlWinModule: public wxModule
1599 {
1600 DECLARE_DYNAMIC_CLASS(wxHtmlWinModule)
1601 public:
1602 wxHtmlWinModule() : wxModule() {}
1603 bool OnInit() { return true; }
1604 void OnExit() { wxHtmlWindow::CleanUpStatics(); }
1605 };
1606
1607 IMPLEMENT_DYNAMIC_CLASS(wxHtmlWinModule, wxModule)
1608
1609
1610 // This hack forces the linker to always link in m_* files
1611 // (wxHTML doesn't work without handlers from these files)
1612 #include "wx/html/forcelnk.h"
1613 FORCE_WXHTML_MODULES()
1614
1615 #endif // wxUSE_HTML
1616