Fixed some warnings (don't know why dialoged Makefile is being committed)
[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/wx.h"
26 #endif
27
28 #include "wx/html/htmldefs.h"
29 #include "wx/html/winpars.h"
30 #include "wx/html/htmlwin.h"
31 #include "wx/fontmap.h"
32 #include "wx/log.h"
33
34
35 //-----------------------------------------------------------------------------
36 // wxHtmlWinParser
37 //-----------------------------------------------------------------------------
38
39
40 wxList wxHtmlWinParser::m_Modules;
41
42 wxHtmlWinParser::wxHtmlWinParser(wxWindow *wnd) : wxHtmlParser()
43 {
44 m_Window = wnd;
45 m_Container = NULL;
46 m_DC = NULL;
47 m_CharHeight = m_CharWidth = 0;
48 m_UseLink = FALSE;
49 m_EncConv = NULL;
50 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
51
52 {
53 int i, j, k, l, m;
54 for (i = 0; i < 2; i++)
55 for (j = 0; j < 2; j++)
56 for (k = 0; k < 2; k++)
57 for (l = 0; l < 2; l++)
58 for (m = 0; m < 7; m++)
59 {
60 m_FontsTable[i][j][k][l][m] = NULL;
61 m_FontsFacesTable[i][j][k][l][m] = wxEmptyString;
62 m_FontsEncTable[i][j][k][l][m] = wxFONTENCODING_DEFAULT;
63 }
64 #ifdef __WXMSW__
65 static int default_sizes[7] = {7, 8, 10, 12, 16, 22, 30};
66 #elif defined(__WXMAC__)
67 static int default_sizes[7] = {9, 12, 14, 18, 24, 30, 36};
68 #else
69 static int default_sizes[7] = {10, 12, 14, 16, 19, 24, 32};
70 #endif
71 SetFonts("", "", default_sizes);
72 }
73
74 // fill in wxHtmlParser's tables:
75 wxNode *node = m_Modules.GetFirst();
76 while (node)
77 {
78 wxHtmlTagsModule *mod = (wxHtmlTagsModule*) node->GetData();
79 mod->FillHandlersTable(this);
80 node = node->GetNext();
81 }
82 }
83
84
85 wxHtmlWinParser::~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 (m_EncConv) delete m_EncConv;
99 }
100
101
102 void wxHtmlWinParser::AddModule(wxHtmlTagsModule *module)
103 {
104 m_Modules.Append(module);
105 }
106
107
108
109 void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule *module)
110 {
111 m_Modules.DeleteObject(module);
112 }
113
114
115
116 void wxHtmlWinParser::SetFonts(wxString normal_face, wxString fixed_face, const int *sizes)
117 {
118 int i, j, k, l, m;
119
120 for (i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
121 m_FontFaceFixed = fixed_face;
122 m_FontFaceNormal = normal_face;
123
124 SetInputEncoding(m_InputEnc);
125
126 for (i = 0; i < 2; i++)
127 for (j = 0; j < 2; j++)
128 for (k = 0; k < 2; k++)
129 for (l = 0; l < 2; l++)
130 for (m = 0; m < 7; m++) {
131 if (m_FontsTable[i][j][k][l][m] != NULL)
132 {
133 delete m_FontsTable[i][j][k][l][m];
134 m_FontsTable[i][j][k][l][m] = NULL;
135 }
136 }
137 }
138
139
140
141 void wxHtmlWinParser::InitParser(const wxString& source)
142 {
143 wxHtmlParser::InitParser(source);
144 wxASSERT_MSG(m_DC != NULL, _T("no DC assigned to wxHtmlWinParser!!"));
145
146 m_FontBold = m_FontItalic = m_FontUnderlined = m_FontFixed = FALSE;
147 m_FontSize = 3; //default one
148 CreateCurrentFont(); // we're selecting default font into
149 m_DC->GetTextExtent("H", &m_CharWidth, &m_CharHeight);
150 /* NOTE : we're not using GetCharWidth/Height() because
151 of differences under X and win
152 */
153
154 m_UseLink = FALSE;
155 m_Link = wxHtmlLinkInfo("", "");
156 m_LinkColor.Set(0, 0, 0xFF);
157 m_ActualColor.Set(0, 0, 0);
158 m_Align = wxHTML_ALIGN_LEFT;
159 m_tmpLastWasSpace = FALSE;
160
161 OpenContainer();
162
163 OpenContainer();
164 m_Container->InsertCell(new wxHtmlColourCell(m_ActualColor));
165 m_Container->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
166 }
167
168
169
170 void wxHtmlWinParser::DoneParser()
171 {
172 m_Container = NULL;
173 SetInputEncoding(wxFONTENCODING_DEFAULT); // for next call
174 wxHtmlParser::DoneParser();
175 }
176
177
178
179 wxObject* wxHtmlWinParser::GetProduct()
180 {
181 wxHtmlContainerCell *top;
182
183 CloseContainer();
184 OpenContainer();
185
186 top = m_Container;
187 while (top->GetParent()) top = top->GetParent();
188 return top;
189 }
190
191
192
193 void wxHtmlWinParser::AddText(const char* txt)
194 {
195 wxHtmlCell *c;
196 int i = 0, x, lng = strlen(txt);
197 char temp[wxHTML_BUFLEN];
198 register char d;
199 int templen = 0;
200
201 if (m_tmpLastWasSpace)
202 {
203 while ((i < lng) && ((txt[i] == '\n') || (txt[i] == '\r') || (txt[i] == ' ') || (txt[i] == '\t'))) i++;
204 }
205
206 while (i < lng)
207 {
208 x = 0;
209 d = temp[templen++] = txt[i];
210 if ((d == '\n') || (d == '\r') || (d == ' ') || (d == '\t'))
211 {
212 i++, x++;
213 while ((i < lng) && ((txt[i] == '\n') || (txt[i] == '\r') || (txt[i] == ' ') || (txt[i] == '\t'))) i++, x++;
214 }
215 else i++;
216
217 if (x)
218 {
219 temp[templen-1] = ' ';
220 temp[templen] = 0;
221 templen = 0;
222 if (m_EncConv) m_EncConv->Convert(temp);
223 c = new wxHtmlWordCell(temp, *(GetDC()));
224 if (m_UseLink) c->SetLink(m_Link);
225 m_Container->InsertCell(c);
226 m_tmpLastWasSpace = TRUE;
227 }
228 }
229 if (templen)
230 {
231 temp[templen] = 0;
232 if (m_EncConv) m_EncConv->Convert(temp);
233 c = new wxHtmlWordCell(temp, *(GetDC()));
234 if (m_UseLink) c->SetLink(m_Link);
235 m_Container->InsertCell(c);
236 m_tmpLastWasSpace = FALSE;
237 }
238 }
239
240
241
242 wxHtmlContainerCell* wxHtmlWinParser::OpenContainer()
243 {
244 m_Container = new wxHtmlContainerCell(m_Container);
245 m_Container->SetAlignHor(m_Align);
246 m_tmpLastWasSpace = TRUE;
247 /* to avoid space being first character in paragraph */
248 return m_Container;
249 }
250
251
252
253 wxHtmlContainerCell* wxHtmlWinParser::SetContainer(wxHtmlContainerCell *c)
254 {
255 m_tmpLastWasSpace = TRUE;
256 /* to avoid space being first character in paragraph */
257 return m_Container = c;
258 }
259
260
261
262 wxHtmlContainerCell* wxHtmlWinParser::CloseContainer()
263 {
264 m_Container = m_Container->GetParent();
265 return m_Container;
266 }
267
268
269 void wxHtmlWinParser::SetFontSize(int s)
270 {
271 if (s < 1) s = 1;
272 else if (s > 7) s = 7;
273 m_FontSize = s;
274 }
275
276
277
278 wxFont* wxHtmlWinParser::CreateCurrentFont()
279 {
280 int fb = GetFontBold(),
281 fi = GetFontItalic(),
282 fu = GetFontUnderlined(),
283 ff = GetFontFixed(),
284 fs = GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
285
286 wxString face = ff ? m_FontFaceFixed : m_FontFaceNormal;
287 wxString *faceptr = &(m_FontsFacesTable[fb][fi][fu][ff][fs]);
288 wxFont **fontptr = &(m_FontsTable[fb][fi][fu][ff][fs]);
289 wxFontEncoding *encptr = &(m_FontsEncTable[fb][fi][fu][ff][fs]);
290
291 if (*fontptr != NULL && (*faceptr != face || *encptr != m_OutputEnc))
292 {
293 delete *fontptr;
294 *fontptr = NULL;
295 }
296
297 if (*fontptr == NULL)
298 {
299 *faceptr = face;
300 *encptr = m_OutputEnc;
301 *fontptr = new wxFont(
302 (int) (m_FontsSizes[fs] * m_PixelScale),
303 ff ? wxMODERN : wxSWISS,
304 fi ? wxITALIC : wxNORMAL,
305 fb ? wxBOLD : wxNORMAL,
306 fu ? TRUE : FALSE, face,
307 m_OutputEnc);
308 }
309 m_DC->SetFont(**fontptr);
310 return (*fontptr);
311 }
312
313
314
315 void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo& link)
316 {
317 m_Link = link;
318 m_UseLink = (link.GetHref() != wxEmptyString);
319 }
320
321
322 void wxHtmlWinParser::SetFontFace(const wxString& face)
323 {
324 if (GetFontFixed()) m_FontFaceFixed = face;
325 else m_FontFaceNormal = face;
326
327 if (m_InputEnc != wxFONTENCODING_DEFAULT)
328 SetInputEncoding(m_InputEnc);
329 }
330
331
332
333 void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc)
334 {
335 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
336 if (m_EncConv) {delete m_EncConv; m_EncConv = NULL;}
337
338 if (enc == wxFONTENCODING_DEFAULT) return;
339
340 wxFontEncoding altfix, altnorm;
341 bool availfix, availnorm;
342
343 // exact match?
344 availnorm = wxTheFontMapper->IsEncodingAvailable(enc, m_FontFaceNormal);
345 availfix = wxTheFontMapper->IsEncodingAvailable(enc, m_FontFaceFixed);
346 if (availnorm && availfix)
347 m_OutputEnc = enc;
348
349 // alternatives?
350 else if (wxTheFontMapper->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, FALSE) &&
351 wxTheFontMapper->GetAltForEncoding(enc, &altfix, m_FontFaceFixed, FALSE) &&
352 altnorm == altfix)
353 m_OutputEnc = altnorm;
354
355 // at least normal face?
356 else if (availnorm)
357 m_OutputEnc = enc;
358 else if (wxTheFontMapper->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, FALSE))
359 m_OutputEnc = altnorm;
360
361 // okay, let convert to ISO_8859-1, available always
362 else
363 m_OutputEnc = wxFONTENCODING_DEFAULT;
364
365 m_InputEnc = enc;
366
367 if (m_InputEnc == m_OutputEnc) return;
368
369 m_EncConv = new wxEncodingConverter();
370 if (!m_EncConv->Init(m_InputEnc,
371 (m_OutputEnc == wxFONTENCODING_DEFAULT) ?
372 wxFONTENCODING_ISO8859_1 : m_OutputEnc,
373 wxCONVERT_SUBSTITUTE))
374 { // total failture :-(
375 wxLogError(_("Failed to display HTML document in %s encoding"),
376 wxFontMapper::GetEncodingName(enc).c_str());
377 m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
378 delete m_EncConv;
379 m_EncConv = NULL;
380 }
381 }
382
383
384
385
386
387 //-----------------------------------------------------------------------------
388 // wxHtmlWinTagHandler
389 //-----------------------------------------------------------------------------
390
391 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler, wxHtmlTagHandler)
392
393
394
395 //-----------------------------------------------------------------------------
396 // wxHtmlTagsModule
397 //-----------------------------------------------------------------------------
398
399
400 IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule, wxModule)
401
402
403 bool wxHtmlTagsModule::OnInit()
404 {
405 wxHtmlWinParser::AddModule(this);
406 return TRUE;
407 }
408
409
410
411 void wxHtmlTagsModule::OnExit()
412 {
413 wxHtmlWinParser::RemoveModule(this);
414 }
415 #endif
416