1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxHtmlParser class (generic parser) 
   4 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 #include "wx/wxprec.h" 
  13 #if wxUSE_HTML && wxUSE_STREAMS 
  24 #include "wx/html/htmldefs.h" 
  25 #include "wx/html/winpars.h" 
  26 #include "wx/html/htmlwin.h" 
  27 #include "wx/fontmap.h" 
  29 #include "wx/settings.h" 
  33 //----------------------------------------------------------------------------- 
  35 //----------------------------------------------------------------------------- 
  37 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser
, wxHtmlParser
) 
  39 wxList 
wxHtmlWinParser::m_Modules
; 
  41 wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow 
*wnd
) : wxHtmlParser() 
  48     m_CharHeight 
= m_CharWidth 
= 0; 
  52     m_InputEnc 
= wxFONTENCODING_ISO8859_1
; 
  53     m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
  55     m_lastWordCell 
= NULL
; 
  59         for (i 
= 0; i 
< 2; i
++) 
  60             for (j 
= 0; j 
< 2; j
++) 
  61                 for (k 
= 0; k 
< 2; k
++) 
  62                     for (l 
= 0; l 
< 2; l
++) 
  63                         for (m 
= 0; m 
< 7; m
++) 
  65                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
  66                             m_FontsFacesTable
[i
][j
][k
][l
][m
] = wxEmptyString
; 
  68                             m_FontsEncTable
[i
][j
][k
][l
][m
] = wxFONTENCODING_DEFAULT
; 
  72         SetFonts(wxEmptyString
, wxEmptyString
, NULL
); 
  75     // fill in wxHtmlParser's tables: 
  76     wxList::compatibility_iterator node 
= m_Modules
.GetFirst(); 
  79         wxHtmlTagsModule 
*mod 
= (wxHtmlTagsModule
*) node
->GetData(); 
  80         mod
->FillHandlersTable(this); 
  81         node 
= node
->GetNext(); 
  85 wxHtmlWinParser::~wxHtmlWinParser() 
  89     for (i 
= 0; i 
< 2; i
++) 
  90         for (j 
= 0; j 
< 2; j
++) 
  91             for (k 
= 0; k 
< 2; k
++) 
  92                 for (l 
= 0; l 
< 2; l
++) 
  93                     for (m 
= 0; m 
< 7; m
++) 
  95                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
  96                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 101     delete[] m_tmpStrBuf
; 
 104 void wxHtmlWinParser::AddModule(wxHtmlTagsModule 
*module) 
 106     m_Modules
.Append(module); 
 109 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule 
*module) 
 111     m_Modules
