1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxHtmlParser class (generic parser) 
   4 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  12 #pragma implementation "winpars.h" 
  15 #include "wx/wxprec.h" 
  18 #if wxUSE_HTML && wxUSE_STREAMS 
  29 #include "wx/html/htmldefs.h" 
  30 #include "wx/html/winpars.h" 
  31 #include "wx/html/htmlwin.h" 
  32 #include "wx/fontmap.h" 
  34 #include "wx/settings.h" 
  38 //----------------------------------------------------------------------------- 
  40 //----------------------------------------------------------------------------- 
  42 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser
, wxHtmlParser
) 
  44 wxList 
wxHtmlWinParser::m_Modules
; 
  46 wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow 
*wnd
) : wxHtmlParser() 
  53     m_CharHeight 
= m_CharWidth 
= 0; 
  57     m_InputEnc 
= wxFONTENCODING_ISO8859_1
; 
  58     m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
  60     m_lastWordCell 
= NULL
; 
  64         for (i 
= 0; i 
< 2; i
++) 
  65             for (j 
= 0; j 
< 2; j
++) 
  66                 for (k 
= 0; k 
< 2; k
++) 
  67                     for (l 
= 0; l 
< 2; l
++) 
  68                         for (m 
= 0; m 
< 7; m
++) 
  70                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
  71                             m_FontsFacesTable
[i
][j
][k
][l
][m
] = wxEmptyString
; 
  73                             m_FontsEncTable
[i
][j
][k
][l
][m
] = wxFONTENCODING_DEFAULT
; 
  77         SetFonts(wxEmptyString
, wxEmptyString
, NULL
); 
  80     // fill in wxHtmlParser's tables: 
  81     wxList::compatibility_iterator node 
= m_Modules
.GetFirst(); 
  84         wxHtmlTagsModule 
*mod 
= (wxHtmlTagsModule
*) node
->GetData(); 
  85         mod
->FillHandlersTable(this); 
  86         node 
= node
->GetNext(); 
  90 wxHtmlWinParser::~wxHtmlWinParser() 
  94     for (i 
= 0; i 
< 2; i
++) 
  95         for (j 
= 0; j 
< 2; j
++) 
  96             for (k 
= 0; k 
< 2; k
++) 
  97                 for (l 
= 0; l 
< 2; l
++) 
  98                     for (m 
= 0; m 
< 7; m
++) 
 100                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
 101                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 106     delete[] m_tmpStrBuf
; 
 109 void wxHtmlWinParser::AddModule(wxHtmlTagsModule 
*module) 
 111     m_Modules
.Append(module); 
 114 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule 
*module) 
 116     m_Modules
