1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 #include <com/sun/star/accessibility/AccessibleRole.hpp>
27 
28 #include <vcl/svapp.hxx>
29 
30 #include <ipwin.hxx>
31 #include <hatchwindow.hxx>
32 
33 /************************************************************************/
34 /*************************************************************************
35 |*    SvResizeHelper::SvResizeHelper()
36 |*
37 |*    Beschreibung
38 *************************************************************************/
SvResizeHelper()39 SvResizeHelper::SvResizeHelper()
40 	: aBorder( 5, 5 )
41 	, nGrab( -1 )
42 	, bResizeable( sal_True )
43 {
44 }
45 
46 /*************************************************************************
47 |*    SvResizeHelper::FillHandleRects()
48 |*
49 |*    Beschreibung: Die acht Handles zum vergroessern
50 *************************************************************************/
FillHandleRectsPixel(Rectangle aRects[8]) const51 void SvResizeHelper::FillHandleRectsPixel( Rectangle aRects[ 8 ] ) const
52 {
53 	// nur wegen EMPTY_RECT
54 	Point aBottomRight = aOuter.BottomRight();
55 
56 	// Links Oben
57 	aRects[ 0 ] = Rectangle( aOuter.TopLeft(), aBorder );
58 	// Oben Mitte
59 	aRects[ 1 ] = Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2,
60 									aOuter.Top() ),
61 							aBorder );
62 	// Oben Rechts
63 	aRects[ 2 ] = Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
64 									aOuter.Top() ),
65 							aBorder );
66 	// Mitte Rechts
67 	aRects[ 3 ] = Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
68 									aOuter.Center().Y() - aBorder.Height() / 2 ),
69 							aBorder );
70 	// Unten Rechts
71 	aRects[ 4 ] = Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
72 									aBottomRight.Y() - aBorder.Height() +1 ),
73 							aBorder );
74 	// Mitte Unten
75 	aRects[ 5 ] = Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2,
76 									aBottomRight.Y() - aBorder.Height() +1),
77 							aBorder );
78 	// Links Unten
79 	aRects[ 6 ] = Rectangle( Point( aOuter.Left(),
80 									aBottomRight.Y() - aBorder.Height() +1),
81 							aBorder );
82 	// Mitte Links
83 	aRects[ 7 ] = Rectangle( Point( aOuter.Left(),
84 									aOuter.Center().Y() - aBorder.Height() / 2 ),
85 							aBorder );
86 }
87 
88 /*************************************************************************
89 |*    SvResizeHelper::FillMoveRectsPixel()
90 |*
91 |*    Beschreibung: Die vier Kanten werden berechnet
92 *************************************************************************/
FillMoveRectsPixel(Rectangle aRects[4]) const93 void SvResizeHelper::FillMoveRectsPixel( Rectangle aRects[ 4 ] ) const
94 {
95 	// Oben
96 	aRects[ 0 ] = aOuter;
97 	aRects[ 0 ].Bottom() = aRects[ 0 ].Top() + aBorder.Height() -1;
98 	// Rechts
99 	aRects[ 1 ] = aOuter;
100 	aRects[ 1 ].Left() = aRects[ 1 ].Right() - aBorder.Width() -1;
101 	//Unten
102 	aRects[ 2 ] = aOuter;
103 	aRects[ 2 ].Top() = aRects[ 2 ].Bottom() - aBorder.Height() -1;
104 	//Links
105 	aRects[ 3 ] = aOuter;
106 	aRects[ 3 ].Right() = aRects[ 3 ].Left() + aBorder.Width() -1;
107 }
108 
109 /*************************************************************************
110 |*    SvResizeHelper::Draw()
111 |*
112 |*    Beschreibung
113 *************************************************************************/
Draw(OutputDevice * pDev)114 void SvResizeHelper::Draw( OutputDevice * pDev )
115 {
116 	pDev->Push();
117 	pDev->SetMapMode( MapMode() );
118 	Color aColBlack;
119 	Color aFillColor( COL_LIGHTGRAY );
120 
121 	pDev->SetFillColor( aFillColor );
122 	pDev->SetLineColor();
123 
124 	Rectangle   aMoveRects[ 4 ];
125 	FillMoveRectsPixel( aMoveRects );
126 	sal_uInt16 i;
127 	for( i = 0; i < 4; i++ )
128 		pDev->DrawRect( aMoveRects[ i ] );
129 	if( bResizeable )
130 	{
131 		// Handles malen
132 		pDev->SetFillColor( aColBlack );
133 		Rectangle   aRects[ 8 ];
134 		FillHandleRectsPixel( aRects );
135 		for( i = 0; i < 8; i++ )
136 			pDev->DrawRect( aRects[ i ] );
137 	}
138 	pDev->Pop();
139 }
140 
141 /*************************************************************************
142 |*    SvResizeHelper::InvalidateBorder()
143 |*
144 |*    Beschreibung
145 *************************************************************************/
InvalidateBorder(Window * pWin)146 void SvResizeHelper::InvalidateBorder( Window * pWin )
147 {
148 	Rectangle   aMoveRects[ 4 ];
149 	FillMoveRectsPixel( aMoveRects );
150 	for( sal_uInt16 i = 0; i < 4; i++ )
151 		pWin->Invalidate( aMoveRects[ i ] );
152 }
153 
154 /*************************************************************************
155 |*    SvResizeHelper::SelectBegin()
156 |*
157 |*    Beschreibung
158 *************************************************************************/
SelectBegin(Window * pWin,const Point & rPos)159 sal_Bool SvResizeHelper::SelectBegin( Window * pWin, const Point & rPos )
160 {
161 	if( -1 == nGrab )
162 	{
163 		nGrab = SelectMove( pWin, rPos );
164 		if( -1 != nGrab )
165 		{
166 			aSelPos = rPos; // Start-Position merken
167 			pWin->CaptureMouse();
168 			return sal_True;
169 		}
170 	}
171 	return sal_False;
172 }
173 
174 /*************************************************************************
175 |*    SvResizeHelper::SelectMove()
176 |*
177 |*    Beschreibung
178 *************************************************************************/
SelectMove(Window * pWin,const Point & rPos)179 short SvResizeHelper::SelectMove( Window * pWin, const Point & rPos )
180 {
181 	if( -1 == nGrab )
182 	{
183 		if( bResizeable )
184 		{
185 			Rectangle aRects[ 8 ];
186 			FillHandleRectsPixel( aRects );
187 			for( sal_uInt16 i = 0; i < 8; i++ )
188 				if( aRects[ i ].IsInside( rPos ) )
189 					return i;
190 		}
191 		// Move-Rect ueberlappen Handles
192 		Rectangle aMoveRects[ 4 ];
193 		FillMoveRectsPixel( aMoveRects );
194 		for( sal_uInt16 i = 0; i < 4; i++ )
195 			if( aMoveRects[ i ].IsInside( rPos ) )
196 				return 8;
197 	}
198 	else
199 	{
200 		Rectangle aRect( GetTrackRectPixel( rPos ) );
201 		aRect.SetSize( pWin->PixelToLogic( aRect.GetSize() ) );
202 		aRect.SetPos( pWin->PixelToLogic( aRect.TopLeft() ) );
203 		pWin->ShowTracking( aRect );
204 	}
205 	return nGrab;
206 }
207 
GetTrackPosPixel(const Rectangle & rRect) const208 Point SvResizeHelper::GetTrackPosPixel( const Rectangle & rRect ) const
209 {
210 	// wie das Rechteck zurueckkommt ist egal, es zaehlt welches Handle
211 	// initial angefasst wurde
212 	Point aPos;
213 	Rectangle aRect( rRect );
214 	aRect.Justify();
215 	// nur wegen EMPTY_RECT
216 	Point aBR = aOuter.BottomRight();
217 	Point aTR = aOuter.TopRight();
218 	Point aBL = aOuter.BottomLeft();
219 	switch( nGrab )
220 	{
221 		case 0:
222 			aPos = aRect.TopLeft() - aOuter.TopLeft();
223 			break;
224 		case 1:
225 			aPos.Y() =  aRect.Top() - aOuter.Top();
226 			break;
227 		case 2:
228 			aPos =  aRect.TopRight() - aTR;
229 			break;
230 		case 3:
231 			aPos.X() = aRect.Right() - aTR.X();
232 			break;
233 		case 4:
234 			aPos =  aRect.BottomRight() - aBR;
235 			break;
236 		case 5:
237 			aPos.Y() = aRect.Bottom() - aBR.Y();
238 			break;
239 		case 6:
240 			aPos =  aRect.BottomLeft() - aBL;
241 			break;
242 		case 7:
243 			aPos.X() = aRect.Left() - aOuter.Left();
244 			break;
245 		case 8:
246 			aPos = aRect.TopLeft() - aOuter.TopLeft();
247 			break;
248 	}
249 	return aPos += aSelPos;
250 }
251 
252 /*************************************************************************
253 |*    SvResizeHelper::GetTrackRectPixel()
254 |*
255 |*    Beschreibung
256 *************************************************************************/
GetTrackRectPixel(const Point & rTrackPos) const257 Rectangle SvResizeHelper::GetTrackRectPixel( const Point & rTrackPos ) const
258 {
259 	Rectangle aTrackRect;
260 	if( -1 != nGrab )
261 	{
262 		Point aDiff = rTrackPos - aSelPos;
263 		aTrackRect = aOuter;
264 		Point aBR = aOuter.BottomRight();
265 		switch( nGrab )
266 		{
267 			case 0:
268 				aTrackRect.Top() += aDiff.Y();
269 				aTrackRect.Left() += aDiff.X();
270 				break;
271 			case 1:
272 				aTrackRect.Top() += aDiff.Y();
273 				break;
274 			case 2:
275 				aTrackRect.Top() += aDiff.Y();
276 				aTrackRect.Right() = aBR.X() + aDiff.X();
277 				break;
278 			case 3:
279 				aTrackRect.Right() = aBR.X() + aDiff.X();
280 				break;
281 			case 4:
282 				aTrackRect.Bottom() = aBR.Y() + aDiff.Y();
283 				aTrackRect.Right() = aBR.X() + aDiff.X();
284 				break;
285 			case 5:
286 				aTrackRect.Bottom() = aBR.Y() + aDiff.Y();
287 				break;
288 			case 6:
289 				aTrackRect.Bottom() = aBR.Y() + aDiff.Y();
290 				aTrackRect.Left() += aDiff.X();
291 				break;
292 			case 7:
293 				aTrackRect.Left() += aDiff.X();
294 				break;
295 			case 8:
296                 if( Application::GetSettings().GetLayoutRTL() )
297                     aDiff.X() = -aDiff.X(); // workaround for move in RTL mode
298 				aTrackRect.SetPos( aTrackRect.TopLeft() + aDiff );
299 				break;
300 /*
301 			case 0:
302 				aTrackRect = Rectangle( rTrackPos, aOuter.BottomRight() );
303 				break;
304 			case 1:
305 				aTrackRect = Rectangle( Point( aOuter.Left(), rTrackPos.Y() ),
306 										 aOuter.BottomRight() );
307 				break;
308 			case 2:
309 				aTrackRect = Rectangle( rTrackPos, aOuter.BottomLeft() );
310 				break;
311 			case 3:
312 				aTrackRect = Rectangle( Point( rTrackPos.X(), aOuter.Top() ),
313 										 aOuter.BottomLeft() );
314 				break;
315 			case 4:
316 				aTrackRect = Rectangle( rTrackPos, aOuter.TopLeft() );
317 				break;
318 			case 5:
319 				aTrackRect = Rectangle( aOuter.TopLeft(),
320 									 Point( aOuter.Right(), rTrackPos.Y() ) );
321 				break;
322 			case 6:
323 				aTrackRect = Rectangle( aOuter.TopRight(), rTrackPos );
324 				break;
325 			case 7:
326 				aTrackRect = Rectangle( Point( rTrackPos.X(), aOuter.Top() ),
327 										 aOuter.BottomRight() );
328 				break;
329 			case 8:
330 				aTrackRect = Rectangle( aOuter.TopLeft() + rTrackPos - aSelPos,
331 										aOuter.GetSize() );
332 				break;
333 */
334 		}
335 	}
336 	return aTrackRect;
337 }
338 
ValidateRect(Rectangle & rValidate) const339 void SvResizeHelper::ValidateRect( Rectangle & rValidate ) const
340 {
341 	switch( nGrab )
342 	{
343 		case 0:
344 			if( rValidate.Top() > rValidate.Bottom() )
345 			{
346 				rValidate.Top() = rValidate.Bottom();
347 				rValidate.Bottom() = RECT_EMPTY;
348 			}
349 			if( rValidate.Left() > rValidate.Right() )
350 			{
351 				rValidate.Left() = rValidate.Right();
352 				rValidate.Right() = RECT_EMPTY;
353 			}
354 			break;
355 		case 1:
356 			if( rValidate.Top() > rValidate.Bottom() )
357 			{
358 				rValidate.Top() = rValidate.Bottom();
359 				rValidate.Bottom() = RECT_EMPTY;
360 			}
361 			break;
362 		case 2:
363 			if( rValidate.Top() > rValidate.Bottom() )
364 			{
365 				rValidate.Top() = rValidate.Bottom();
366 				rValidate.Bottom() = RECT_EMPTY;
367 			}
368 			if( rValidate.Left() > rValidate.Right() )
369 				rValidate.Right() = RECT_EMPTY;
370 			break;
371 		case 3:
372 			if( rValidate.Left() > rValidate.Right() )
373 				rValidate.Right() = RECT_EMPTY;
374 			break;
375 		case 4:
376 			if( rValidate.Top() > rValidate.Bottom() )
377 				rValidate.Bottom() = RECT_EMPTY;
378 			if( rValidate.Left() > rValidate.Right() )
379 				rValidate.Right() = RECT_EMPTY;
380 			break;
381 		case 5:
382 			if( rValidate.Top() > rValidate.Bottom() )
383 				rValidate.Bottom() = RECT_EMPTY;
384 			break;
385 		case 6:
386 			if( rValidate.Top() > rValidate.Bottom() )
387 				rValidate.Bottom() = RECT_EMPTY;
388 			if( rValidate.Left() > rValidate.Right() )
389 			{
390 				rValidate.Left() = rValidate.Right();
391 				rValidate.Right() = RECT_EMPTY;
392 			}
393 			break;
394 		case 7:
395 			if( rValidate.Left() > rValidate.Right() )
396 			{
397 				rValidate.Left() = rValidate.Right();
398 				rValidate.Right() = RECT_EMPTY;
399 			}
400 			break;
401 	}
402 	if( rValidate.Right() == RECT_EMPTY )
403 		rValidate.Right() = rValidate.Left();
404 	if( rValidate.Bottom() == RECT_EMPTY )
405 		rValidate.Bottom() = rValidate.Top();
406 
407 	// Mindestgr"osse 5 x 5
408 	if( rValidate.Left() + 5 > rValidate.Right() )
409 		rValidate.Right() = rValidate.Left() +5;
410 	if( rValidate.Top() + 5 > rValidate.Bottom() )
411 		rValidate.Bottom() = rValidate.Top() +5;
412 }
413 
414 /*************************************************************************
415 |*    SvResizeHelper::SelectRelease()
416 |*
417 |*    Beschreibung
418 *************************************************************************/
SelectRelease(Window * pWin,const Point & rPos,Rectangle & rOutPosSize)419 sal_Bool SvResizeHelper::SelectRelease( Window * pWin, const Point & rPos,
420 									Rectangle & rOutPosSize )
421 {
422 	if( -1 != nGrab )
423 	{
424 		rOutPosSize = GetTrackRectPixel( rPos );
425 		rOutPosSize.Justify();
426 		nGrab = -1;
427 		pWin->ReleaseMouse();
428 		pWin->HideTracking();
429 		return sal_True;
430 	}
431 	return sal_False;
432 }
433 
434 /*************************************************************************
435 |*    SvResizeHelper::Release()
436 |*
437 |*    Beschreibung
438 *************************************************************************/
Release(Window * pWin)439 void SvResizeHelper::Release( Window * pWin )
440 {
441 	if( nGrab != -1 )
442 	{
443 		pWin->ReleaseMouse();
444 		pWin->HideTracking();
445 		nGrab = -1;
446 	}
447 }
448 
449 /*************************************************************************
450 |*    SvResizeWindow::SvResizeWindow()
451 |*
452 |*    Beschreibung
453 *************************************************************************/
SvResizeWindow(Window * pParent,VCLXHatchWindow * pWrapper)454 SvResizeWindow::SvResizeWindow
455 (
456 	Window * pParent,
457 	VCLXHatchWindow* pWrapper
458 )
459 	: Window( pParent, WB_CLIPCHILDREN )
460 	, m_nMoveGrab( -1 )
461     , m_bActive( sal_False )
462 	, m_pWrapper( pWrapper )
463 {
464 	OSL_ENSURE( pParent != NULL && pWrapper != NULL, "Wrong initialization of hatch window!\n" );
465 	SetBackground();
466 	SetAccessibleRole( ::com::sun::star::accessibility::AccessibleRole::EMBEDDED_OBJECT );
467 	m_aResizer.SetOuterRectPixel( Rectangle( Point(), GetOutputSizePixel() ) );
468 }
469 
470 /*************************************************************************
471 |*    SvResizeWindow::SetHatchBorderPixel()
472 |*
473 |*    Beschreibung
474 *************************************************************************/
SetHatchBorderPixel(const Size & rSize)475 void SvResizeWindow::SetHatchBorderPixel( const Size & rSize )
476 {
477 	 m_aResizer.SetBorderPixel( rSize );
478 }
479 
480 /*************************************************************************
481 |*    SvResizeWindow::SelectMouse()
482 |*
483 |*    Beschreibung
484 *************************************************************************/
SelectMouse(const Point & rPos)485 void SvResizeWindow::SelectMouse( const Point & rPos )
486 {
487 	short nGrab = m_aResizer.SelectMove( this, rPos );
488 	if( nGrab >= 4 )
489 		nGrab -= 4;
490 	if( m_nMoveGrab != nGrab )
491 	{ // Pointer hat sich geaendert
492 		if( -1 == nGrab )
493 			SetPointer( m_aOldPointer );
494 		else
495 		{
496 			PointerStyle aStyle = POINTER_MOVE;
497 			if( nGrab == 3 )
498 				aStyle = POINTER_ESIZE;
499 			else if( nGrab == 2 )
500 				aStyle = POINTER_NESIZE;
501 			else if( nGrab == 1 )
502 				aStyle = POINTER_SSIZE;
503 			else if( nGrab == 0 )
504 				aStyle = POINTER_SESIZE;
505 			if( m_nMoveGrab == -1 ) // das erste mal
506 			{
507 				m_aOldPointer = GetPointer();
508 				SetPointer( Pointer( aStyle ) );
509 			}
510 			else
511 				SetPointer( Pointer( aStyle ) );
512 		}
513 		m_nMoveGrab = nGrab;
514 	}
515 }
516 
517 /*************************************************************************
518 |*    SvResizeWindow::MouseButtonDown()
519 |*
520 |*    Beschreibung
521 *************************************************************************/
MouseButtonDown(const MouseEvent & rEvt)522 void SvResizeWindow::MouseButtonDown( const MouseEvent & rEvt )
523 {
524 	if( m_aResizer.SelectBegin( this, rEvt.GetPosPixel() ) )
525 		SelectMouse( rEvt.GetPosPixel() );
526 }
527 
528 /*************************************************************************
529 |*    SvResizeWindow::MouseMove()
530 |*
531 |*    Beschreibung
532 *************************************************************************/
MouseMove(const MouseEvent & rEvt)533 void SvResizeWindow::MouseMove( const MouseEvent & rEvt )
534 {
535 	if( m_aResizer.GetGrab() == -1 )
536 		SelectMouse( rEvt.GetPosPixel() );
537 	else
538 	{
539 		Rectangle aRect( m_aResizer.GetTrackRectPixel( rEvt.GetPosPixel() ) );
540 		Point aDiff = GetPosPixel();
541 		aRect.SetPos( aRect.TopLeft() + aDiff );
542 		m_aResizer.ValidateRect( aRect );
543 
544 		m_pWrapper->QueryObjAreaPixel( aRect );
545 		aRect.SetPos( aRect.TopLeft() - aDiff );
546 		Point aPos = m_aResizer.GetTrackPosPixel( aRect );
547 
548 		SelectMouse( aPos );
549 	}
550 }
551 
552 /*************************************************************************
553 |*    SvResizeWindow::MouseButtonUp()
554 |*
555 |*    Beschreibung
556 *************************************************************************/
MouseButtonUp(const MouseEvent & rEvt)557 void SvResizeWindow::MouseButtonUp( const MouseEvent & rEvt )
558 {
559 	if( m_aResizer.GetGrab() != -1 )
560 	{
561 		Rectangle aRect( m_aResizer.GetTrackRectPixel( rEvt.GetPosPixel() ) );
562 		Point aDiff = GetPosPixel();
563 		aRect.SetPos( aRect.TopLeft() + aDiff );
564 		// aRect -= GetAllBorderPixel();
565 		m_aResizer.ValidateRect( aRect );
566 
567 		m_pWrapper->QueryObjAreaPixel( aRect );
568 
569 		Rectangle aOutRect;
570 		if( m_aResizer.SelectRelease( this, rEvt.GetPosPixel(), aOutRect ) )
571 		{
572 			m_nMoveGrab = -1;
573 			SetPointer( m_aOldPointer );
574 			m_pWrapper->RequestObjAreaPixel( aRect );
575 		}
576 	}
577 }
578 
579 /*************************************************************************
580 |*    SvResizeWindow::KeyEvent()
581 |*
582 |*    Beschreibung
583 *************************************************************************/
KeyInput(const KeyEvent & rEvt)584 void SvResizeWindow::KeyInput( const KeyEvent & rEvt )
585 {
586 	if( rEvt.GetKeyCode().GetCode() == KEY_ESCAPE )
587 	{
588 		m_aResizer.Release( this );
589 		m_pWrapper->InplaceDeactivate();
590 	}
591 }
592 
593 /*************************************************************************
594 |*    SvResizeWindow::Resize()
595 |*
596 |*    Beschreibung
597 *************************************************************************/
Resize()598 void SvResizeWindow::Resize()
599 {
600 	m_aResizer.InvalidateBorder( this ); // alten Bereich
601 	m_aResizer.SetOuterRectPixel( Rectangle( Point(), GetOutputSizePixel() ) );
602 	m_aResizer.InvalidateBorder( this ); // neuen Bereich
603 }
604 
605 /*************************************************************************
606 |*    SvResizeWindow::Paint()
607 |*
608 |*    Beschreibung
609 *************************************************************************/
Paint(const Rectangle &)610 void SvResizeWindow::Paint( const Rectangle & /*rRect*/ )
611 {
612 	m_aResizer.Draw( this );
613 }
614 
PreNotify(NotifyEvent & rEvt)615 long SvResizeWindow::PreNotify( NotifyEvent& rEvt )
616 {
617     if ( rEvt.GetType() == EVENT_GETFOCUS && !m_bActive )
618     {
619         m_bActive = sal_True;
620         m_pWrapper->Activated();
621     }
622 
623     return Window::PreNotify(rEvt);
624 }
625 
Notify(NotifyEvent & rEvt)626 long SvResizeWindow::Notify( NotifyEvent& rEvt )
627 {
628     if ( rEvt.GetType() == EVENT_LOSEFOCUS && m_bActive )
629     {
630         sal_Bool bHasFocus = HasChildPathFocus(sal_True);
631         if ( !bHasFocus )
632         {
633             m_bActive = sal_False;
634             m_pWrapper->Deactivated();
635         }
636     }
637 
638     return Window::Notify(rEvt);
639 }
640 
641