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"
38 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
42 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser
, wxHtmlParser
)
44 wxList
wxHtmlWinParser::m_Modules
;
46 wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow
*wnd
) : wxHtmlParser()
53 m_CharHeight
= m_CharWidth
= 0;
57 m_InputEnc
= wxFONTENCODING_ISO8859_1
;
58 m_OutputEnc
= wxFONTENCODING_DEFAULT
;
60 m_lastWordCell
= NULL
;
64 for (i
= 0; i
< 2; i
++)
65 for (j
= 0; j
< 2; j
++)
66 for (k
= 0; k
< 2; k
++)
67 for (l
= 0; l
< 2; l
++)
68 for (m
= 0; m
< 7; m
++)
70 m_FontsTable
[i
][j
][k
][l
][m
] = NULL
;
71 m_FontsFacesTable
[i
][j
][k
][l
][m
] = wxEmptyString
;
73 m_FontsEncTable
[i
][j
][k
][l
][m
] = wxFONTENCODING_DEFAULT
;
77 SetFonts(wxEmptyString
, wxEmptyString
, NULL
);
80 // fill in wxHtmlParser's tables:
81 wxList::compatibility_iterator node
= m_Modules
.GetFirst();
84 wxHtmlTagsModule
*mod
= (wxHtmlTagsModule
*) node
->GetData();
85 mod
->FillHandlersTable(this);
86 node
= node
->GetNext();
90 wxHtmlWinParser::~wxHtmlWinParser()
94 for (i
= 0; i
< 2; i
++)
95 for (j
= 0; j
< 2; j
++)
96 for (k
= 0; k
< 2; k
++)
97 for (l
= 0; l
< 2; l
++)
98 for (m
= 0; m
< 7; m
++)
100 if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
)
101 delete m_FontsTable
[i
][j
][k
][l
][m
];
106 delete[] m_tmpStrBuf
;
109 void wxHtmlWinParser::AddModule(wxHtmlTagsModule
*module)
111 m_Modules
.Append(module);
114 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule
*module)
116 m_Modules
.DeleteObject(module);
119 void wxHtmlWinParser::SetFonts(wxString normal_face
, wxString fixed_face
,
122 static int default_sizes
[7] =
133 if (sizes
== NULL
) sizes
= default_sizes
;
137 for (i
= 0; i
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
];
138 m_FontFaceFixed
= fixed_face
;
139 m_FontFaceNormal
= normal_face
;
142 SetInputEncoding(m_InputEnc
);
145 for (i
= 0; i
< 2; i
++)
146 for (j
= 0; j
< 2; j
++)
147 for (k
= 0; k
< 2; k
++)
148 for (l
= 0; l
< 2; l
++)
149 for (m
= 0; m
< 7; m
++) {
150 if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
)
152 delete m_FontsTable
[i
][j
][k
][l
][m
];
153 m_FontsTable
[i
][j
][k
][l
][m
] = NULL
;
158 void wxHtmlWinParser::SetStandardFonts(int size
,
159 const wxString
& normal_face
,
160 const wxString
& fixed_face
)
162 wxFont defaultFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
166 size
= defaultFont
.GetPointSize();
168 f_sizes
[0] = int(size
* 0.6);
169 f_sizes
[1] = int(size
* 0.8);
171 f_sizes
[3] = int(size
* 1.2);
172 f_sizes
[4] = int(size
* 1.4);
173 f_sizes
[5] = int(size
* 1.6);
174 f_sizes
[6] = int(size
* 1.8);
176 wxString normal
= normal_face
.empty() ?
177 defaultFont
.GetFaceName() : normal_face
;
179 SetFonts(normal
, fixed_face
, f_sizes
);
182 void wxHtmlWinParser::InitParser(const wxString
& source
)
184 wxHtmlParser::InitParser(source
);
185 wxASSERT_MSG(m_DC
!= NULL
, wxT("no DC assigned to wxHtmlWinParser!!"));
187 m_FontBold
= m_FontItalic
= m_FontUnderlined
= m_FontFixed
= FALSE
;
188 m_FontSize
= 3; //default one
189 CreateCurrentFont(); // we're selecting default font into
190 m_DC
->GetTextExtent( wxT("H"), &m_CharWidth
, &m_CharHeight
);
191 /* NOTE : we're not using GetCharWidth/Height() because
192 of differences under X and win
196 m_Link
= wxHtmlLinkInfo( wxT(""), wxT("") );
197 m_LinkColor
.Set(0, 0, 0xFF);
198 m_ActualColor
.Set(0, 0, 0);
199 m_Align
= wxHTML_ALIGN_LEFT
;
200 m_tmpLastWasSpace
= false;
201 m_lastWordCell
= NULL
;
207 wxString charset
= ExtractCharsetInformation(source
);
208 if (!charset
.empty())
210 wxFontEncoding enc
= wxFontMapper::Get()->CharsetToEncoding(charset
);
211 if (enc
!= wxFONTENCODING_SYSTEM
)
212 SetInputEncoding(enc
);
216 m_Container
->InsertCell(new wxHtmlColourCell(m_ActualColor
));
217 wxColour windowColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
) ;
218 m_Container
->InsertCell(
219 new wxHtmlColourCell(GetWindow() ?
220 GetWindow()->GetBackgroundColour() :
222 wxHTML_CLR_BACKGROUND
));
223 m_Container
->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
226 void wxHtmlWinParser::DoneParser()
230 SetInputEncoding(wxFONTENCODING_ISO8859_1
); // for next call
232 wxHtmlParser::DoneParser();
235 wxObject
* wxHtmlWinParser::GetProduct()
237 wxHtmlContainerCell
*top
;
243 while (top
->GetParent()) top
= top
->GetParent();
244 top
->RemoveExtraSpacing(true, true);
249 wxFSFile
*wxHtmlWinParser::OpenURL(wxHtmlURLType type
,
250 const wxString
& url
) const
255 wxHtmlOpeningStatus status
;
258 wxString
myfullurl(myurl
);
261 // consider url as absolute path first
262 wxURL
current(wxURL::Unescape(myurl
));
263 myfullurl
= current
.GetURL();
265 // if not absolute then ...
266 if( current
.IsReference() )
268 wxString basepath
= GetFS()->GetPath();
269 wxURI
base(wxURL::Unescape(basepath
));
271 // try to apply base path if valid ...
272 if( !base
.IsReference() )
274 wxURI
path(myfullurl
);
275 path
.Resolve( base
);
276 myfullurl
= path
.BuildURI();
280 // ... or force such addition if not included already
281 if( !current
.GetURL().Contains(basepath
) )
284 wxURL
connected( wxURL::Unescape(basepath
) );
285 myfullurl
= connected
.GetURL();
292 status
= m_Window
->OnOpeningURL(type
, myfullurl
, &redirect
);
293 if ( status
!= wxHTML_REDIRECT
)
299 if ( status
== wxHTML_BLOCK
)
302 return GetFS()->OpenFile(myurl
);
305 return wxHtmlParser::OpenURL(type
, url
);
308 void wxHtmlWinParser::AddText(const wxChar
* txt
)
316 wxChar nbsp
= GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
318 if (lng
+1 > m_tmpStrBufSize
)
320 delete[] m_tmpStrBuf
;
321 m_tmpStrBuf
= new wxChar
[lng
+1];
322 m_tmpStrBufSize
= lng
+1;
324 wxChar
*temp
= m_tmpStrBuf
;
326 if (m_tmpLastWasSpace
)
329 ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || (txt
[i
] == wxT(' ')) ||
330 (txt
[i
] == wxT('\t')))) i
++;
336 d
= temp
[templen
++] = txt
[i
];
337 if ((d
== wxT('\n')) || (d
== wxT('\r')) || (d
== wxT(' ')) || (d
== wxT('\t')))
340 while ((i
< lng
) && ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) ||
341 (txt
[i
] == wxT(' ')) || (txt
[i
] == wxT('\t')))) i
++, x
++;
347 temp
[templen
-1] = wxT(' ');
352 m_EncConv
->Convert(temp
);
354 size_t len
= wxStrlen(temp
);
355 for (size_t j
= 0; j
< len
; j
++)
358 c
= new wxHtmlWordCell(temp
, *(GetDC()));
361 m_Container
->InsertCell(c
);
362 ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
);
363 m_lastWordCell
= (wxHtmlWordCell
*)c
;
364 m_tmpLastWasSpace
= true;
368 if (templen
&& (templen
> 1 || temp
[0] != wxT(' ')))
373 m_EncConv
->Convert(temp
);
375 size_t len
= wxStrlen(temp
);
376 for (size_t j
= 0; j
< len
; j
++)
379 c
= new wxHtmlWordCell(temp
, *(GetDC()));
382 m_Container
->InsertCell(c
);
383 ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
);
384 m_lastWordCell
= (wxHtmlWordCell
*)c
;
385 m_tmpLastWasSpace
= false;
391 wxHtmlContainerCell
* wxHtmlWinParser::OpenContainer()
393 m_Container
= new wxHtmlContainerCell(m_Container
);
394 m_Container
->SetAlignHor(m_Align
);
395 m_tmpLastWasSpace
= true;
396 /* to avoid space being first character in paragraph */
402 wxHtmlContainerCell
* wxHtmlWinParser::SetContainer(wxHtmlContainerCell
*c
)
404 m_tmpLastWasSpace
= true;
405 /* to avoid space being first character in paragraph */
406 return m_Container
= c
;
411 wxHtmlContainerCell
* wxHtmlWinParser::CloseContainer()
413 m_Container
= m_Container
->GetParent();
418 void wxHtmlWinParser::SetFontSize(int s
)
421 else if (s
> 7) s
= 7;
427 wxFont
* wxHtmlWinParser::CreateCurrentFont()
429 int fb
= GetFontBold(),
430 fi
= GetFontItalic(),
431 fu
= GetFontUnderlined(),
433 fs
= GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
435 wxString face
= ff
? m_FontFaceFixed
: m_FontFaceNormal
;
436 wxString
*faceptr
= &(m_FontsFacesTable
[fb
][fi
][fu
][ff
][fs
]);
437 wxFont
**fontptr
= &(m_FontsTable
[fb
][fi
][fu
][ff
][fs
]);
439 wxFontEncoding
*encptr
= &(m_FontsEncTable
[fb
][fi
][fu
][ff
][fs
]);
442 if (*fontptr
!= NULL
&& (*faceptr
!= face
444 || *encptr
!= m_OutputEnc
452 if (*fontptr
== NULL
)
455 *fontptr
= new wxFont(
456 (int) (m_FontsSizes
[fs
] * m_PixelScale
),
457 ff
? wxMODERN
: wxSWISS
,
458 fi
? wxITALIC
: wxNORMAL
,
459 fb
? wxBOLD
: wxNORMAL
,
460 fu
? true : false, face
465 *encptr
= m_OutputEnc
;
468 m_DC
->SetFont(**fontptr
);
474 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo
& link
)
477 m_UseLink
= (link
.GetHref() != wxEmptyString
);
481 void wxHtmlWinParser::SetFontFace(const wxString
& face
)
483 if (GetFontFixed()) m_FontFaceFixed
= face
;
484 else m_FontFaceNormal
= face
;
487 if (m_InputEnc
!= wxFONTENCODING_DEFAULT
)
488 SetInputEncoding(m_InputEnc
);
495 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc
)
497 m_InputEnc
= m_OutputEnc
= wxFONTENCODING_DEFAULT
;
504 if (enc
== wxFONTENCODING_DEFAULT
) return;
506 wxFontEncoding altfix
, altnorm
;
507 bool availfix
, availnorm
;
510 availnorm
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceNormal
);
511 availfix
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceFixed
);
512 if (availnorm
&& availfix
)
516 else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, false) &&
517 wxFontMapper::Get()->GetAltForEncoding(enc
, &altfix
, m_FontFaceFixed
, false) &&
519 m_OutputEnc
= altnorm
;
521 // at least normal face?
524 else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, false))
525 m_OutputEnc
= altnorm
;
530 // okay, let convert to ISO_8859-1, available always
531 m_OutputEnc
= wxFONTENCODING_DEFAULT
;
533 m_OutputEnc
= wxLocale::GetSystemEncoding() ;
538 if (m_OutputEnc
== wxFONTENCODING_DEFAULT
)
539 GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM
);
541 GetEntitiesParser()->SetEncoding(m_OutputEnc
);
543 if (m_InputEnc
== m_OutputEnc
) return;
545 m_EncConv
= new wxEncodingConverter();
546 if (!m_EncConv
->Init(m_InputEnc
,
547 (m_OutputEnc
== wxFONTENCODING_DEFAULT
) ?
548 wxFONTENCODING_ISO8859_1
: m_OutputEnc
,
549 wxCONVERT_SUBSTITUTE
))
550 { // total failture :-(
551 wxLogError(_("Failed to display HTML document in %s encoding"),
552 wxFontMapper::GetEncodingName(enc
).c_str());
553 m_InputEnc
= m_OutputEnc
= wxFONTENCODING_DEFAULT
;
563 //-----------------------------------------------------------------------------
564 // wxHtmlWinTagHandler
565 //-----------------------------------------------------------------------------
567 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler
, wxHtmlTagHandler
)
569 //-----------------------------------------------------------------------------
571 //-----------------------------------------------------------------------------
573 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!!
574 // This module is an ancestor for tag handlers modules defined
575 // in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct.
577 // Do not add any winpars.cpp shutdown or initialization code to it,
578 // create a new module instead!
580 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule
, wxModule
)
582 bool wxHtmlTagsModule::OnInit()
584 wxHtmlWinParser::AddModule(this);
588 void wxHtmlTagsModule::OnExit()
590 wxHtmlWinParser::RemoveModule(this);