.DeleteObject(module); 
 119 void wxHtmlWinParser::SetFonts(wxString normal_face
, wxString fixed_face
, 
 122     static int default_sizes
[7] = 
 133     if (sizes 
== NULL
) sizes 
= default_sizes
; 
 137     for (i 
= 0; i 
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
]; 
 138     m_FontFaceFixed 
= fixed_face
; 
 139     m_FontFaceNormal 
= normal_face
; 
 142     SetInputEncoding(m_InputEnc
); 
 145     for (i 
= 0; i 
< 2; i
++) 
 146         for (j 
= 0; j 
< 2; j
++) 
 147             for (k 
= 0; k 
< 2; k
++) 
 148                 for (l 
= 0; l 
< 2; l
++) 
 149                     for (m 
= 0; m 
< 7; m
++) { 
 150                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
 152                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 153                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
 158 void wxHtmlWinParser::SetStandardFonts(int size
, 
 159                                        const wxString
& normal_face
, 
 160                                        const wxString
& fixed_face
) 
 162     wxFont defaultFont 
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 166         size 
= defaultFont
.GetPointSize(); 
 168     f_sizes
[0] = int(size 
* 0.6); 
 169     f_sizes
[1] = int(size 
* 0.8); 
 171     f_sizes
[3] = int(size 
* 1.2); 
 172     f_sizes
[4] = int(size 
* 1.4); 
 173     f_sizes
[5] = int(size 
* 1.6); 
 174     f_sizes
[6] = int(size 
* 1.8); 
 176     wxString normal 
= normal_face
.empty() ? 
 177                       defaultFont
.GetFaceName() : normal_face
; 
 179     SetFonts(normal
, fixed_face
, f_sizes
); 
 182 void wxHtmlWinParser::InitParser(const wxString
& source
) 
 184     wxHtmlParser::InitParser(source
); 
 185     wxASSERT_MSG(m_DC 
!= NULL
, wxT("no DC assigned to wxHtmlWinParser!!")); 
 187     m_FontBold 
= m_FontItalic 
= m_FontUnderlined 
= m_FontFixed 
= FALSE
; 
 188     m_FontSize 
= 3; //default one 
 189     CreateCurrentFont();           // we're selecting default font into 
 190     m_DC
->GetTextExtent( wxT("H"), &m_CharWidth
, &m_CharHeight
); 
 191                 /* NOTE : we're not using GetCharWidth/Height() because 
 192                    of differences under X and win 
 196     m_Link 
= wxHtmlLinkInfo( wxEmptyString 
); 
 197     m_LinkColor
.Set(0, 0, 0xFF); 
 198     m_ActualColor
.Set(0, 0, 0); 
 199     m_Align 
= wxHTML_ALIGN_LEFT
; 
 200     m_tmpLastWasSpace 
= false; 
 201     m_lastWordCell 
= NULL
; 
 207     wxString charset 
= ExtractCharsetInformation(source
); 
 208     if (!charset
.empty()) 
 210         wxFontEncoding enc 
= wxFontMapper::Get()->CharsetToEncoding(charset
); 
 211         if (enc 
!= wxFONTENCODING_SYSTEM
) 
 212           SetInputEncoding(enc
); 
 216     m_Container
->InsertCell(new wxHtmlColourCell(m_ActualColor
)); 
 217     wxColour windowColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
) ; 
 218     m_Container
->InsertCell( 
 219             new wxHtmlColourCell(GetWindow() ? 
 220                                      GetWindow()->GetBackgroundColour() : 
 222                                  wxHTML_CLR_BACKGROUND
)); 
 223     m_Container
->InsertCell(new wxHtmlFontCell(CreateCurrentFont())); 
 226 void wxHtmlWinParser::DoneParser() 
 230     SetInputEncoding(wxFONTENCODING_ISO8859_1
); // for next call 
 232     wxHtmlParser::DoneParser(); 
 235 wxObject
* wxHtmlWinParser::GetProduct() 
 237     wxHtmlContainerCell 
*top
; 
 243     while (top
->GetParent()) top 
= top
->GetParent(); 
 244     top
->RemoveExtraSpacing(true, true); 
 249 wxFSFile 
*wxHtmlWinParser::OpenURL(wxHtmlURLType type
, 
 250                                    const wxString
& url
) const 
 255         wxHtmlOpeningStatus status
; 
 258             wxString 
myfullurl(myurl
); 
 260             // consider url as absolute path first 
 261             wxURI 
current(myurl
); 
 262             myfullurl 
= current
.BuildUnescapedURI(); 
 264             // if not absolute then ... 
 265             if( current
.IsReference() ) 
 267                 wxString basepath 
= GetFS()->GetPath(); 
 268                 wxURI 
base(basepath
); 
 270                 // ... try to apply base path if valid ... 
 271                 if( !base
.IsReference() ) 
 273                     wxURI 
path(myfullurl
); 
 274                     path
.Resolve( base 
); 
 275                     myfullurl 
= path
.BuildUnescapedURI(); 
 279                     // ... or force such addition if not included already 
 280                     if( !current
.GetPath().Contains(base
.GetPath()) ) 
 283                         wxURI 
connected( basepath 
); 
 284                         myfullurl 
= connected
.BuildUnescapedURI(); 
 290             status 
= m_Window
->OnOpeningURL(type
, myfullurl
, &redirect
); 
 291             if ( status 
!= wxHTML_REDIRECT 
) 
 297         if ( status 
== wxHTML_BLOCK 
) 
 300         return GetFS()->OpenFile(myurl
); 
 303     return wxHtmlParser::OpenURL(type
, url
); 
 306 void wxHtmlWinParser::AddText(const wxChar
* txt
) 
 314     wxChar nbsp 
= GetEntitiesParser()->GetCharForCode(160 /* nbsp */); 
 316     if (lng
+1 > m_tmpStrBufSize
) 
 318         delete[] m_tmpStrBuf
; 
 319         m_tmpStrBuf 
= new wxChar
[lng
+1]; 
 320         m_tmpStrBufSize 
= lng
+1; 
 322     wxChar 
*temp 
= m_tmpStrBuf
; 
 324     if (m_tmpLastWasSpace
) 
 327                ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || (txt
[i
] == wxT(' ')) || 
 328                 (txt
[i
] == wxT('\t')))) i
++; 
 334         d 
