1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxHtmlParser class (generic parser) 
   4 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik 
   7 // Licence:     wxWindows Licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  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" 
  36 //----------------------------------------------------------------------------- 
  38 //----------------------------------------------------------------------------- 
  41 wxList 
wxHtmlWinParser::m_Modules
; 
  43 wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow 
*wnd
) : wxHtmlParser() 
  50     m_CharHeight 
= m_CharWidth 
= 0; 
  54     m_InputEnc 
= wxFONTENCODING_ISO8859_1
; 
  55     m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
  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
++) 
  66                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
  67                             m_FontsFacesTable
[i
][j
][k
][l
][m
] = wxEmptyString
; 
  69                             m_FontsEncTable
[i
][j
][k
][l
][m
] = wxFONTENCODING_DEFAULT
; 
  73         SetFonts(wxEmptyString
, wxEmptyString
, NULL
); 
  76     // fill in wxHtmlParser's tables: 
  77     wxNode 
*node 
= m_Modules
.GetFirst(); 
  80         wxHtmlTagsModule 
*mod 
= (wxHtmlTagsModule
*) node
->GetData(); 
  81         mod
->FillHandlersTable(this); 
  82         node 
= node
->GetNext(); 
  86 wxHtmlWinParser::~wxHtmlWinParser() 
  90     for (i 
= 0; i 
< 2; i
++) 
  91         for (j 
= 0; j 
< 2; j
++) 
  92             for (k 
= 0; k 
< 2; k
++) 
  93                 for (l 
= 0; l 
< 2; l
++) 
  94                     for (m 
= 0; m 
< 7; m
++) 
  96                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
  97                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 102     delete[] m_tmpStrBuf
; 
 105 void wxHtmlWinParser::AddModule(wxHtmlTagsModule 
*module) 
 107     m_Modules
.Append(module); 
 110 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule 
*module) 
 112     m_Modules
.DeleteObject(module); 
 115 void wxHtmlWinParser::SetFonts(wxString normal_face
, wxString fixed_face
, 
 118     static int default_sizes
[7] = 
 129     if (sizes 
== NULL
) sizes 
= default_sizes
; 
 133     for (i 
= 0; i 
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
]; 
 134     m_FontFaceFixed 
= fixed_face
; 
 135     m_FontFaceNormal 
= normal_face
; 
 138     SetInputEncoding(m_InputEnc
); 
 141     for (i 
= 0; i 
< 2; i
++) 
 142         for (j 
= 0; j 
< 2; j
++) 
 143             for (k 
= 0; k 
< 2; k
++) 
 144                 for (l 
= 0; l 
< 2; l
++) 
 145                     for (m 
= 0; m 
< 7; m
++) { 
 146                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
 148                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 149                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
 154 void wxHtmlWinParser::InitParser(const wxString
& source
) 
 156     wxHtmlParser::InitParser(source
); 
 157     wxASSERT_MSG(m_DC 
!= NULL
, wxT("no DC assigned to wxHtmlWinParser!!")); 
 159     m_FontBold 
= m_FontItalic 
= m_FontUnderlined 
= m_FontFixed 
= FALSE
; 
 160     m_FontSize 
= 3; //default one 
 161     CreateCurrentFont();           // we're selecting default font into 
 162     m_DC
->GetTextExtent( wxT("H"), &m_CharWidth
, &m_CharHeight
); 
 163                 /* NOTE : we're not using GetCharWidth/Height() because 
 164                    of differences under X and win 
 168     m_Link 
= wxHtmlLinkInfo( wxT(""), wxT("") ); 
 169     m_LinkColor
.Set(0, 0, 0xFF); 
 170     m_ActualColor
.Set(0, 0, 0); 
 171     m_Align 
= wxHTML_ALIGN_LEFT
; 
 172     m_tmpLastWasSpace 
= FALSE
; 
 178     wxString charset 
= ExtractCharsetInformation(source
); 
 179     if (!charset
.empty()) 
 181         wxFontEncoding enc 
= wxFontMapper::Get()->CharsetToEncoding(charset
); 
 182         if (enc 
!= wxFONTENCODING_SYSTEM
) 
 183           SetInputEncoding(enc
); 
 187     m_Container
->InsertCell(new wxHtmlColourCell(m_ActualColor
)); 
 188     m_Container
->InsertCell(new wxHtmlFontCell(CreateCurrentFont())); 
 191 void wxHtmlWinParser::DoneParser() 
 195     SetInputEncoding(wxFONTENCODING_ISO8859_1
); // for next call 
 197     wxHtmlParser::DoneParser(); 
 200 wxObject
* wxHtmlWinParser::GetProduct() 
 202     wxHtmlContainerCell 
*top
; 
 208     while (top
->GetParent()) top 
= top
->GetParent(); 
 212 wxFSFile 
*wxHtmlWinParser::OpenURL(wxHtmlURLType type
, 
 213                                    const wxString
& url
) const 
 215     // FIXME - normalize the URL to full path before passing to 
 220         wxHtmlOpeningStatus status
; 
 224             status 
= m_Window
->OnOpeningURL(type
, myurl
, &redirect
); 
 225             if ( status 
!= wxHTML_REDIRECT 
) 
 231         if ( status 
== wxHTML_BLOCK 
) 
 234         return GetFS()->OpenFile(myurl
); 
 237     return wxHtmlParser::OpenURL(type
, url
); 
 240 void wxHtmlWinParser::AddText(const wxChar
* txt
) 
 248     wxChar nbsp 
= GetEntitiesParser()->GetCharForCode(160 /* nbsp */); 
 250     if (lng
+1 > m_tmpStrBufSize
) 
 252         delete[] m_tmpStrBuf
; 
 253         m_tmpStrBuf 
= new wxChar
[lng
+1]; 
 254         m_tmpStrBufSize 
= lng
+1; 
 256     wxChar 
*temp 
= m_tmpStrBuf
; 
 258     if (m_tmpLastWasSpace
) 
 261                ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || (txt
[i
] == wxT(' ')) || 
 262                 (txt
[i
] == wxT('\t')))) i
++; 
 268         d 
