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" 
  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
; 
  57     m_lastWordCell 
= NULL
; 
  61         for (i 
= 0; i 
< 2; i
++) 
  62             for (j 
= 0; j 
< 2; j
++) 
  63                 for (k 
= 0; k 
< 2; k
++) 
  64                     for (l 
= 0; l 
< 2; l
++) 
  65                         for (m 
= 0; m 
< 7; m
++) 
  67                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
  68                             m_FontsFacesTable
[i
][j
][k
][l
][m
] = wxEmptyString
; 
  70                             m_FontsEncTable
[i
][j
][k
][l
][m
] = wxFONTENCODING_DEFAULT
; 
  74         SetFonts(wxEmptyString
, wxEmptyString
, NULL
); 
  77     // fill in wxHtmlParser's tables: 
  78     wxList::compatibility_iterator node 
= m_Modules
.GetFirst(); 
  81         wxHtmlTagsModule 
*mod 
= (wxHtmlTagsModule
*) node
->GetData(); 
  82         mod
->FillHandlersTable(this); 
  83         node 
= node
->GetNext(); 
  87 wxHtmlWinParser::~wxHtmlWinParser() 
  91     for (i 
= 0; i 
< 2; i
++) 
  92         for (j 
= 0; j 
< 2; j
++) 
  93             for (k 
= 0; k 
< 2; k
++) 
  94                 for (l 
= 0; l 
< 2; l
++) 
  95                     for (m 
= 0; m 
< 7; m
++) 
  97                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
  98                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 103     delete[] m_tmpStrBuf
; 
 106 void wxHtmlWinParser::AddModule(wxHtmlTagsModule 
*module) 
 108     m_Modules
.Append(module); 
 111 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule 
*module) 
 113     m_Modules
.DeleteObject(module); 
 116 void wxHtmlWinParser::SetFonts(wxString normal_face
, wxString fixed_face
, 
 119     static int default_sizes
[7] = 
 130     if (sizes 
== NULL
) sizes 
= default_sizes
; 
 134     for (i 
= 0; i 
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
]; 
 135     m_FontFaceFixed 
= fixed_face
; 
 136     m_FontFaceNormal 
= normal_face
; 
 139     SetInputEncoding(m_InputEnc
); 
 142     for (i 
= 0; i 
< 2; i
++) 
 143         for (j 
= 0; j 
< 2; j
++) 
 144             for (k 
= 0; k 
< 2; k
++) 
 145                 for (l 
= 0; l 
< 2; l
++) 
 146                     for (m 
= 0; m 
< 7; m
++) { 
 147                         if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
) 
 149                             delete m_FontsTable
[i
][j
][k
][l
][m
]; 
 150                             m_FontsTable
[i
][j
][k
][l
][m
] = NULL
; 
 155 void wxHtmlWinParser::InitParser(const wxString
& source
) 
 157     wxHtmlParser::InitParser(source
); 
 158     wxASSERT_MSG(m_DC 
!= NULL
, wxT("no DC assigned to wxHtmlWinParser!!")); 
 160     m_FontBold 
= m_FontItalic 
= m_FontUnderlined 
= m_FontFixed 
= FALSE
; 
 161     m_FontSize 
= 3; //default one 
 162     CreateCurrentFont();           // we're selecting default font into 
 163     m_DC
->GetTextExtent( wxT("H"), &m_CharWidth
, &m_CharHeight
); 
 164                 /* NOTE : we're not using GetCharWidth/Height() because 
 165                    of differences under X and win 
 169     m_Link 
= wxHtmlLinkInfo( wxT(""), wxT("") ); 
 170     m_LinkColor
.Set(0, 0, 0xFF); 
 171     m_ActualColor
.Set(0, 0, 0); 
 172     m_Align 
= wxHTML_ALIGN_LEFT
; 
 173     m_tmpLastWasSpace 
= FALSE
; 
 174     m_lastWordCell 
= NULL
; 
 180     wxString charset 
= ExtractCharsetInformation(source
); 
 181     if (!charset
.empty()) 
 183         wxFontEncoding enc 
= wxFontMapper::Get()->CharsetToEncoding(charset
); 
 184         if (enc 
!= wxFONTENCODING_SYSTEM
) 
 185           SetInputEncoding(enc
); 
 189     m_Container
->InsertCell(new wxHtmlColourCell(m_ActualColor
)); 
 190     m_Container
->InsertCell( 
 191             new wxHtmlColourCell(GetWindow()->GetBackgroundColour(), 
 192                                  wxHTML_CLR_BACKGROUND
)); 
 193     m_Container
->InsertCell(new wxHtmlFontCell(CreateCurrentFont())); 
 196 void wxHtmlWinParser::DoneParser() 
 200     SetInputEncoding(wxFONTENCODING_ISO8859_1
); // for next call 
 202     wxHtmlParser::DoneParser(); 
 205 wxObject
* wxHtmlWinParser::GetProduct() 
 207     wxHtmlContainerCell 
*top
; 
 213     while (top
->GetParent()) top 
= top
->GetParent(); 
 214     top
->RemoveExtraSpacing(true, true); 
 219 wxFSFile 
*wxHtmlWinParser::OpenURL(wxHtmlURLType type
, 
 220                                    const wxString
& url
) const 
 222     // FIXME - normalize the URL to full path before passing to 
 227         wxHtmlOpeningStatus status
; 
 231             status 
= m_Window
->OnOpeningURL(type
, myurl
, &redirect
); 
 232             if ( status 
!= wxHTML_REDIRECT 
) 
 238         if ( status 
== wxHTML_BLOCK 
) 
 241         return GetFS()->OpenFile(myurl
); 
 244     return wxHtmlParser::OpenURL(type
, url
); 
 247 void wxHtmlWinParser::AddText(const wxChar
* txt
) 
 255     wxChar nbsp 
= GetEntitiesParser()->GetCharForCode(160 /* nbsp */); 
 257     if (lng
+1 > m_tmpStrBufSize
) 
 259         delete[] m_tmpStrBuf
