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 &nbsp; 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