]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/html/winpars.cpp
Additions for webkit wrapper support.
[wxWidgets.git] / src / html / winpars.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: winpars.cpp
3// Purpose: wxHtmlParser class (generic parser)
4// Author: Vaclav Slavik
5// RCS-ID: $Id$
6// Copyright: (c) 1999 Vaclav Slavik
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10
11#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
12#pragma implementation "winpars.h"
13#endif
14
15#include "wx/wxprec.h"
16
17#include "wx/defs.h"
18#if wxUSE_HTML && wxUSE_STREAMS
19
20#ifdef __BORLANDC__
21#pragma hdrstop
22#endif
23
24#ifndef WXPRECOMP
25 #include "wx/intl.h"
26 #include "wx/dc.h"
27#endif
28
29#include "wx/html/htmldefs.h"
30#include "wx/html/winpars.h"
31#include "wx/html/htmlwin.h"
32#include "wx/fontmap.h"
33#include "wx/log.h"
34#include "wx/settings.h"
35
36
37//-----------------------------------------------------------------------------
38// wxHtmlWinParser
39//-----------------------------------------------------------------------------
40
41IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser, wxHtmlParser)
42
43wxList wxHtmlWinParser::m_Modules;
44
45wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow *wnd) : wxHtmlParser()
46{
47 m_tmpStrBuf = NULL;
48 m_tmpStrBufSize = 0;
49 m_Window = wnd;
50 m_Container = NULL;
51 m_DC = NULL;
52 m_CharHeight = m_CharWidth = 0;
53 m_UseLink = false;
54#if !wxUSE_UNICODE
55 m_EncConv = NULL;
56 m_InputEnc = wxFONTENCODING_ISO8859_1;
57 m_OutputEnc = wxFONTENCODING_DEFAULT;
58#endif
59 m_lastWordCell = NULL;
60
61 {
62 int i, j, k, l, m;
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++)
68 {
69 m_FontsTable[i][j][k][l][m] = NULL;
70 m_FontsFacesTable[i][j][k][l][m] = wxEmptyString;
71#if !wxUSE_UNICODE
72 m_FontsEncTable[i][j][k][l][m] = wxFONTENCODING_DEFAULT;
73#endif
74 }
75
76 SetFonts(wxEmptyString, wxEmptyString, NULL);
77 }
78
79 // fill in wxHtmlParser's tables:
80 wxList::compatibility_iterator node = m_Modules.GetFirst();
81 while (node)
82 {
83 wxHtmlTagsModule *mod = (wxHtmlTagsModule*) node->GetData();
84 mod->FillHandlersTable(this);
85 node = node->GetNext();
86 }
87}
88
89wxHtmlWinParser::~wxHtmlWinParser()
90{
91 int i, j, k, l, m;
92
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++)
98 {
99 if (m_FontsTable[i][j][k][l][m] != NULL)
100 delete m_FontsTable[i][j][k][l][m];
101 }
102#if !wxUSE_UNICODE
103 delete m_EncConv;
104#endif
105 delete[] m_tmpStrBuf;
106}
107
108void wxHtmlWinParser::AddModule(wxHtmlTagsModule *module)
109{
110 m_Modules.Append(module);
111}
112
113void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule *module)
114{
115 m_Modules.DeleteObject(module);
116}
117
118void wxHtmlWinParser::SetFonts(wxString normal_face, wxString fixed_face,
119 const int *sizes)
120{
121 static int default_sizes[7] =
122 {
123 wxHTML_FONT_SIZE_1,
124 wxHTML_FONT_SIZE_2,
125 wxHTML_FONT_SIZE_3,
126 wxHTML_FONT_SIZE_4,
127 wxHTML_FONT_SIZE_5,
128 wxHTML_FONT_SIZE_6,
129 wxHTML_FONT_SIZE_7
130 };
131
132 if (sizes == NULL) sizes = default_sizes;
133
134 int i, j, k, l, m;
135
136 for (i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
137 m_FontFaceFixed = fixed_face;
138 m_FontFaceNormal = normal_face;
139
140#if !wxUSE_UNICODE
141 SetInputEncoding(m_InputEnc);
142#endif
143
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)
150 {
151 delete m_FontsTable[i][j][k][l][m];
152 m_FontsTable[i][j][k][l][m] = NULL;
153 }
154 }
155}
156
157void wxHtmlWinParser::SetStandardFonts(int size,
158 const wxString& normal_face,
159 const wxString& fixed_face)
160{
161 wxFont defaultFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
162
163 int f_sizes[7];
164 if (size == -1)
165 size = defaultFont.GetPointSize();
166
167 f_sizes[0] = int(size * 0.6);
168 f_sizes[1] = int(size * 0.8);
169 f_sizes[2] = size;
170 f_sizes[3] = int(size * 1.2);
171 f_sizes[4] = int(size * 1.4);
172 f_sizes[5] = int(size * 1.6);
173 f_sizes[6] = int(size * 1.8);
174
175 wxString normal = normal_face.empty() ?
176 defaultFont.GetFaceName() : normal_face;
177
178 SetFonts(normal, fixed_face, f_sizes);
179}
180
181void wxHtmlWinParser::InitParser(const wxString& source)
182{
183 wxHtmlParser::InitParser(source);
184 wxASSERT_MSG(m_DC != NULL, wxT("no DC assigned to wxHtmlWinParser!!"));
185
186 m_FontBold = m_FontItalic = m_FontUnderlined = m_FontFixed = FALSE;
187 m_FontSize = 3; //default one
188 CreateCurrentFont(); // we're selecting default font into
189 m_DC->GetTextExtent( wxT("H"), &m_CharWidth, &m_CharHeight);
190 /* NOTE : we're not using GetCharWidth/Height() because
191 of differences under X and win
192 */
193
194 m_UseLink = false;
195 m_Link = wxHtmlLinkInfo( wxT(""), wxT("") );
196 m_LinkColor.Set(0, 0, 0xFF);
197 m_ActualColor.Set(0, 0, 0);
198 m_Align = wxHTML_ALIGN_LEFT;
199 m_tmpLastWasSpace = false;
200 m_lastWordCell = NULL;
201
202 OpenContainer();
203 OpenContainer();
204
205#if !wxUSE_UNICODE
206 wxString charset = ExtractCharsetInformation(source);
207 if (!charset.empty())
208 {
209 wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(charset);
210 if (enc != wxFONTENCODING_SYSTEM)
211 SetInputEncoding(enc);
212 }
213#endif
214
215 m_Container->InsertCell(new wxHtmlColourCell(m_ActualColor));
216 wxColour windowColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) ;
217 m_Container->InsertCell(
218 new wxHtmlColourCell(GetWindow() ?
219 GetWindow()->GetBackgroundColour() :
220 windowColour,
221 wxHTML_CLR_BACKGROUND));
222 m_Container->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
223}
224
225void wxHtmlWinParser::DoneParser()
226{
227 m_Container = NULL;
228#if !wxUSE_UNICODE
229 SetInputEncoding(wxFONTENCODING_ISO8859_1); // for next call
230#endif
231 wxHtmlParser::DoneParser();
232}
233
234wxObject* wxHtmlWinParser::GetProduct()
235{
236 wxHtmlContainerCell *top;
237
238 CloseContainer();
239 OpenContainer();
240
241 top = m_Container;
242 while (top->GetParent()) top = top->GetParent();
243 top->RemoveExtraSpacing(true, true);
244
245 return top;
246}
247
248wxFSFile *wxHtmlWinParser::OpenURL(wxHtmlURLType type,
249 const wxString& url) const
250{
251 // FIXME - normalize the URL to full path before passing to
252 // OnOpeningURL!!
253 if ( m_Window )
254 {
255 wxString myurl(url);
256 wxHtmlOpeningStatus status;
257 for (;;)
258 {
259 wxString redirect;
260 status = m_Window->OnOpeningURL(type, myurl, &redirect);
261 if ( status != wxHTML_REDIRECT )
262 break;
263
264 myurl = redirect;
265 }
266
267 if ( status == wxHTML_BLOCK )
268 return NULL;
269
270 return GetFS()->OpenFile(myurl);
271 }
272
273 return wxHtmlParser::OpenURL(type, url);
274}
275
276void wxHtmlWinParser::AddText(const wxChar* txt)
277{
278 wxHtmlCell *c;
279 size_t i = 0,
280 x,
281 lng = wxStrlen(txt);
282 register wxChar d;
283 int templen = 0;
284 wxChar nbsp = GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
285
286 if (lng+1 > m_tmpStrBufSize)
287 {
288 delete[] m_tmpStrBuf;
289 m_tmpStrBuf = new wxChar[lng+1];
290 m_tmpStrBufSize = lng+1;
291 }
292 wxChar *temp = m_tmpStrBuf;
293
294 if (m_tmpLastWasSpace)
295 {
296 while ((i < lng) &&
297 ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) || (txt[i] == wxT(' ')) ||
298 (txt[i] == wxT('\t')))) i++;
299 }
300
301 while (i < lng)
302 {
303 x = 0;
304 d = temp[templen++] = txt[i];
305 if ((d == wxT('\n')) || (d == wxT('\r')) || (d == wxT(' ')) || (d == wxT('\t')))
306 {
307 i++, x++;
308 while ((i < lng) && ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) ||
309 (txt[i] == wxT(' ')) || (txt[i] == wxT('\t')))) i++, x++;
310 }
311 else i++;
312
313 if (x)
314 {
315 temp[templen-1] = wxT(' ');
316 temp[templen] = 0;
317 templen = 0;
318#if !wxUSE_UNICODE
319 if (m_EncConv)
320 m_EncConv->Convert(temp);
321#endif
322 size_t len = wxStrlen(temp);
323 for (size_t j = 0; j < len; j++)
324 if (temp[j] == nbsp)
325 temp[j] = wxT(' ');
326 c = new wxHtmlWordCell(temp, *(GetDC()));
327 if (m_UseLink)
328 c->SetLink(m_Link);
329 m_Container->InsertCell(c);
330 ((wxHtmlWordCell*)c)->SetPreviousWord(m_lastWordCell);
331 m_lastWordCell = (wxHtmlWordCell*)c;
332 m_tmpLastWasSpace = true;
333 }
334 }
335
336 if (templen && (templen > 1 || temp[0] != wxT(' ')))
337 {
338 temp[templen] = 0;
339#if !wxUSE_UNICODE
340 if (m_EncConv)
341 m_EncConv->Convert(temp);
342#endif
343 size_t len = wxStrlen(temp);
344 for (size_t j = 0; j < len; j++)
345 if (temp[j] == nbsp)
346 temp[j] = wxT(' ');
347 c = new wxHtmlWordCell(temp, *(GetDC()));
348 if (m_UseLink)
349 c->SetLink(m_Link);
350 m_Container->InsertCell(c);
351 ((wxHtmlWordCell*)c)->SetPreviousWord(m_lastWordCell);
352 m_lastWordCell = (wxHtmlWordCell*)c;
353 m_tmpLastWasSpace = false;
354 }
355}
356
357
358
359wxHtmlContainerCell* wxHtmlWinParser::OpenContainer()
360{
361 m_Container = new wxHtmlContainerCell(m_Container);
362 m_Container->SetAlignHor(m_Align);
363 m_tmpLastWasSpace = true;
364 /* to avoid space being first character in paragraph */
365 return m_Container;
366}
367
368
369
370wxHtmlContainerCell* wxHtmlWinParser::SetContainer(wxHtmlContainerCell *c)
371{
372 m_tmpLastWasSpace = true;
373 /* to avoid space being first character in paragraph */
374 return m_Container = c;
375}
376
377
378
379wxHtmlContainerCell* wxHtmlWinParser::CloseContainer()
380{
381 m_Container = m_Container->GetParent();
382 return m_Container;
383}
384
385
386void wxHtmlWinParser::SetFontSize(int s)
387{
388 if (s < 1) s = 1;
389 else if (s > 7) s = 7;
390 m_FontSize = s;
391}
392
393
394
395wxFont* wxHtmlWinParser::CreateCurrentFont()
396{
397 int fb = GetFontBold(),
398 fi = GetFontItalic(),
399 fu = GetFontUnderlined(),
400 ff = GetFontFixed(),
401 fs = GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
402
403 wxString face = ff ? m_FontFaceFixed : m_FontFaceNormal;
404 wxString *faceptr = &(m_FontsFacesTable[fb][fi][fu][ff][fs]);
405 wxFont **fontptr = &(m_FontsTable[fb][fi][fu][ff][fs]);
406#if !wxUSE_UNICODE
407 wxFontEncoding *encptr = &(m_FontsEncTable[fb][fi][fu][ff][fs]);
408#endif
409
410 if (*fontptr != NULL && (*faceptr != face
411#if !wxUSE_UNICODE
412 || *encptr != m_OutputEnc
413#endif
414 ))
415 {
416 delete *fontptr;
417 *fontptr = NULL;
418 }
419
420 if (*fontptr == NULL)
421 {
422 *faceptr = face;
423 *fontptr = new wxFont(
424 (int) (m_FontsSizes[fs] * m_PixelScale),
425 ff ? wxMODERN : wxSWISS,
426 fi ? wxITALIC : wxNORMAL,
427 fb ? wxBOLD : wxNORMAL,
428 fu ? true : false, face
429#if wxUSE_UNICODE
430 );
431#else
432 , m_OutputEnc);
433 *encptr = m_OutputEnc;
434#endif
435 }
436 m_DC->SetFont(**fontptr);
437 return (*fontptr);
438}
439
440
441
442void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo& link)
443{
444 m_Link = link;
445 m_UseLink = (link.GetHref() != wxEmptyString);
446}
447
448
449void wxHtmlWinParser::SetFontFace(const wxString& face)
450{
451 if (GetFontFixed()) m_FontFaceFixed = face;
452 else m_FontFaceNormal = face;
453
454#if !wxUSE_UNICODE
455 if (m_InputEnc != wxFONTENCODING_DEFAULT)
456 SetInputEncoding(m_InputEnc);
457#endif
458}
459
460
461
462#if !wxUSE_UNICODE
463void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc)
464{
465 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
466 if (m_EncConv)
467 {
468 delete m_EncConv;
469 m_EncConv = NULL;
470 }
471
472 if (enc == wxFONTENCODING_DEFAULT) return;
473
474 wxFontEncoding altfix, altnorm;
475 bool availfix, availnorm;
476
477 // exact match?
478 availnorm = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceNormal);
479 availfix = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceFixed);
480 if (availnorm && availfix)
481 m_OutputEnc = enc;
482
483 // alternatives?
484 else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, false) &&
485 wxFontMapper::Get()->GetAltForEncoding(enc, &altfix, m_FontFaceFixed, false) &&
486 altnorm == altfix)
487 m_OutputEnc = altnorm;
488
489 // at least normal face?
490 else if (availnorm)
491 m_OutputEnc = enc;
492 else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, false))
493 m_OutputEnc = altnorm;
494
495 else
496 {
497#ifndef __WXMAC__
498 // okay, let convert to ISO_8859-1, available always
499 m_OutputEnc = wxFONTENCODING_DEFAULT;
500#else
501 m_OutputEnc = wxLocale::GetSystemEncoding() ;
502#endif
503 }
504
505 m_InputEnc = enc;
506 if (m_OutputEnc == wxFONTENCODING_DEFAULT)
507 GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM);
508 else
509 GetEntitiesParser()->SetEncoding(m_OutputEnc);
510
511 if (m_InputEnc == m_OutputEnc) return;
512
513 m_EncConv = new wxEncodingConverter();
514 if (!m_EncConv->Init(m_InputEnc,
515 (m_OutputEnc == wxFONTENCODING_DEFAULT) ?
516 wxFONTENCODING_ISO8859_1 : m_OutputEnc,
517 wxCONVERT_SUBSTITUTE))
518 { // total failture :-(
519 wxLogError(_("Failed to display HTML document in %s encoding"),
520 wxFontMapper::GetEncodingName(enc).c_str());
521 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
522 delete m_EncConv;
523 m_EncConv = NULL;
524 }
525}
526#endif
527
528
529
530
531//-----------------------------------------------------------------------------
532// wxHtmlWinTagHandler
533//-----------------------------------------------------------------------------
534
535IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler, wxHtmlTagHandler)
536
537//-----------------------------------------------------------------------------
538// wxHtmlTagsModule
539//-----------------------------------------------------------------------------
540
541// NB: This is *NOT* winpars.cpp's initialization and shutdown code!!
542// This module is an ancestor for tag handlers modules defined
543// in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct.
544//
545// Do not add any winpars.cpp shutdown or initialization code to it,
546// create a new module instead!
547
548IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule, wxModule)
549
550bool wxHtmlTagsModule::OnInit()
551{
552 wxHtmlWinParser::AddModule(this);
553 return true;
554}
555
556void wxHtmlTagsModule::OnExit()
557{
558 wxHtmlWinParser::RemoveModule(this);
559}
560
561#endif
562