.DeleteObject(module); 
 114 void wxHtmlWinParser::SetFonts(const wxString
& normal_face
, const wxString
& fixed_face
, 
 117     static int default_sizes
[7] = 
 128     if (sizes 
== NULL
) sizes 
= default_sizes
; 
 132     for (i 
= 0; i 
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
]; 
 133     m_FontFaceFixed 
= fixed_face
; 
 134     m_FontFaceNormal 
= normal_face
; 
 137     SetInputEncoding(m_InputEnc
); 
 140     for (i 
= 0; i 
< 2; i
++) 
 141         for (j 
= 0; j 
< 2; j
++) 
 142             for (k 
= 0; k 
< 2; k
++) 
 143                 for (l 
= 0; l 
< 2; l
++) 
 144                     for (m 
= 0; m 
< 7; m
++) { 
 145                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
 147                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 148                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
 153 void wxHtmlWinParser::SetStandardFonts(int size
, 
 154                                        const wxString
& normal_face
, 
 155                                        const wxString
& fixed_face
) 
 157     wxFont defaultFont 
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 161         size 
= defaultFont
.GetPointSize(); 
 163     f_sizes
[0] = int(size 
* 0.6); 
 164     f_sizes
[1] = int(size 
* 0.8); 
 166     f_sizes
[3] = int(size 
* 1.2); 
 167     f_sizes
[4] = int(size 
* 1.4); 
 168     f_sizes
[5] = int(size 
* 1.6); 
 169     f_sizes
[6] = int(size 
* 1.8); 
 171     wxString normal 
= normal_face
.empty() ? 
 172                       defaultFont
.GetFaceName() : normal_face
; 
 174     SetFonts(normal
, fixed_face
, f_sizes
); 
 177 void wxHtmlWinParser::InitParser(const wxString
& source
) 
 179     wxHtmlParser::InitParser(source
); 
 180     wxASSERT_MSG(m_DC 
!= NULL
, wxT("no DC assigned to wxHtmlWinParser!!")); 
 182     m_FontBold 
= m_FontItalic 
= m_FontUnderlined 
= m_FontFixed 
= FALSE
; 
 183     m_FontSize 
= 3; //default one 
 184     CreateCurrentFont();           // we're selecting default font into 
 185     m_DC
->GetTextExtent( wxT("H"), &m_CharWidth
, &m_CharHeight
); 
 186                 /* NOTE : we're not using GetCharWidth/Height() because 
 187                    of differences under X and win 
 191     m_Link 
= wxHtmlLinkInfo( wxEmptyString 
); 
 192     m_LinkColor
.Set(0, 0, 0xFF); 
 193     m_ActualColor
.Set(0, 0, 0); 
 194     m_Align 
= wxHTML_ALIGN_LEFT
; 
 195     m_ScriptMode 
= wxHTML_SCRIPT_NORMAL
; 
 196     m_ScriptBaseline 
= 0; 
 197     m_tmpLastWasSpace 
= false; 
 198     m_lastWordCell 
= NULL
; 
 204     wxString charset 
= ExtractCharsetInformation(source
); 
 205     if (!charset
.empty()) 
 207         wxFontEncoding enc 
= wxFontMapper::Get()->CharsetToEncoding(charset
); 
 208         if (enc 
!= wxFONTENCODING_SYSTEM
) 
 209           SetInputEncoding(enc
); 
 213     m_Container
->InsertCell(new wxHtmlColourCell(m_ActualColor
)); 
 214     wxColour windowColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
) ; 
 215     m_Container
->InsertCell( 
 216             new wxHtmlColourCell(GetWindow() ? 
 217                                      GetWindow()->GetBackgroundColour() : 
 219                                  wxHTML_CLR_BACKGROUND
)); 
 220     m_Container
->InsertCell(new wxHtmlFontCell(CreateCurrentFont())); 
 223 void wxHtmlWinParser::DoneParser() 
 227     SetInputEncoding(wxFONTENCODING_ISO8859_1
); // for next call 
 229     wxHtmlParser::DoneParser(); 
 232 wxObject
* wxHtmlWinParser::GetProduct() 
 234     wxHtmlContainerCell 
*top
; 
 240     while (top
->GetParent()) top 
= top
->GetParent(); 
 241     top
->RemoveExtraSpacing(true, true); 
 246 wxFSFile 
*wxHtmlWinParser::OpenURL(wxHtmlURLType type
, 
 247                                    const wxString
& url
) const 
 252         wxHtmlOpeningStatus status
; 
 255             wxString 
myfullurl(myurl
); 
 257             // consider url as absolute path first 
 258             wxURI 
current(myurl
); 
 259             myfullurl 
= current
.BuildUnescapedURI(); 
 261             // if not absolute then ... 
 262             if( current
.IsReference() ) 
 264                 wxString basepath 
= GetFS()->GetPath(); 
 265                 wxURI 
base(basepath
); 
 267                 // ... try to apply base path if valid ... 
 268                 if( !base
.IsReference() ) 
 270                     wxURI 
path(myfullurl
); 
 271                     path
.Resolve( base 
); 
 272                     myfullurl 
= path
.BuildUnescapedURI(); 
 276                     // ... or force such addition if not included already 
 277                     if( !current
.GetPath().Contains(base
.GetPath()) ) 
 280                         wxURI 
connected( basepath 
); 
 281                         myfullurl 
= connected
.BuildUnescapedURI(); 
 287             status 
= m_Window
->OnOpeningURL(type
, myfullurl
, &redirect
); 
 288             if ( status 
!= wxHTML_REDIRECT 
) 
 294         if ( status 
== wxHTML_BLOCK 
) 
 297         return GetFS()->OpenFile(myurl
); 
 300     return wxHtmlParser::OpenURL(type
, url
); 
 303 void wxHtmlWinParser::AddText(const wxChar
* txt
) 
 310     wxChar nbsp 
= GetEntitiesParser()->GetCharForCode(160 /* nbsp */); 
 312     if (lng
+1 > m_tmpStrBufSize
) 
 314         delete[] m_tmpStrBuf
; 
 315         m_tmpStrBuf 
= new wxChar
[lng
+1]; 
 316         m_tmpStrBufSize 
= lng
+1; 
 318     wxChar 
*temp 
= m_tmpStrBuf
; 
 320     if (m_tmpLastWasSpace
) 
 323                ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || (txt
[i
] == wxT(' ')) || 
 324                 (txt
[i
] == wxT('\t')))) i
++; 
 330         d 
