]> git.saurik.com Git - wxWidgets.git/blame - src/html/winpars.cpp
warning fix - only use the function in debug mode
[wxWidgets.git] / src / html / winpars.cpp
CommitLineData
5526e819 1/////////////////////////////////////////////////////////////////////////////
69941f05 2// Name: winpars.cpp
5526e819
VS
3// Purpose: wxHtmlParser class (generic parser)
4// Author: Vaclav Slavik
69941f05 5// RCS-ID: $Id$
5526e819 6// Copyright: (c) 1999 Vaclav Slavik
65571936 7// Licence: wxWindows licence
5526e819
VS
8/////////////////////////////////////////////////////////////////////////////
9
10
14f355c2 11#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
1aedb1dd 12#pragma implementation "winpars.h"
5526e819
VS
13#endif
14
3096bd2f 15#include "wx/wxprec.h"
5526e819
VS
16
17#include "wx/defs.h"
f6bcfd97 18#if wxUSE_HTML && wxUSE_STREAMS
5526e819 19
2b5f62a0 20#ifdef __BORLANDC__
5526e819
VS
21#pragma hdrstop
22#endif
23
24#ifndef WXPRECOMP
04dbb646
VZ
25 #include "wx/intl.h"
26 #include "wx/dc.h"
5526e819
VS
27#endif
28
69941f05
VS
29#include "wx/html/htmldefs.h"
30#include "wx/html/winpars.h"
31#include "wx/html/htmlwin.h"
b250d384 32#include "wx/fontmap.h"
f3c82859 33#include "wx/log.h"
3403ccd5 34#include "wx/settings.h"
5526e819
VS
35
36
37//-----------------------------------------------------------------------------
38// wxHtmlWinParser
39//-----------------------------------------------------------------------------
40
4f44ea36 41IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser, wxHtmlParser)
5526e819
VS
42
43wxList wxHtmlWinParser::m_Modules;
44
04db5c3f 45wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow *wnd) : wxHtmlParser()
5526e819 46{
211dfedd
VS
47 m_tmpStrBuf = NULL;
48 m_tmpStrBufSize = 0;
5526e819
VS
49 m_Window = wnd;
50 m_Container = NULL;
51 m_DC = NULL;
52 m_CharHeight = m_CharWidth = 0;
53 m_UseLink = FALSE;
2b5f62a0 54#if !wxUSE_UNICODE
b250d384 55 m_EncConv = NULL;
2b5f62a0
VZ
56 m_InputEnc = wxFONTENCODING_ISO8859_1;
57 m_OutputEnc = wxFONTENCODING_DEFAULT;
58#endif
b6d93b26 59 m_lastWordCell = NULL;
5526e819
VS
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++)
3c8c8da2 67 for (m = 0; m < 7; m++)
e3c7fd79 68 {
5526e819 69 m_FontsTable[i][j][k][l][m] = NULL;
f1ad10f3 70 m_FontsFacesTable[i][j][k][l][m] = wxEmptyString;
2b5f62a0 71#if !wxUSE_UNICODE
b250d384 72 m_FontsEncTable[i][j][k][l][m] = wxFONTENCODING_DEFAULT;
2b5f62a0 73#endif
f1ad10f3 74 }
4eecf115
VS
75
76 SetFonts(wxEmptyString, wxEmptyString, NULL);
5526e819
VS
77 }
78
79 // fill in wxHtmlParser's tables:
222ed1d6 80 wxList::compatibility_iterator node = m_Modules.GetFirst();
3c8c8da2 81 while (node)
4f9297b0
VS
82 {
83 wxHtmlTagsModule *mod = (wxHtmlTagsModule*) node->GetData();
84 mod->FillHandlersTable(this);
85 node = node->GetNext();
5526e819
VS
86 }
87}
88
b250d384
VS
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++)
3c8c8da2 97 for (m = 0; m < 7; m++)
e3c7fd79 98 {
3c8c8da2 99 if (m_FontsTable[i][j][k][l][m] != NULL)
b250d384
VS
100 delete m_FontsTable[i][j][k][l][m];
101 }
2b5f62a0 102#if !wxUSE_UNICODE
211dfedd 103 delete m_EncConv;
2b5f62a0 104#endif
211dfedd 105 delete[] m_tmpStrBuf;
b250d384
VS
106}
107
5526e819
VS
108void wxHtmlWinParser::AddModule(wxHtmlTagsModule *module)
109{
110 m_Modules.Append(module);
111}
112
f6bcfd97
BP
113void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule *module)
114{
115 m_Modules.DeleteObject(module);
116}
117
4eecf115
VS
118void wxHtmlWinParser::SetFonts(wxString normal_face, wxString fixed_face,
119 const int *sizes)
5526e819 120{
4eecf115
VS
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
c9f56e70
VS
134 int i, j, k, l, m;
135
136 for (i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
5526e819
VS
137 m_FontFaceFixed = fixed_face;
138 m_FontFaceNormal = normal_face;
3c8c8da2 139
2b5f62a0 140#if !wxUSE_UNICODE
b250d384 141 SetInputEncoding(m_InputEnc);
2b5f62a0 142#endif
c9f56e70
VS
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++) {
3c8c8da2 149 if (m_FontsTable[i][j][k][l][m] != NULL)
e3c7fd79 150 {
c9f56e70
VS
151 delete m_FontsTable[i][j][k][l][m];
152 m_FontsTable[i][j][k][l][m] = NULL;
153 }
154 }
5526e819
VS
155}
156
10e5c7ea
VS
157void wxHtmlWinParser::SetStandardFonts(int size,
158 const wxString& normal_face,
159 const wxString& fixed_face)
7acd3625 160{
10e5c7ea
VS
161 wxFont defaultFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
162
7acd3625
RD
163 int f_sizes[7];
164 if (size == -1)
10e5c7ea 165 size = defaultFont.GetPointSize();
7acd3625
RD
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);
10e5c7ea
VS
174
175 wxString normal = normal_face.empty() ?
176 defaultFont.GetFaceName() : normal_face;
7acd3625 177
10e5c7ea 178 SetFonts(normal, fixed_face, f_sizes);
7acd3625
RD
179}
180
5526e819
VS
181void wxHtmlWinParser::InitParser(const wxString& source)
182{
183 wxHtmlParser::InitParser(source);
2b5f62a0 184 wxASSERT_MSG(m_DC != NULL, wxT("no DC assigned to wxHtmlWinParser!!"));
5526e819
VS
185
186 m_FontBold = m_FontItalic = m_FontUnderlined = m_FontFixed = FALSE;
f2c2fa4d 187 m_FontSize = 3; //default one
5526e819 188 CreateCurrentFont(); // we're selecting default font into
2b5f62a0 189 m_DC->GetTextExtent( wxT("H"), &m_CharWidth, &m_CharHeight);
5526e819 190 /* NOTE : we're not using GetCharWidth/Height() because
0e8c8233 191 of differences under X and win
5526e819
VS
192 */
193
f2c2fa4d 194 m_UseLink = FALSE;
2b5f62a0 195 m_Link = wxHtmlLinkInfo( wxT(""), wxT("") );
5526e819
VS
196 m_LinkColor.Set(0, 0, 0xFF);
197 m_ActualColor.Set(0, 0, 0);
efba2b89 198 m_Align = wxHTML_ALIGN_LEFT;
5526e819 199 m_tmpLastWasSpace = FALSE;
b6d93b26 200 m_lastWordCell = NULL;
5526e819
VS
201
202 OpenContainer();
5526e819 203 OpenContainer();
2b5f62a0 204
fa2f5d3b 205#if !wxUSE_UNICODE
2b5f62a0
VZ
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
4f9297b0 215 m_Container->InsertCell(new wxHtmlColourCell(m_ActualColor));
44d0c580 216 wxColour windowColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) ;
eb6a4098 217 m_Container->InsertCell(
3403ccd5
RD
218 new wxHtmlColourCell(GetWindow() ?
219 GetWindow()->GetBackgroundColour() :
44d0c580 220 windowColour,
eb6a4098 221 wxHTML_CLR_BACKGROUND));
4f9297b0 222 m_Container->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
5526e819
VS
223}
224
5526e819
VS
225void wxHtmlWinParser::DoneParser()
226{
227 m_Container = NULL;
2b5f62a0
VZ
228#if !wxUSE_UNICODE
229 SetInputEncoding(wxFONTENCODING_ISO8859_1); // for next call
230#endif
5526e819
VS
231 wxHtmlParser::DoneParser();
232}
233
5526e819
VS
234wxObject* wxHtmlWinParser::GetProduct()
235{
236 wxHtmlContainerCell *top;
237
238 CloseContainer();
239 OpenContainer();
67cfebc2 240
5526e819 241 top = m_Container;
4f9297b0 242 while (top->GetParent()) top = top->GetParent();
ace0fab4
VS
243 top->RemoveExtraSpacing(true, true);
244
5526e819
VS
245 return top;
246}
247
0423bdc7 248wxFSFile *wxHtmlWinParser::OpenURL(wxHtmlURLType type,
6cc4e6b8 249 const wxString& url) const
04db5c3f
VS
250{
251 // FIXME - normalize the URL to full path before passing to
252 // OnOpeningURL!!
253 if ( m_Window )
6cc4e6b8 254 {
6cc4e6b8
VS
255 wxString myurl(url);
256 wxHtmlOpeningStatus status;
257 for (;;)
258 {
0423bdc7
VZ
259 wxString redirect;
260 status = m_Window->OnOpeningURL(type, myurl, &redirect);
261 if ( status != wxHTML_REDIRECT )
6cc4e6b8 262 break;
0423bdc7
VZ
263
264 myurl = redirect;
6cc4e6b8 265 }
0423bdc7 266
6cc4e6b8
VS
267 if ( status == wxHTML_BLOCK )
268 return NULL;
2c892c0b
VZ
269
270 return GetFS()->OpenFile(myurl);
6cc4e6b8 271 }
2c892c0b
VZ
272
273 return wxHtmlParser::OpenURL(type, url);
04db5c3f 274}
5526e819 275
211dfedd 276void wxHtmlWinParser::AddText(const wxChar* txt)
5526e819
VS
277{
278 wxHtmlCell *c;
e3c7fd79
VZ
279 size_t i = 0,
280 x,
281 lng = wxStrlen(txt);
211dfedd 282 register wxChar d;
5526e819 283 int templen = 0;
f23e92e7 284 wxChar nbsp = GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
211dfedd
VS
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;
3c8c8da2
VZ
293
294 if (m_tmpLastWasSpace)
4f9297b0 295 {
3c8c8da2
VZ
296 while ((i < lng) &&
297 ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) || (txt[i] == wxT(' ')) ||
211dfedd 298 (txt[i] == wxT('\t')))) i++;
5526e819
VS
299 }
300
3c8c8da2 301 while (i < lng)
4f9297b0 302 {
5526e819
VS
303 x = 0;
304 d = temp[templen++] = txt[i];
3c8c8da2 305 if ((d == wxT('\n')) || (d == wxT('\r')) || (d == wxT(' ')) || (d == wxT('\t')))
e3c7fd79 306 {
5526e819 307 i++, x++;
3c8c8da2 308 while ((i < lng) && ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) ||
211dfedd 309 (txt[i] == wxT(' ')) || (txt[i] == wxT('\t')))) i++, x++;
5526e819
VS
310 }
311 else i++;
312
3c8c8da2 313 if (x)
e3c7fd79 314 {
211dfedd 315 temp[templen-1] = wxT(' ');
5526e819
VS
316 temp[templen] = 0;
317 templen = 0;
2b5f62a0 318#if !wxUSE_UNICODE
3c8c8da2 319 if (m_EncConv)
daa616fc 320 m_EncConv->Convert(temp);
2b5f62a0 321#endif
88dcf47c 322 size_t len = wxStrlen(temp);
f23e92e7 323 for (size_t j = 0; j < len; j++)
88dcf47c
VS
324 if (temp[j] == nbsp)
325 temp[j] = wxT(' ');
326 c = new wxHtmlWordCell(temp, *(GetDC()));
3c8c8da2 327 if (m_UseLink)
daa616fc 328 c->SetLink(m_Link);
4f9297b0 329 m_Container->InsertCell(c);
b6d93b26
VS
330 ((wxHtmlWordCell*)c)->SetPreviousWord(m_lastWordCell);
331 m_lastWordCell = (wxHtmlWordCell*)c;
5526e819
VS
332 m_tmpLastWasSpace = TRUE;
333 }
334 }
af035b26
VS
335
336 if (templen && (templen > 1 || temp[0] != wxT(' ')))
4f9297b0 337 {
5526e819 338 temp[templen] = 0;
2b5f62a0 339#if !wxUSE_UNICODE
3c8c8da2 340 if (m_EncConv)
daa616fc 341 m_EncConv->Convert(temp);
2b5f62a0 342#endif
88dcf47c 343 size_t len = wxStrlen(temp);
f23e92e7 344 for (size_t j = 0; j < len; j++)
88dcf47c
VS
345 if (temp[j] == nbsp)
346 temp[j] = wxT(' ');
347 c = new wxHtmlWordCell(temp, *(GetDC()));
211dfedd 348 if (m_UseLink)
daa616fc 349 c->SetLink(m_Link);
4f9297b0 350 m_Container->InsertCell(c);
b6d93b26
VS
351 ((wxHtmlWordCell*)c)->SetPreviousWord(m_lastWordCell);
352 m_lastWordCell = (wxHtmlWordCell*)c;
5526e819
VS
353 m_tmpLastWasSpace = FALSE;
354 }
355}
356
357
358
359wxHtmlContainerCell* wxHtmlWinParser::OpenContainer()
360{
361 m_Container = new wxHtmlContainerCell(m_Container);
4f9297b0 362 m_Container->SetAlignHor(m_Align);
5526e819
VS
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{
4f9297b0 381 m_Container = m_Container->GetParent();
5526e819
VS
382 return m_Container;
383}
384
385
f2c2fa4d
VS
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
5526e819
VS
395wxFont* wxHtmlWinParser::CreateCurrentFont()
396{
397 int fb = GetFontBold(),
398 fi = GetFontItalic(),
399 fu = GetFontUnderlined(),
400 ff = GetFontFixed(),
f2c2fa4d 401 fs = GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
5526e819 402
f1ad10f3
VS
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]);
2b5f62a0 406#if !wxUSE_UNICODE
b250d384 407 wxFontEncoding *encptr = &(m_FontsEncTable[fb][fi][fu][ff][fs]);
2b5f62a0 408#endif
f1ad10f3 409
2b5f62a0
VZ
410 if (*fontptr != NULL && (*faceptr != face
411#if !wxUSE_UNICODE
412 || *encptr != m_OutputEnc
413#endif
414 ))
4f9297b0 415 {
f1ad10f3
VS
416 delete *fontptr;
417 *fontptr = NULL;
418 }
419
3c8c8da2 420 if (*fontptr == NULL)
4f9297b0 421 {
f1ad10f3
VS
422 *faceptr = face;
423 *fontptr = new wxFont(
7a5e6267 424 (int) (m_FontsSizes[fs] * m_PixelScale),
f1ad10f3
VS
425 ff ? wxMODERN : wxSWISS,
426 fi ? wxITALIC : wxNORMAL,
427 fb ? wxBOLD : wxNORMAL,
2b5f62a0
VZ
428 fu ? TRUE : FALSE, face
429#if wxUSE_UNICODE
430 );
431#else
432 , m_OutputEnc);
433 *encptr = m_OutputEnc;
434#endif
5526e819 435 }
4f9297b0 436 m_DC->SetFont(**fontptr);
f1ad10f3 437 return (*fontptr);
5526e819
VS
438}
439
440
441
f2c2fa4d
VS
442void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo& link)
443{
3c8c8da2 444 m_Link = link;
f2c2fa4d
VS
445 m_UseLink = (link.GetHref() != wxEmptyString);
446}
447
448
3c8c8da2 449void wxHtmlWinParser::SetFontFace(const wxString& face)
b250d384 450{
3c8c8da2 451 if (GetFontFixed()) m_FontFaceFixed = face;
b250d384
VS
452 else m_FontFaceNormal = face;
453
2b5f62a0 454#if !wxUSE_UNICODE
b250d384
VS
455 if (m_InputEnc != wxFONTENCODING_DEFAULT)
456 SetInputEncoding(m_InputEnc);
2b5f62a0 457#endif
b250d384
VS
458}
459
460
461
2b5f62a0 462#if !wxUSE_UNICODE
b250d384
VS
463void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc)
464{
465 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
3c8c8da2 466 if (m_EncConv)
daa616fc 467 {
3c8c8da2 468 delete m_EncConv;
daa616fc
VS
469 m_EncConv = NULL;
470 }
b250d384
VS
471
472 if (enc == wxFONTENCODING_DEFAULT) return;
473
474 wxFontEncoding altfix, altnorm;
475 bool availfix, availnorm;
3c8c8da2
VZ
476
477 // exact match?
142b3bc2
VS
478 availnorm = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceNormal);
479 availfix = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceFixed);
3c8c8da2 480 if (availnorm && availfix)
b250d384 481 m_OutputEnc = enc;
3c8c8da2 482
b250d384 483 // alternatives?
142b3bc2
VS
484 else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, FALSE) &&
485 wxFontMapper::Get()->GetAltForEncoding(enc, &altfix, m_FontFaceFixed, FALSE) &&
b250d384
VS
486 altnorm == altfix)
487 m_OutputEnc = altnorm;
3c8c8da2 488
b250d384
VS
489 // at least normal face?
490 else if (availnorm)
491 m_OutputEnc = enc;
142b3bc2 492 else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, FALSE))
b250d384 493 m_OutputEnc = altnorm;
3c8c8da2 494
b250d384 495 else
c83e1237
SC
496 {
497#ifndef __WXMAC__
498 // okay, let convert to ISO_8859-1, available always
b250d384 499 m_OutputEnc = wxFONTENCODING_DEFAULT;
90548138 500#else
c83e1237 501 m_OutputEnc = wxLocale::GetSystemEncoding() ;
90548138 502#endif
c83e1237 503 }
3c8c8da2 504
b250d384 505 m_InputEnc = enc;
daa616fc
VS
506 if (m_OutputEnc == wxFONTENCODING_DEFAULT)
507 GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM);
508 else
509 GetEntitiesParser()->SetEncoding(m_OutputEnc);
3c8c8da2 510
b250d384
VS
511 if (m_InputEnc == m_OutputEnc) return;
512
513 m_EncConv = new wxEncodingConverter();
3c8c8da2 514 if (!m_EncConv->Init(m_InputEnc,
b250d384
VS
515 (m_OutputEnc == wxFONTENCODING_DEFAULT) ?
516 wxFONTENCODING_ISO8859_1 : m_OutputEnc,
3c8c8da2 517 wxCONVERT_SUBSTITUTE))
b250d384 518 { // total failture :-(
3c8c8da2
VZ
519 wxLogError(_("Failed to display HTML document in %s encoding"),
520 wxFontMapper::GetEncodingName(enc).c_str());
b250d384
VS
521 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
522 delete m_EncConv;
523 m_EncConv = NULL;
524 }
525}
2b5f62a0 526#endif
b250d384
VS
527
528
f2c2fa4d 529
5526e819
VS
530
531//-----------------------------------------------------------------------------
532// wxHtmlWinTagHandler
533//-----------------------------------------------------------------------------
534
535IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler, wxHtmlTagHandler)
536
5526e819
VS
537//-----------------------------------------------------------------------------
538// wxHtmlTagsModule
539//-----------------------------------------------------------------------------
540
d6a6d666
VS
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!
5526e819
VS
547
548IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule, wxModule)
549
5526e819
VS
550bool wxHtmlTagsModule::OnInit()
551{
552 wxHtmlWinParser::AddModule(this);
553 return TRUE;
554}
555
5526e819
VS
556void wxHtmlTagsModule::OnExit()
557{
f6bcfd97 558 wxHtmlWinParser::RemoveModule(this);
5526e819 559}
d6a6d666 560
223d09f6 561#endif
5526e819 562