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