= temp
[templen
++] = txt
[i
]; 
 269         if ((d 
== wxT('\n')) || (d 
== wxT('\r')) || (d 
== wxT(' ')) || (d 
== wxT('\t'))) 
 272             while ((i 
< lng
) && ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || 
 273                                  (txt
[i
] == wxT(' ')) || (txt
[i
] == wxT('\t')))) i
++, x
++; 
 279             temp
[templen
-1] = wxT(' '); 
 281 #if 0 // VS - WHY was this here?! 
 282             if (templen 
== 1) continue; 
 287                 m_EncConv
->Convert(temp
); 
 289             size_t len 
= wxStrlen(temp
); 
 290             for (size_t j 
= 0; j 
< len
; j
++) 
 293             c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 296             m_Container
->InsertCell(c
); 
 297             m_tmpLastWasSpace 
= TRUE
; 
 301     if (templen 
&& (templen 
> 1 || temp
[0] != wxT(' '))) 
 306             m_EncConv
->Convert(temp
); 
 308         size_t len 
= wxStrlen(temp
); 
 309         for (size_t j 
= 0; j 
< len
; j
++) 
 312         c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 315         m_Container
->InsertCell(c
); 
 316         m_tmpLastWasSpace 
= FALSE
; 
 322 wxHtmlContainerCell
* wxHtmlWinParser::OpenContainer() 
 324     m_Container 
= new wxHtmlContainerCell(m_Container
); 
 325     m_Container
->SetAlignHor(m_Align
); 
 326     m_tmpLastWasSpace 
= TRUE
; 
 327         /* to avoid space being first character in paragraph */ 
 333 wxHtmlContainerCell
* wxHtmlWinParser::SetContainer(wxHtmlContainerCell 
*c
) 
 335     m_tmpLastWasSpace 
= TRUE
; 
 336         /* to avoid space being first character in paragraph */ 
 337     return m_Container 
= c
; 
 342 wxHtmlContainerCell
* wxHtmlWinParser::CloseContainer() 
 344     m_Container 
= m_Container
->GetParent(); 
 349 void wxHtmlWinParser::SetFontSize(int s
) 
 352     else if (s 
> 7) s 
= 7; 
 358 wxFont
* wxHtmlWinParser::CreateCurrentFont() 
 360     int fb 
