home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / html / winpars.cpp < prev   
C/C++ Source or Header  |  2003-01-03  |  14KB  |  512 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        winpars.cpp
  3. // Purpose:     wxHtmlParser class (generic parser)
  4. // Author:      Vaclav Slavik
  5. // RCS-ID:      $Id: winpars.cpp,v 1.35.2.5 2002/12/30 18:55:33 VS Exp $
  6. // Copyright:   (c) 1999 Vaclav Slavik
  7. // Licence:     wxWindows Licence
  8. /////////////////////////////////////////////////////////////////////////////
  9.  
  10.  
  11. #ifdef __GNUG__
  12. #pragma implementation "winpars.h"
  13. #endif
  14.  
  15. #include "wx/wxprec.h"
  16.  
  17. #include "wx/defs.h"
  18. #if wxUSE_HTML && wxUSE_STREAMS
  19.  
  20. #ifdef __BORLANDC__
  21. #pragma hdrstop
  22. #endif
  23.  
  24. #ifndef WXPRECOMP
  25.     #include "wx/intl.h"
  26.     #include "wx/dc.h"
  27. #endif
  28.  
  29. #include "wx/html/htmldefs.h"
  30. #include "wx/html/winpars.h"
  31. #include "wx/html/htmlwin.h"
  32. #include "wx/fontmap.h"
  33. #include "wx/log.h"
  34.  
  35.  
  36. //-----------------------------------------------------------------------------
  37. // wxHtmlWinParser
  38. //-----------------------------------------------------------------------------
  39.  
  40.  
  41. wxList wxHtmlWinParser::m_Modules;
  42.  
  43. wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow *wnd) : wxHtmlParser()
  44. {
  45.     m_tmpStrBuf = NULL;
  46.     m_tmpStrBufSize = 0;
  47.     m_Window = wnd;
  48.     m_Container = NULL;
  49.     m_DC = NULL;
  50.     m_CharHeight = m_CharWidth = 0;
  51.     m_UseLink = FALSE;
  52. #if !wxUSE_UNICODE
  53.     m_EncConv = NULL;
  54.     m_InputEnc = wxFONTENCODING_ISO8859_1;
  55.     m_OutputEnc = wxFONTENCODING_DEFAULT;
  56. #endif
  57.  
  58.     {
  59.         int i, j, k, l, m;
  60.         for (i = 0; i < 2; i++)
  61.             for (j = 0; j < 2; j++)
  62.                 for (k = 0; k < 2; k++)
  63.                     for (l = 0; l < 2; l++)
  64.                         for (m = 0; m < 7; m++)
  65.                         {
  66.                             m_FontsTable[i][j][k][l][m] = NULL;
  67.                             m_FontsFacesTable[i][j][k][l][m] = wxEmptyString;
  68. #if !wxUSE_UNICODE
  69.                             m_FontsEncTable[i][j][k][l][m] = wxFONTENCODING_DEFAULT;
  70. #endif
  71.                         }
  72. #ifdef __WXMSW__
  73.         static int default_sizes[7] = {7, 8, 10, 12, 16, 22, 30};
  74. #elif defined(__WXMAC__)
  75.         static int default_sizes[7] = {9, 12, 14, 18, 24, 30, 36};
  76. #else
  77.         static int default_sizes[7] = {10, 12, 14, 16, 19, 24, 32};
  78. #endif
  79.         SetFonts(wxT(""), wxT(""), default_sizes);
  80.     }
  81.  
  82.     // fill in wxHtmlParser's tables:
  83.     wxNode *node = m_Modules.GetFirst();
  84.     while (node)
  85.     {
  86.         wxHtmlTagsModule *mod = (wxHtmlTagsModule*) node->GetData();
  87.         mod->FillHandlersTable(this);
  88.         node = node->GetNext();
  89.     }
  90. }
  91.  
  92. wxHtmlWinParser::~wxHtmlWinParser()
  93. {
  94.     int i, j, k, l, m;
  95.  
  96.     for (i = 0; i < 2; i++)
  97.         for (j = 0; j < 2; j++)
  98.             for (k = 0; k < 2; k++)
  99.                 for (l = 0; l < 2; l++)
  100.                     for (m = 0; m < 7; m++)
  101.                     {
  102.                         if (m_FontsTable[i][j][k][l][m] != NULL)
  103.                             delete m_FontsTable[i][j][k][l][m];
  104.                     }
  105. #if !wxUSE_UNICODE
  106.     delete m_EncConv;
  107. #endif
  108.     delete[] m_tmpStrBuf;
  109. }
  110.  
  111. void wxHtmlWinParser::AddModule(wxHtmlTagsModule *module)
  112. {
  113.     m_Modules.Append(module);
  114. }
  115.  
  116. void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule *module)
  117. {
  118.     m_Modules.DeleteObject(module);
  119. }
  120.  
  121. void wxHtmlWinParser::SetFonts(wxString normal_face, wxString fixed_face, const int *sizes)
  122. {
  123.     int i, j, k, l, m;
  124.  
  125.     for (i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
  126.     m_FontFaceFixed = fixed_face;
  127.     m_FontFaceNormal = normal_face;
  128.  
  129. #if !wxUSE_UNICODE
  130.     SetInputEncoding(m_InputEnc);
  131. #endif
  132.  
  133.     for (i = 0; i < 2; i++)
  134.         for (j = 0; j < 2; j++)
  135.             for (k = 0; k < 2; k++)
  136.                 for (l = 0; l < 2; l++)
  137.                     for (m = 0; m < 7; m++) {
  138.                         if (m_FontsTable[i][j][k][l][m] != NULL)
  139.                         {
  140.                             delete m_FontsTable[i][j][k][l][m];
  141.                             m_FontsTable[i][j][k][l][m] = NULL;
  142.                         }
  143.                     }
  144. }
  145.  
  146. void wxHtmlWinParser::InitParser(const wxString& source)
  147. {
  148.     wxHtmlParser::InitParser(source);
  149.     wxASSERT_MSG(m_DC != NULL, wxT("no DC assigned to wxHtmlWinParser!!"));
  150.  
  151.     m_FontBold = m_FontItalic = m_FontUnderlined = m_FontFixed = FALSE;
  152.     m_FontSize = 3; //default one
  153.     CreateCurrentFont();           // we're selecting default font into
  154.     m_DC->GetTextExtent( wxT("H"), &m_CharWidth, &m_CharHeight);
  155.                 /* NOTE : we're not using GetCharWidth/Height() because
  156.                    of differences under X and win
  157.                  */
  158.  
  159.     m_UseLink = FALSE;
  160.     m_Link = wxHtmlLinkInfo( wxT(""), wxT("") );
  161.     m_LinkColor.Set(0, 0, 0xFF);
  162.     m_ActualColor.Set(0, 0, 0);
  163.     m_Align = wxHTML_ALIGN_LEFT;
  164.     m_tmpLastWasSpace = FALSE;
  165.  
  166.     OpenContainer();
  167.     OpenContainer();
  168.  
  169. #if !wxUSE_UNICODE
  170.     wxString charset = ExtractCharsetInformation(source);
  171.     if (!charset.empty())
  172.     {
  173.         wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(charset);
  174.         if (enc != wxFONTENCODING_SYSTEM)
  175.           SetInputEncoding(enc);
  176.     }
  177. #endif
  178.  
  179.     m_Container->InsertCell(new wxHtmlColourCell(m_ActualColor));
  180.     m_Container->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
  181. }
  182.  
  183. void wxHtmlWinParser::DoneParser()
  184. {
  185.     m_Container = NULL;
  186. #if !wxUSE_UNICODE
  187.     SetInputEncoding(wxFONTENCODING_ISO8859_1); // for next call
  188. #endif
  189.     wxHtmlParser::DoneParser();
  190. }
  191.  
  192. wxObject* wxHtmlWinParser::GetProduct()
  193. {
  194.     wxHtmlContainerCell *top;
  195.  
  196.     CloseContainer();
  197.     OpenContainer();
  198.  
  199.     top = m_Container;
  200.     while (top->GetParent()) top = top->GetParent();
  201.     return top;
  202. }
  203.  
  204. wxFSFile *wxHtmlWinParser::OpenURL(wxHtmlURLType type,
  205.                                    const wxString& url) const
  206. {
  207.     // FIXME - normalize the URL to full path before passing to
  208.     //         OnOpeningURL!!
  209.     if ( m_Window )
  210.     {
  211.         wxString myurl(url);
  212.         wxHtmlOpeningStatus status;
  213.         for (;;)
  214.         {
  215.             wxString redirect;
  216.             status = m_Window->OnOpeningURL(type, myurl, &redirect);
  217.             if ( status != wxHTML_REDIRECT )
  218.                 break;
  219.  
  220.             myurl = redirect;
  221.         }
  222.  
  223.         if ( status == wxHTML_BLOCK )
  224.             return NULL;
  225.  
  226.         return GetFS()->OpenFile(myurl);
  227.     }
  228.  
  229.     return wxHtmlParser::OpenURL(type, url);
  230. }
  231.  
  232. void wxHtmlWinParser::AddText(const wxChar* txt)
  233. {
  234.     wxHtmlCell *c;
  235.     size_t i = 0,
  236.            x,
  237.            lng = wxStrlen(txt);
  238.     register wxChar d;
  239.     int templen = 0;
  240.     wxChar nbsp = GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
  241.  
  242.     if (lng+1 > m_tmpStrBufSize)
  243.     {
  244.         delete[] m_tmpStrBuf;
  245.         m_tmpStrBuf = new wxChar[lng+1];
  246.         m_tmpStrBufSize = lng+1;
  247.     }
  248.     wxChar *temp = m_tmpStrBuf;
  249.  
  250.     if (m_tmpLastWasSpace)
  251.     {
  252.         while ((i < lng) &&
  253.                ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) || (txt[i] == wxT(' ')) ||
  254.                 (txt[i] == wxT('\t')))) i++;
  255.     }
  256.  
  257.     while (i < lng)
  258.     {
  259.         x = 0;
  260.         d = temp[templen++] = txt[i];
  261.         if ((d == wxT('\n')) || (d == wxT('\r')) || (d == wxT(' ')) || (d == wxT('\t')))
  262.         {
  263.             i++, x++;
  264.             while ((i < lng) && ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) ||
  265.                                  (txt[i] == wxT(' ')) || (txt[i] == wxT('\t')))) i++, x++;
  266.         }
  267.         else i++;
  268.  
  269.         if (x)
  270.         {
  271.             temp[templen-1] = wxT(' ');
  272.             temp[templen] = 0;
  273. #if 0 // VS - WHY was this here?!
  274.             if (templen == 1) continue;
  275. #endif
  276.             templen = 0;
  277. #if !wxUSE_UNICODE
  278.             if (m_EncConv)
  279.                 m_EncConv->Convert(temp);
  280. #endif
  281.             size_t len = wxStrlen(temp);
  282.             for (size_t j = 0; j < len; j++)
  283.                 if (temp[j] == nbsp)
  284.                     temp[j] = wxT(' ');
  285.             c = new wxHtmlWordCell(temp, *(GetDC()));
  286.             if (m_UseLink)
  287.                 c->SetLink(m_Link);
  288.             m_Container->InsertCell(c);
  289.             m_tmpLastWasSpace = TRUE;
  290.         }
  291.     }
  292.  
  293.     if (templen && (templen > 1 || temp[0] != wxT(' ')))
  294.     {
  295.         temp[templen] = 0;
  296. #if !wxUSE_UNICODE
  297.         if (m_EncConv)
  298.             m_EncConv->Convert(temp);
  299. #endif
  300.         size_t len = wxStrlen(temp);
  301.         for (size_t j = 0; j < len; j++)
  302.             if (temp[j] == nbsp)
  303.                 temp[j] = wxT(' ');
  304.         c = new wxHtmlWordCell(temp, *(GetDC()));
  305.         if (m_UseLink)
  306.             c->SetLink(m_Link);
  307.         m_Container->InsertCell(c);
  308.         m_tmpLastWasSpace = FALSE;
  309.     }
  310. }
  311.  
  312.  
  313.  
  314. wxHtmlContainerCell* wxHtmlWinParser::OpenContainer()
  315. {
  316.     m_Container = new wxHtmlContainerCell(m_Container);
  317.     m_Container->SetAlignHor(m_Align);
  318.     m_tmpLastWasSpace = TRUE;
  319.         /* to avoid space being first character in paragraph */
  320.     return m_Container;
  321. }
  322.  
  323.  
  324.  
  325. wxHtmlContainerCell* wxHtmlWinParser::SetContainer(wxHtmlContainerCell *c)
  326. {
  327.     m_tmpLastWasSpace = TRUE;
  328.         /* to avoid space being first character in paragraph */
  329.     return m_Container = c;
  330. }
  331.  
  332.  
  333.  
  334. wxHtmlContainerCell* wxHtmlWinParser::CloseContainer()
  335. {
  336.     m_Container = m_Container->GetParent();
  337.     return m_Container;
  338. }
  339.  
  340.  
  341. void wxHtmlWinParser::SetFontSize(int s)
  342. {
  343.     if (s < 1) s = 1;
  344.     else if (s > 7) s = 7;
  345.     m_FontSize = s;
  346. }
  347.  
  348.  
  349.  
  350. wxFont* wxHtmlWinParser::CreateCurrentFont()
  351. {
  352.     int fb = GetFontBold(),
  353.         fi = GetFontItalic(),
  354.         fu = GetFontUnderlined(),
  355.         ff = GetFontFixed(),
  356.         fs = GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
  357.  
  358.     wxString face = ff ? m_FontFaceFixed : m_FontFaceNormal;
  359.     wxString *faceptr = &(m_FontsFacesTable[fb][fi][fu][ff][fs]);
  360.     wxFont **fontptr = &(m_FontsTable[fb][fi][fu][ff][fs]);
  361. #if !wxUSE_UNICODE
  362.     wxFontEncoding *encptr = &(m_FontsEncTable[fb][fi][fu][ff][fs]);
  363. #endif
  364.  
  365.     if (*fontptr != NULL && (*faceptr != face
  366. #if !wxUSE_UNICODE
  367.                              || *encptr != m_OutputEnc
  368. #endif
  369.                             ))
  370.     {
  371.         delete *fontptr;
  372.         *fontptr = NULL;
  373.     }
  374.  
  375.     if (*fontptr == NULL)
  376.     {
  377.         *faceptr = face;
  378.         *fontptr = new wxFont(
  379.                        (int) (m_FontsSizes[fs] * m_PixelScale),
  380.                        ff ? wxMODERN : wxSWISS,
  381.                        fi ? wxITALIC : wxNORMAL,
  382.                        fb ? wxBOLD : wxNORMAL,
  383.                        fu ? TRUE : FALSE, face
  384. #if wxUSE_UNICODE
  385.                        );
  386. #else
  387.                        , m_OutputEnc);
  388.         *encptr = m_OutputEnc;
  389. #endif
  390.     }
  391.     m_DC->SetFont(**fontptr);
  392.     return (*fontptr);
  393. }
  394.  
  395.  
  396.  
  397. void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo& link)
  398. {
  399.     m_Link = link;
  400.     m_UseLink = (link.GetHref() != wxEmptyString);
  401. }
  402.  
  403.  
  404. void wxHtmlWinParser::SetFontFace(const wxString& face)
  405. {
  406.     if (GetFontFixed()) m_FontFaceFixed = face;
  407.     else m_FontFaceNormal = face;
  408.  
  409. #if !wxUSE_UNICODE
  410.     if (m_InputEnc != wxFONTENCODING_DEFAULT)
  411.         SetInputEncoding(m_InputEnc);
  412. #endif
  413. }
  414.  
  415.  
  416.  
  417. #if !wxUSE_UNICODE
  418. void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc)
  419. {
  420.     m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
  421.     if (m_EncConv)
  422.     {
  423.         delete m_EncConv;
  424.         m_EncConv = NULL;
  425.     }
  426.  
  427.     if (enc == wxFONTENCODING_DEFAULT) return;
  428.  
  429.     wxFontEncoding altfix, altnorm;
  430.     bool availfix, availnorm;
  431.  
  432.     // exact match?
  433.     availnorm = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceNormal);
  434.     availfix = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceFixed);
  435.     if (availnorm && availfix)
  436.         m_OutputEnc = enc;
  437.  
  438.     // alternatives?
  439.     else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, FALSE) &&
  440.              wxFontMapper::Get()->GetAltForEncoding(enc, &altfix, m_FontFaceFixed, FALSE) &&
  441.              altnorm == altfix)
  442.         m_OutputEnc = altnorm;
  443.  
  444.     // at least normal face?
  445.     else if (availnorm)
  446.         m_OutputEnc = enc;
  447.     else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, FALSE))
  448.         m_OutputEnc = altnorm;
  449.  
  450.     // okay, let convert to ISO_8859-1, available always
  451.     else
  452.         m_OutputEnc = wxFONTENCODING_DEFAULT;
  453.  
  454.     m_InputEnc = enc;
  455.     if (m_OutputEnc == wxFONTENCODING_DEFAULT)
  456.         GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM);
  457.     else
  458.         GetEntitiesParser()->SetEncoding(m_OutputEnc);
  459.  
  460.     if (m_InputEnc == m_OutputEnc) return;
  461.  
  462.     m_EncConv = new wxEncodingConverter();
  463.     if (!m_EncConv->Init(m_InputEnc,
  464.                            (m_OutputEnc == wxFONTENCODING_DEFAULT) ?
  465.                                       wxFONTENCODING_ISO8859_1 : m_OutputEnc,
  466.                            wxCONVERT_SUBSTITUTE))
  467.     { // total failture :-(
  468.         wxLogError(_("Failed to display HTML document in %s encoding"),
  469.                    wxFontMapper::GetEncodingName(enc).c_str());
  470.         m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
  471.         delete m_EncConv;
  472.         m_EncConv = NULL;
  473.     }
  474. }
  475. #endif
  476.  
  477.  
  478.  
  479.  
  480. //-----------------------------------------------------------------------------
  481. // wxHtmlWinTagHandler
  482. //-----------------------------------------------------------------------------
  483.  
  484. IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler, wxHtmlTagHandler)
  485.  
  486. //-----------------------------------------------------------------------------
  487. // wxHtmlTagsModule
  488. //-----------------------------------------------------------------------------
  489.  
  490. // NB: This is *NOT* winpars.cpp's initialization and shutdown code!!
  491. //     This module is an ancestor for tag handlers modules defined
  492. //     in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct.
  493. //
  494. //     Do not add any winpars.cpp shutdown or initialization code to it,
  495. //     create a new module instead!
  496.  
  497. IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule, wxModule)
  498.  
  499. bool wxHtmlTagsModule::OnInit()
  500. {
  501.     wxHtmlWinParser::AddModule(this);
  502.     return TRUE;
  503. }
  504.  
  505. void wxHtmlTagsModule::OnExit()
  506. {
  507.     wxHtmlWinParser::RemoveModule(this);
  508. }
  509.  
  510. #endif
  511.  
  512.