home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / html / htmlwin.cpp < prev    next >
C/C++ Source or Header  |  2002-11-09  |  21KB  |  787 lines

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