= GetFontBold(), 
 361         fi 
= GetFontItalic(), 
 362         fu 
= GetFontUnderlined(), 
 364         fs 
= GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ; 
 366     wxString face 
= ff 
? m_FontFaceFixed 
: m_FontFaceNormal
; 
 367     wxString 
*faceptr 
= &(m_FontsFacesTable
[fb
][fi
][fu
][ff
][fs
]); 
 368     wxFont 
**fontptr 
= &(m_FontsTable
[fb
][fi
][fu
][ff
][fs
]); 
 370     wxFontEncoding 
*encptr 
= &(m_FontsEncTable
[fb
][fi
][fu
][ff
][fs
]); 
 373     if (*fontptr 
!= NULL 
&& (*faceptr 
!= face
 
 375                              || *encptr 
!= m_OutputEnc
 
 383     if (*fontptr 
== NULL
) 
 386         *fontptr 
= new wxFont( 
 387                        (int) (m_FontsSizes
[fs
] * m_PixelScale
), 
 388                        ff 
? wxMODERN 
: wxSWISS
, 
 389                        fi 
? wxITALIC 
: wxNORMAL
, 
 390                        fb 
? wxBOLD 
: wxNORMAL
, 
 391                        fu 
? TRUE 
: FALSE
, face
 
 396         *encptr 
= m_OutputEnc
; 
 399     m_DC
->SetFont(**fontptr
); 
 405 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo
& link
) 
 408     m_UseLink 
= (link
.GetHref() != wxEmptyString
); 
 412 void wxHtmlWinParser::SetFontFace(const wxString
& face
) 
 414     if (GetFontFixed()) m_FontFaceFixed 
= face
; 
 415     else m_FontFaceNormal 
= face
; 
 418     if (m_InputEnc 
!= wxFONTENCODING_DEFAULT
) 
 419         SetInputEncoding(m_InputEnc
); 
 426 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc
) 
 428     m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 435     if (enc 
== wxFONTENCODING_DEFAULT
) return; 
 437     wxFontEncoding altfix
, altnorm
; 
 438     bool availfix
, availnorm
; 
 441     availnorm 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceNormal
); 
 442     availfix 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceFixed
); 
 443     if (availnorm 
&& availfix
) 
 447     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, FALSE
) && 
 448              wxFontMapper::Get()->GetAltForEncoding(enc
, &altfix
, m_FontFaceFixed
, FALSE
) && 
 450         m_OutputEnc 
= altnorm
; 
 452     // at least normal face? 
 455     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, FALSE
)) 
 456         m_OutputEnc 
= altnorm
; 
 458     // okay, let convert to ISO_8859-1, available always 
 460         m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 463     if (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) 
 464         GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM
); 
 466         GetEntitiesParser()->SetEncoding(m_OutputEnc
); 
 468     if (m_InputEnc 
== m_OutputEnc
) return; 
 470     m_EncConv 
= new wxEncodingConverter(); 
 471     if (!m_EncConv
->Init(m_InputEnc
, 
 472                            (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) ? 
 473                                       wxFONTENCODING_ISO8859_1 
: m_OutputEnc
, 
 474                            wxCONVERT_SUBSTITUTE
)) 
 475     { // total failture :-( 
 476         wxLogError(_("Failed to display HTML document in %s encoding"), 
 477                    wxFontMapper::GetEncodingName(enc
).c_str()); 
 478         m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 488 //----------------------------------------------------------------------------- 
 489 // wxHtmlWinTagHandler 
 490 //----------------------------------------------------------------------------- 
 492 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler
, wxHtmlTagHandler
) 
 494 //----------------------------------------------------------------------------- 
 496 //----------------------------------------------------------------------------- 
 498 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!! 
 499 //     This module is an ancestor for tag handlers modules defined 
 500 //     in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct. 
 502 //     Do not add any winpars.cpp shutdown or initialization code to it, 
 503 //     create a new module instead! 
 505 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule
, wxModule
) 
 507 bool wxHtmlTagsModule::OnInit() 
 509     wxHtmlWinParser::AddModule(this); 
 513 void wxHtmlTagsModule::OnExit() 
 515     wxHtmlWinParser::RemoveModule(this);