]> git.saurik.com Git - wxWidgets.git/blob - src/html/winpars.cpp
Corrected assertion
[wxWidgets.git] / src / html / winpars.cpp
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 #ifdef __GNUG__
12 #pragma implementation
13 #endif
14
15 #include "wx/wxprec.h"
16
17 #include "wx/defs.h"
18 #if wxUSE_HTML && wxUSE_STREAMS
19
20 #ifdef __BORDLANDC__
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
35
36 //-----------------------------------------------------------------------------
37 // wxHtmlWinParser
38 //-----------------------------------------------------------------------------
39
40
41 wxList wxHtmlWinParser::m_Modules;
42
43 wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow *wnd) : wxHtmlParser()
44 {
45 m_tmpStrBuf = NULL;
46 m_tmpStrBufSize = 0;
47 m_Window = wnd;
48 m_Container = NULL;
49 m_DC = NULL;
50 m_CharHeight = m_CharWidth = 0;
51 m_UseLink = FALSE;
52 m_EncConv = NULL;
53 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
54
55 {
56 int i, j, k, l, m;
57 for (i = 0; i < 2; i++)
58 for (j = 0; j < 2; j++)
59 for (k = 0; k < 2; k++)
60 for (l = 0; l < 2; l++)
61 for (m = 0; m < 7; m++)
62 {
63 m_FontsTable[i][j][k][l][m] = NULL;
64 m_FontsFacesTable[i][j][k][l][m] = wxEmptyString;
65 m_FontsEncTable[i][j][k][l][m] = wxFONTENCODING_DEFAULT;
66 }
67 #ifdef __WXMSW__
68 static int default_sizes[7] = {7, 8, 10, 12, 16, 22, 30};
69 #elif defined(__WXMAC__)
70 static int default_sizes[7] = {9, 12, 14, 18, 24, 30, 36};
71 #else
72 static int default_sizes[7] = {10, 12, 14, 16, 19, 24, 32};
73 #endif
74 SetFonts("", "", default_sizes);
75 }
76
77 // fill in wxHtmlParser's tables:
78 wxNode *node = m_Modules.GetFirst();
79 while (node)
80 {
81 wxHtmlTagsModule *mod = (wxHtmlTagsModule*) node->GetData();
82 mod->FillHandlersTable(this);
83 node = node->GetNext();
84 }
85 }
86
87 wxHtmlWinParser::~wxHtmlWinParser()
88 {
89 int i, j, k, l, m;
90
91 for (i = 0; i < 2; i++)
92 for (j = 0; j < 2; j++)
93 for (k = 0; k < 2; k++)
94 for (l = 0; l < 2; l++)
95 for (m = 0; m < 7; m++)
96 {
97 if (m_FontsTable[i][j][k][l][m] != NULL)
98 delete m_FontsTable[i][j][k][l][m];
99 }
100 delete m_EncConv;
101 delete[] m_tmpStrBuf;
102 }
103
104 void wxHtmlWinParser::AddModule(wxHtmlTagsModule *module)
105 {
106 m_Modules.Append(module);
107 }
108
109 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule *module)
110 {
111 m_Modules.DeleteObject(module);
112 }
113
114 void wxHtmlWinParser::SetFonts(wxString normal_face, wxString fixed_face, const int *sizes)
115 {
116 int i, j, k, l, m;
117
118 for (i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
119 m_FontFaceFixed = fixed_face;
120 m_FontFaceNormal = normal_face;
121
122 SetInputEncoding(m_InputEnc);
123
124 for (i = 0; i < 2; i++)
125 for (j = 0; j < 2; j++)
126 for (k = 0; k < 2; k++)
127 for (l = 0; l < 2; l++)
128 for (m = 0; m < 7; m++) {
129 if (m_FontsTable[i][j][k][l][m] != NULL)
130 {
131 delete m_FontsTable[i][j][k][l][m];
132 m_FontsTable[i][j][k][l][m] = NULL;
133 }
134 }
135 }
136
137 void wxHtmlWinParser::InitParser(const wxString& source)
138 {
139 wxHtmlParser::InitParser(source);
140 wxASSERT_MSG(m_DC != NULL, _T("no DC assigned to wxHtmlWinParser!!"));
141
142 m_FontBold = m_FontItalic = m_FontUnderlined = m_FontFixed = FALSE;
143 m_FontSize = 3; //default one
144 CreateCurrentFont(); // we're selecting default font into
145 m_DC->GetTextExtent("H", &m_CharWidth, &m_CharHeight);
146 /* NOTE : we're not using GetCharWidth/Height() because
147 of differences under X and win
148 */
149
150 m_UseLink = FALSE;
151 m_Link = wxHtmlLinkInfo("", "");
152 m_LinkColor.Set(0, 0, 0xFF);
153 m_ActualColor.Set(0, 0, 0);
154 m_Align = wxHTML_ALIGN_LEFT;
155 m_tmpLastWasSpace = FALSE;
156
157 OpenContainer();
158
159 OpenContainer();
160 m_Container->InsertCell(new wxHtmlColourCell(m_ActualColor));
161 m_Container->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
162 }
163
164 void wxHtmlWinParser::DoneParser()
165 {
166 m_Container = NULL;
167 SetInputEncoding(wxFONTENCODING_DEFAULT); // for next call
168 wxHtmlParser::DoneParser();
169 }
170
171 wxObject* wxHtmlWinParser::GetProduct()
172 {
173 wxHtmlContainerCell *top;
174
175 CloseContainer();
176 OpenContainer();
177
178 top = m_Container;
179 while (top->GetParent()) top = top->GetParent();
180 return top;
181 }
182
183 wxFSFile *wxHtmlWinParser::OpenURL(wxHtmlURLType type,
184 const wxString& url) const
185 {
186 // FIXME - normalize the URL to full path before passing to
187 // OnOpeningURL!!
188 if ( m_Window )
189 {
190 wxString myurl(url);
191 wxHtmlOpeningStatus status;
192 for (;;)
193 {
194 wxString redirect;
195 status = m_Window->OnOpeningURL(type, myurl, &redirect);
196 if ( status != wxHTML_REDIRECT )
197 break;
198
199 myurl = redirect;
200 }
201
202 if ( status == wxHTML_BLOCK )
203 return NULL;
204
205 return GetFS()->OpenFile(myurl);
206 }
207
208 return wxHtmlParser::OpenURL(type, url);
209 }
210
211 void wxHtmlWinParser::AddText(const wxChar* txt)
212 {
213 wxHtmlCell *c;
214 size_t i = 0,
215 x,
216 lng = wxStrlen(txt);
217 register wxChar d;
218 int templen = 0;
219 wxChar nbsp = GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
220
221 if (lng+1 > m_tmpStrBufSize)
222 {
223 delete[] m_tmpStrBuf;
224 m_tmpStrBuf = new wxChar[lng+1];
225 m_tmpStrBufSize = lng+1;
226 }
227 wxChar *temp = m_tmpStrBuf;
228
229 if (m_tmpLastWasSpace)
230 {
231 while ((i < lng) &&
232 ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) || (txt[i] == wxT(' ')) ||
233 (txt[i] == wxT('\t')))) i++;
234 }
235
236 while (i < lng)
237 {
238 x = 0;
239 d = temp[templen++] = txt[i];
240 if ((d == wxT('\n')) || (d == wxT('\r')) || (d == wxT(' ')) || (d == wxT('\t')))
241 {
242 i++, x++;
243 while ((i < lng) && ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) ||
244 (txt[i] == wxT(' ')) || (txt[i] == wxT('\t')))) i++, x++;
245 }
246 else i++;
247
248 if (x)
249 {
250 temp[templen-1] = wxT(' ');
251 temp[templen] = 0;
252 if (templen == 1) continue;
253 templen = 0;
254 if (m_EncConv)
255 m_EncConv->Convert(temp);
256 size_t len = wxStrlen(temp);
257 for (size_t j = 0; j < len; j++)
258 if (temp[j] == nbsp)
259 temp[j] = wxT(' ');
260 c = new wxHtmlWordCell(temp, *(GetDC()));
261 if (m_UseLink)
262 c->SetLink(m_Link);
263 m_Container->InsertCell(c);
264 m_tmpLastWasSpace = TRUE;
265 }
266 }
267
268 if (templen && (templen > 1 || temp[0] != wxT(' ')))
269 {
270 temp[templen] = 0;
271 if (m_EncConv)
272 m_EncConv->Convert(temp);
273 size_t len = wxStrlen(temp);
274 for (size_t j = 0; j < len; j++)
275 if (temp[j] == nbsp)
276 temp[j] = wxT(' ');
277 c = new wxHtmlWordCell(temp, *(GetDC()));
278 if (m_UseLink)
279 c->SetLink(m_Link);
280 m_Container->InsertCell(c);
281 m_tmpLastWasSpace = FALSE;
282 }
283 }
284
285
286
287 wxHtmlContainerCell* wxHtmlWinParser::OpenContainer()
288 {
289 m_Container = new wxHtmlContainerCell(m_Container);
290 m_Container->SetAlignHor(m_Align);
291 m_tmpLastWasSpace = TRUE;
292 /* to avoid space being first character in paragraph */
293 return m_Container;
294 }
295
296
297
298 wxHtmlContainerCell* wxHtmlWinParser::SetContainer(wxHtmlContainerCell *c)
299 {
300 m_tmpLastWasSpace = TRUE;
301 /* to avoid space being first character in paragraph */
302 return m_Container = c;
303 }
304
305
306
307 wxHtmlContainerCell* wxHtmlWinParser::CloseContainer()
308 {
309 m_Container = m_Container->GetParent();
310 return m_Container;
311 }
312
313
314 void wxHtmlWinParser::SetFontSize(int s)
315 {
316 if (s < 1) s = 1;
317 else if (s > 7) s = 7;
318 m_FontSize = s;
319 }
320
321
322
323 wxFont* wxHtmlWinParser::CreateCurrentFont()
324 {
325 int fb = GetFontBold(),
326 fi = GetFontItalic(),
327 fu = GetFontUnderlined(),
328 ff = GetFontFixed(),
329 fs = GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
330
331 wxString face = ff ? m_FontFaceFixed : m_FontFaceNormal;
332 wxString *faceptr = &(m_FontsFacesTable[fb][fi][fu][ff][fs]);
333 wxFont **fontptr = &(m_FontsTable[fb][fi][fu][ff][fs]);
334 wxFontEncoding *encptr = &(m_FontsEncTable[fb][fi][fu][ff][fs]);
335
336 if (*fontptr != NULL && (*faceptr != face || *encptr != m_OutputEnc))
337 {
338 delete *fontptr;
339 *fontptr = NULL;
340 }
341
342 if (*fontptr == NULL)
343 {
344 *faceptr = face;
345 *encptr = m_OutputEnc;
346 *fontptr = new wxFont(
347 (int) (m_FontsSizes[fs] * m_PixelScale),
348 ff ? wxMODERN : wxSWISS,
349 fi ? wxITALIC : wxNORMAL,
350 fb ? wxBOLD : wxNORMAL,
351 fu ? TRUE : FALSE, face,
352 m_OutputEnc);
353 }
354 m_DC->SetFont(**fontptr);
355 return (*fontptr);
356 }
357
358
359
360 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo& link)
361 {
362 m_Link = link;
363 m_UseLink = (link.GetHref() != wxEmptyString);
364 }
365
366
367 void wxHtmlWinParser::SetFontFace(const wxString& face)
368 {
369 if (GetFontFixed()) m_FontFaceFixed = face;
370 else m_FontFaceNormal = face;
371
372 if (m_InputEnc != wxFONTENCODING_DEFAULT)
373 SetInputEncoding(m_InputEnc);
374 }
375
376
377
378 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc)
379 {
380 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
381 if (m_EncConv)
382 {
383 delete m_EncConv;
384 m_EncConv = NULL;
385 }
386
387 if (enc == wxFONTENCODING_DEFAULT) return;
388
389 wxFontEncoding altfix, altnorm;
390 bool availfix, availnorm;
391
392 // exact match?
393 availnorm = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceNormal);
394 availfix = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceFixed);
395 if (availnorm && availfix)
396 m_OutputEnc = enc;
397
398 // alternatives?
399 else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, FALSE) &&
400 wxFontMapper::Get()->GetAltForEncoding(enc, &altfix, m_FontFaceFixed, FALSE) &&
401 altnorm == altfix)
402 m_OutputEnc = altnorm;
403
404 // at least normal face?
405 else if (availnorm)
406 m_OutputEnc = enc;
407 else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, FALSE))
408 m_OutputEnc = altnorm;
409
410 // okay, let convert to ISO_8859-1, available always
411 else
412 m_OutputEnc = wxFONTENCODING_DEFAULT;
413
414 m_InputEnc = enc;
415 if (m_OutputEnc == wxFONTENCODING_DEFAULT)
416 GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM);
417 else
418 GetEntitiesParser()->SetEncoding(m_OutputEnc);
419
420 if (m_InputEnc == m_OutputEnc) return;
421
422 m_EncConv = new wxEncodingConverter();
423 if (!m_EncConv->Init(m_InputEnc,
424 (m_OutputEnc == wxFONTENCODING_DEFAULT) ?
425 wxFONTENCODING_ISO8859_1 : m_OutputEnc,
426 wxCONVERT_SUBSTITUTE))
427 { // total failture :-(
428 wxLogError(_("Failed to display HTML document in %s encoding"),
429 wxFontMapper::GetEncodingName(enc).c_str());
430 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
431 delete m_EncConv;
432 m_EncConv = NULL;
433 }
434 }
435
436
437
438
439
440 //-----------------------------------------------------------------------------
441 // wxHtmlWinTagHandler
442 //-----------------------------------------------------------------------------
443
444 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler, wxHtmlTagHandler)
445
446 //-----------------------------------------------------------------------------
447 // wxHtmlTagsModule
448 //-----------------------------------------------------------------------------
449
450 // NB: This is *NOT* winpars.cpp's initialization and shutdown code!!
451 // This module is an ancestor for tag handlers modules defined
452 // in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct.
453 //
454 // Do not add any winpars.cpp shutdown or initialization code to it,
455 // create a new module instead!
456
457 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule, wxModule)
458
459 bool wxHtmlTagsModule::OnInit()
460 {
461 wxHtmlWinParser::AddModule(this);
462 return TRUE;
463 }
464
465 void wxHtmlTagsModule::OnExit()
466 {
467 wxHtmlWinParser::RemoveModule(this);
468 }
469
470 #endif
471