; 
 260         m_tmpStrBuf 
= new wxChar
[lng
+1]; 
 261         m_tmpStrBufSize 
= lng
+1; 
 263     wxChar 
*temp 
= m_tmpStrBuf
; 
 265     if (m_tmpLastWasSpace
) 
 268                ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || (txt
[i
] == wxT(' ')) || 
 269                 (txt
[i
] == wxT('\t')))) i
++; 
 275         d 
= temp
[templen
++] = txt
[i
]; 
 276         if ((d 
== wxT('\n')) || (d 
== wxT('\r')) || (d 
== wxT(' ')) || (d 
== wxT('\t'))) 
 279             while ((i 
< lng
) && ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || 
 280                                  (txt
[i
] == wxT(' ')) || (txt
[i
] == wxT('\t')))) i
++, x
++; 
 286             temp
[templen
-1] = wxT(' '); 
 291                 m_EncConv
->Convert(temp
); 
 293             size_t len 
= wxStrlen(temp
); 
 294             for (size_t j 
= 0; j 
< len
; j
++) 
 297             c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 300             m_Container
->InsertCell(c
); 
 301             ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
); 
 302             m_lastWordCell 
= (wxHtmlWordCell
*)c
; 
 303             m_tmpLastWasSpace 
= TRUE
; 
 307     if (templen 
&& (templen 
> 1 || temp
[0] != wxT(' '))) 
 312             m_EncConv
->Convert(temp
); 
 314         size_t len 
= wxStrlen(temp
); 
 315         for (size_t j 
= 0; j 
< len
; j
++) 
 318         c 
= new wxHtmlWordCell(temp
, *(GetDC())); 
 321         m_Container
->InsertCell(c
); 
 322         ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
); 
 323         m_lastWordCell 
= (wxHtmlWordCell
*)c
; 
 324         m_tmpLastWasSpace 
= FALSE
; 
 330 wxHtmlContainerCell
* wxHtmlWinParser::OpenContainer() 
 332     m_Container 
= new wxHtmlContainerCell(m_Container
); 
 333     m_Container
->SetAlignHor(m_Align
); 
 334     m_tmpLastWasSpace 
= TRUE
; 
 335         /* to avoid space being first character in paragraph */ 
 341 wxHtmlContainerCell
* wxHtmlWinParser::SetContainer(wxHtmlContainerCell 
*c
) 
 343     m_tmpLastWasSpace 
= TRUE
; 
 344         /* to avoid space being first character in paragraph */ 
 345     return m_Container 
= c
; 
 350 wxHtmlContainerCell
* wxHtmlWinParser::CloseContainer() 
 352     m_Container 
= m_Container
->GetParent(); 
 357 void wxHtmlWinParser::SetFontSize(int s
) 
 360     else if (s 
> 7) s 
= 7; 
 366 wxFont
