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" 
  37 //----------------------------------------------------------------------------- 
  39 //----------------------------------------------------------------------------- 
  41 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser
, wxHtmlParser
) 
  43 wxList 
wxHtmlWinParser::m_Modules
; 
  45 wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow 
*wnd
) : wxHtmlParser() 
  52     m_CharHeight 
= m_CharWidth 
= 0; 
  56     m_InputEnc 
= wxFONTENCODING_ISO8859_1
; 
  57     m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
  59     m_lastWordCell 
= NULL
; 
  63         for (i 
= 0; i 
< 2; i
++) 
  64             for (j 
= 0; j 
< 2; j
++) 
  65                 for (k 
= 0; k 
< 2; k
++) 
  66                     for (l 
= 0; l 
< 2; l
++) 
  67                         for (m 
= 0; m 
< 7; m
++) 
  69                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
  70                             m_FontsFacesTable
[i
][j
][k
][l
][m
] = wxEmptyString
; 
  72                             m_FontsEncTable
[i
][j
][k
][l
][m
] = wxFONTENCODING_DEFAULT
; 
  76         SetFonts(wxEmptyString
, wxEmptyString
, NULL
); 
  79     // fill in wxHtmlParser's tables: 
  80     wxList::compatibility_iterator node 
= m_Modules
.GetFirst(); 
  83         wxHtmlTagsModule 
*mod 
= (wxHtmlTagsModule
*) node
->GetData(); 
  84         mod
->FillHandlersTable(this); 
  85         node 
= node
->GetNext(); 
  89 wxHtmlWinParser::~wxHtmlWinParser() 
  93     for (i 
= 0; i 
< 2; i
++) 
  94         for (j 
= 0; j 
< 2; j
++) 
  95             for (k 
= 0; k 
< 2; k
++) 
  96                 for (l 
= 0; l 
< 2; l
++) 
  97                     for (m 
= 0; m 
< 7; m
++) 
  99                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
 100                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 105     delete[] m_tmpStrBuf
; 
 108 void wxHtmlWinParser::AddModule(wxHtmlTagsModule 
*module) 
 110     m_Modules
.Append(module); 
 113 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule 
*module) 
 115     m_Modules