= temp
[templen
++] = txt
[i
]; 
 331         if ((d 
== wxT('\n')) || (d 
== wxT('\r')) || (d 
== wxT(' ')) || (d 
== wxT('\t'))) 
 334             while ((i 
< lng
) && ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || 
 335                                  (txt
[i
] == wxT(' ')) || (txt
[i
] == wxT('\t')))) i
++, x
++; 
 341             temp
[templen
-1] = wxT(' '); 
 342             DoAddText(temp
, templen
, nbsp
); 
 343             m_tmpLastWasSpace 
= true; 
 347     if (templen 
&& (templen 
> 1 || temp
[0] != wxT(' '))) 
 349         DoAddText(temp
, templen
, nbsp
); 
 350         m_tmpLastWasSpace 
= false; 
 354 void wxHtmlWinParser::DoAddText(wxChar 
*temp
, int& templen
, wxChar nbsp
) 
 360         m_EncConv
->Convert(temp
); 
 362     size_t len 
= wxStrlen(temp
); 
 363     for (size_t j 
= 0; j 
< len
; j
++) 
 369     wxHtmlCell 
*c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 373     m_Container
->InsertCell(c
); 
 374     ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
); 
 375     m_lastWordCell 
= (wxHtmlWordCell
*)c
; 
 380 wxHtmlContainerCell
* wxHtmlWinParser::OpenContainer() 
 382     m_Container 
= new wxHtmlContainerCell(m_Container
); 
 383     m_Container
->SetAlignHor(m_Align
); 
 384     m_tmpLastWasSpace 
= true; 
 385         /* to avoid space being first character in paragraph */ 
 391 wxHtmlContainerCell
* wxHtmlWinParser::SetContainer(wxHtmlContainerCell 
*c
) 
 393     m_tmpLastWasSpace 
= true; 
 394         /* to avoid space being first character in paragraph */ 
 395     return m_Container 
= c
; 
 400 wxHtmlContainerCell
* wxHtmlWinParser::CloseContainer() 
 402     m_Container 
= m_Container
->GetParent(); 
 407 void wxHtmlWinParser::SetFontSize(int s
) 
 410     else if (s 
> 7) s 
= 7; 
 416 wxFont
* wxHtmlWinParser::CreateCurrentFont() 
 418     int fb 
= GetFontBold(), 
 419         fi 
= GetFontItalic(), 
 420         fu 
= GetFontUnderlined(), 
 422         fs 
= GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ; 
 424     wxString face 
= ff 
? m_FontFaceFixed 
: m_FontFaceNormal
; 
 425     wxString 
*faceptr 
= &(m_FontsFacesTable
[fb
][fi
][fu
][ff
][fs
]); 
 426     wxFont 
**fontptr 
= &(m_FontsTable
[fb
][fi
][fu
][ff
][fs
]); 
 428     wxFontEncoding 