= temp
[templen
++] = txt
[i
]; 
 335         if ((d 
== wxT('\n')) || (d 
== wxT('\r')) || (d 
== wxT(' ')) || (d 
== wxT('\t'))) 
 338             while ((i 
< lng
) && ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || 
 339                                  (txt
[i
] == wxT(' ')) || (txt
[i
] == wxT('\t')))) i
++, x
++; 
 345             temp
[templen
-1] = wxT(' '); 
 350                 m_EncConv
->Convert(temp
); 
 352             size_t len 
= wxStrlen(temp
); 
 353             for (size_t j 
= 0; j 
< len
; j
++) 
 356             c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 359             m_Container
->InsertCell(c
); 
 360             ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
); 
 361             m_lastWordCell 
= (wxHtmlWordCell
*)c
; 
 362             m_tmpLastWasSpace 
= true; 
 366     if (templen 
&& (templen 
> 1 || temp
[0] != wxT(' '))) 
 371             m_EncConv
->Convert(temp
); 
 373         size_t len 
= wxStrlen(temp
); 
 374         for (size_t j 
= 0; j 
< len
; j
++) 
 377         c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 380         m_Container
->InsertCell(c
); 
 381         ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
); 
 382         m_lastWordCell 
= (wxHtmlWordCell
*)c
; 
 383         m_tmpLastWasSpace 
= false; 
 389 wxHtmlContainerCell
* wxHtmlWinParser::OpenContainer() 
 391     m_Container 
= new wxHtmlContainerCell(m_Container
); 
 392     m_Container
->SetAlignHor(m_Align
); 
 393     m_tmpLastWasSpace 
= true; 
 394         /* to avoid space being first character in paragraph */ 
 400 wxHtmlContainerCell
* wxHtmlWinParser::SetContainer(wxHtmlContainerCell 
*c
) 
 402     m_tmpLastWasSpace 
= true; 
 403         /* to avoid space being first character in paragraph */ 
 404     return m_Container 
= c
; 
 409 wxHtmlContainerCell
* wxHtmlWinParser::CloseContainer() 
 411     m_Container 
= m_Container
->GetParent(); 
 416 void wxHtmlWinParser::SetFontSize(int s
) 
 419     else if (s 
> 7) s 
= 7; 
 425 wxFont
* wxHtmlWinParser::CreateCurrentFont() 
 427     int fb 
= GetFontBold(), 
 428         fi 
= GetFontItalic(), 
 429         fu 
= GetFontUnderlined(), 
 431         fs 
= GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ; 
 433     wxString face 
= ff 
? m_FontFaceFixed 
: m_FontFaceNormal
; 
 434     wxString 