* wxHtmlWinParser::CreateCurrentFont() 
 368     int fb 
= GetFontBold(), 
 369         fi 
= GetFontItalic(), 
 370         fu 
= GetFontUnderlined(), 
 372         fs 
= GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ; 
 374     wxString face 
= ff 
? m_FontFaceFixed 
: m_FontFaceNormal
; 
 375     wxString 
*faceptr 
= &(m_FontsFacesTable
[fb
][fi
][fu
][ff
][fs
]); 
 376     wxFont 
**fontptr 
= &(m_FontsTable
[fb
][fi
][fu
][ff
][fs
]); 
 378     wxFontEncoding 
*encptr 
= &(m_FontsEncTable
[fb
][fi
][fu
][ff
][fs
]); 
 381     if (*fontptr 
!= NULL 
&& (*faceptr 
!= face
 
 383                              || *encptr 
!= m_OutputEnc
 
 391     if (*fontptr 
== NULL
) 
 394         *fontptr 
= new wxFont( 
 395                        (int) (m_FontsSizes
[fs
] * m_PixelScale
), 
 396                        ff 
? wxMODERN 
: wxSWISS
, 
 397                        fi 
? wxITALIC 
: wxNORMAL
, 
 398                        fb 
? wxBOLD 
: wxNORMAL
, 
 399                        fu 
? TRUE 
: FALSE
, face
 
 404         *encptr 
= m_OutputEnc
; 
 407     m_DC
->SetFont(**fontptr
); 
 413 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo
& link
) 
 416     m_UseLink 
= (link
.GetHref() != wxEmptyString
); 
 420 void wxHtmlWinParser::SetFontFace(const wxString
& face
) 
 422     if (GetFontFixed()) m_FontFaceFixed 
= face
; 
 423     else m_FontFaceNormal 
= face
; 
 426     if (m_InputEnc 
!= wxFONTENCODING_DEFAULT
) 
 427         SetInputEncoding(m_InputEnc
); 
 434 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc
) 
 436     m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 443     if (enc 
== wxFONTENCODING_DEFAULT
) return; 
 445     wxFontEncoding altfix
, altnorm
; 
 446     bool availfix
, availnorm
; 
 449     availnorm 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceNormal
); 
 450     availfix 
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceFixed
); 
 451     if (availnorm 
&& availfix
) 
 455     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, FALSE
) && 
 456              wxFontMapper::Get()->GetAltForEncoding(enc
, &altfix
, m_FontFaceFixed
, FALSE
) && 
 458         m_OutputEnc 
= altnorm
; 
 460     // at least normal face? 
 463     else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, FALSE
)) 
 464         m_OutputEnc 
= altnorm
; 
 466     // okay, let convert to ISO_8859-1, available always 
 468         m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 471     if (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) 
 472         GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM
); 
 474         GetEntitiesParser()->SetEncoding(m_OutputEnc
); 
 476     if (m_InputEnc 
== m_OutputEnc
) return; 
 478     m_EncConv 
= new wxEncodingConverter(); 
 479     if (!m_EncConv
->Init(m_InputEnc
, 
 480                            (m_OutputEnc 
== wxFONTENCODING_DEFAULT
) ? 
 481                                       wxFONTENCODING_ISO8859_1 
: m_OutputEnc
, 
 482                            wxCONVERT_SUBSTITUTE
)) 
 483     { // total failture :-( 
 484         wxLogError(_("Failed to display HTML document in %s encoding"), 
 485                    wxFontMapper::GetEncodingName(enc
).c_str()); 
 486         m_InputEnc 
= m_OutputEnc 
= wxFONTENCODING_DEFAULT
; 
 496 //----------------------------------------------------------------------------- 
 497 // wxHtmlWinTagHandler 
 498 //----------------------------------------------------------------------------- 
 500 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler
, wxHtmlTagHandler
) 
 502 //----------------------------------------------------------------------------- 
 504 //----------------------------------------------------------------------------- 
 506 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!! 
 507 //     This module is an ancestor for tag handlers modules defined 
 508 //     in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct. 
 510 //     Do not add any winpars.cpp shutdown or initialization code to it, 
 511 //     create a new module instead! 
 513 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule
, wxModule
) 
 515 bool wxHtmlTagsModule::OnInit() 
 517     wxHtmlWinParser::AddModule(this); 
 521 void wxHtmlTagsModule::OnExit() 
 523     wxHtmlWinParser::RemoveModule(this);