1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 9426 $
6  * $Id: cbeditorprintout.cpp 9426 2013-11-02 19:42:20Z alpha0010 $
7  * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/sdk/cbeditorprintout.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13     #include <wx/dc.h>
14 
15     #include "manager.h"
16     #include "logmanager.h"
17     #include "cbeditor.h"
18 #endif
19 #include "cbstyledtextctrl.h"
20 
21 #include "cbeditorprintout.h"
22 #include "printing_types.h"
23 #include <wx/paper.h>
24 
cbEditorPrintout(const wxString & title,cbStyledTextCtrl * control,bool selectionOnly)25 cbEditorPrintout::cbEditorPrintout(const wxString& title, cbStyledTextCtrl* control, bool selectionOnly)
26         : wxPrintout(title),
27         m_TextControl(control)
28 {
29     // ctor
30     m_SelStart = 0;
31     m_SelEnd = control->GetLength();
32     if (selectionOnly && !control->GetSelectedText().IsEmpty())
33     {
34         m_SelStart = control->GetSelectionStart();
35         m_SelEnd = control->GetSelectionEnd();
36     }
37     m_pPageSelStart = new wxArrayInt;
38 }
39 
~cbEditorPrintout()40 cbEditorPrintout::~cbEditorPrintout()
41 {
42     // dtor
43     delete m_pPageSelStart;
44     m_pPageSelStart = nullptr;
45 }
46 
OnPrintPage(int page)47 bool cbEditorPrintout::OnPrintPage(int page)
48 {
49     wxDC *dc = GetDC();
50     if (dc)
51     {
52         // scale DC
53         ScaleDC(dc);
54 
55         // print selected page
56         int maxpage = m_pPageSelStart->GetCount();
57         if (page && page<maxpage)
58             m_printed = (*m_pPageSelStart)[page-1];
59         else
60         {
61             Manager::Get()->GetLogManager()->DebugLog(F(_T("OnPrintPage ERROR: page = %d , maxpage = %d"), page, maxpage));
62             return false;
63         }
64 
65         //Manager::Get()->GetLogManager()->DebugLog(_T("OnPrintPage: page %d , m_printed %d"), page, m_printed);
66         m_printed = m_TextControl->FormatRange (1, m_printed, m_SelEnd,
67                                                 dc, dc, m_printRect, m_pageRect);
68         return true;
69     }
70     return false;
71 }
72 
HasPage(cb_unused int page)73 bool cbEditorPrintout::HasPage(cb_unused int page)
74 {
75     return (m_printed < m_SelEnd);
76 }
77 
GetPageInfo(int * minPage,int * maxPage,int * selPageFrom,int * selPageTo)78 void cbEditorPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
79 {
80     // initialize values
81     *minPage = 0;
82     *maxPage = 0;
83     *selPageFrom = 0;
84     *selPageTo = 0;
85     // get print page information and convert to printer pixels
86     wxSize ppiScr;
87     GetPPIScreen (&ppiScr.x, &ppiScr.y);
88     if (ppiScr.x == 0 || ppiScr.y == 0)
89     {
90         // guess
91         ppiScr.x = 96;
92         ppiScr.y = 96;
93     }
94 
95     wxPrintData* ppd = &(g_printer->GetPrintDialogData().GetPrintData());
96     // We cannot use GetSize from wxPrintData, because it always returns -1 for page.x and page.y,
97     wxPrintPaperDatabase paperDB;
98     paperDB.CreateDatabase();
99     wxSize page=paperDB.GetSize(ppd->GetPaperId());
100     if(ppd->GetOrientation() == wxLANDSCAPE )
101     {
102         int temp = page.x;
103         page.x = page.y;
104         page.y = temp;
105     }
106 
107     // We have to divide through 254 instead of 25.4, because GetSize() of paperDB returns tenth of millimeters
108     page.x = static_cast<int> (page.x * ppiScr.x / 254);
109     page.y = static_cast<int> (page.y * ppiScr.y / 254);
110     m_pageRect = wxRect (0,
111                          0,
112                          page.x,
113                          page.y);
114     // get margins information and convert to printer pixels
115     int  top = 15; // default 25
116     int  bottom = 15; // default 25
117     int  left = 20; // default 20
118     int  right = 15; // default 20
119 // TODO (Tiwag#1#): get margins from PageSetup Dialog
120 //    wxPoint (top, left) = g_pageSetupData->GetMarginTopLeft();
121 //    wxPoint (bottom, right) = g_pageSetupData->GetMarginBottomRight();
122     top = static_cast<int> (top * ppiScr.y / 25.4);
123     bottom = static_cast<int> (bottom * ppiScr.y / 25.4);
124     left = static_cast<int> (left * ppiScr.x / 25.4);
125     right = static_cast<int> (right * ppiScr.x / 25.4);
126     m_printRect = wxRect (left,
127                           top,
128                           page.x - (left + right),
129                           page.y - (top + bottom));
130 
131     // wxWidgets 2.4.2, have some printing-related bugs.
132     // one of them is that that GetDC always returns 0 in GetPageInfo.
133     // this means we can't count the pages...
134     wxDC *dc = GetDC();
135     if (dc)
136     {
137         ScaleDC(dc);
138 
139         // count pages and save SelStart value of each page
140         m_pPageSelStart->Clear();
141         m_pPageSelStart->Add(m_SelStart);
142         m_printed = m_SelStart;
143         while (HasPage(*maxPage))
144         {
145             //Manager::Get()->GetLogManager()->DebugLog(_T("CountPages: PageCount %d , m_printed %d"), m_pPageSelStart->GetCount(), m_printed);
146             m_printed = m_TextControl->FormatRange (0, m_printed, m_SelEnd,
147                                              dc, dc, m_printRect, m_pageRect);
148             m_pPageSelStart->Add(m_printed);
149             *maxPage += 1;
150         }
151     }
152     else
153         *maxPage = 32000; // use a fictitious high number
154 
155     if (*maxPage > 0)
156         *minPage = 1;
157     *selPageFrom = *minPage;
158     *selPageTo = *maxPage;
159     m_printed = m_SelStart;
160 }
161 
OnBeginDocument(int startPage,int endPage)162 bool cbEditorPrintout::OnBeginDocument(int startPage, int endPage)
163 {
164     bool result = wxPrintout::OnBeginDocument(startPage, endPage);
165     // FIXME (Tiwag#1#): when the first time a printout is initiated
166     // and you request a page to print which is out of bounds of available pages
167     // it is not recognized by the above check, don't know how to fix this better
168     int maxpage = m_pPageSelStart->GetCount();
169     if( startPage > maxpage || endPage > maxpage )
170     {
171         Manager::Get()->GetLogManager()->DebugLog(F(_T("OnBeginDocument ERROR: startPage %d , endPage %d , maxpage %d "), startPage, endPage, maxpage));
172         return false;
173     }
174     return result;
175 }
176 
ScaleDC(wxDC * dc)177 bool cbEditorPrintout::ScaleDC(wxDC *dc)
178 {
179     if (!dc)
180         return false;
181     // get printer and screen sizing values
182     wxSize ppiScr;
183     GetPPIScreen (&ppiScr.x, &ppiScr.y);
184     if (ppiScr.x == 0)
185     { // most possible guess 96 dpi
186         ppiScr.x = 96;
187         ppiScr.y = 96;
188     }
189     wxSize ppiPrt;
190     GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
191     if (ppiPrt.x == 0)
192     { // scaling factor to 1
193         ppiPrt.x = ppiScr.x;
194         ppiPrt.y = ppiScr.y;
195     }
196     wxSize dcSize = dc->GetSize();
197     wxSize pageSize;
198     GetPageSizePixels (&pageSize.x, &pageSize.y);
199     // set user scale
200     float scale_x = (float)(ppiPrt.x * dcSize.x) /
201                     (float)(ppiScr.x * pageSize.x);
202     float scale_y = (float)(ppiPrt.y * dcSize.y) /
203                     (float)(ppiScr.y * pageSize.y);
204     dc->SetUserScale (scale_x, scale_y);
205     return true;
206 }
207