*faceptr 
= &(m_FontsFacesTable
[fb
][fi
][fu
][ff
][fs
]); 
 435     wxFont 
**fontptr 
= &(m_FontsTable
[fb
][fi
][fu
][ff
][fs
]); 
 437     wxFontEncoding 
*encptr 
= &(m_FontsEncTable
[fb
][fi
][fu
][ff
][fs
]); 
 440     if (*fontptr 
!= NULL 
&& (*faceptr 
!= face
 
 442                              || *encptr 
!= m_OutputEnc
 
 450     if (*fontptr 
== NULL
) 
 453         *fontptr 
= new wxFont( 
 454                        (int) (m_FontsSizes
[fs
] * m_PixelScale
), 
 455                        ff 
? wxMODERN 
: wxSWISS
, 
 456                        fi 
? wxITALIC 
: wxNORMAL
, 
 457                        fb 
? wxBOLD 
: wxNORMAL
, 
 458                        fu 
? true : false, face
 
 463         *encptr 
= m_OutputEnc
; 
 466     m_DC
->SetFont(**fontptr
); 
 472 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo
& link
) 
 475     m_UseLink 
= (link
.GetHref() != wxEmptyString
); 
 479 void wxHtmlWinParser::SetFontFace(const wxString
& face
) 
 481     if (GetFontFixed()) m_FontFaceFixed 
= face
; 
 482     else m_FontFaceNormal 
= face
; 
 485     if (m_InputEnc 
!= wxFONTENCODING_DEFAULT
) 
 486         SetInputEncoding(m_InputEnc
); 
 493 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc
) 
 495     m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 502     if (enc 
== wxFONTENCODING_DEFAULT
) return; 
 504     wxFontEncoding altfix
, altnorm
; 
 505     bool availfix
, availnorm
; 
 508     availnorm 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceNormal
); 
 509     availfix 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceFixed
); 
 510     if (availnorm 
&& availfix
) 
 514     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, false) && 
 515              wxFontMapper::Get()->GetAltForEncoding(enc
, &altfix
, m_FontFaceFixed
, false) && 
 517         m_OutputEnc 
= altnorm
; 
 519     // at least normal face? 
 522     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, false)) 
 523         m_OutputEnc 
= altnorm
; 
 528         // okay, let convert to ISO_8859-1, available always 
 529         m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 531         m_OutputEnc 
= wxLocale::GetSystemEncoding() ; 
 536     if (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) 
 537         GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM
); 
 539         GetEntitiesParser()->SetEncoding(m_OutputEnc
); 
 541     if (m_InputEnc 
== m_OutputEnc
) return; 
 543     m_EncConv 
= new wxEncodingConverter(); 
 544     if (!m_EncConv
->Init(m_InputEnc
, 
 545                            (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) ? 
 546                                       wxFONTENCODING_ISO8859_1 
: m_OutputEnc
, 
 547                            wxCONVERT_SUBSTITUTE
)) 
 548     { // total failture :-( 
 549         wxLogError(_("Failed to display HTML document in %s encoding"), 
 550                    wxFontMapper::GetEncodingName(enc
).c_str()); 
 551         m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 561 //----------------------------------------------------------------------------- 
 562 // wxHtmlWinTagHandler 
 563 //----------------------------------------------------------------------------- 
 565 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler
, wxHtmlTagHandler
) 
 567 //----------------------------------------------------------------------------- 
 569 //----------------------------------------------------------------------------- 
 571 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!! 
 572 //     This module is an ancestor for tag handlers modules defined 
 573 //     in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct. 
 575 //     Do not add any winpars.cpp shutdown or initialization code to it, 
 576 //     create a new module instead! 
 578 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule
, wxModule
) 
 580 bool wxHtmlTagsModule::OnInit() 
 582     wxHtmlWinParser::AddModule(this); 
 586 void wxHtmlTagsModule::OnExit() 
 588     wxHtmlWinParser::RemoveModule(this);