.DeleteObject(module); 
 118 void wxHtmlWinParser::SetFonts(wxString normal_face
, wxString fixed_face
, 
 121     static int default_sizes
[7] = 
 132     if (sizes 
== NULL
) sizes 
= default_sizes
; 
 136     for (i 
= 0; i 
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
]; 
 137     m_FontFaceFixed 
= fixed_face
; 
 138     m_FontFaceNormal 
= normal_face
; 
 141     SetInputEncoding(m_InputEnc
); 
 144     for (i 
= 0; i 
< 2; i
++) 
 145         for (j 
= 0; j 
< 2; j
++) 
 146             for (k 
= 0; k 
< 2; k
++) 
 147                 for (l 
= 0; l 
< 2; l
++) 
 148                     for (m 
= 0; m 
< 7; m
++) { 
 149                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
 151                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 152                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
 157 void wxHtmlWinParser::InitParser(const wxString
& source
) 
 159     wxHtmlParser::InitParser(source
); 
 160     wxASSERT_MSG(m_DC 
!= NULL
, wxT("no DC assigned to wxHtmlWinParser!!")); 
 162     m_FontBold 
= m_FontItalic 
= m_FontUnderlined 
= m_FontFixed 
= FALSE
; 
 163     m_FontSize 
= 3; //default one 
 164     CreateCurrentFont();           // we're selecting default font into 
 165     m_DC
->GetTextExtent( wxT("H"), &m_CharWidth
, &m_CharHeight
); 
 166                 /* NOTE : we're not using GetCharWidth/Height() because 
 167                    of differences under X and win 
 171     m_Link 
= wxHtmlLinkInfo( wxT(""), wxT("") ); 
 172     m_LinkColor
.Set(0, 0, 0xFF); 
 173     m_ActualColor
.Set(0, 0, 0); 
 174     m_Align 
= wxHTML_ALIGN_LEFT
; 
 175     m_tmpLastWasSpace 
= FALSE
; 
 176     m_lastWordCell 
= NULL
; 
 182     wxString charset 
= ExtractCharsetInformation(source
); 
 183     if (!charset
.empty()) 
 185         wxFontEncoding enc 
= wxFontMapper::Get()->CharsetToEncoding(charset
); 
 186         if (enc 
!= wxFONTENCODING_SYSTEM
) 
 187           SetInputEncoding(enc
); 
 191     m_Container
->InsertCell(new wxHtmlColourCell(m_ActualColor
)); 
 192     wxColour windowColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
) ; 
 193     m_Container
->InsertCell( 
 194             new wxHtmlColourCell(GetWindow() ? 
 195                                      GetWindow()->GetBackgroundColour() : 
 197                                  wxHTML_CLR_BACKGROUND
)); 
 198     m_Container
->InsertCell(new wxHtmlFontCell(CreateCurrentFont())); 
 201 void wxHtmlWinParser::DoneParser() 
 205     SetInputEncoding(wxFONTENCODING_ISO8859_1
); // for next call 
 207     wxHtmlParser::DoneParser(); 
 210 wxObject
* wxHtmlWinParser::GetProduct() 
 212     wxHtmlContainerCell 
*top
; 
 218     while (top
->GetParent()) top 
= top
->GetParent(); 
 219     top
->RemoveExtraSpacing(true, true); 
 224 wxFSFile 
*wxHtmlWinParser::OpenURL(wxHtmlURLType type
, 
 225                                    const wxString
& url
) const 
 227     // FIXME - normalize the URL to full path before passing to 
 232         wxHtmlOpeningStatus status
; 
 236             status 
= m_Window
->OnOpeningURL(type
, myurl
, &redirect
); 
 237             if ( status 
!= wxHTML_REDIRECT 
) 
 243         if ( status 
== wxHTML_BLOCK 
) 
 246         return GetFS()->OpenFile(myurl
); 
 249     return wxHtmlParser::OpenURL(type
, url
); 
 252 void wxHtmlWinParser::AddText(const wxChar
* txt
) 
 260     wxChar nbsp 
= GetEntitiesParser()->GetCharForCode(160 /* nbsp */); 
 262     if (lng
+1 > m_tmpStrBufSize
) 
 264         delete[] m_tmpStrBuf
; 
 265         m_tmpStrBuf 
= new wxChar
[lng
+1]; 
 266         m_tmpStrBufSize 
= lng
+1; 
 268     wxChar 
*temp 
= m_tmpStrBuf
; 
 270     if (m_tmpLastWasSpace
) 
 273                ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || (txt
[i
] == wxT(' ')) || 
 274                 (txt
[i
] == wxT('\t')))) i
++; 
 280         d 
= temp
[templen
++] = txt
[i
]; 
 281         if ((d 
== wxT('\n')) || (d 
== wxT('\r')) || (d 
== wxT(' ')) || (d 
== wxT('\t'))) 
 284             while ((i 
< lng
) && ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || 
 285                                  (txt
[i
] == wxT(' ')) || (txt
[i
] == wxT('\t')))) i
++, x
++; 
 291             temp
[templen
-1] = wxT(' '); 
 296                 m_EncConv
->Convert(temp
); 
 298             size_t len 
= wxStrlen(temp
); 
 299             for (size_t j 
= 0; j 
< len
; j
++) 
 302             c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 305             m_Container
->InsertCell(c
); 
 306             ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
); 
 307             m_lastWordCell 
= (wxHtmlWordCell
*)c
; 
 308             m_tmpLastWasSpace 
= TRUE
; 
 312     if (templen 
&& (templen 
> 1 || temp
[0] != wxT(' '))) 
 317             m_EncConv
->Convert(temp
); 
 319         size_t len 
= wxStrlen(temp
); 
 320         for (size_t j 
= 0; j 
< len
; j
++) 
 323         c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 326         m_Container
->InsertCell(c
); 
 327         ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
); 
 328         m_lastWordCell 
= (wxHtmlWordCell
*)c
; 
 329         m_tmpLastWasSpace 
= FALSE
; 
 335 wxHtmlContainerCell
* wxHtmlWinParser::OpenContainer() 
 337     m_Container 
= new wxHtmlContainerCell(m_Container
); 
 338     m_Container
->SetAlignHor(m_Align
); 
 339     m_tmpLastWasSpace 
= TRUE
; 
 340         /* to avoid space being first character in paragraph */ 
 346 wxHtmlContainerCell
* wxHtmlWinParser::SetContainer(wxHtmlContainerCell 
*c
) 
 348     m_tmpLastWasSpace 
= TRUE
; 
 349         /* to avoid space being first character in paragraph */ 
 350     return m_Container 
= c
; 
 355 wxHtmlContainerCell
* wxHtmlWinParser::CloseContainer() 
 357     m_Container 
