wx/wxprec.h already includes wx/defs.h (with other minor cleaning).
[wxWidgets.git] / src / html / htmprint.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/html/htmprint.cpp
3 // Purpose: html printing classes
4 // Author: Vaclav Slavik
5 // Created: 25/09/99
6 // RCS-ID: $Id$
7 // Copyright: (c) Vaclav Slavik, 1999
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #if wxUSE_HTML && wxUSE_PRINTING_ARCHITECTURE && wxUSE_STREAMS
19
20 #ifndef WX_PRECOMP
21 #include "wx/log.h"
22 #include "wx/intl.h"
23 #include "wx/dc.h"
24 #endif
25
26 #include "wx/dc.h"
27 #include "wx/print.h"
28 #include "wx/printdlg.h"
29 #include "wx/html/htmprint.h"
30 #include "wx/wxhtml.h"
31 #include "wx/wfstream.h"
32 #include "wx/module.h"
33 #include "wx/settings.h"
34
35
36 //--------------------------------------------------------------------------------
37 // wxHtmlDCRenderer
38 //--------------------------------------------------------------------------------
39
40
41 wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject()
42 {
43 m_DC = NULL;
44 m_Width = m_Height = 0;
45 m_Cells = NULL;
46 m_Parser = new wxHtmlWinParser();
47 m_FS = new wxFileSystem();
48 m_Parser->SetFS(m_FS);
49 }
50
51
52
53 wxHtmlDCRenderer::~wxHtmlDCRenderer()
54 {
55 if (m_Cells) delete m_Cells;
56 if (m_Parser) delete m_Parser;
57 if (m_FS) delete m_FS;
58 }
59
60
61
62 void wxHtmlDCRenderer::SetDC(wxDC *dc, double pixel_scale)
63 {
64 m_DC = dc;
65 m_Parser->SetDC(m_DC, pixel_scale);
66 }
67
68
69
70 void wxHtmlDCRenderer::SetSize(int width, int height)
71 {
72 m_Width = width;
73 m_Height = height;
74 }
75
76
77 void wxHtmlDCRenderer::SetHtmlText(const wxString& html, const wxString& basepath, bool isdir)
78 {
79 if (m_DC == NULL) return;
80
81 if (m_Cells != NULL) delete m_Cells;
82
83 m_FS->ChangePathTo(basepath, isdir);
84 m_Cells = (wxHtmlContainerCell*) m_Parser->Parse(html);
85 m_Cells->SetIndent(0, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
86 m_Cells->Layout(m_Width);
87 }
88
89
90 void wxHtmlDCRenderer::SetFonts(const wxString& normal_face, const wxString& fixed_face,
91 const int *sizes)
92 {
93 m_Parser->SetFonts(normal_face, fixed_face, sizes);
94 if (m_DC == NULL && m_Cells != NULL)
95 m_Cells->Layout(m_Width);
96 }
97
98 void wxHtmlDCRenderer::SetStandardFonts(int size,
99 const wxString& normal_face,
100 const wxString& fixed_face)
101 {
102 m_Parser->SetStandardFonts(size, normal_face, fixed_face);
103 if (m_DC == NULL && m_Cells != NULL)
104 m_Cells->Layout(m_Width);
105 }
106
107
108 int wxHtmlDCRenderer::Render(int x, int y, int from, int dont_render,
109 int maxHeight,
110 int *known_pagebreaks, int number_of_pages)
111 {
112 int pbreak, hght;
113
114 if (m_Cells == NULL || m_DC == NULL) return 0;
115
116 pbreak = (int)(from + m_Height);
117 while (m_Cells->AdjustPagebreak(&pbreak, known_pagebreaks, number_of_pages)) {}
118 hght = pbreak - from;
119 if (maxHeight < hght)
120 hght = maxHeight;
121
122 if (!dont_render)
123 {
124 wxHtmlRenderingInfo rinfo;
125 wxDefaultHtmlRenderingStyle rstyle;
126 rinfo.SetStyle(&rstyle);
127 m_DC->SetBrush(*wxWHITE_BRUSH);
128 m_DC->SetClippingRegion(x, y, m_Width, hght);
129 m_Cells->Draw(*m_DC,
130 x, (y - from),
131 y, pbreak + (y /*- from*/),
132 rinfo);
133 m_DC->DestroyClippingRegion();
134 }
135
136 if (pbreak < m_Cells->GetHeight()) return pbreak;
137 else return GetTotalHeight();
138 }
139
140
141
142 int wxHtmlDCRenderer::GetTotalHeight()
143 {
144 if (m_Cells) return m_Cells->GetHeight();
145 else return 0;
146 }
147
148
149 //--------------------------------------------------------------------------------
150 // wxHtmlPrintout
151 //--------------------------------------------------------------------------------
152
153
154 wxList wxHtmlPrintout::m_Filters;
155
156 wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title)
157 {
158 m_Renderer = new wxHtmlDCRenderer;
159 m_RendererHdr = new wxHtmlDCRenderer;
160 m_NumPages = wxHTML_PRINT_MAX_PAGES;
161 m_Document = m_BasePath = wxEmptyString; m_BasePathIsDir = true;
162 m_Headers[0] = m_Headers[1] = wxEmptyString;
163 m_Footers[0] = m_Footers[1] = wxEmptyString;
164 m_HeaderHeight = m_FooterHeight = 0;
165 SetMargins(); // to default values
166 }
167
168
169
170 wxHtmlPrintout::~wxHtmlPrintout()
171 {
172 delete m_Renderer;
173 delete m_RendererHdr;
174 }
175
176 void wxHtmlPrintout::CleanUpStatics()
177 {
178 WX_CLEAR_LIST(wxList, m_Filters);
179 }
180
181 // Adds input filter
182 void wxHtmlPrintout::AddFilter(wxHtmlFilter *filter)
183 {
184 m_Filters.Append(filter);
185 }
186
187 void wxHtmlPrintout::OnPreparePrinting()
188 {
189 int pageWidth, pageHeight, mm_w, mm_h, scr_w, scr_h, dc_w, dc_h;
190 float ppmm_h, ppmm_v;
191
192 GetPageSizePixels(&pageWidth, &pageHeight);
193 GetPageSizeMM(&mm_w, &mm_h);
194 ppmm_h = (float)pageWidth / mm_w;
195 ppmm_v = (float)pageHeight / mm_h;
196
197 int ppiPrinterX, ppiPrinterY;
198 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
199 int ppiScreenX, ppiScreenY;
200 GetPPIScreen(&ppiScreenX, &ppiScreenY);
201
202 wxDisplaySize(&scr_w, &scr_h);
203 GetDC()->GetSize(&dc_w, &dc_h);
204
205 GetDC()->SetUserScale((double)dc_w / (double)pageWidth, (double)dc_w / (double)pageWidth);
206
207 /* prepare headers/footers renderer: */
208
209 m_RendererHdr->SetDC(GetDC(), (double)ppiPrinterY / (double)ppiScreenY);
210 m_RendererHdr->SetSize((int) (ppmm_h * (mm_w - m_MarginLeft - m_MarginRight)),
211 (int) (ppmm_v * (mm_h - m_MarginTop - m_MarginBottom)));
212 if (m_Headers[0] != wxEmptyString)
213 {
214 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[0], 1));
215 m_HeaderHeight = m_RendererHdr->GetTotalHeight();
216 }
217 else if (m_Headers[1] != wxEmptyString)
218 {
219 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[1], 1));
220 m_HeaderHeight = m_RendererHdr->GetTotalHeight();
221 }
222 if (m_Footers[0] != wxEmptyString)
223 {
224 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[0], 1));
225 m_FooterHeight = m_RendererHdr->GetTotalHeight();
226 }
227 else if (m_Footers[1] != wxEmptyString)
228 {
229 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[1], 1));
230 m_FooterHeight = m_RendererHdr->GetTotalHeight();
231 }
232
233 /* prepare main renderer: */
234 m_Renderer->SetDC(GetDC(), (double)ppiPrinterY / (double)ppiScreenY);
235 m_Renderer->SetSize((int) (ppmm_h * (mm_w - m_MarginLeft - m_MarginRight)),
236 (int) (ppmm_v * (mm_h - m_MarginTop - m_MarginBottom) -
237 m_FooterHeight - m_HeaderHeight -
238 ((m_HeaderHeight == 0) ? 0 : m_MarginSpace * ppmm_v) -
239 ((m_FooterHeight == 0) ? 0 : m_MarginSpace * ppmm_v)
240 ));
241 m_Renderer->SetHtmlText(m_Document, m_BasePath, m_BasePathIsDir);
242 CountPages();
243 }
244
245 bool wxHtmlPrintout::OnBeginDocument(int startPage, int endPage)
246 {
247 if (!wxPrintout::OnBeginDocument(startPage, endPage)) return false;
248
249 return true;
250 }
251
252
253 bool wxHtmlPrintout::OnPrintPage(int page)
254 {
255 wxDC *dc = GetDC();
256 if (dc)
257 {
258 if (HasPage(page))
259 RenderPage(dc, page);
260 return true;
261 }
262 else return false;
263 }
264
265
266 void wxHtmlPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
267 {
268 *minPage = 1;
269 *maxPage = m_NumPages;
270 *selPageFrom = 1;
271 *selPageTo = m_NumPages;
272 }
273
274
275
276 bool wxHtmlPrintout::HasPage(int pageNum)
277 {
278 return (pageNum >= 1 && pageNum <= m_NumPages);
279 }
280
281
282
283 void wxHtmlPrintout::SetHtmlText(const wxString& html, const wxString &basepath, bool isdir)
284 {
285 m_Document = html;
286 m_BasePath = basepath;
287 m_BasePathIsDir = isdir;
288 }
289
290 void wxHtmlPrintout::SetHtmlFile(const wxString& htmlfile)
291 {
292 wxFileSystem fs;
293 wxFSFile *ff;
294
295 if (wxFileExists(htmlfile))
296 ff = fs.OpenFile(wxFileSystem::FileNameToURL(htmlfile));
297 else
298 ff = fs.OpenFile(htmlfile);
299
300 if (ff == NULL)
301 {
302 wxLogError(htmlfile + _(": file does not exist!"));
303 return;
304 }
305
306 bool done = false;
307 wxHtmlFilterHTML defaultFilter;
308 wxString doc;
309
310 wxList::compatibility_iterator node = m_Filters.GetFirst();
311 while (node)
312 {
313 wxHtmlFilter *h = (wxHtmlFilter*) node->GetData();
314 if (h->CanRead(*ff))
315 {
316 doc = h->ReadFile(*ff);
317 done = true;
318 break;
319 }
320 node = node->GetNext();
321 }
322
323 if (!done)
324 doc = defaultFilter.ReadFile(*ff);
325
326 SetHtmlText(doc, htmlfile, false);
327 delete ff;
328 }
329
330
331
332 void wxHtmlPrintout::SetHeader(const wxString& header, int pg)
333 {
334 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
335 m_Headers[0] = header;
336 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
337 m_Headers[1] = header;
338 }
339
340
341
342 void wxHtmlPrintout::SetFooter(const wxString& footer, int pg)
343 {
344 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
345 m_Footers[0] = footer;
346 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
347 m_Footers[1] = footer;
348 }
349
350
351
352 void wxHtmlPrintout::CountPages()
353 {
354 wxBusyCursor wait;
355 int pageWidth, pageHeight, mm_w, mm_h;
356 float ppmm_h, ppmm_v;
357
358 GetPageSizePixels(&pageWidth, &pageHeight);
359 GetPageSizeMM(&mm_w, &mm_h);
360 ppmm_h = (float)pageWidth / mm_w;
361 ppmm_v = (float)pageHeight / mm_h;
362
363 int pos = 0;
364
365 m_NumPages = 0;
366
367 m_PageBreaks[0] = 0;
368 do
369 {
370 pos = m_Renderer->Render((int)( ppmm_h * m_MarginLeft),
371 (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight),
372 pos, true, INT_MAX, m_PageBreaks, m_NumPages);
373 m_PageBreaks[++m_NumPages] = pos;
374 } while (pos < m_Renderer->GetTotalHeight());
375 }
376
377
378
379 void wxHtmlPrintout::RenderPage(wxDC *dc, int page)
380 {
381 wxBusyCursor wait;
382
383 int pageWidth, pageHeight, mm_w, mm_h, scr_w, scr_h, dc_w, dc_h;
384 float ppmm_h, ppmm_v;
385
386 GetPageSizePixels(&pageWidth, &pageHeight);
387 GetPageSizeMM(&mm_w, &mm_h);
388 ppmm_h = (float)pageWidth / mm_w;
389 ppmm_v = (float)pageHeight / mm_h;
390 wxDisplaySize(&scr_w, &scr_h);
391 dc->GetSize(&dc_w, &dc_h);
392
393 int ppiPrinterX, ppiPrinterY;
394 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
395 wxUnusedVar(ppiPrinterX);
396 int ppiScreenX, ppiScreenY;
397 GetPPIScreen(&ppiScreenX, &ppiScreenY);
398 wxUnusedVar(ppiScreenX);
399
400 dc->SetUserScale((double)dc_w / (double)pageWidth, (double)dc_w / (double)pageWidth);
401
402 m_Renderer->SetDC(dc, (double)ppiPrinterY / (double)ppiScreenY);
403
404 dc->SetBackgroundMode(wxTRANSPARENT);
405
406 m_Renderer->Render((int) (ppmm_h * m_MarginLeft),
407 (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight),
408 m_PageBreaks[page-1], false, m_PageBreaks[page]-m_PageBreaks[page-1]);
409
410 m_RendererHdr->SetDC(dc, (double)ppiPrinterY / (double)ppiScreenY);
411 if (m_Headers[page % 2] != wxEmptyString)
412 {
413 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[page % 2], page));
414 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop));
415 }
416 if (m_Footers[page % 2] != wxEmptyString)
417 {
418 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[page % 2], page));
419 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight));
420 }
421 }
422
423
424
425 wxString wxHtmlPrintout::TranslateHeader(const wxString& instr, int page)
426 {
427 wxString r = instr;
428 wxString num;
429
430 num.Printf(wxT("%i"), page);
431 r.Replace(wxT("@PAGENUM@"), num);
432
433 num.Printf(wxT("%i"), m_NumPages);
434 r.Replace(wxT("@PAGESCNT@"), num);
435
436 return r;
437 }
438
439
440
441 void wxHtmlPrintout::SetMargins(float top, float bottom, float left, float right, float spaces)
442 {
443 m_MarginTop = top;
444 m_MarginBottom = bottom;
445 m_MarginLeft = left;
446 m_MarginRight = right;
447 m_MarginSpace = spaces;
448 }
449
450
451
452
453 void wxHtmlPrintout::SetFonts(const wxString& normal_face, const wxString& fixed_face,
454 const int *sizes)
455 {
456 m_Renderer->SetFonts(normal_face, fixed_face, sizes);
457 m_RendererHdr->SetFonts(normal_face, fixed_face, sizes);
458 }
459
460 void wxHtmlPrintout::SetStandardFonts(int size,
461 const wxString& normal_face,
462 const wxString& fixed_face)
463 {
464 m_Renderer->SetStandardFonts(size, normal_face, fixed_face);
465 m_RendererHdr->SetStandardFonts(size, normal_face, fixed_face);
466 }
467
468
469
470 //----------------------------------------------------------------------------
471 // wxHtmlEasyPrinting
472 //----------------------------------------------------------------------------
473
474
475 wxHtmlEasyPrinting::wxHtmlEasyPrinting(const wxString& name, wxWindow *parentWindow)
476 {
477 m_ParentWindow = parentWindow;
478 m_Name = name;
479 m_PrintData = NULL;
480 m_PageSetupData = new wxPageSetupDialogData;
481 m_Headers[0] = m_Headers[1] = m_Footers[0] = m_Footers[1] = wxEmptyString;
482
483 m_PageSetupData->EnableMargins(true);
484 m_PageSetupData->SetMarginTopLeft(wxPoint(25, 25));
485 m_PageSetupData->SetMarginBottomRight(wxPoint(25, 25));
486
487 SetFonts(wxEmptyString, wxEmptyString, NULL);
488 }
489
490
491
492 wxHtmlEasyPrinting::~wxHtmlEasyPrinting()
493 {
494 delete m_PrintData;
495 delete m_PageSetupData;
496 }
497
498
499 wxPrintData *wxHtmlEasyPrinting::GetPrintData()
500 {
501 if (m_PrintData == NULL)
502 m_PrintData = new wxPrintData();
503 return m_PrintData;
504 }
505
506
507 bool wxHtmlEasyPrinting::PreviewFile(const wxString &htmlfile)
508 {
509 wxHtmlPrintout *p1 = CreatePrintout();
510 p1->SetHtmlFile(htmlfile);
511 wxHtmlPrintout *p2 = CreatePrintout();
512 p2->SetHtmlFile(htmlfile);
513 return DoPreview(p1, p2);
514 }
515
516
517
518 bool wxHtmlEasyPrinting::PreviewText(const wxString &htmltext, const wxString &basepath)
519 {
520 wxHtmlPrintout *p1 = CreatePrintout();
521 p1->SetHtmlText(htmltext, basepath, true);
522 wxHtmlPrintout *p2 = CreatePrintout();
523 p2->SetHtmlText(htmltext, basepath, true);
524 return DoPreview(p1, p2);
525 }
526
527
528
529 bool wxHtmlEasyPrinting::PrintFile(const wxString &htmlfile)
530 {
531 wxHtmlPrintout *p = CreatePrintout();
532 p->SetHtmlFile(htmlfile);
533 bool ret = DoPrint(p);
534 delete p;
535 return ret;
536 }
537
538
539
540 bool wxHtmlEasyPrinting::PrintText(const wxString &htmltext, const wxString &basepath)
541 {
542 wxHtmlPrintout *p = CreatePrintout();
543 p->SetHtmlText(htmltext, basepath, true);
544 bool ret = DoPrint(p);
545 delete p;
546 return ret;
547 }
548
549
550
551 bool wxHtmlEasyPrinting::DoPreview(wxHtmlPrintout *printout1, wxHtmlPrintout *printout2)
552 {
553 // Pass two printout objects: for preview, and possible printing.
554 wxPrintDialogData printDialogData(*GetPrintData());
555 wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData);
556 if (!preview->Ok())
557 {
558 delete preview;
559 return false;
560 }
561
562 wxPreviewFrame *frame = new wxPreviewFrame(preview, m_ParentWindow,
563 m_Name + _(" Preview"),
564 wxPoint(100, 100), wxSize(650, 500));
565 frame->Centre(wxBOTH);
566 frame->Initialize();
567 frame->Show(true);
568 return true;
569 }
570
571
572
573 bool wxHtmlEasyPrinting::DoPrint(wxHtmlPrintout *printout)
574 {
575 wxPrintDialogData printDialogData(*GetPrintData());
576 wxPrinter printer(&printDialogData);
577
578 if (!printer.Print(m_ParentWindow, printout, true))
579 {
580 return false;
581 }
582
583 (*GetPrintData()) = printer.GetPrintDialogData().GetPrintData();
584 return true;
585 }
586
587
588
589
590 void wxHtmlEasyPrinting::PageSetup()
591 {
592 if (!GetPrintData()->Ok())
593 {
594 wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
595 return;
596 }
597
598 m_PageSetupData->SetPrintData(*GetPrintData());
599 wxPageSetupDialog pageSetupDialog(m_ParentWindow, m_PageSetupData);
600
601 if (pageSetupDialog.ShowModal() == wxID_OK)
602 {
603 (*GetPrintData()) = pageSetupDialog.GetPageSetupData().GetPrintData();
604 (*m_PageSetupData) = pageSetupDialog.GetPageSetupData();
605 }
606 }
607
608
609
610 void wxHtmlEasyPrinting::SetHeader(const wxString& header, int pg)
611 {
612 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
613 m_Headers[0] = header;
614 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
615 m_Headers[1] = header;
616 }
617
618
619
620 void wxHtmlEasyPrinting::SetFooter(const wxString& footer, int pg)
621 {
622 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
623 m_Footers[0] = footer;
624 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
625 m_Footers[1] = footer;
626 }
627
628
629 void wxHtmlEasyPrinting::SetFonts(const wxString& normal_face, const wxString& fixed_face,
630 const int *sizes)
631 {
632 m_fontMode = FontMode_Explicit;
633 m_FontFaceNormal = normal_face;
634 m_FontFaceFixed = fixed_face;
635
636 if (sizes)
637 {
638 m_FontsSizes = m_FontsSizesArr;
639 for (int i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
640 }
641 else
642 m_FontsSizes = NULL;
643 }
644
645 void wxHtmlEasyPrinting::SetStandardFonts(int size,
646 const wxString& normal_face,
647 const wxString& fixed_face)
648 {
649 m_fontMode = FontMode_Standard;
650 m_FontFaceNormal = normal_face;
651 m_FontFaceFixed = fixed_face;
652 m_FontsSizesArr[0] = size;
653 }
654
655
656 wxHtmlPrintout *wxHtmlEasyPrinting::CreatePrintout()
657 {
658 wxHtmlPrintout *p = new wxHtmlPrintout(m_Name);
659
660 if (m_fontMode == FontMode_Explicit)
661 {
662 p->SetFonts(m_FontFaceNormal, m_FontFaceFixed, m_FontsSizes);
663 }
664 else // FontMode_Standard
665 {
666 p->SetStandardFonts(m_FontsSizesArr[0],
667 m_FontFaceNormal, m_FontFaceFixed);
668 }
669
670 p->SetHeader(m_Headers[0], wxPAGE_EVEN);
671 p->SetHeader(m_Headers[1], wxPAGE_ODD);
672 p->SetFooter(m_Footers[0], wxPAGE_EVEN);
673 p->SetFooter(m_Footers[1], wxPAGE_ODD);
674
675 p->SetMargins(m_PageSetupData->GetMarginTopLeft().y,
676 m_PageSetupData->GetMarginBottomRight().y,
677 m_PageSetupData->GetMarginTopLeft().x,
678 m_PageSetupData->GetMarginBottomRight().x);
679
680 return p;
681 }
682
683 // A module to allow initialization/cleanup
684 // without calling these functions from app.cpp or from
685 // the user's application.
686
687 class wxHtmlPrintingModule: public wxModule
688 {
689 DECLARE_DYNAMIC_CLASS(wxHtmlPrintingModule)
690 public:
691 wxHtmlPrintingModule() : wxModule() {}
692 bool OnInit() { return true; }
693 void OnExit() { wxHtmlPrintout::CleanUpStatics(); }
694 };
695
696 IMPLEMENT_DYNAMIC_CLASS(wxHtmlPrintingModule, wxModule)
697
698
699 // This hack forces the linker to always link in m_* files
700 // (wxHTML doesn't work without handlers from these files)
701 #include "wx/html/forcelnk.h"
702 FORCE_WXHTML_MODULES()
703
704 #endif // wxUSE_HTML & wxUSE_PRINTING_ARCHITECTURE