*encptr 
= &(m_FontsEncTable
[fb
][fi
][fu
][ff
][fs
]); 
 431     if (*fontptr 
!= NULL 
&& (*faceptr 
!= face
 
 433                              || *encptr 
!= m_OutputEnc
 
 441     if (*fontptr 
== NULL
) 
 444         *fontptr 
= new wxFont( 
 445                        (int) (m_FontsSizes
[fs
] * m_PixelScale
), 
 446                        ff 
? wxMODERN 
: wxSWISS
, 
 447                        fi 
? wxITALIC 
: wxNORMAL
, 
 448                        fb 
? wxBOLD 
: wxNORMAL
, 
 449                        fu 
? true : false, face
 
 454         *encptr 
= m_OutputEnc
; 
 457     m_DC
->SetFont(**fontptr
); 
 463 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo
& link
) 
 466     m_UseLink 
= (link
.GetHref() != wxEmptyString
); 
 469 void wxHtmlWinParser::SetFontFace(const wxString
& face
) 
 471     if (GetFontFixed()) m_FontFaceFixed 
= face
; 
 472     else m_FontFaceNormal 
= face
; 
 475     if (m_InputEnc 
!= wxFONTENCODING_DEFAULT
) 
 476         SetInputEncoding(m_InputEnc
); 
 480 void wxHtmlWinParser::ApplyStateToCell(wxHtmlCell 
*cell
) 
 484         cell
->SetLink(GetLink()); 
 486     // apply current script mode settings: 
 487     cell
->SetScriptMode(GetScriptMode(), GetScriptBaseline()); 
 492 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc
) 
 494     m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 501     if (enc 
== wxFONTENCODING_DEFAULT
) return; 
 503     wxFontEncoding altfix
, altnorm
; 
 504     bool availfix
, availnorm
; 
 507     availnorm 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceNormal
); 
 508     availfix 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceFixed
); 
 509     if (availnorm 
&& availfix
) 
 513     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, false) && 
 514              wxFontMapper::Get()->GetAltForEncoding(enc
, &altfix
, m_FontFaceFixed
, false) && 
 516         m_OutputEnc 
= altnorm
; 
 518     // at least normal face? 
 521     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, false)) 
 522         m_OutputEnc 
= altnorm
; 
 527         // okay, let convert to ISO_8859-1, available always 
 528         m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 530         m_OutputEnc 
= wxLocale::GetSystemEncoding() ; 
 535     if (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) 
 536         GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM
); 
 538         GetEntitiesParser()->SetEncoding(m_OutputEnc
); 
 540     if (m_InputEnc 
== m_OutputEnc
) return; 
 542     m_EncConv 
= new wxEncodingConverter(); 
 543     if (!m_EncConv
->Init(m_InputEnc
, 
 544                            (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) ? 
 545                                       wxFONTENCODING_ISO8859_1 
: m_OutputEnc
, 
 546                            wxCONVERT_SUBSTITUTE
)) 
 547     { // total failture :-( 
 548         wxLogError(_("Failed to display HTML document in %s encoding"), 
 549                    wxFontMapper::GetEncodingName(enc
).c_str()); 
 550         m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 560 //----------------------------------------------------------------------------- 
 561 // wxHtmlWinTagHandler 
 562 //----------------------------------------------------------------------------- 
 564 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler
, wxHtmlTagHandler
) 
 566 //----------------------------------------------------------------------------- 
 568 //----------------------------------------------------------------------------- 
 570 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!! 
 571 //     This module is an ancestor for tag handlers modules defined 
 572 //     in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct. 
 574 //     Do not add any winpars.cpp shutdown or initialization code to it, 
 575 //     create a new module instead! 
 577 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule
, wxModule
) 
 579 bool wxHtmlTagsModule::OnInit() 
 581     wxHtmlWinParser::AddModule(this); 
 585 void wxHtmlTagsModule::OnExit() 
 587     wxHtmlWinParser::RemoveModule(this);