]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/region.cpp
Added clipboard cut and paste
[wxWidgets.git] / src / os2 / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// File: region.cpp
3// Purpose: Region class
4// Author: David Webster
5// Modified by:
6// Created: 10/15/99
7// RCS-ID: $Id$
8// Copyright: (c) Davdi Webster
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#include "wx/app.h"
16#include "wx/os2/region.h"
17#include "wx/gdicmn.h"
18
19#include "wx/window.h"
20#include "wx/os2/private.h"
21
22 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
23 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
24
25//-----------------------------------------------------------------------------
26// wxRegionRefData implementation
27//-----------------------------------------------------------------------------
28
29class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
30public:
31 wxRegionRefData()
32 {
33 m_hRegion = 0;
34 m_hPS = 0;
35 }
36
37 wxRegionRefData(const wxRegionRefData& rData)
38 {
39 RGNRECT vRgnData;
40 PRECTL pRect = NULL;
41
42 if (::GpiQueryRegionRects( rData.m_hPS // Pres space
43 ,rData.m_hRegion // Handle of region to query
44 ,NULL // Return all RECTs
45 ,&vRgnData // Will contain number or RECTs in region
46 ,NULL // NULL to return number of RECTs
47 ))
48 {
49 pRect = new RECTL[vRgnData.crcReturned];
50 vRgnData.crc = vRgnData.crcReturned;
51 vRgnData.ircStart = 1;
52 if (::GpiQueryRegionRects( rData.m_hPS // Pres space of source
53 ,rData.m_hRegion // Handle of source region
54 ,NULL // Return all RECTs
55 ,&vRgnData // Operations set to return rects
56 ,pRect // Will contain the actual RECTS
57 ))
58 {
59 m_hRegion = ::GpiCreateRegion( rData.m_hPS
60 ,vRgnData.crcReturned
61 ,pRect
62 );
63 m_hPS = rData.m_hPS;
64 }
65 delete [] pRect;
66 }
67 }
68
69 ~wxRegionRefData()
70 {
71 ::GpiDestroyRegion(m_hPS, m_hRegion);
72 }
73
74 HRGN m_hRegion;
75 HPS m_hPS;
76};
77
78#define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion)
79
80//-----------------------------------------------------------------------------
81// wxRegion
82//-----------------------------------------------------------------------------
83
84/*!
85 * Create an empty region.
86 */
87wxRegion::wxRegion()
88{
89 m_refData = new wxRegionRefData;
90} // end of wxRegion::wxRegion
91
92wxRegion::wxRegion(
93 WXHRGN hRegion,
94 WXHDC hPS
95)
96{
97 m_refData = new wxRegionRefData;
98 M_REGION = (HRGN) hRegion;
99 (((wxRegionRefData*)m_refData)->m_hPS) = hPS;
100} // end of wxRegion::wxRegion
101
102wxRegion::wxRegion(
103 wxCoord x
104, wxCoord y
105, wxCoord vWidth
106, wxCoord vHeight
107)
108{
109 RECTL vRect;
110 SIZEL vSize = {0, 0};
111 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
112 HDC hDC = ::DevOpenDC( vHabmain
113 ,OD_MEMORY
114 ,"*"
115 ,5L
116 ,(PDEVOPENDATA)&vDop
117 ,NULLHANDLE
118 );
119
120
121 vRect.xLeft = x;
122 vRect.xRight = x + vWidth;
123 vRect.yBottom = y;
124 vRect.yTop = y + vHeight;
125
126 m_refData = new wxRegionRefData;
127
128 //
129 // Need a PS to create a Region
130 //
131 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
132 ,hDC
133 ,&vSize
134 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
135 );
136 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
137 ,1
138 ,&vRect
139 );
140} // end of wxRegion::wxRegion
141
142wxRegion::wxRegion(
143 const wxPoint& rTopLeft
144, const wxPoint& rBottomRight
145)
146{
147 RECTL vRect;
148 SIZEL vSize = {0, 0};
149 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
150 HDC hDC = ::DevOpenDC( vHabmain
151 ,OD_MEMORY
152 ,"*"
153 ,5L
154 ,(PDEVOPENDATA)&vDop
155 ,NULLHANDLE
156 );
157
158 vRect.xLeft = rTopLeft.x;
159 vRect.xRight = rBottomRight.x;
160 vRect.yBottom = rBottomRight.y;
161 vRect.yTop = rTopLeft.y;
162
163 m_refData = new wxRegionRefData;
164
165 //
166 // Need a PS to create a Region
167 //
168 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
169 ,hDC
170 ,&vSize
171 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
172 );
173 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
174 ,1
175 ,&vRect
176 );
177} // end of wxRegion::wxRegion
178
179wxRegion::wxRegion(
180 const wxRect& rRect
181)
182{
183 RECTL vRect;
184 SIZEL vSize = {0, 0};
185 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
186 HDC hDC = ::DevOpenDC( vHabmain
187 ,OD_MEMORY
188 ,"*"
189 ,5L
190 ,(PDEVOPENDATA)&vDop
191 ,NULLHANDLE
192 );
193
194
195 vRect.xLeft = rRect.x;
196 vRect.xRight = rRect.x + rRect.width;
197 vRect.yBottom = rRect.y;
198 vRect.yTop = rRect.y + rRect.height;
199
200 m_refData = new wxRegionRefData;
201
202 //
203 // Need a PS to create a Region
204 //
205 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
206 ,hDC
207 ,&vSize
208 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
209 );
210 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
211 ,1
212 ,&vRect
213 );
214} // end of wxRegion::wxRegion
215
216//
217// Destroy the region.
218//
219wxRegion::~wxRegion()
220{
221} // end of wxRegion::~wxRegion
222
223//-----------------------------------------------------------------------------
224//# Modify region
225//-----------------------------------------------------------------------------
226
227//
228// Clear current region
229//
230void wxRegion::Clear()
231{
232 UnRef();
233} // end of wxRegion::Clear
234
235//
236// Combine rectangle (x, y, w, h) with this.
237//
238bool wxRegion::Combine(
239 wxCoord x
240, wxCoord y
241, wxCoord vWidth
242, wxCoord vHeight
243, wxRegionOp eOp
244)
245{
246 //
247 // Don't change shared data
248 //
249 if (!m_refData)
250 {
251 m_refData = new wxRegionRefData();
252 }
253 else if (m_refData->GetRefCount() > 1)
254 {
255 wxRegionRefData* pRef = (wxRegionRefData*)m_refData;
256
257 UnRef();
258 m_refData = new wxRegionRefData(*pRef);
259 }
260
261 //
262 // If ref count is 1, that means it's 'ours' anyway so no action.
263 //
264 RECTL vRect;
265
266 vRect.xLeft = x;
267 vRect.xRight = x + vWidth;
268 vRect.yBottom = y;
269 vRect.yTop = y + vHeight;
270
271 HRGN hRgn = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
272 ,1
273 ,&vRect
274 );
275 LONG lMode = 0L;
276
277 switch (eOp)
278 {
279 case wxRGN_AND:
280 lMode = CRGN_AND;
281 break;
282
283 case wxRGN_OR:
284 lMode = CRGN_OR;
285 break;
286
287 case wxRGN_XOR:
288 lMode = CRGN_XOR;
289 break;
290
291 case wxRGN_DIFF:
292 lMode = CRGN_DIFF;
293 break;
294
295 case wxRGN_COPY:
296 default:
297 lMode = CRGN_COPY;
298 break;
299 }
300 bool bSuccess = ::GpiCombineRegion( ((wxRegionRefData*)m_refData)->m_hPS
301 ,M_REGION
302 ,M_REGION
303 ,hRgn
304 ,lMode
305 );
306 ::GpiDestroyRegion ( ((wxRegionRefData*)m_refData)->m_hPS
307 ,hRgn
308 );
309
310 return bSuccess;
311} // end of wxRegion::Combine
312
313//
314// Union region with this.
315//
316bool wxRegion::Combine(
317 const wxRegion& rRegion
318, wxRegionOp eOp
319)
320{
321 if (rRegion.Empty())
322 return FALSE;
323
324 //
325 // Don't change shared data
326 //
327 if (!m_refData)
328 {
329 m_refData = new wxRegionRefData();
330 }
331 else if (m_refData->GetRefCount() > 1)
332 {
333 wxRegionRefData* pRef = (wxRegionRefData*)m_refData;
334
335 UnRef();
336 m_refData = new wxRegionRefData(*pRef);
337 }
338
339 LONG lMode = 0;
340
341 switch (eOp)
342 {
343 case wxRGN_AND:
344 lMode = CRGN_AND;
345 break;
346
347 case wxRGN_OR:
348 lMode = CRGN_OR;
349 break;
350
351 case wxRGN_XOR:
352 lMode = CRGN_XOR;
353 break;
354
355 case wxRGN_DIFF:
356 lMode = CRGN_DIFF;
357 break;
358
359 case wxRGN_COPY:
360 default:
361 lMode = CRGN_COPY;
362 break;
363 }
364 return (::GpiCombineRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
365 ,M_REGION
366 ,M_REGION
367 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion
368 ,lMode
369 ) != RGN_ERROR);
370} // end of wxRegion::Combine
371
372bool wxRegion::Combine(
373 const wxRect& rRect
374, wxRegionOp eOp
375)
376{
377 return Combine( rRect.GetLeft()
378 ,rRect.GetTop()
379 ,rRect.GetWidth()
380 ,rRect.GetHeight()
381 ,eOp
382 );
383} // end of wxRegion::Combine
384
385//-----------------------------------------------------------------------------
386//# Information on region
387//-----------------------------------------------------------------------------
388
389//
390// Outer bounds of region
391//
392void wxRegion::GetBox(
393 wxCoord& x
394, wxCoord& y
395, wxCoord& vWidth
396, wxCoord& vHeight
397) const
398{
399 if (m_refData)
400 {
401 RECTL vRect;
402 APIRET rc;
403
404 rc = ::GpiQueryRegionBox( ((wxRegionRefData*)m_refData)->m_hPS
405 ,M_REGION
406 ,&vRect
407 );
408 x = vRect.xLeft;
409 y = vRect.yTop;
410 vWidth = vRect.xRight - vRect.xLeft;
411 vHeight = vRect.yTop - vRect.yBottom;
412 }
413 else
414 {
415 x = y = vWidth = vHeight = 0L;
416 }
417} // end of wxRegion::GetBox
418
419wxRect wxRegion::GetBox() const
420{
421 wxCoord x, y, w, h;
422 GetBox(x, y, w, h);
423 return wxRect(x, y, w, h);
424}
425
426//
427// Is region empty?
428//
429bool wxRegion::Empty() const
430{
431 wxCoord x;
432 wxCoord y;
433 wxCoord vWidth;
434 wxCoord vHeight;
435
436 if (M_REGION == 0)
437 return TRUE;
438
439 GetBox( x
440 ,y
441 ,vWidth
442 ,vHeight
443 );
444 return ((vWidth == 0) && (vHeight == 0));
445} // end of wxRegion::Empty
446
447//-----------------------------------------------------------------------------
448// Tests
449//-----------------------------------------------------------------------------
450
451//
452// Does the region contain the point (x,y)?
453wxRegionContain wxRegion::Contains(
454 wxCoord x
455, wxCoord y
456) const
457{
458 bool bOK = FALSE;
459 POINTL vPoint;
460
461 vPoint.x = x;
462 vPoint.y = y;
463
464 if (!m_refData)
465 return wxOutRegion;
466
467 LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS
468 ,M_REGION
469 ,&vPoint
470 );
471 if (lInside == PRGN_INSIDE)
472 return wxInRegion;
473 return wxOutRegion;
474} // end of wxRegion::Contains
475
476//
477// Does the region contain the point pt?
478//
479wxRegionContain wxRegion::Contains(
480 const wxPoint& rPoint
481) const
482{
483 POINTL vPoint = { rPoint.x, rPoint.y };
484
485 if (!m_refData)
486 return wxOutRegion;
487
488 LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS
489 ,M_REGION
490 ,&vPoint
491 );
492 if (lInside == PRGN_INSIDE)
493 return wxInRegion;
494 else
495 return wxOutRegion;
496} // end of wxRegion::Contains
497
498//
499// Does the region contain the rectangle (x, y, w, h)?
500//
501wxRegionContain wxRegion::Contains(
502 wxCoord x
503, wxCoord y
504, wxCoord vWidth
505, wxCoord vHeight
506) const
507{
508 RECTL vRect;
509
510 if (!m_refData)
511 return wxOutRegion;
512
513 vRect.xLeft = x;
514 vRect.yTop = y;
515 vRect.xRight = x + vWidth;
516 vRect.yBottom = y + vHeight;
517
518 if (PRGN_INSIDE == ::GpiRectInRegion( ((wxRegionRefData*)m_refData)->m_hPS
519 ,M_REGION
520 ,&vRect
521 ))
522 return wxInRegion;
523 else
524 return wxOutRegion;
525} // end of wxRegion::Contains
526
527//
528// Does the region contain the rectangle rect
529//
530wxRegionContain wxRegion::Contains(
531 const wxRect& rRect
532) const
533{
534 if (!m_refData)
535 return wxOutRegion;
536
537 wxCoord x;
538 wxCoord y;
539 wxCoord vWidth;
540 wxCoord vHeight;
541
542 x = rRect.x;
543 y = rRect.y;
544 vWidth = rRect.GetWidth();
545 vHeight = rRect.GetHeight();
546 return Contains( x
547 ,y
548 ,vWidth
549 ,vHeight
550 );
551} // end of wxRegion::Contains
552
553//
554// Get internal region handle
555//
556WXHRGN wxRegion::GetHRGN() const
557{
558 if (!m_refData)
559 return (WXHRGN) 0;
560 return (WXHRGN) M_REGION;
561}
562
563//
564// Set a new PS, this means we have to recreate the old region in the new
565// PS
566//
567void wxRegion::SetPS(
568 HPS hPS
569)
570{
571 RGNRECT vRgnData;
572 PRECTL pRect = NULL;
573
574 if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
575 ,((wxRegionRefData*)m_refData)->m_hRegion
576 ,NULL
577 ,&vRgnData
578 ,NULL
579 ))
580 {
581 pRect = new RECTL[vRgnData.crcReturned];
582 vRgnData.crc = vRgnData.crcReturned;
583 vRgnData.ircStart = 1;
584 if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
585 ,((wxRegionRefData*)m_refData)->m_hRegion
586 ,NULL
587 ,&vRgnData
588 ,pRect
589 ))
590 {
591 //
592 // First destroy the region out of the old PS
593 // and then create it in the new and set the new to current
594 //
595 ::GpiDestroyRegion( ((wxRegionRefData*)m_refData)->m_hPS
596 ,M_REGION
597 );
598 ((wxRegionRefData*)m_refData)->m_hRegion = ::GpiCreateRegion( hPS
599 ,vRgnData.crcReturned
600 ,pRect
601 );
602 ((wxRegionRefData*)m_refData)->m_hPS = hPS;
603 }
604 delete [] pRect;
605 }
606} // end of wxRegion::SetPS
607
608///////////////////////////////////////////////////////////////////////////////
609// //
610// wxRegionIterator //
611// //
612///////////////////////////////////////////////////////////////////////////////
613
614//
615// Initialize empty iterator
616//
617wxRegionIterator::wxRegionIterator()
618: m_lCurrent(0)
619, m_lNumRects(0)
620, m_pRects(NULL)
621{
622} // end of wxRegionIterator::wxRegionIterator
623
624wxRegionIterator::~wxRegionIterator()
625{
626 if (m_pRects)
627 delete[] m_pRects;
628} // end of wxRegionIterator::~wxRegionIterator
629
630//
631// Initialize iterator for region
632//
633wxRegionIterator::wxRegionIterator(
634 const wxRegion& rRegion
635)
636{
637 m_pRects = NULL;
638 Reset(rRegion);
639} // end of wxRegionIterator::wxRegionIterator
640
641//
642// Reset iterator for a new /e region.
643//
644void wxRegionIterator::Reset(
645 const wxRegion& rRegion
646)
647{
648 m_lCurrent = 0;
649 m_vRegion = rRegion;
650
651 if (m_pRects)
652 delete[] m_pRects;
653
654 m_pRects = NULL;
655
656 if (m_vRegion.Empty())
657 m_lNumRects = 0;
658 else
659 {
660 RGNRECT vRgnData;
661 PRECTL pRect;
662
663 if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS // Pres space
664 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of region to query
665 ,NULL // Return all RECTs
666 ,&vRgnData // Will contain number or RECTs in region
667 ,NULL // NULL to return number of RECTs
668 ))
669 {
670 pRect = new RECTL[vRgnData.crcReturned];
671 m_pRects = new wxRect[vRgnData.crcReturned];
672 vRgnData.crc = vRgnData.crcReturned;
673 m_lNumRects = vRgnData.crcReturned;
674 vRgnData.ircStart = 1;
675 if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS // Pres space of source
676 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of source region
677 ,NULL // Return all RECTs
678 ,&vRgnData // Operations set to return rects
679 ,pRect // Will contain the actual RECTS
680 ))
681 {
682 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
683 ,vRgnData.crcReturned
684 ,pRect
685 );
686 for( LONG i = 0; i < m_lNumRects; i++)
687 {
688 m_pRects[i].x = pRect[i].xLeft;
689 m_pRects[i].width = pRect[i].xRight - pRect[i].xLeft;
690 m_pRects[i].y = pRect[i].yBottom;
691 m_pRects[i].height = pRect[i].yTop - pRect[i].yBottom;
692 }
693 ((wxRegionRefData*)m_refData)->m_hPS = ((wxRegionRefData*)rRegion.m_refData)->m_hPS;
694 }
695 }
696 }
697} // end of wxRegionIterator::Reset
698
699//
700// Increment iterator. The rectangle returned is the one after the
701// incrementation.
702//
703void wxRegionIterator::operator++ ()
704{
705 if (m_lCurrent < m_lNumRects)
706 ++m_lCurrent;
707} // end of wxRegionIterator::operator ++
708
709//
710// Increment iterator. The rectangle returned is the one before the
711// incrementation.
712//
713void wxRegionIterator::operator++ (int)
714{
715 if (m_lCurrent < m_lNumRects)
716 ++m_lCurrent;
717} // end of wxRegionIterator::operator++
718
719wxCoord wxRegionIterator::GetX() const
720{
721 if (m_lCurrent < m_lNumRects)
722 return m_pRects[m_lCurrent].x;
723 return 0L;
724} // end of wxRegionIterator::GetX
725
726wxCoord wxRegionIterator::GetY() const
727{
728 if (m_lCurrent < m_lNumRects)
729 return m_pRects[m_lCurrent].y;
730 return 0L;
731} // end of wxRegionIterator::GetY
732
733wxCoord wxRegionIterator::GetW() const
734{
735 if (m_lCurrent < m_lNumRects)
736 return m_pRects[m_lCurrent].width ;
737 return 0L;
738} // end of wxRegionIterator::GetW
739
740wxCoord wxRegionIterator::GetH() const
741{
742 if (m_lCurrent < m_lNumRects)
743 return m_pRects[m_lCurrent].height;
744 return 0L;
745} // end of wxRegionIterator::GetH
746