1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/html/winpars.cpp
3 // Purpose: wxHtmlParser class (generic parser)
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id: winpars.cpp 58846 2009-02-12 19:38:20Z VS $
6 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #include "wx/wxprec.h"
11
12 #ifdef __BORLANDC__
13 #pragma hdrstop
14 #endif
15
16 #if wxUSE_HTML && wxUSE_STREAMS
17
18 #ifndef WXPRECOMP
19 #include "wx/intl.h"
20 #include "wx/dc.h"
21 #include "wx/log.h"
22 #include "wx/settings.h"
23 #endif
24
25 #include "wx/html/htmldefs.h"
26 #include "wx/html/winpars.h"
27 #include "wx/html/htmlwin.h"
28 #include "wx/fontmap.h"
29 #include "wx/uri.h"
30
31 //-----------------------------------------------------------------------------
32 // wxHtmlWordWithTabsCell
33 //-----------------------------------------------------------------------------
34
35 // NB: this is backported from wx-2.9 and moved to this file so that it
36 // stays private; trunk version is in htmlcell.h/cpp.
37
38
39 // wxHtmlWordCell specialization for storing text fragments with embedded
40 // '\t's; these differ from normal words in that the displayed text is
41 // different from the text copied to clipboard
42 class WXDLLIMPEXP_HTML wxHtmlWordWithTabsCell : public wxHtmlWordCell
43 {
44 public:
wxHtmlWordWithTabsCell(const wxString & word,const wxString & wordOrig,size_t linepos,const wxDC & dc)45 wxHtmlWordWithTabsCell(const wxString& word,
46 const wxString& wordOrig,
47 size_t linepos,
48 const wxDC& dc)
49 : wxHtmlWordCell(word, dc),
50 m_wordOrig(wordOrig),
51 m_linepos(linepos)
52 {}
53
54 virtual wxString ConvertToText(wxHtmlSelection *sel) const;
55
56 protected:
57 wxString GetPartAsText(int begin, int end) const;
58
59 wxString m_wordOrig;
60 size_t m_linepos;
61 };
62
ConvertToText(wxHtmlSelection * s) const63 wxString wxHtmlWordWithTabsCell::ConvertToText(wxHtmlSelection *s) const
64 {
65 if ( s && (this == s->GetFromCell() || this == s->GetToCell()) )
66 {
67 wxPoint priv = this == s->GetFromCell() ? s->GetFromPrivPos()
68 : s->GetToPrivPos();
69
70 // VZ: we may be called before we had a chance to re-render ourselves
71 // and in this case GetFrom/ToPrivPos() is not set yet -- assume
72 // that this only happens in case of a double/triple click (which
73 // seems to be the case now) and so it makes sense to select the
74 // entire contents of the cell in this case
75 //
76 // TODO: but this really needs to be fixed in some better way later...
77 if ( priv != wxDefaultPosition )
78 {
79 int part1 = priv.x;
80 int part2 = priv.y;
81 if ( part1 == part2 )
82 return wxEmptyString;
83 return GetPartAsText(part1, part2);
84 }
85 //else: return the whole word below
86 }
87
88 return m_wordOrig;
89 }
90
GetPartAsText(int begin,int end) const91 wxString wxHtmlWordWithTabsCell::GetPartAsText(int begin, int end) const
92 {
93 // NB: The 'begin' and 'end' positions are in the _displayed_ text
94 // (stored in m_Word) and not in the text with tabs that should
95 // be copied to clipboard (m_wordOrig).
96 //
97 // NB: Because selection is performed on displayed text, it's possible
98 // to select e.g. "half of TAB character" -- IOW, 'begin' and 'end'
99 // may be in the middle of TAB character expansion into ' 's. In this
100 // case, we copy the TAB character to clipboard once.
101
102 wxASSERT( begin < end );
103
104 const unsigned SPACES_PER_TAB = 8;
105
106 wxString sel;
107
108 int pos = 0;
109 wxString::const_iterator i = m_wordOrig.begin();
110
111 // find the beginning of text to copy:
112 for ( ; pos < begin; ++i )
113 {
114 if ( *i == '\t' )
115 {
116 pos += 8 - (m_linepos + pos) % SPACES_PER_TAB;
117 if ( pos >= begin )
118 {
119 sel += '\t';
120 }
121 }
122 else
123 {
124 ++pos;
125 }
126 }
127
128 // copy the content until we reach 'end':
129 for ( ; pos < end; ++i )
130 {
131 const wxChar c = *i;
132 sel += c;
133
134 if ( c == '\t' )
135 pos += 8 - (m_linepos + pos) % SPACES_PER_TAB;
136 else
137 ++pos;
138 }
139
140 return sel;
141 }
142
143
144 //-----------------------------------------------------------------------------
145 // wxHtmlWinParser
146 //-----------------------------------------------------------------------------
147
148 struct wxHtmlWinParser_TextParsingState
149 {
150 // current whitespace handling mode
151 wxHtmlWinParser::WhitespaceMode m_whitespaceMode;
152
153 wxHtmlWordCell *m_lastWordCell;
154
155 // current position on line, in num. of characters; used to properly
156 // expand TABs; only updated while inside <pre>
157 int m_posColumn;
158 };
159
160 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser, wxHtmlParser)
161
162 wxList wxHtmlWinParser::m_Modules;
163
wxHtmlWinParser(wxHtmlWindowInterface * wndIface)164 wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindowInterface *wndIface)
165 {
166 m_textParsingState = new wxHtmlWinParser_TextParsingState;
167 m_textParsingState->m_whitespaceMode = Whitespace_Normal;
168 m_textParsingState->m_lastWordCell = NULL;
169 m_textParsingState->m_posColumn = 0;
170
171 m_tmpStrBuf = NULL;
172 m_tmpStrBufSize = 0;
173 m_windowInterface = wndIface;
174 m_Container = NULL;
175 m_DC = NULL;
176 m_CharHeight = m_CharWidth = 0;
177 m_UseLink = false;
178 #if !wxUSE_UNICODE
179 m_EncConv = NULL;
180 m_InputEnc = wxFONTENCODING_ISO8859_1;
181 m_OutputEnc = wxFONTENCODING_DEFAULT;
182 #endif
183
184 {
185 int i, j, k, l, m;
186 for (i = 0; i < 2; i++)
187 for (j = 0; j < 2; j++)
188 for (k = 0; k < 2; k++)
189 for (l = 0; l < 2; l++)
190 for (m = 0; m < 7; m++)
191 {
192 m_FontsTable[i][j][k][l][m] = NULL;
193 m_FontsFacesTable[i][j][k][l][m] = wxEmptyString;
194 #if !wxUSE_UNICODE
195 m_FontsEncTable[i][j][k][l][m] = wxFONTENCODING_DEFAULT;
196 #endif
197 }
198
199 SetFonts(wxEmptyString, wxEmptyString, NULL);
200 }
201
202 // fill in wxHtmlParser's tables:
203 wxList::compatibility_iterator node = m_Modules.GetFirst();
204 while (node)
205 {
206 wxHtmlTagsModule *mod = (wxHtmlTagsModule*) node->GetData();
207 mod->FillHandlersTable(this);
208 node = node->GetNext();
209 }
210 }
211
~wxHtmlWinParser()212 wxHtmlWinParser::~wxHtmlWinParser()
213 {
214 int i, j, k, l, m;
215
216 for (i = 0; i < 2; i++)
217 for (j = 0; j < 2; j++)
218 for (k = 0; k < 2; k++)
219 for (l = 0; l < 2; l++)
220 for (m = 0; m < 7; m++)
221 {
222 if (m_FontsTable[i][j][k][l][m] != NULL)
223 delete m_FontsTable[i][j][k][l][m];
224 }
225 #if !wxUSE_UNICODE
226 delete m_EncConv;
227 #endif
228 delete[] m_tmpStrBuf;
229
230 delete m_textParsingState;
231 }
232
AddModule(wxHtmlTagsModule * module)233 void wxHtmlWinParser::AddModule(wxHtmlTagsModule *module)
234 {
235 m_Modules.Append(module);
236 }
237
RemoveModule(wxHtmlTagsModule * module)238 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule *module)
239 {
240 m_Modules.DeleteObject(module);
241 }
242
243 // build all HTML font sizes (1..7) from the given base size
wxBuildFontSizes(int * sizes,int size)244 static void wxBuildFontSizes(int *sizes, int size)
245 {
246 // using a fixed factor (1.2, from CSS2) is a bad idea as explained at
247 // http://www.w3.org/TR/CSS21/fonts.html#font-size-props but this is by far
248 // simplest thing to do so still do it like this for now
249 sizes[0] = int(size * 0.75); // exception to 1.2 rule, otherwise too small
250 sizes[1] = int(size * 0.83);
251 sizes[2] = size;
252 sizes[3] = int(size * 1.2);
253 sizes[4] = int(size * 1.44);
254 sizes[5] = int(size * 1.73);
255 sizes[6] = int(size * 2);
256 }
257
wxGetDefaultHTMLFontSize()258 static int wxGetDefaultHTMLFontSize()
259 {
260 // base the default font size on the size of the default system font but
261 // also ensure that we have a font of reasonable size, otherwise small HTML
262 // fonts are unreadable
263 int size = wxNORMAL_FONT->GetPointSize();
264 if ( size < 10 )
265 size = 10;
266 return size;
267 }
268
SetFonts(const wxString & normal_face,const wxString & fixed_face,const int * sizes)269 void wxHtmlWinParser::SetFonts(const wxString& normal_face,
270 const wxString& fixed_face,
271 const int *sizes)
272 {
273 static int default_sizes[7] = { 0 };
274 if ( !sizes )
275 {
276 if ( !default_sizes[0] )
277 wxBuildFontSizes(default_sizes, wxGetDefaultHTMLFontSize());
278
279 sizes = default_sizes;
280 }
281
282 int i, j, k, l, m;
283
284 for (i = 0; i < 7; i++)
285 m_FontsSizes[i] = sizes[i];
286
287 m_FontFaceFixed = fixed_face;
288 m_FontFaceNormal = normal_face;
289
290 #if !wxUSE_UNICODE
291 SetInputEncoding(m_InputEnc);
292 #endif
293
294 for (i = 0; i < 2; i++)
295 for (j = 0; j < 2; j++)
296 for (k = 0; k < 2; k++)
297 for (l = 0; l < 2; l++)
298 for (m = 0; m < 7; m++) {
299 if (m_FontsTable[i][j][k][l][m] != NULL)
300 {
301 delete m_FontsTable[i][j][k][l][m];
302 m_FontsTable[i][j][k][l][m] = NULL;
303 }
304 }
305 }
306
SetStandardFonts(int size,const wxString & normal_face,const wxString & fixed_face)307 void wxHtmlWinParser::SetStandardFonts(int size,
308 const wxString& normal_face,
309 const wxString& fixed_face)
310 {
311 if (size == -1)
312 size = wxGetDefaultHTMLFontSize();
313
314 int f_sizes[7];
315 wxBuildFontSizes(f_sizes, size);
316
317 wxString normal = normal_face;
318 if ( normal.empty() )
319 normal = wxNORMAL_FONT->GetFaceName();
320
321 SetFonts(normal, fixed_face, f_sizes);
322 }
323
InitParser(const wxString & source)324 void wxHtmlWinParser::InitParser(const wxString& source)
325 {
326 wxHtmlParser::InitParser(source);
327 wxASSERT_MSG(m_DC != NULL, wxT("no DC assigned to wxHtmlWinParser!!"));
328
329 m_FontBold = m_FontItalic = m_FontUnderlined = m_FontFixed = FALSE;
330 m_FontSize = 3; //default one
331 CreateCurrentFont(); // we're selecting default font into
332 m_DC->GetTextExtent( wxT("H"), &m_CharWidth, &m_CharHeight);
333 /* NOTE : we're not using GetCharWidth/Height() because
334 of differences under X and win
335 */
336
337 m_UseLink = false;
338 m_Link = wxHtmlLinkInfo( wxEmptyString );
339 m_LinkColor.Set(0, 0, 0xFF);
340 m_ActualColor.Set(0, 0, 0);
341 m_Align = wxHTML_ALIGN_LEFT;
342 m_ScriptMode = wxHTML_SCRIPT_NORMAL;
343 m_ScriptBaseline = 0;
344 m_tmpLastWasSpace = false;
345 m_textParsingState->m_lastWordCell = NULL;
346
347 // open the toplevel container that contains everything else and that
348 // is never closed (this makes parser's life easier):
349 OpenContainer();
350
351 // then open the first container into which page's content will go:
352 OpenContainer();
353
354 #if !wxUSE_UNICODE
355 wxString charset = ExtractCharsetInformation(source);
356 if (!charset.empty())
357 {
358 wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(charset);
359 if (enc != wxFONTENCODING_SYSTEM)
360 SetInputEncoding(enc);
361 }
362 #endif
363
364 m_Container->InsertCell(new wxHtmlColourCell(m_ActualColor));
365 wxColour windowColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) ;
366
367 m_Container->InsertCell
368 (
369 new wxHtmlColourCell
370 (
371 m_windowInterface
372 ? m_windowInterface->GetHTMLBackgroundColour()
373 : windowColour,
374 wxHTML_CLR_BACKGROUND
375 )
376 );
377
378 m_Container->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
379 }
380
DoneParser()381 void wxHtmlWinParser::DoneParser()
382 {
383 m_Container = NULL;
384 #if !wxUSE_UNICODE
385 SetInputEncoding(wxFONTENCODING_ISO8859_1); // for next call
386 #endif
387 wxHtmlParser::DoneParser();
388 }
389
390 #if WXWIN_COMPATIBILITY_2_6
GetWindow()391 wxHtmlWindow *wxHtmlWinParser::GetWindow()
392 {
393 if (!m_windowInterface)
394 return NULL;
395 return wxDynamicCast(m_windowInterface->GetHTMLWindow(), wxHtmlWindow);
396 }
397 #endif
398
GetProduct()399 wxObject* wxHtmlWinParser::GetProduct()
400 {
401 wxHtmlContainerCell *top;
402
403 CloseContainer();
404 OpenContainer();
405
406 top = m_Container;
407 while (top->GetParent()) top = top->GetParent();
408 top->RemoveExtraSpacing(true, true);
409
410 return top;
411 }
412
OpenURL(wxHtmlURLType type,const wxString & url) const413 wxFSFile *wxHtmlWinParser::OpenURL(wxHtmlURLType type,
414 const wxString& url) const
415 {
416 if ( !m_windowInterface )
417 return wxHtmlParser::OpenURL(type, url);
418
419 wxString myurl(url);
420 wxHtmlOpeningStatus status;
421 for (;;)
422 {
423 wxString myfullurl(myurl);
424
425 // consider url as absolute path first
426 wxURI current(myurl);
427 myfullurl = current.BuildUnescapedURI();
428
429 // if not absolute then ...
430 if( current.IsReference() )
431 {
432 wxString basepath = GetFS()->GetPath();
433 wxURI base(basepath);
434
435 // ... try to apply base path if valid ...
436 if( !base.IsReference() )
437 {
438 wxURI path(myfullurl);
439 path.Resolve( base );
440 myfullurl = path.BuildUnescapedURI();
441 }
442 else
443 {
444 // ... or force such addition if not included already
445 if( !current.GetPath().Contains(base.GetPath()) )
446 {
447 basepath += myurl;
448 wxURI connected( basepath );
449 myfullurl = connected.BuildUnescapedURI();
450 }
451 }
452 }
453
454 wxString redirect;
455 status = m_windowInterface->OnHTMLOpeningURL(type, myfullurl, &redirect);
456 if ( status != wxHTML_REDIRECT )
457 break;
458
459 myurl = redirect;
460 }
461
462 if ( status == wxHTML_BLOCK )
463 return NULL;
464
465 int flags = wxFS_READ;
466 if (type == wxHTML_URL_IMAGE)
467 flags |= wxFS_SEEKABLE;
468
469 return GetFS()->OpenFile(myurl, flags);
470 }
471
SetWhitespaceMode(wxHtmlWinParser::WhitespaceMode mode)472 void wxHtmlWinParser::SetWhitespaceMode(wxHtmlWinParser::WhitespaceMode mode)
473 {
474 m_textParsingState->m_whitespaceMode = mode;
475 }
476
GetWhitespaceMode() const477 wxHtmlWinParser::WhitespaceMode wxHtmlWinParser::GetWhitespaceMode() const
478 {
479 return m_textParsingState->m_whitespaceMode;
480 }
481
AddText(const wxChar * txt)482 void wxHtmlWinParser::AddText(const wxChar* txt)
483 {
484 const wxChar nbsp = GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
485
486 if ( m_textParsingState->m_whitespaceMode == Whitespace_Normal )
487 {
488 size_t i = 0,
489 x,
490 lng = wxStrlen(txt);
491 int templen = 0;
492
493 if (lng+1 > m_tmpStrBufSize)
494 {
495 delete[] m_tmpStrBuf;
496 m_tmpStrBuf = new wxChar[lng+1];
497 m_tmpStrBufSize = lng+1;
498 }
499 wxChar *temp = m_tmpStrBuf;
500
501 if (m_tmpLastWasSpace)
502 {
503 while ((i < lng) &&
504 ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) || (txt[i] == wxT(' ')) ||
505 (txt[i] == wxT('\t')))) i++;
506 }
507
508 while (i < lng)
509 {
510 x = 0;
511 const wxChar d = temp[templen++] = txt[i];
512 if ((d == wxT('\n')) || (d == wxT('\r')) || (d == wxT(' ')) || (d == wxT('\t')))
513 {
514 i++, x++;
515 while ((i < lng) && ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) ||
516 (txt[i] == wxT(' ')) || (txt[i] == wxT('\t')))) i++, x++;
517 }
518 else i++;
519
520 if (x)
521 {
522 temp[templen-1] = wxT(' ');
523 FlushWordBuf(temp, templen, nbsp);
524 m_tmpLastWasSpace = true;
525 }
526 }
527
528 if (templen && (templen > 1 || temp[0] != wxT(' ')))
529 {
530 FlushWordBuf(temp, templen, nbsp);
531 m_tmpLastWasSpace = false;
532 }
533 }
534 else // m_whitespaceMode == Whitespace_Pre
535 {
536 if ( wxStrchr(txt, nbsp) != NULL )
537 {
538 // we need to substitute spaces for here just like we
539 // did in the Whitespace_Normal branch above
540 wxString txt2(txt);
541 wxChar nbsp_str[2];
542 nbsp_str[0] = nbsp;
543 nbsp_str[1] = 0;
544 txt2.Replace(nbsp_str, wxT(" "));
545 AddPreBlock(txt2);
546 }
547 else
548 {
549 AddPreBlock(txt);
550 }
551
552 // don't eat any whitespace in <pre> block
553 m_tmpLastWasSpace = false;
554 }
555 }
556
FlushWordBuf(wxChar * buf,int & len,wxChar nbsp)557 void wxHtmlWinParser::FlushWordBuf(wxChar *buf, int& len, wxChar nbsp)
558 {
559 buf[len] = 0;
560
561 for ( int i = 0; i < len; i++ )
562 {
563 if ( buf[i] == nbsp )
564 buf[i] = ' ';
565 }
566
567 #if !wxUSE_UNICODE
568 if (m_EncConv)
569 m_EncConv->Convert(buf);
570 #endif
571
572 AddWord(wxString(buf, len));
573
574 len = 0;
575 }
576
AddWord(const wxString & word)577 void wxHtmlWinParser::AddWord(const wxString& word)
578 {
579 AddWord(new wxHtmlWordCell(word, *(GetDC())));
580 }
581
AddWord(wxHtmlWordCell * c)582 void wxHtmlWinParser::AddWord(wxHtmlWordCell *c)
583 {
584 ApplyStateToCell(c);
585
586 m_Container->InsertCell(c);
587 c->SetPreviousWord(m_textParsingState->m_lastWordCell);
588 m_textParsingState->m_lastWordCell = c;
589 }
590
AddPreBlock(const wxString & text)591 void wxHtmlWinParser::AddPreBlock(const wxString& text)
592 {
593 if ( text.find(wxT('\t')) != wxString::npos )
594 {
595 wxString text2;
596 text2.reserve(text.length());
597
598 const wxString::const_iterator end = text.end();
599 wxString::const_iterator copyFrom = text.begin();
600 size_t posFrom = 0;
601 size_t pos = 0;
602 int posColumn = m_textParsingState->m_posColumn;
603 for ( wxString::const_iterator i = copyFrom; i != end; ++i, ++pos )
604 {
605 if ( *i == wxT('\t') )
606 {
607 if ( copyFrom != i )
608 text2.append(copyFrom, i);
609
610 const unsigned SPACES_PER_TAB = 8;
611 const size_t expandTo = SPACES_PER_TAB - posColumn % SPACES_PER_TAB;
612 text2.append(expandTo, wxT(' '));
613
614 posColumn += expandTo;
615 copyFrom = i + 1;
616 posFrom = pos + 1;
617 }
618 else
619 {
620 ++posColumn;
621 }
622 }
623 if ( copyFrom != text.end() )
624 text2.append(copyFrom, text.end());
625
626 AddWord(new wxHtmlWordWithTabsCell(text2, text,
627 m_textParsingState->m_posColumn,
628 *(GetDC())));
629
630 m_textParsingState->m_posColumn = posColumn;
631 }
632 else
633 {
634 // no special formatting needed
635 AddWord(text);
636 m_textParsingState->m_posColumn += text.length();
637 }
638 }
639
640
641
OpenContainer()642 wxHtmlContainerCell* wxHtmlWinParser::OpenContainer()
643 {
644 m_Container = new wxHtmlContainerCell(m_Container);
645 m_Container->SetAlignHor(m_Align);
646 m_textParsingState->m_posColumn = 0;
647 m_tmpLastWasSpace = true;
648 /* to avoid space being first character in paragraph */
649 return m_Container;
650 }
651
652
653
SetContainer(wxHtmlContainerCell * c)654 wxHtmlContainerCell* wxHtmlWinParser::SetContainer(wxHtmlContainerCell *c)
655 {
656 m_tmpLastWasSpace = true;
657 /* to avoid space being first character in paragraph */
658 return m_Container = c;
659 }
660
661
662
CloseContainer()663 wxHtmlContainerCell* wxHtmlWinParser::CloseContainer()
664 {
665 m_Container = m_Container->GetParent();
666 return m_Container;
667 }
668
669
SetFontSize(int s)670 void wxHtmlWinParser::SetFontSize(int s)
671 {
672 if (s < 1) s = 1;
673 else if (s > 7) s = 7;
674 m_FontSize = s;
675 }
676
677
678
CreateCurrentFont()679 wxFont* wxHtmlWinParser::CreateCurrentFont()
680 {
681 int fb = GetFontBold(),
682 fi = GetFontItalic(),
683 fu = GetFontUnderlined(),
684 ff = GetFontFixed(),
685 fs = GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
686
687 wxString face = ff ? m_FontFaceFixed : m_FontFaceNormal;
688 wxString *faceptr = &(m_FontsFacesTable[fb][fi][fu][ff][fs]);
689 wxFont **fontptr = &(m_FontsTable[fb][fi][fu][ff][fs]);
690 #if !wxUSE_UNICODE
691 wxFontEncoding *encptr = &(m_FontsEncTable[fb][fi][fu][ff][fs]);
692 #endif
693
694 if (*fontptr != NULL && (*faceptr != face
695 #if !wxUSE_UNICODE
696 || *encptr != m_OutputEnc
697 #endif
698 ))
699 {
700 delete *fontptr;
701 *fontptr = NULL;
702 }
703
704 if (*fontptr == NULL)
705 {
706 *faceptr = face;
707 *fontptr = new wxFont(
708 (int) (m_FontsSizes[fs] * m_PixelScale),
709 ff ? wxMODERN : wxSWISS,
710 fi ? wxITALIC : wxNORMAL,
711 fb ? wxBOLD : wxNORMAL,
712 fu ? true : false, face
713 #if wxUSE_UNICODE
714 );
715 #else
716 , m_OutputEnc);
717 *encptr = m_OutputEnc;
718 #endif
719 }
720 m_DC->SetFont(**fontptr);
721 return (*fontptr);
722 }
723
724
725
SetLink(const wxHtmlLinkInfo & link)726 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo& link)
727 {
728 m_Link = link;
729 m_UseLink = (link.GetHref() != wxEmptyString);
730 }
731
SetFontFace(const wxString & face)732 void wxHtmlWinParser::SetFontFace(const wxString& face)
733 {
734 if (GetFontFixed()) m_FontFaceFixed = face;
735 else m_FontFaceNormal = face;
736
737 #if !wxUSE_UNICODE
738 if (m_InputEnc != wxFONTENCODING_DEFAULT)
739 SetInputEncoding(m_InputEnc);
740 #endif
741 }
742
ApplyStateToCell(wxHtmlCell * cell)743 void wxHtmlWinParser::ApplyStateToCell(wxHtmlCell *cell)
744 {
745 // set the link:
746 if (m_UseLink)
747 cell->SetLink(GetLink());
748
749 // apply current script mode settings:
750 cell->SetScriptMode(GetScriptMode(), GetScriptBaseline());
751 }
752
753
754 #if !wxUSE_UNICODE
SetInputEncoding(wxFontEncoding enc)755 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc)
756 {
757 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
758 if (m_EncConv)
759 {
760 delete m_EncConv;
761 m_EncConv = NULL;
762 }
763
764 if (enc == wxFONTENCODING_DEFAULT) return;
765
766 wxFontEncoding altfix, altnorm;
767 bool availfix, availnorm;
768
769 // exact match?
770 availnorm = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceNormal);
771 availfix = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceFixed);
772 if (availnorm && availfix)
773 m_OutputEnc = enc;
774
775 // alternatives?
776 else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, false) &&
777 wxFontMapper::Get()->GetAltForEncoding(enc, &altfix, m_FontFaceFixed, false) &&
778 altnorm == altfix)
779 m_OutputEnc = altnorm;
780
781 // at least normal face?
782 else if (availnorm)
783 m_OutputEnc = enc;
784 else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, false))
785 m_OutputEnc = altnorm;
786
787 else
788 {
789 #ifndef __WXMAC__
790 // okay, let's convert to ISO_8859-1, available always
791 m_OutputEnc = wxFONTENCODING_DEFAULT;
792 #else
793 m_OutputEnc = wxLocale::GetSystemEncoding() ;
794 #endif
795 }
796
797 m_InputEnc = enc;
798 if (m_OutputEnc == wxFONTENCODING_DEFAULT)
799 GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM);
800 else
801 GetEntitiesParser()->SetEncoding(m_OutputEnc);
802
803 if (m_InputEnc == m_OutputEnc) return;
804
805 m_EncConv = new wxEncodingConverter();
806 if (!m_EncConv->Init(m_InputEnc,
807 (m_OutputEnc == wxFONTENCODING_DEFAULT) ?
808 wxFONTENCODING_ISO8859_1 : m_OutputEnc,
809 wxCONVERT_SUBSTITUTE))
810 { // total failure :-(
811 wxLogError(_("Failed to display HTML document in %s encoding"),
812 wxFontMapper::GetEncodingName(enc).c_str());
813 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
814 delete m_EncConv;
815 m_EncConv = NULL;
816 }
817 }
818 #endif
819
820
821
822
823 //-----------------------------------------------------------------------------
824 // wxHtmlWinTagHandler
825 //-----------------------------------------------------------------------------
826
IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler,wxHtmlTagHandler)827 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler, wxHtmlTagHandler)
828
829 //-----------------------------------------------------------------------------
830 // wxHtmlTagsModule
831 //-----------------------------------------------------------------------------
832
833 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!!
834 // This module is an ancestor for tag handlers modules defined
835 // in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct.
836 //
837 // Do not add any winpars.cpp shutdown or initialization code to it,
838 // create a new module instead!
839
840 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule, wxModule)
841
842 bool wxHtmlTagsModule::OnInit()
843 {
844 wxHtmlWinParser::AddModule(this);
845 return true;
846 }
847
OnExit()848 void wxHtmlTagsModule::OnExit()
849 {
850 wxHtmlWinParser::RemoveModule(this);
851 }
852
853 #endif
854