]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dcclient.cpp
paper size, duplex support
[wxWidgets.git] / src / os2 / dcclient.cpp
CommitLineData
0e320a79 1/////////////////////////////////////////////////////////////////////////////
df91131c 2// Name: src/os2/dcclient.cpp
0e320a79 3// Purpose: wxClientDC class
f0a56ab0 4// Author: David Webster
0e320a79 5// Modified by:
f0a56ab0 6// Created: 09/21/99
0e320a79 7// RCS-ID: $Id$
f0a56ab0 8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
23e4b7d8
DW
12// ===========================================================================
13// declarations
14// ===========================================================================
0e320a79 15
23e4b7d8
DW
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
0e320a79 19
23e4b7d8
DW
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
0e320a79 22
df91131c
WS
23#include "wx/dcclient.h"
24
25#ifndef WX_PRECOMP
26 #include "wx/string.h"
e4db172a 27 #include "wx/log.h"
670f9935 28 #include "wx/app.h"
cdccdfab 29 #include "wx/window.h"
df91131c
WS
30#endif
31
ce44c50e 32#include "wx/os2/private.h"
0e320a79 33
23e4b7d8
DW
34// ----------------------------------------------------------------------------
35// array/list types
36// ----------------------------------------------------------------------------
0e320a79 37
23e4b7d8 38struct WXDLLEXPORT wxPaintDCInfo
0e320a79 39{
e99762c0
DW
40 wxPaintDCInfo( wxWindow* pWin
41 ,wxDC* pDC
42 )
23e4b7d8 43 {
e99762c0
DW
44 m_hWnd = pWin->GetHWND();
45 m_hDC = pDC->GetHDC();
46 m_nCount = 1;
23e4b7d8 47 }
0e320a79 48
e99762c0
DW
49 WXHWND m_hWnd; // window for this DC
50 WXHDC m_hDC; // the DC handle
51 size_t m_nCount; // usage count
52}; // end of wxPaintDCInfot
0e320a79 53
23e4b7d8 54#include "wx/arrimpl.cpp"
1408104d 55
23e4b7d8 56WX_DEFINE_OBJARRAY(wxArrayDCInfo);
1408104d 57
23e4b7d8
DW
58// ----------------------------------------------------------------------------
59// macros
60// ----------------------------------------------------------------------------
0e320a79 61
23e4b7d8
DW
62 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
63 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
64 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
0e320a79 65
23e4b7d8
DW
66// ----------------------------------------------------------------------------
67// global variables
68// ----------------------------------------------------------------------------
1408104d 69
ce44c50e 70static RECT g_paintStruct;
1408104d 71
23e4b7d8
DW
72#ifdef __WXDEBUG__
73 // a global variable which we check to verify that wxPaintDC are only
74 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
77ffb593 75 // common programming error among wxWidgets programmers and might lead to
23e4b7d8
DW
76 // very subtle and difficult to debug refresh/repaint bugs.
77 int g_isPainting = 0;
78#endif // __WXDEBUG__
1408104d 79
23e4b7d8
DW
80// ===========================================================================
81// implementation
82// ===========================================================================
1408104d 83
23e4b7d8
DW
84// ----------------------------------------------------------------------------
85// wxWindowDC
86// ----------------------------------------------------------------------------
0e320a79 87
23e4b7d8 88wxWindowDC::wxWindowDC()
0e320a79 89{
26ac77db 90 m_pCanvas = NULL;
1d27f802
SN
91 m_PageSize.cx = m_PageSize.cy = 0;
92
23e4b7d8 93}
0e320a79 94
e99762c0
DW
95wxWindowDC::wxWindowDC(
96 wxWindow* pTheCanvas
97)
0e320a79 98{
26ac77db
DW
99 ERRORID vError;
100 wxString sError;
1d27f802 101 int nWidth, nHeight;
1408104d 102
e99762c0 103 m_pCanvas = pTheCanvas;
1d27f802
SN
104 DoGetSize(&nWidth, &nHeight);
105 m_PageSize.cx = nWidth;
106 m_PageSize.cy = nHeight;
e99762c0 107 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
e1a688e4 108
23e4b7d8 109 //
26ac77db
DW
110 // default under PM is that Window and Client DC's are the same
111 // so we offer a separate Presentation Space to use for the
112 // entire window. Otherwise, calling BeginPaint will just create
113 // chached-micro client presentation space
23e4b7d8 114 //
e1a688e4
DW
115 m_hPS = ::GpiCreatePS( vHabmain
116 ,m_hDC
117 ,&m_PageSize
118 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
119 );
1d27f802
SN
120 if (!m_hPS)
121 {
122 vError = ::WinGetLastError(vHabmain);
123 sError = wxPMErrorToStr(vError);
0fba44b4 124 wxLogError(_T("Unable to create presentation space. Error: %s\n"), sError.c_str());
1d27f802 125 }
26ac77db
DW
126 ::GpiAssociate(m_hPS, NULLHANDLE);
127 ::GpiAssociate(m_hPS, m_hDC);
e1a688e4
DW
128
129 //
77ffb593 130 // Set the wxWidgets color table
e1a688e4 131 //
26ac77db
DW
132 if (!::GpiCreateLogColorTable( m_hPS
133 ,0L
134 ,LCOLF_CONSECRGB
135 ,0L
136 ,(LONG)wxTheColourDatabase->m_nSize
137 ,(PLONG)wxTheColourDatabase->m_palTable
138 ))
7e99520b 139 {
26ac77db
DW
140 vError = ::WinGetLastError(vHabmain);
141 sError = wxPMErrorToStr(vError);
da51aebe 142 wxLogError(_T("Unable to set current color table (3). Error: %s\n"), sError.c_str());
7e99520b 143 }
5afb9458
DW
144 ::GpiCreateLogColorTable( m_hPS
145 ,0L
146 ,LCOLF_RGB
147 ,0L
148 ,0L
149 ,NULL
150 );
5afb9458
DW
151 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
152 ,&m_vRclPaint
153 );
e1a688e4
DW
154 InitDC();
155} // end of wxWindowDC::wxWindowDC
1408104d 156
e1a688e4 157void wxWindowDC::InitDC()
26ac77db 158{
2b0ec34b 159
e1a688e4
DW
160 //
161 // The background mode is only used for text background and is set in
162 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
163 //
164 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE);
26ac77db 165
e1a688e4
DW
166 //
167 // Default bg colour is pne of the window
168 //
169 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
938aa9c4 170
19bc1514
WS
171 m_pen.SetColour(*wxBLACK);
172 m_brush.SetColour(*wxWHITE);
938aa9c4 173 InitializePalette();
19bc1514 174 wxFont* pFont = new wxFont( 10, wxMODERN, wxNORMAL, wxBOLD );
c354beea
DW
175 SetFont(*pFont);
176 delete pFont;
177 //
d6922577 178 // OS/2 default vertical character alignment needs to match the other OS's
c354beea
DW
179 //
180 ::GpiSetTextAlignment((HPS)GetHPS(), TA_NORMAL_HORIZ, TA_BOTTOM);
181
e1a688e4 182} // end of wxWindowDC::InitDC
0e320a79 183
bc5a847c
DW
184void wxWindowDC::DoGetSize(
185 int* pnWidth
186, int* pnHeight
187) const
188{
189 wxCHECK_RET( m_pCanvas, _T("wxWindowDC without a window?") );
190 m_pCanvas->GetSize( pnWidth
191 ,pnHeight
192 );
193} // end of wxWindowDC::DoGetSize
194
23e4b7d8
DW
195// ----------------------------------------------------------------------------
196// wxClientDC
197// ----------------------------------------------------------------------------
0e320a79 198
23e4b7d8 199wxClientDC::wxClientDC()
0e320a79 200{
26ac77db 201 m_pCanvas = NULL;
23e4b7d8 202}
0e320a79 203
e99762c0
DW
204wxClientDC::wxClientDC(
205 wxWindow* pTheCanvas
206)
0e320a79 207{
7e99520b 208 SIZEL vSizl = { 0,0};
26ac77db
DW
209 ERRORID vError;
210 wxString sError;
0e320a79 211
e99762c0 212 m_pCanvas = pTheCanvas;
1408104d 213
7e99520b
DW
214 //
215 // default under PM is that Window and Client DC's are the same
216 //
e99762c0 217 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
7e99520b
DW
218 m_hPS = ::GpiCreatePS( wxGetInstance()
219 ,m_hDC
f44fdfb0 220 ,&vSizl
7e99520b
DW
221 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
222 );
223
77ffb593 224 // Set the wxWidgets color table
26ac77db
DW
225 if (!::GpiCreateLogColorTable( m_hPS
226 ,0L
227 ,LCOLF_CONSECRGB
228 ,0L
229 ,(LONG)wxTheColourDatabase->m_nSize
230 ,(PLONG)wxTheColourDatabase->m_palTable
231 ))
232 {
233 vError = ::WinGetLastError(vHabmain);
234 sError = wxPMErrorToStr(vError);
da51aebe 235 wxLogError(_T("Unable to set current color table (4). Error: %s\n"), sError.c_str());
26ac77db 236 }
5afb9458
DW
237 ::GpiCreateLogColorTable( m_hPS
238 ,0L
239 ,LCOLF_RGB
240 ,0L
241 ,0L
242 ,NULL
243 );
7e99520b 244 //
5afb9458
DW
245 // Set the DC/PS rectangle
246 //
247 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
248 ,&m_vRclPaint
249 );
e1a688e4 250 InitDC();
e99762c0 251} // end of wxClientDC::wxClientDC
0e320a79 252
0367c1c0
DW
253void wxClientDC::InitDC()
254{
255 wxWindowDC::InitDC();
256
257 // in wxUniv build we must manually do some DC adjustments usually
258 // performed by Windows for us
259#ifdef __WXUNIVERSAL__
19193a2c 260 wxPoint ptOrigin = m_pCanvas->GetClientAreaOrigin();
0367c1c0
DW
261 if ( ptOrigin.x || ptOrigin.y )
262 {
263 // no need to shift DC origin if shift is null
264 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
265 }
266
267 // clip the DC to avoid overwriting the non client area
19193a2c 268 SetClippingRegion(wxPoint(0, 0), m_pCanvas->GetClientSize());
0367c1c0
DW
269#endif // __WXUNIVERSAL__
270} // end of wxClientDC::InitDC
271
272wxClientDC::~wxClientDC()
273{
274} // end of wxClientDC::~wxClientDC
275
bc5a847c
DW
276void wxClientDC::DoGetSize(
277 int* pnWidth
278, int* pnHeight
279) const
280{
281 wxCHECK_RET( m_pCanvas, _T("wxWindowDC without a window?") );
282 m_pCanvas->GetClientSize( pnWidth
283 ,pnHeight
284 );
285} // end of wxClientDC::DoGetSize
286
23e4b7d8
DW
287// ----------------------------------------------------------------------------
288// wxPaintDC
289// ----------------------------------------------------------------------------
290
23e4b7d8
DW
291wxArrayDCInfo wxPaintDC::ms_cache;
292
293wxPaintDC::wxPaintDC()
294{
f6bcfd97 295 m_pCanvas = NULL;
23e4b7d8
DW
296 m_hDC = 0;
297}
0e320a79 298
7e99520b
DW
299wxPaintDC::wxPaintDC(
300 wxWindow* pCanvas
301)
0e320a79 302{
f44fdfb0 303 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
1408104d 304
23e4b7d8 305#ifdef __WXDEBUG__
7e99520b 306 if (g_isPainting <= 0)
23e4b7d8 307 {
223d09f6 308 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
23e4b7d8
DW
309 return;
310 }
311#endif // __WXDEBUG__
0e320a79 312
7e99520b 313 m_pCanvas = pCanvas;
1408104d 314
7e99520b
DW
315 //
316 // Do we have a DC for this window in the cache?
317 //
318 wxPaintDCInfo* pInfo = FindInCache();
319
320 if (pInfo)
0e320a79 321 {
e99762c0
DW
322 m_hDC = pInfo->m_hDC;
323 pInfo->m_nCount++;
23e4b7d8
DW
324 }
325 else // not in cache, create a new one
326 {
7e99520b
DW
327 HPS hPS;
328
52315bc3 329 m_hDC = ::WinOpenWindowDC(GetWinHwnd(m_pCanvas));
7e99520b
DW
330 hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
331 ,NULLHANDLE
332 ,&g_paintStruct
333 );
334 if(hPS)
335 {
ba3e10c9 336 ::GpiAssociate(hPS, m_hDC);
7e99520b
DW
337 m_hOldPS = m_hPS;
338 m_hPS = hPS;
26ac77db
DW
339 ::GpiCreateLogColorTable( m_hPS
340 ,0L
341 ,LCOLF_CONSECRGB
342 ,0L
343 ,(LONG)wxTheColourDatabase->m_nSize
344 ,(PLONG)wxTheColourDatabase->m_palTable
345 );
346 ::GpiCreateLogColorTable( m_hPS
347 ,0L
348 ,LCOLF_RGB
349 ,0L
350 ,0L
351 ,NULL
352 );
8d854fa9
DW
353
354 ::WinFillRect(hPS, &g_paintStruct, m_pCanvas->GetBackgroundColour().GetPixel());
eeff964a
DW
355 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
356 ,&m_vRclPaint
357 );
7e99520b 358 }
e99762c0 359
df91131c 360 m_bIsPaintTime = true;
f6bcfd97 361 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
0e320a79 362 }
e1a688e4
DW
363 InitDC();
364} // end of wxPaintDC::wxPaintDC
0e320a79 365
23e4b7d8 366wxPaintDC::~wxPaintDC()
0e320a79 367{
23e4b7d8
DW
368 if ( m_hDC )
369 {
370 SelectOldObjects(m_hDC);
0e320a79 371
e99762c0
DW
372 size_t nIndex;
373 wxPaintDCInfo* pInfo = FindInCache(&nIndex);
0e320a79 374
e99762c0 375 wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
0e320a79 376
e99762c0 377 if ( !--pInfo->m_nCount )
23e4b7d8 378 {
ce44c50e 379 ::WinEndPaint(m_hPS);
f44fdfb0 380 m_hPS = m_hOldPS;
df91131c 381 m_bIsPaintTime = false;
893758d5 382 ms_cache.RemoveAt(nIndex);
23e4b7d8
DW
383 }
384 //else: cached DC entry is still in use
0e320a79 385
23e4b7d8
DW
386 // prevent the base class dtor from ReleaseDC()ing it again
387 m_hDC = 0;
0e320a79
DW
388 }
389}
390
e99762c0
DW
391wxPaintDCInfo* wxPaintDC::FindInCache(
392 size_t* pIndex
393) const
0e320a79 394{
e99762c0
DW
395 wxPaintDCInfo* pInfo = NULL;
396 size_t nCache = ms_cache.GetCount();
397
398 for (size_t n = 0; n < nCache; n++)
0e320a79 399 {
e99762c0
DW
400 pInfo = &ms_cache[n];
401 if (pInfo->m_hWnd == m_pCanvas->GetHWND())
23e4b7d8 402 {
e99762c0
DW
403 if (pIndex)
404 *pIndex = n;
23e4b7d8
DW
405 break;
406 }
0e320a79 407 }
e99762c0
DW
408 return pInfo;
409} // end of wxPaintDC::FindInCache
0e320a79 410
e1a688e4
DW
411// find the entry for this DC in the cache (keyed by the window)
412WXHDC wxPaintDC::FindDCInCache(
413 wxWindow* pWin
414)
415{
416 wxPaintDCInfo* pInfo = NULL;
417 size_t nCache = ms_cache.GetCount();
418
419 for (size_t n = 0; n < nCache; n++)
420 {
421 pInfo = &ms_cache[n];
422 if (pInfo->m_hWnd == pWin->GetHWND())
423 {
424 return pInfo->m_hDC;
425 }
426 }
427 return 0;
428} // end of wxPaintDC::FindInCache