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(wxHtmlWindowInterface
*wndIface
)
45 m_windowInterface
= wndIface
;
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
) ;
216 m_Container
->InsertCell
221 ? m_windowInterface
->GetHTMLBackgroundColour()
223 wxHTML_CLR_BACKGROUND
227 m_Container
->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
230 void wxHtmlWinParser::DoneParser()
234 SetInputEncoding(wxFONTENCODING_ISO8859_1
); // for next call
236 wxHtmlParser::DoneParser();
239 #if WXWIN_COMPATIBILITY_2_6
240 wxHtmlWindow
*wxHtmlWinParser::GetWindow()
242 if (!m_windowInterface
)
244 return wxDynamicCast(m_windowInterface
->GetHTMLWindow(), wxHtmlWindow
);
248 wxObject
* wxHtmlWinParser::GetProduct()
250 wxHtmlContainerCell
*top
;
256 while (top
->GetParent()) top
= top
->GetParent();
257 top
->RemoveExtraSpacing(true, true);
262 wxFSFile
*wxHtmlWinParser::OpenURL(wxHtmlURLType type
,
263 const wxString
& url
) const
265 if ( !m_windowInterface
)
266 return wxHtmlParser::OpenURL(type
, url
);
269 wxHtmlOpeningStatus status
;
272 wxString
myfullurl(myurl
);
274 // consider url as absolute path first
275 wxURI
current(myurl
);
276 myfullurl
= current
.BuildUnescapedURI();
278 // if not absolute then ...
279 if( current
.IsReference() )
281 wxString basepath
= GetFS()->GetPath();
282 wxURI
base(basepath
);
284 // ... try to apply base path if valid ...
285 if( !base
.IsReference() )
287 wxURI
path(myfullurl
);
288 path
.Resolve( base
);
289 myfullurl
= path
.BuildUnescapedURI();
293 // ... or force such addition if not included already
294 if( !current
.GetPath().Contains(base
.GetPath()) )
297 wxURI
connected( basepath
);
298 myfullurl
= connected
.BuildUnescapedURI();
304 status
= m_windowInterface
->OnHTMLOpeningURL(type
, myfullurl
, &redirect
);
305 if ( status
!= wxHTML_REDIRECT
)
311 if ( status
== wxHTML_BLOCK
)
314 return GetFS()->OpenFile(myurl
);
317 void wxHtmlWinParser::AddText(const wxChar
* txt
)
324 wxChar nbsp
= GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
326 if (lng
+1 > m_tmpStrBufSize
)
328 delete[] m_tmpStrBuf
;
329 m_tmpStrBuf
= new wxChar
[lng
+1];
330 m_tmpStrBufSize
= lng
+1;
332 wxChar
*temp
= m_tmpStrBuf
;
334 if (m_tmpLastWasSpace
)
337 ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || (txt
[i
] == wxT(' ')) ||
338 (txt
[i
] == wxT('\t')))) i
++;
344 d
= temp
[templen
++] = txt
[i
];
345 if ((d
== wxT('\n')) || (d
== wxT('\r')) || (d
== wxT(' ')) || (d
== wxT('\t')))
348 while ((i
< lng
) && ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) ||
349 (txt
[i
] == wxT(' ')) || (txt
[i
] == wxT('\t')))) i
++, x
++;
355 temp
[templen
-1] = wxT(' ');
356 DoAddText(temp
, templen
, nbsp
);
357 m_tmpLastWasSpace
= true;
361 if (templen
&& (templen
> 1 || temp
[0] != wxT(' ')))
363 DoAddText(temp
, templen
, nbsp
);
364 m_tmpLastWasSpace
= false;
368 void wxHtmlWinParser::DoAddText(wxChar
*temp
, int& templen
, wxChar nbsp
)
374 m_EncConv
->Convert(temp
);
376 size_t len
= wxStrlen(temp
);
377 for (size_t j
= 0; j
< len
; j
++)
383 wxHtmlCell
*c
= new wxHtmlWordCell(temp
, *(GetDC()));
387 m_Container
->InsertCell(c
);
388 ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
);
389 m_lastWordCell
= (wxHtmlWordCell
*)c
;
394 wxHtmlContainerCell
* wxHtmlWinParser::OpenContainer()
396 m_Container
= new wxHtmlContainerCell(m_Container
);
397 m_Container
->SetAlignHor(m_Align
);
398 m_tmpLastWasSpace
= true;
399 /* to avoid space being first character in paragraph */
405 wxHtmlContainerCell
* wxHtmlWinParser::SetContainer(wxHtmlContainerCell
*c
)
407 m_tmpLastWasSpace
= true;
408 /* to avoid space being first character in paragraph */
409 return m_Container
= c
;
414 wxHtmlContainerCell
* wxHtmlWinParser::CloseContainer()
416 m_Container
= m_Container
->GetParent();
421 void wxHtmlWinParser::SetFontSize(int s
)
424 else if (s
> 7) s
= 7;
430 wxFont
* wxHtmlWinParser::CreateCurrentFont()
432 int fb
= GetFontBold(),
433 fi
= GetFontItalic(),
434 fu
= GetFontUnderlined(),
436 fs
= GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
438 wxString face
= ff
? m_FontFaceFixed
: m_FontFaceNormal
;
439 wxString
*faceptr
= &(m_FontsFacesTable
[fb
][fi
][fu
][ff
][fs
]);
440 wxFont
**fontptr
= &(m_FontsTable
[fb
][fi
][fu
][ff
][fs
]);
442 wxFontEncoding
*encptr
= &(m_FontsEncTable
[fb
][fi
][fu
][ff
][fs
]);
445 if (*fontptr
!= NULL
&& (*faceptr
!= face
447 || *encptr
!= m_OutputEnc
455 if (*fontptr
== NULL
)
458 *fontptr
= new wxFont(
459 (int) (m_FontsSizes
[fs
] * m_PixelScale
),
460 ff
? wxMODERN
: wxSWISS
,
461 fi
? wxITALIC
: wxNORMAL
,
462 fb
? wxBOLD
: wxNORMAL
,
463 fu
? true : false, face
468 *encptr
= m_OutputEnc
;
471 m_DC
->SetFont(**fontptr
);
477 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo
& link
)
480 m_UseLink
= (link
.GetHref() != wxEmptyString
);
483 void wxHtmlWinParser::SetFontFace(const wxString
& face
)
485 if (GetFontFixed()) m_FontFaceFixed
= face
;
486 else m_FontFaceNormal
= face
;
489 if (m_InputEnc
!= wxFONTENCODING_DEFAULT
)
490 SetInputEncoding(m_InputEnc
);
494 void wxHtmlWinParser::ApplyStateToCell(wxHtmlCell
*cell
)
498 cell
->SetLink(GetLink());
500 // apply current script mode settings:
501 cell
->SetScriptMode(GetScriptMode(), GetScriptBaseline());
506 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc
)
508 m_InputEnc
= m_OutputEnc
= wxFONTENCODING_DEFAULT
;
515 if (enc
== wxFONTENCODING_DEFAULT
) return;
517 wxFontEncoding altfix
, altnorm
;
518 bool availfix
, availnorm
;
521 availnorm
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceNormal
);
522 availfix
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceFixed
);
523 if (availnorm
&& availfix
)
527 else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, false) &&
528 wxFontMapper::Get()->GetAltForEncoding(enc
, &altfix
, m_FontFaceFixed
, false) &&
530 m_OutputEnc
= altnorm
;
532 // at least normal face?
535 else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, false))
536 m_OutputEnc
= altnorm
;
541 // okay, let convert to ISO_8859-1, available always
542 m_OutputEnc
= wxFONTENCODING_DEFAULT
;
544 m_OutputEnc
= wxLocale::GetSystemEncoding() ;
549 if (m_OutputEnc
== wxFONTENCODING_DEFAULT
)
550 GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM
);
552 GetEntitiesParser()->SetEncoding(m_OutputEnc
);
554 if (m_InputEnc
== m_OutputEnc
) return;
556 m_EncConv
= new wxEncodingConverter();
557 if (!m_EncConv
->Init(m_InputEnc
,
558 (m_OutputEnc
== wxFONTENCODING_DEFAULT
) ?
559 wxFONTENCODING_ISO8859_1
: m_OutputEnc
,
560 wxCONVERT_SUBSTITUTE
))
561 { // total failture :-(
562 wxLogError(_("Failed to display HTML document in %s encoding"),
563 wxFontMapper::GetEncodingName(enc
).c_str());
564 m_InputEnc
= m_OutputEnc
= wxFONTENCODING_DEFAULT
;
574 //-----------------------------------------------------------------------------
575 // wxHtmlWinTagHandler
576 //-----------------------------------------------------------------------------
578 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler
, wxHtmlTagHandler
)
580 //-----------------------------------------------------------------------------
582 //-----------------------------------------------------------------------------
584 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!!
585 // This module is an ancestor for tag handlers modules defined
586 // in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct.
588 // Do not add any winpars.cpp shutdown or initialization code to it,
589 // create a new module instead!
591 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule
, wxModule
)
593 bool wxHtmlTagsModule::OnInit()
595 wxHtmlWinParser::AddModule(this);
599 void wxHtmlTagsModule::OnExit()
601 wxHtmlWinParser::RemoveModule(this);