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