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