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"
37 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
41 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser
, wxHtmlParser
)
43 wxList
wxHtmlWinParser::m_Modules
;
45 wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow
*wnd
) : wxHtmlParser()
52 m_CharHeight
= m_CharWidth
= 0;
56 m_InputEnc
= wxFONTENCODING_ISO8859_1
;
57 m_OutputEnc
= wxFONTENCODING_DEFAULT
;
59 m_lastWordCell
= NULL
;
63 for (i
= 0; i
< 2; i
++)
64 for (j
= 0; j
< 2; j
++)
65 for (k
= 0; k
< 2; k
++)
66 for (l
= 0; l
< 2; l
++)
67 for (m
= 0; m
< 7; m
++)
69 m_FontsTable
[i
][j
][k
][l
][m
] = NULL
;
70 m_FontsFacesTable
[i
][j
][k
][l
][m
] = wxEmptyString
;
72 m_FontsEncTable
[i
][j
][k
][l
][m
] = wxFONTENCODING_DEFAULT
;
76 SetFonts(wxEmptyString
, wxEmptyString
, NULL
);
79 // fill in wxHtmlParser's tables:
80 wxList::compatibility_iterator node
= m_Modules
.GetFirst();
83 wxHtmlTagsModule
*mod
= (wxHtmlTagsModule
*) node
->GetData();
84 mod
->FillHandlersTable(this);
85 node
= node
->GetNext();
89 wxHtmlWinParser::~wxHtmlWinParser()
93 for (i
= 0; i
< 2; i
++)
94 for (j
= 0; j
< 2; j
++)
95 for (k
= 0; k
< 2; k
++)
96 for (l
= 0; l
< 2; l
++)
97 for (m
= 0; m
< 7; m
++)
99 if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
)
100 delete m_FontsTable
[i
][j
][k
][l
][m
];
105 delete[] m_tmpStrBuf
;
108 void wxHtmlWinParser::AddModule(wxHtmlTagsModule
*module)
110 m_Modules
.Append(module);
113 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule
*module)
115 m_Modules
.DeleteObject(module);
118 void wxHtmlWinParser::SetFonts(wxString normal_face
, wxString fixed_face
,
121 static int default_sizes
[7] =
132 if (sizes
== NULL
) sizes
= default_sizes
;
136 for (i
= 0; i
< 7; i
++) m_FontsSizes
[i
] = sizes
[i
];
137 m_FontFaceFixed
= fixed_face
;
138 m_FontFaceNormal
= normal_face
;
141 SetInputEncoding(m_InputEnc
);
144 for (i
= 0; i
< 2; i
++)
145 for (j
= 0; j
< 2; j
++)
146 for (k
= 0; k
< 2; k
++)
147 for (l
= 0; l
< 2; l
++)
148 for (m
= 0; m
< 7; m
++) {
149 if (m_FontsTable
[i
][j
][k
][l
][m
] != NULL
)
151 delete m_FontsTable
[i
][j
][k
][l
][m
];
152 m_FontsTable
[i
][j
][k
][l
][m
] = NULL
;
157 void wxHtmlWinParser::InitParser(const wxString
& source
)
159 wxHtmlParser::InitParser(source
);
160 wxASSERT_MSG(m_DC
!= NULL
, wxT("no DC assigned to wxHtmlWinParser!!"));
162 m_FontBold
= m_FontItalic
= m_FontUnderlined
= m_FontFixed
= FALSE
;
163 m_FontSize
= 3; //default one
164 CreateCurrentFont(); // we're selecting default font into
165 m_DC
->GetTextExtent( wxT("H"), &m_CharWidth
, &m_CharHeight
);
166 /* NOTE : we're not using GetCharWidth/Height() because
167 of differences under X and win
171 m_Link
= wxHtmlLinkInfo( wxT(""), wxT("") );
172 m_LinkColor
.Set(0, 0, 0xFF);
173 m_ActualColor
.Set(0, 0, 0);
174 m_Align
= wxHTML_ALIGN_LEFT
;
175 m_tmpLastWasSpace
= FALSE
;
176 m_lastWordCell
= NULL
;
182 wxString charset
= ExtractCharsetInformation(source
);
183 if (!charset
.empty())
185 wxFontEncoding enc
= wxFontMapper::Get()->CharsetToEncoding(charset
);
186 if (enc
!= wxFONTENCODING_SYSTEM
)
187 SetInputEncoding(enc
);
191 m_Container
->InsertCell(new wxHtmlColourCell(m_ActualColor
));
192 wxColour windowColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
) ;
193 m_Container
->InsertCell(
194 new wxHtmlColourCell(GetWindow() ?
195 GetWindow()->GetBackgroundColour() :
197 wxHTML_CLR_BACKGROUND
));
198 m_Container
->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
201 void wxHtmlWinParser::DoneParser()
205 SetInputEncoding(wxFONTENCODING_ISO8859_1
); // for next call
207 wxHtmlParser::DoneParser();
210 wxObject
* wxHtmlWinParser::GetProduct()
212 wxHtmlContainerCell
*top
;
218 while (top
->GetParent()) top
= top
->GetParent();
219 top
->RemoveExtraSpacing(true, true);
224 wxFSFile
*wxHtmlWinParser::OpenURL(wxHtmlURLType type
,
225 const wxString
& url
) const
227 // FIXME - normalize the URL to full path before passing to
232 wxHtmlOpeningStatus status
;
236 status
= m_Window
->OnOpeningURL(type
, myurl
, &redirect
);
237 if ( status
!= wxHTML_REDIRECT
)
243 if ( status
== wxHTML_BLOCK
)
246 return GetFS()->OpenFile(myurl
);
249 return wxHtmlParser::OpenURL(type
, url
);
252 void wxHtmlWinParser::AddText(const wxChar
* txt
)
260 wxChar nbsp
= GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
262 if (lng
+1 > m_tmpStrBufSize
)
264 delete[] m_tmpStrBuf
;
265 m_tmpStrBuf
= new wxChar
[lng
+1];
266 m_tmpStrBufSize
= lng
+1;
268 wxChar
*temp
= m_tmpStrBuf
;
270 if (m_tmpLastWasSpace
)
273 ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) || (txt
[i
] == wxT(' ')) ||
274 (txt
[i
] == wxT('\t')))) i
++;
280 d
= temp
[templen
++] = txt
[i
];
281 if ((d
== wxT('\n')) || (d
== wxT('\r')) || (d
== wxT(' ')) || (d
== wxT('\t')))
284 while ((i
< lng
) && ((txt
[i
] == wxT('\n')) || (txt
[i
] == wxT('\r')) ||
285 (txt
[i
] == wxT(' ')) || (txt
[i
] == wxT('\t')))) i
++, x
++;
291 temp
[templen
-1] = wxT(' ');
296 m_EncConv
->Convert(temp
);
298 size_t len
= wxStrlen(temp
);
299 for (size_t j
= 0; j
< len
; j
++)
302 c
= new wxHtmlWordCell(temp
, *(GetDC()));
305 m_Container
->InsertCell(c
);
306 ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
);
307 m_lastWordCell
= (wxHtmlWordCell
*)c
;
308 m_tmpLastWasSpace
= TRUE
;
312 if (templen
&& (templen
> 1 || temp
[0] != wxT(' ')))
317 m_EncConv
->Convert(temp
);
319 size_t len
= wxStrlen(temp
);
320 for (size_t j
= 0; j
< len
; j
++)
323 c
= new wxHtmlWordCell(temp
, *(GetDC()));
326 m_Container
->InsertCell(c
);
327 ((wxHtmlWordCell
*)c
)->SetPreviousWord(m_lastWordCell
);
328 m_lastWordCell
= (wxHtmlWordCell
*)c
;
329 m_tmpLastWasSpace
= FALSE
;
335 wxHtmlContainerCell
* wxHtmlWinParser::OpenContainer()
337 m_Container
= new wxHtmlContainerCell(m_Container
);
338 m_Container
->SetAlignHor(m_Align
);
339 m_tmpLastWasSpace
= TRUE
;
340 /* to avoid space being first character in paragraph */
346 wxHtmlContainerCell
* wxHtmlWinParser::SetContainer(wxHtmlContainerCell
*c
)
348 m_tmpLastWasSpace
= TRUE
;
349 /* to avoid space being first character in paragraph */
350 return m_Container
= c
;
355 wxHtmlContainerCell
* wxHtmlWinParser::CloseContainer()
357 m_Container
= m_Container
->GetParent();
362 void wxHtmlWinParser::SetFontSize(int s
)
365 else if (s
> 7) s
= 7;
371 wxFont
* wxHtmlWinParser::CreateCurrentFont()
373 int fb
= GetFontBold(),
374 fi
= GetFontItalic(),
375 fu
= GetFontUnderlined(),
377 fs
= GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
379 wxString face
= ff
? m_FontFaceFixed
: m_FontFaceNormal
;
380 wxString
*faceptr
= &(m_FontsFacesTable
[fb
][fi
][fu
][ff
][fs
]);
381 wxFont
**fontptr
= &(m_FontsTable
[fb
][fi
][fu
][ff
][fs
]);
383 wxFontEncoding
*encptr
= &(m_FontsEncTable
[fb
][fi
][fu
][ff
][fs
]);
386 if (*fontptr
!= NULL
&& (*faceptr
!= face
388 || *encptr
!= m_OutputEnc
396 if (*fontptr
== NULL
)
399 *fontptr
= new wxFont(
400 (int) (m_FontsSizes
[fs
] * m_PixelScale
),
401 ff
? wxMODERN
: wxSWISS
,
402 fi
? wxITALIC
: wxNORMAL
,
403 fb
? wxBOLD
: wxNORMAL
,
404 fu
? TRUE
: FALSE
, face
409 *encptr
= m_OutputEnc
;
412 m_DC
->SetFont(**fontptr
);
418 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo
& link
)
421 m_UseLink
= (link
.GetHref() != wxEmptyString
);
425 void wxHtmlWinParser::SetFontFace(const wxString
& face
)
427 if (GetFontFixed()) m_FontFaceFixed
= face
;
428 else m_FontFaceNormal
= face
;
431 if (m_InputEnc
!= wxFONTENCODING_DEFAULT
)
432 SetInputEncoding(m_InputEnc
);
439 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc
)
441 m_InputEnc
= m_OutputEnc
= wxFONTENCODING_DEFAULT
;
448 if (enc
== wxFONTENCODING_DEFAULT
) return;
450 wxFontEncoding altfix
, altnorm
;
451 bool availfix
, availnorm
;
455 availnorm
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceNormal
);
456 availfix
= wxFontMapper::Get()->IsEncodingAvailable(enc
, m_FontFaceFixed
);
457 if (availnorm
&& availfix
)
461 else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, FALSE
) &&
462 wxFontMapper::Get()->GetAltForEncoding(enc
, &altfix
, m_FontFaceFixed
, FALSE
) &&
464 m_OutputEnc
= altnorm
;
466 // at least normal face?
469 else if (wxFontMapper::Get()->GetAltForEncoding(enc
, &altnorm
, m_FontFaceNormal
, FALSE
))
470 m_OutputEnc
= altnorm
;
472 // okay, let convert to ISO_8859-1, available always
474 m_OutputEnc
= wxFONTENCODING_DEFAULT
;
476 // we only have the current system encoding
477 m_OutputEnc
= wxFONTENCODING_MACROMAN
;
481 if (m_OutputEnc
== wxFONTENCODING_DEFAULT
)
482 GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM
);
484 GetEntitiesParser()->SetEncoding(m_OutputEnc
);
486 if (m_InputEnc
== m_OutputEnc
) return;
488 m_EncConv
= new wxEncodingConverter();
489 if (!m_EncConv
->Init(m_InputEnc
,
490 (m_OutputEnc
== wxFONTENCODING_DEFAULT
) ?
491 wxFONTENCODING_ISO8859_1
: m_OutputEnc
,
492 wxCONVERT_SUBSTITUTE
))
493 { // total failture :-(
494 wxLogError(_("Failed to display HTML document in %s encoding"),
495 wxFontMapper::GetEncodingName(enc
).c_str());
496 m_InputEnc
= m_OutputEnc
= wxFONTENCODING_DEFAULT
;
506 //-----------------------------------------------------------------------------
507 // wxHtmlWinTagHandler
508 //-----------------------------------------------------------------------------
510 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler
, wxHtmlTagHandler
)
512 //-----------------------------------------------------------------------------
514 //-----------------------------------------------------------------------------
516 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!!
517 // This module is an ancestor for tag handlers modules defined
518 // in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct.
520 // Do not add any winpars.cpp shutdown or initialization code to it,
521 // create a new module instead!
523 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule
, wxModule
)
525 bool wxHtmlTagsModule::OnInit()
527 wxHtmlWinParser::AddModule(this);
531 void wxHtmlTagsModule::OnExit()
533 wxHtmlWinParser::RemoveModule(this);