= m_Container
->GetParent(); 
 362 void wxHtmlWinParser::SetFontSize(int s
) 
 365     else if (s 
> 7) s 
= 7; 
 371 wxFont
* wxHtmlWinParser::CreateCurrentFont() 
 373     int fb 
= GetFontBold(), 
 374         fi 
= GetFontItalic(), 
 375         fu 
= GetFontUnderlined(), 
 377         fs 
= GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ; 
 379     wxString face 
= ff 
? m_FontFaceFixed 
: m_FontFaceNormal
; 
 380     wxString 
*faceptr 
= &(m_FontsFacesTable
[fb
][fi
][fu
][ff
][fs
]); 
 381     wxFont 
**fontptr 
= &(m_FontsTable
[fb
][fi
][fu
][ff
][fs
]); 
 383     wxFontEncoding 
*encptr 
= &(m_FontsEncTable
[fb
][fi
][fu
][ff
][fs
]); 
 386     if (*fontptr 
!= NULL 
&& (*faceptr 
!= face
 
 388                              || *encptr 
!= m_OutputEnc
 
 396     if (*fontptr 
== NULL
) 
 399         *fontptr 
= new wxFont( 
 400                        (int) (m_FontsSizes
[fs
] * m_PixelScale
), 
 401                        ff 
? wxMODERN 
: wxSWISS
, 
 402                        fi 
? wxITALIC 
: wxNORMAL
, 
 403                        fb 
? wxBOLD 
: wxNORMAL
, 
 404                        fu 
? TRUE 
: FALSE
, face
 
 409         *encptr 
= m_OutputEnc
; 
 412     m_DC
->SetFont(**fontptr
); 
 418 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo
& link
) 
 421     m_UseLink 
= (link
.GetHref() != wxEmptyString
); 
 425 void wxHtmlWinParser::SetFontFace(const wxString
& face
) 
 427     if (GetFontFixed()) m_FontFaceFixed 
= face
; 
 428     else m_FontFaceNormal 
= face
; 
 431     if (m_InputEnc 
!= wxFONTENCODING_DEFAULT
) 
 432         SetInputEncoding(m_InputEnc
); 
 439 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc
) 
 441     m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 448     if (enc 
== wxFONTENCODING_DEFAULT
) return; 
 450     wxFontEncoding altfix
, altnorm
; 
 451     bool availfix
, availnorm
; 
 454     availnorm 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceNormal
); 
 455     availfix 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceFixed
); 
 456     if (availnorm 
&& availfix
) 
 460     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, FALSE
) && 
 461              wxFontMapper::Get()->GetAltForEncoding(enc
, &altfix
, m_FontFaceFixed
, FALSE
) && 
 463         m_OutputEnc 
= altnorm
; 
 465     // at least normal face? 
 468     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, FALSE
)) 
 469         m_OutputEnc 
= altnorm
; 
 474         // okay, let convert to ISO_8859-1, available always 
 475         m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 477         m_OutputEnc 
= wxLocale::GetSystemEncoding() ; 
 482     if (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) 
 483         GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM
); 
 485         GetEntitiesParser()->SetEncoding(m_OutputEnc
); 
 487     if (m_InputEnc 
== m_OutputEnc
) return; 
 489     m_EncConv 
= new wxEncodingConverter(); 
 490     if (!m_EncConv
->Init(m_InputEnc
, 
 491                            (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) ? 
 492                                       wxFONTENCODING_ISO8859_1 
: m_OutputEnc
, 
 493                            wxCONVERT_SUBSTITUTE
)) 
 494     { // total failture :-( 
 495         wxLogError(_("Failed to display HTML document in %s encoding"), 
 496                    wxFontMapper::GetEncodingName(enc
).c_str()); 
 497         m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 507 //----------------------------------------------------------------------------- 
 508 // wxHtmlWinTagHandler 
 509 //----------------------------------------------------------------------------- 
 511 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler
, wxHtmlTagHandler
) 
 513 //----------------------------------------------------------------------------- 
 515 //----------------------------------------------------------------------------- 
 517 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!! 
 518 //     This module is an ancestor for tag handlers modules defined 
 519 //     in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct. 
 521 //     Do not add any winpars.cpp shutdown or initialization code to it, 
 522 //     create a new module instead! 
 524 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule
, wxModule
) 
 526 bool wxHtmlTagsModule::OnInit() 
 528     wxHtmlWinParser::AddModule(this); 
 532 void wxHtmlTagsModule::OnExit() 
 534     wxHtmlWinParser::RemoveModule(this);