merge the formfield patch from ooo-build
[ooovba.git] / svx / source / editeng / impedit.cxx
blob0283856ee3d6fb3e0f52d1d4b8e7fb57d33858b7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: impedit.cxx,v $
10 * $Revision: 1.64 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <eeng_pch.hxx>
36 #include <impedit.hxx>
37 #include <svx/editeng.hxx>
38 #include <svx/editview.hxx>
39 #include <tools/poly.hxx>
40 #include <unolingu.hxx>
41 #include <sfx2/sfxuno.hxx>
42 #include <com/sun/star/linguistic2/XDictionaryEntry.hpp>
43 #include <com/sun/star/linguistic2/DictionaryType.hpp>
44 #include <com/sun/star/linguistic2/DictionaryEvent.hpp>
45 #include <com/sun/star/linguistic2/XDictionaryEventListener.hpp>
46 #include <com/sun/star/linguistic2/DictionaryEventFlags.hpp>
47 #include <com/sun/star/linguistic2/XDictionary.hpp>
49 #ifndef _COM_SUN_STAR_DATATRANSFER_DND_DNDCONSTANS_HPP_
50 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
51 #endif
52 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
53 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
54 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
55 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
57 #include <vos/mutex.hxx>
59 #include <svx/flditem.hxx>
60 #include <svtools/intitem.hxx>
61 #include <svtools/transfer.hxx>
63 #include <sot/exchange.hxx>
64 #include <sot/formats.hxx>
67 using namespace ::com::sun::star;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::linguistic2;
71 #define SCRLRANGE 20 // 1/20 der Breite/Hoehe scrollen, wenn im QueryDrop
73 inline void lcl_AllignToPixel( Point& rPoint, OutputDevice* pOutDev, short nDiffX, short nDiffY )
75 rPoint = pOutDev->LogicToPixel( rPoint );
77 if ( nDiffX )
78 rPoint.X() += nDiffX;
79 if ( nDiffY )
80 rPoint.Y() += nDiffY;
82 rPoint = pOutDev->PixelToLogic( rPoint );
85 \f// ----------------------------------------------------------------------
86 // class ImpEditView
87 // ----------------------------------------------------------------------
88 ImpEditView::ImpEditView( EditView* pView, EditEngine* pEng, Window* pWindow ) :
89 aOutArea( Point(), pEng->GetPaperSize() )
91 pEditView = pView;
92 pEditEngine = pEng;
93 pOutWin = pWindow;
94 pPointer = NULL;
95 pBackgroundColor = NULL;
96 nScrollDiffX = 0;
97 nExtraCursorFlags = 0;
98 nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW;
99 pCursor = NULL;
100 pDragAndDropInfo = NULL;
101 bReadOnly = sal_False;
102 bClickedInSelection = sal_False;
103 eSelectionMode = EE_SELMODE_TXTONLY;
104 eAnchorMode = ANCHOR_TOP_LEFT;
105 nInvMore = 1;
106 nTravelXPos = TRAVEL_X_DONTKNOW;
107 nControl = EV_CNTRL_AUTOSCROLL | EV_CNTRL_ENABLEPASTE;
108 bActiveDragAndDropListener = FALSE;
110 aEditSelection.Min() = pEng->pImpEditEngine->GetEditDoc().GetStartPaM();
111 aEditSelection.Max() = pEng->pImpEditEngine->GetEditDoc().GetEndPaM();
114 ImpEditView::~ImpEditView()
116 RemoveDragAndDropListeners();
118 if ( pOutWin && ( pOutWin->GetCursor() == pCursor ) )
119 pOutWin->SetCursor( NULL );
121 delete pCursor;
122 delete pBackgroundColor;
123 delete pPointer;
124 delete pDragAndDropInfo;
127 void ImpEditView::SetBackgroundColor( const Color& rColor )
129 delete pBackgroundColor;
130 pBackgroundColor = new Color( rColor );
133 void ImpEditView::SetEditSelection( const EditSelection& rEditSelection )
135 // #100856# set state before notification
136 aEditSelection = rEditSelection;
138 if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() )
140 EENotify aNotify( EE_NOTIFY_TEXTVIEWSELECTIONCHANGED );
141 aNotify.pEditEngine = pEditEngine;
142 aNotify.pEditView = GetEditViewPtr();
143 pEditEngine->pImpEditEngine->CallNotify( aNotify );
148 void ImpEditView::DrawSelection( EditSelection aTmpSel, Region* pRegion )
150 if ( GetSelectionMode() == EE_SELMODE_HIDDEN )
151 return;
153 // Vor dem Zeichnen der Selektion muss sichergestellt werden,
154 // das der Fensterinhalt komplett gueltig ist!
155 // Muss hier stehen, damit auf jeden Fall weg wenn lerr, nicht spaeter
156 // zwei Paint-Events!
157 // 19.10: Muss sogar vor Abfrage von bUpdate, falls nach Invalidate
158 // noch Paints in der Queue, aber jemand schaltet den UpdateMode um!
160 // pRegion: Wenn nicht NULL, dann nur Region berechnen.
161 PolyPolygon* pPolyPoly = NULL;
162 if ( pRegion )
163 pPolyPoly = new PolyPolygon;
165 sal_Bool bClipRegion = pOutWin->IsClipRegion();
166 Region aOldRegion = pOutWin->GetClipRegion();
168 if ( !pRegion )
170 if ( pEditEngine->pImpEditEngine->GetUpdateMode() == sal_False )
171 return;
172 if ( pEditEngine->pImpEditEngine->IsInUndo() )
173 return;
175 if ( !aTmpSel.HasRange() )
176 return;
178 // aTmpOutArea: Falls OutputArea > Papierbreite und
179 // Text > Papierbreite ( uebergrosse Felder )
180 Rectangle aTmpOutArea( aOutArea );
181 if ( aTmpOutArea.GetWidth() > pEditEngine->pImpEditEngine->GetPaperSize().Width() )
182 aTmpOutArea.Right() = aTmpOutArea.Left() + pEditEngine->pImpEditEngine->GetPaperSize().Width();
183 pOutWin->IntersectClipRegion( aTmpOutArea );
185 if ( pOutWin->GetCursor() )
186 pOutWin->GetCursor()->Hide();
189 DBG_ASSERT( !pEditEngine->pImpEditEngine->aIdleFormatter.IsActive(), "DrawSelection: Not formatted!" );
190 aTmpSel.Adjust( pEditEngine->pImpEditEngine->GetEditDoc() );
192 ContentNode* pStartNode = aTmpSel.Min().GetNode();
193 ContentNode* pEndNode = aTmpSel.Max().GetNode();
194 sal_uInt16 nStartPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( pStartNode );
195 sal_uInt16 nEndPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( pEndNode );
196 // ueber die Absaetze iterieren....
197 for ( sal_uInt16 nPara = nStartPara; nPara <= nEndPara; nPara++ )
199 ParaPortion* pTmpPortion = pEditEngine->pImpEditEngine->GetParaPortions().SaveGetObject( nPara );
200 DBG_ASSERT( pTmpPortion, "Portion in Selektion nicht gefunden!" );
201 DBG_ASSERT( !pTmpPortion->IsInvalid(), "Portion in Selektion nicht formatiert!" );
203 if ( !pTmpPortion->IsVisible() || pTmpPortion->IsInvalid() )
204 continue;
206 long nParaStart = pEditEngine->pImpEditEngine->GetParaPortions().GetYOffset( pTmpPortion );
207 if ( ( nParaStart + pTmpPortion->GetHeight() ) < GetVisDocTop() )
208 continue;
209 if ( nParaStart > GetVisDocBottom() )
210 break;
212 sal_uInt16 nStartLine = 0;
213 sal_uInt16 nEndLine = pTmpPortion->GetLines().Count() -1;
214 if ( nPara == nStartPara )
215 nStartLine = pTmpPortion->GetLines().FindLine( aTmpSel.Min().GetIndex(), sal_False );
216 if ( nPara == nEndPara )
217 nEndLine = pTmpPortion->GetLines().FindLine( aTmpSel.Max().GetIndex(), sal_True );
219 // ueber die Zeilen iterieren....
220 for ( sal_uInt16 nLine = nStartLine; nLine <= nEndLine; nLine++ )
222 EditLine* pLine = pTmpPortion->GetLines().GetObject( nLine );
223 DBG_ASSERT( pLine, "Zeile nicht gefunden: DrawSelection()" );
225 BOOL bPartOfLine = FALSE;
226 sal_uInt16 nStartIndex = pLine->GetStart();
227 sal_uInt16 nEndIndex = pLine->GetEnd();
228 if ( ( nPara == nStartPara ) && ( nLine == nStartLine ) && ( nStartIndex != aTmpSel.Min().GetIndex() ) )
230 nStartIndex = aTmpSel.Min().GetIndex();
231 bPartOfLine = TRUE;
233 if ( ( nPara == nEndPara ) && ( nLine == nEndLine ) && ( nEndIndex != aTmpSel.Max().GetIndex() ) )
235 nEndIndex = aTmpSel.Max().GetIndex();
236 bPartOfLine = TRUE;
239 // Kann passieren, wenn am Anfang einer umgebrochenen Zeile.
240 if ( nEndIndex < nStartIndex )
241 nEndIndex = nStartIndex;
243 Rectangle aTmpRec( pEditEngine->pImpEditEngine->GetEditCursor( pTmpPortion, nStartIndex ) );
244 Point aTopLeft( aTmpRec.TopLeft() );
245 Point aBottomRight( aTmpRec.BottomRight() );
247 aTopLeft.Y() += nParaStart;
248 aBottomRight.Y() += nParaStart;
250 // Nur Painten, wenn im sichtbaren Bereich...
251 if ( aTopLeft.Y() > GetVisDocBottom() )
252 break;
254 if ( aBottomRight.Y() < GetVisDocTop() )
255 continue;
257 // Now that we have Bidi, the first/last index doesn't have to be the 'most outside' postion
258 if ( !bPartOfLine )
260 Range aLineXPosStartEnd = pEditEngine->pImpEditEngine->GetLineXPosStartEnd( pTmpPortion, pLine );
261 aTopLeft.X() = aLineXPosStartEnd.Min();
262 aBottomRight.X() = aLineXPosStartEnd.Max();
263 ImplDrawHighlightRect( pOutWin, aTopLeft, aBottomRight, pPolyPoly );
265 else
267 USHORT nTmpStartIndex = nStartIndex;
268 USHORT nWritingDirStart, nTmpEndIndex;
270 while ( nTmpStartIndex < nEndIndex )
272 pEditEngine->pImpEditEngine->GetRightToLeft( nPara, nTmpStartIndex+1, &nWritingDirStart, &nTmpEndIndex );
273 if ( nTmpEndIndex > nEndIndex )
274 nTmpEndIndex = nEndIndex;
276 DBG_ASSERT( nTmpEndIndex > nTmpStartIndex, "DrawSelection, Start >= End?" );
278 long nX1 = pEditEngine->pImpEditEngine->GetXPos( pTmpPortion, pLine, nTmpStartIndex, TRUE );
279 long nX2 = pEditEngine->pImpEditEngine->GetXPos( pTmpPortion, pLine, nTmpEndIndex );
281 Point aPt1( Min( nX1, nX2 ), aTopLeft.Y() );
282 Point aPt2( Max( nX1, nX2 ), aBottomRight.Y() );
284 ImplDrawHighlightRect( pOutWin, aPt1, aPt2, pPolyPoly );
286 nTmpStartIndex = nTmpEndIndex;
293 if ( pRegion )
295 *pRegion = Region( *pPolyPoly );
296 delete pPolyPoly;
298 else
300 if ( pOutWin->GetCursor() )
301 pOutWin->GetCursor()->Show();
303 if ( bClipRegion )
304 pOutWin->SetClipRegion( aOldRegion );
305 else
306 pOutWin->SetClipRegion();
310 void ImpEditView::ImplDrawHighlightRect( Window* _pOutWin, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, PolyPolygon* pPolyPoly )
312 if ( rDocPosTopLeft.X() != rDocPosBottomRight.X() )
314 sal_Bool bPixelMode = _pOutWin->GetMapMode() == MAP_PIXEL;
316 Point aPnt1( GetWindowPos( rDocPosTopLeft ) );
317 Point aPnt2( GetWindowPos( rDocPosBottomRight ) );
319 if ( !IsVertical() )
321 lcl_AllignToPixel( aPnt1, _pOutWin, +1, 0 );
322 lcl_AllignToPixel( aPnt2, _pOutWin, 0, ( bPixelMode ? 0 : -1 ) );
324 else
326 lcl_AllignToPixel( aPnt1, _pOutWin, 0, +1 );
327 lcl_AllignToPixel( aPnt2, _pOutWin, ( bPixelMode ? 0 : +1 ), 0 );
330 Rectangle aRect( aPnt1, aPnt2 );
331 if ( pPolyPoly )
333 Polygon aTmpPoly( 4 );
334 aTmpPoly[0] = aRect.TopLeft();
335 aTmpPoly[1] = aRect.TopRight();
336 aTmpPoly[2] = aRect.BottomRight();
337 aTmpPoly[3] = aRect.BottomLeft();
338 pPolyPoly->Insert( aTmpPoly );
340 else
342 _pOutWin->Invert( aRect );
348 BOOL ImpEditView::IsVertical() const
350 return pEditEngine->pImpEditEngine->IsVertical();
353 Rectangle ImpEditView::GetVisDocArea() const
355 return Rectangle( GetVisDocLeft(), GetVisDocTop(), GetVisDocRight(), GetVisDocBottom() );
358 Point ImpEditView::GetDocPos( const Point& rWindowPos ) const
360 // Fensterposition => Dokumentposition
361 Point aPoint;
363 if ( !pEditEngine->pImpEditEngine->IsVertical() )
365 aPoint.X() = rWindowPos.X() - aOutArea.Left() + GetVisDocLeft();
366 aPoint.Y() = rWindowPos.Y() - aOutArea.Top() + GetVisDocTop();
368 else
370 aPoint.X() = rWindowPos.Y() - aOutArea.Top() + GetVisDocLeft();
371 aPoint.Y() = aOutArea.Right() - rWindowPos.X() + GetVisDocTop();
374 return aPoint;
377 Point ImpEditView::GetWindowPos( const Point& rDocPos ) const
379 // Dokumentposition => Fensterposition
380 Point aPoint;
382 if ( !pEditEngine->pImpEditEngine->IsVertical() )
384 aPoint.X() = rDocPos.X() + aOutArea.Left() - GetVisDocLeft();
385 aPoint.Y() = rDocPos.Y() + aOutArea.Top() - GetVisDocTop();
387 else
389 aPoint.X() = aOutArea.Right() - rDocPos.Y() + GetVisDocTop();
390 aPoint.Y() = rDocPos.X() + aOutArea.Top() - GetVisDocLeft();
393 return aPoint;
396 Rectangle ImpEditView::GetWindowPos( const Rectangle& rDocRect ) const
398 // Dokumentposition => Fensterposition
399 Point aPos( GetWindowPos( rDocRect.TopLeft() ) );
400 Size aSz = rDocRect.GetSize();
401 Rectangle aRect;
402 if ( !pEditEngine->pImpEditEngine->IsVertical() )
404 aRect = Rectangle( aPos, aSz );
406 else
408 Point aNewPos( aPos.X()-aSz.Height(), aPos.Y() );
409 aRect = Rectangle( aNewPos, Size( aSz.Height(), aSz.Width() ) );
411 return aRect;
415 Region* ImpEditView::CalcSelectedRegion()
417 Region* pRegion = new Region;
418 DrawSelection( GetEditSelection(), pRegion );
419 return pRegion;
422 void ImpEditView::SetSelectionMode( EESelectionMode eNewMode )
424 if ( eSelectionMode != eNewMode )
426 DrawSelection(); // 'Wegmalen' ...
427 eSelectionMode = eNewMode;
428 DrawSelection(); // und neu zeichnen.
432 void ImpEditView::SetOutputArea( const Rectangle& rRec )
434 // sollte besser auf Pixel allignt sein!
435 Rectangle aNewRec( pOutWin->LogicToPixel( rRec ) );
436 aNewRec = pOutWin->PixelToLogic( aNewRec );
437 aOutArea = aNewRec;
438 if ( aOutArea.Right() < aOutArea.Left() )
439 aOutArea.Right() = aOutArea.Left();
440 if ( aOutArea.Bottom() < aOutArea.Top() )
441 aOutArea.Bottom() = aOutArea.Top();
443 if ( DoBigScroll() )
444 SetScrollDiffX( (sal_uInt16)aOutArea.GetWidth() * 3 / 10 );
445 else
446 SetScrollDiffX( (sal_uInt16)aOutArea.GetWidth() * 2 / 10 );
449 void ImpEditView::ResetOutputArea( const Rectangle& rRec )
451 Rectangle aCurArea( aOutArea );
452 SetOutputArea( rRec );
453 // Umliegende Bereiche invalidieren, wenn UpdateMode der Engine auf sal_True
454 if ( !aCurArea.IsEmpty() && pEditEngine->pImpEditEngine->GetUpdateMode() )
456 long nMore = 0;
457 if ( DoInvalidateMore() )
458 nMore = GetWindow()->PixelToLogic( Size( nInvMore, 0 ) ).Width();
459 if ( aCurArea.Left() < aOutArea.Left() )
461 Rectangle aRect( aCurArea.TopLeft(),
462 Size( aOutArea.Left()-aCurArea.Left(), aCurArea.GetHeight() ) );
463 if ( nMore )
465 aRect.Left() -= nMore;
466 aRect.Top() -= nMore;
467 aRect.Bottom() += nMore;
469 GetWindow()->Invalidate( aRect );
471 if ( aCurArea.Right() > aOutArea.Right() )
473 long nW = aCurArea.Right() - aOutArea.Right();
474 Point aPos( aCurArea.TopRight() );
475 aPos.X() -= nW;
476 Rectangle aRect( aPos, Size( nW, aCurArea.GetHeight() ) );
477 if ( nMore )
479 aRect.Right() += nMore;
480 aRect.Top() -= nMore;
481 aRect.Bottom() += nMore;
483 GetWindow()->Invalidate( aRect );
485 if ( aCurArea.Top() < aOutArea.Top() )
487 Rectangle aRect( aCurArea.TopLeft(), Size( aCurArea.GetWidth(), aOutArea.Top() - aCurArea.Top() ) );
488 if ( nMore )
490 aRect.Top() -= nMore;
491 aRect.Left() -= nMore;
492 aRect.Right() += nMore;
494 GetWindow()->Invalidate( aRect );
496 if ( aCurArea.Bottom() > aOutArea.Bottom() )
498 long nH = aCurArea.Bottom() - aOutArea.Bottom();
499 Point aPos( aCurArea.BottomLeft() );
500 aPos.Y() -= nH;
501 Rectangle aRect( aPos, Size( aCurArea.GetWidth(), nH ) );
502 if ( nMore )
504 aRect.Bottom() += nMore;
505 aRect.Left() -= nMore;
506 aRect.Right() += nMore;
509 GetWindow()->Invalidate( aRect );
514 void ImpEditView::RecalcOutputArea()
516 Rectangle aOldArea( aOutArea );
517 Point aNewTopLeft( aOutArea.TopLeft() );
518 Size aNewSz( aOutArea.GetSize() );
520 // X:
521 if ( DoAutoWidth() )
523 if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageWidth() )
524 aNewSz.Width() = pEditEngine->pImpEditEngine->GetPaperSize().Width();
525 switch ( eAnchorMode )
527 case ANCHOR_TOP_LEFT:
528 case ANCHOR_VCENTER_LEFT:
529 case ANCHOR_BOTTOM_LEFT:
531 aNewTopLeft.X() = aAnchorPoint.X();
533 break;
534 case ANCHOR_TOP_HCENTER:
535 case ANCHOR_VCENTER_HCENTER:
536 case ANCHOR_BOTTOM_HCENTER:
538 aNewTopLeft.X() = aAnchorPoint.X() - aNewSz.Width() / 2;
540 break;
541 case ANCHOR_TOP_RIGHT:
542 case ANCHOR_VCENTER_RIGHT:
543 case ANCHOR_BOTTOM_RIGHT:
545 aNewTopLeft.X() = aAnchorPoint.X() - aNewSz.Width() - 1;
547 break;
551 // Y:
552 if ( DoAutoHeight() )
554 if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageHeight() )
555 aNewSz.Height() = pEditEngine->pImpEditEngine->GetPaperSize().Height();
556 switch ( eAnchorMode )
558 case ANCHOR_TOP_LEFT:
559 case ANCHOR_TOP_HCENTER:
560 case ANCHOR_TOP_RIGHT:
562 aNewTopLeft.Y() = aAnchorPoint.Y();
564 break;
565 case ANCHOR_VCENTER_LEFT:
566 case ANCHOR_VCENTER_HCENTER:
567 case ANCHOR_VCENTER_RIGHT:
569 aNewTopLeft.Y() = aAnchorPoint.Y() - aNewSz.Height() / 2;
571 break;
572 case ANCHOR_BOTTOM_LEFT:
573 case ANCHOR_BOTTOM_HCENTER:
574 case ANCHOR_BOTTOM_RIGHT:
576 aNewTopLeft.Y() = aAnchorPoint.Y() - aNewSz.Height() - 1;
578 break;
581 ResetOutputArea( Rectangle( aNewTopLeft, aNewSz ) );
584 void ImpEditView::SetAnchorMode( EVAnchorMode eMode )
586 eAnchorMode = eMode;
587 CalcAnchorPoint();
590 void ImpEditView::CalcAnchorPoint()
592 // GetHeight() und GetWidth() -1, da Rectangle-Berechnung nicht erwuenscht.
594 // X:
595 switch ( eAnchorMode )
597 case ANCHOR_TOP_LEFT:
598 case ANCHOR_VCENTER_LEFT:
599 case ANCHOR_BOTTOM_LEFT:
601 aAnchorPoint.X() = aOutArea.Left();
603 break;
604 case ANCHOR_TOP_HCENTER:
605 case ANCHOR_VCENTER_HCENTER:
606 case ANCHOR_BOTTOM_HCENTER:
608 aAnchorPoint.X() = aOutArea.Left() + (aOutArea.GetWidth()-1) / 2;
610 break;
611 case ANCHOR_TOP_RIGHT:
612 case ANCHOR_VCENTER_RIGHT:
613 case ANCHOR_BOTTOM_RIGHT:
615 aAnchorPoint.X() = aOutArea.Right();
617 break;
620 // Y:
621 switch ( eAnchorMode )
623 case ANCHOR_TOP_LEFT:
624 case ANCHOR_TOP_HCENTER:
625 case ANCHOR_TOP_RIGHT:
627 aAnchorPoint.Y() = aOutArea.Top();
629 break;
630 case ANCHOR_VCENTER_LEFT:
631 case ANCHOR_VCENTER_HCENTER:
632 case ANCHOR_VCENTER_RIGHT:
634 aAnchorPoint.Y() = aOutArea.Top() + (aOutArea.GetHeight()-1) / 2;
636 break;
637 case ANCHOR_BOTTOM_LEFT:
638 case ANCHOR_BOTTOM_HCENTER:
639 case ANCHOR_BOTTOM_RIGHT:
641 aAnchorPoint.Y() = aOutArea.Bottom() - 1;
643 break;
647 void ImpEditView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, USHORT nShowCursorFlags )
649 // Kein ShowCursor bei einer leeren View...
650 if ( ( aOutArea.Left() >= aOutArea.Right() ) && ( aOutArea.Top() >= aOutArea.Bottom() ) )
651 return;
653 pEditEngine->pImpEditEngine->CheckIdleFormatter();
654 if ( !pEditEngine->pImpEditEngine->IsFormatted() )
655 pEditEngine->pImpEditEngine->FormatDoc();
657 // Aus irgendwelchen Gruenden lande ich waehrend der Formatierung hier,
658 // wenn sich der Outiner im Paint initialisiert, weil kein SetPool();
659 if ( pEditEngine->pImpEditEngine->IsFormatting() )
660 return;
661 if ( pEditEngine->pImpEditEngine->GetUpdateMode() == sal_False )
662 return;
663 if ( pEditEngine->pImpEditEngine->IsInUndo() )
664 return;
666 if ( pOutWin->GetCursor() != GetCursor() )
667 pOutWin->SetCursor( GetCursor() );
669 EditPaM aPaM( aEditSelection.Max() );
671 USHORT nTextPortionStart = 0;
672 USHORT nPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
673 if (nPara == USHRT_MAX) // #i94322
674 return;
675 ParaPortion* pParaPortion = pEditEngine->pImpEditEngine->GetParaPortions().GetObject( nPara );
677 nShowCursorFlags |= nExtraCursorFlags;
679 nShowCursorFlags |= GETCRSR_TXTONLY;
681 // Use CursorBidiLevel 0/1 in meaning of
682 // 0: prefer portion end, normal mode
683 // 1: prefer portion start
685 if ( ( GetCursorBidiLevel() != CURSOR_BIDILEVEL_DONTKNOW ) && GetCursorBidiLevel() )
687 nShowCursorFlags |= GETCRSR_PREFERPORTIONSTART;
690 Rectangle aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, nShowCursorFlags );
691 if ( !IsInsertMode() && !aEditSelection.HasRange() )
693 if ( aPaM.GetNode()->Len() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) )
695 // If we are behind a portion, and the next portion has other direction, we must change position...
696 aEditCursor.Left() = aEditCursor.Right() = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GETCRSR_TXTONLY|GETCRSR_PREFERPORTIONSTART ).Left();
698 USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, TRUE );
699 TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
700 if ( pTextPortion->GetKind() == PORTIONKIND_TAB )
702 aEditCursor.Right() += pTextPortion->GetSize().Width();
704 else
706 EditPaM aNext = pEditEngine->pImpEditEngine->CursorRight( aPaM, (USHORT)i18n::CharacterIteratorMode::SKIPCELL );
707 Rectangle aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GETCRSR_TXTONLY );
708 if ( aTmpRect.Top() != aEditCursor.Top() )
709 aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GETCRSR_TXTONLY|GETCRSR_ENDOFLINE );
710 aEditCursor.Right() = aTmpRect.Left();
714 long nMaxHeight = !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth();
715 if ( aEditCursor.GetHeight() > nMaxHeight )
717 aEditCursor.Bottom() = aEditCursor.Top() + nMaxHeight - 1;
719 if ( bGotoCursor ) // && (!pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() ) )
721 // pruefen, ob scrollen notwendig...
722 // wenn scrollen, dann Update() und Scroll() !
723 long nDocDiffX = 0;
724 long nDocDiffY = 0;
726 Rectangle aTmpVisArea( GetVisDocArea() );
727 // aTmpOutArea: Falls OutputArea > Papierbreite und
728 // Text > Papierbreite ( uebergrosse Felder )
729 long nMaxTextWidth = !IsVertical() ? pEditEngine->pImpEditEngine->GetPaperSize().Width() : pEditEngine->pImpEditEngine->GetPaperSize().Height();
730 if ( aTmpVisArea.GetWidth() > nMaxTextWidth )
731 aTmpVisArea.Right() = aTmpVisArea.Left() + nMaxTextWidth;
733 if ( aEditCursor.Bottom() > aTmpVisArea.Bottom() )
734 { // hochscrollen, hier positiv
735 nDocDiffY = aEditCursor.Bottom() - aTmpVisArea.Bottom();
737 else if ( aEditCursor.Top() < aTmpVisArea.Top() )
738 { // runterscrollen, negativ
739 nDocDiffY = aEditCursor.Top() - aTmpVisArea.Top();
742 if ( aEditCursor.Right() > aTmpVisArea.Right() )
744 // linksscrollen, positiv
745 nDocDiffX = aEditCursor.Right() - aTmpVisArea.Right();
746 // Darfs ein bischen mehr sein?
747 if ( aEditCursor.Right() < ( nMaxTextWidth - GetScrollDiffX() ) )
748 nDocDiffX += GetScrollDiffX();
749 else
751 long n = nMaxTextWidth - aEditCursor.Right();
752 // Bei einem MapMode != RefMapMode kann der EditCursor auch mal ueber
753 // die Papierbreite Wandern!
754 nDocDiffX += ( n > 0 ? n : -n );
757 else if ( aEditCursor.Left() < aTmpVisArea.Left() )
758 { // rechtsscrollen
759 // negativ:
760 nDocDiffX = aEditCursor.Left() - aTmpVisArea.Left();
761 // Darfs ein bischen mehr sein?
762 if ( aEditCursor.Left() > ( - (long)GetScrollDiffX() ) )
763 nDocDiffX -= GetScrollDiffX();
764 else
765 nDocDiffX -= aEditCursor.Left();
767 if ( aPaM.GetIndex() == 0 ) // braucht Olli fuer den Outliner
769 // Aber sicherstellen, dass dadurch der Cursor nicht den
770 // sichtbaren bereich verlaesst!
771 if ( aEditCursor.Left() < aTmpVisArea.GetWidth() )
773 nDocDiffX = -aTmpVisArea.Left();
777 if ( nDocDiffX | nDocDiffY )
779 long nDiffX = !IsVertical() ? nDocDiffX : -nDocDiffY;
780 long nDiffY = !IsVertical() ? nDocDiffY : nDocDiffX;
782 // Negativ: Zum Anfang bzw. linken Rand
783 if ( ( Abs( nDiffY ) > pEditEngine->pImpEditEngine->nOnePixelInRef ) && DoBigScroll() )
785 long nH = aOutArea.GetHeight() / 4;
786 if ( ( nH > aEditCursor.GetHeight() ) && ( Abs( nDiffY ) < nH ) )
788 if ( nDiffY < 0 )
789 nDiffY -= nH;
790 else
791 nDiffY += nH;
795 if ( ( Abs( nDiffX ) > pEditEngine->pImpEditEngine->nOnePixelInRef ) && DoBigScroll() )
797 long nW = aOutArea.GetWidth() / 4;
798 if ( Abs( nDiffX ) < nW )
800 if ( nDiffY < 0 )
801 nDiffY -= nW;
802 else
803 nDiffY += nW;
807 if ( nDiffX )
808 pEditEngine->pImpEditEngine->aStatus.GetStatusWord() = pEditEngine->pImpEditEngine->aStatus.GetStatusWord() | EE_STAT_HSCROLL;
809 if ( nDiffY )
810 pEditEngine->pImpEditEngine->aStatus.GetStatusWord() = pEditEngine->pImpEditEngine->aStatus.GetStatusWord() | EE_STAT_VSCROLL;
811 Scroll( -nDiffX, -nDiffY );
812 pEditEngine->pImpEditEngine->DelayedCallStatusHdl();
816 // Cursor evtl. etwas stutzen...
817 if ( ( aEditCursor.Bottom() > GetVisDocTop() ) &&
818 ( aEditCursor.Top() < GetVisDocBottom() ) )
820 if ( aEditCursor.Bottom() > GetVisDocBottom() )
821 aEditCursor.Bottom() = GetVisDocBottom();
822 if ( aEditCursor.Top() < GetVisDocTop() )
823 aEditCursor.Top() = GetVisDocTop();
826 long nOnePixel = pOutWin->PixelToLogic( Size( 1, 0 ) ).Width();
828 if ( /* pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() || */
829 ( ( aEditCursor.Top() + nOnePixel >= GetVisDocTop() ) &&
830 ( aEditCursor.Bottom() - nOnePixel <= GetVisDocBottom() ) &&
831 ( aEditCursor.Left() + nOnePixel >= GetVisDocLeft() ) &&
832 ( aEditCursor.Right() - nOnePixel <= GetVisDocRight() ) ) )
834 Rectangle aCursorRect = GetWindowPos( aEditCursor );
835 GetCursor()->SetPos( aCursorRect.TopLeft() );
836 Size aCursorSz( aCursorRect.GetSize() );
837 // Rectangle is inclusive
838 aCursorSz.Width()--;
839 aCursorSz.Height()--;
840 if ( !aCursorSz.Width() || !aCursorSz.Height() )
842 long nCursorSz = pOutWin->GetSettings().GetStyleSettings().GetCursorSize();
843 nCursorSz = pOutWin->PixelToLogic( Size( nCursorSz, 0 ) ).Width();
844 if ( !aCursorSz.Width() )
845 aCursorSz.Width() = nCursorSz;
846 if ( !aCursorSz.Height() )
847 aCursorSz.Height() = nCursorSz;
849 // #111036# Let VCL do orientation for cursor, otherwise problem when cursor has direction flag
850 if ( IsVertical() )
852 Size aOldSz( aCursorSz );
853 aCursorSz.Width() = aOldSz.Height();
854 aCursorSz.Height() = aOldSz.Width();
855 GetCursor()->SetPos( aCursorRect.TopRight() );
856 GetCursor()->SetOrientation( 2700 );
858 else
859 // --> FME 2004-10-18 #i32593#
860 // Reset correct orientation in horizontal layout
861 GetCursor()->SetOrientation( 0 );
862 // <--
864 GetCursor()->SetSize( aCursorSz );
866 unsigned char nCursorDir = CURSOR_DIRECTION_NONE;
867 if ( IsInsertMode() && !aEditSelection.HasRange() && ( pEditEngine->pImpEditEngine->HasDifferentRTLLevels( aPaM.GetNode() ) ) )
869 USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, nShowCursorFlags & GETCRSR_PREFERPORTIONSTART ? TRUE : FALSE );
870 TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
871 USHORT nRTLLevel = pTextPortion->GetRightToLeft();
872 if ( nRTLLevel%2 )
873 nCursorDir = CURSOR_DIRECTION_RTL;
874 else
875 nCursorDir = CURSOR_DIRECTION_LTR;
878 GetCursor()->SetDirection( nCursorDir );
880 if ( bForceVisCursor )
881 GetCursor()->Show();
883 // #102936# Call SetInputContext every time, otherwise we may have the wrong font
884 // if ( !pEditEngine->pImpEditEngine->mpIMEInfos )
886 SvxFont aFont;
887 pEditEngine->pImpEditEngine->SeekCursor( aPaM.GetNode(), aPaM.GetIndex()+1, aFont );
888 ULONG nContextFlags = INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT;
889 GetWindow()->SetInputContext( InputContext( aFont, nContextFlags ) );
892 else
894 pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() = pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() | EE_STAT_CURSOROUT;
895 GetCursor()->Hide();
896 GetCursor()->SetPos( Point( -1, -1 ) );
897 GetCursor()->SetSize( Size( 0, 0 ) );
901 Pair ImpEditView::Scroll( long ndX, long ndY, BYTE nRangeCheck )
903 DBG_ASSERT( pEditEngine->pImpEditEngine->IsFormatted(), "Scroll: Nicht formatiert!" );
904 if ( !ndX && !ndY )
905 return Range( 0, 0 );
907 #ifdef DBG_UTIL
908 Rectangle aR( aOutArea );
909 aR = pOutWin->LogicToPixel( aR );
910 aR = pOutWin->PixelToLogic( aR );
911 DBG_ASSERTWARNING( aR == aOutArea, "OutArea vor Scroll nicht aligned" );
912 #endif
914 Rectangle aNewVisArea( GetVisDocArea() );
915 Size aPaperSz( pEditEngine->pImpEditEngine->GetPaperSize() );
917 // Vertical:
918 if ( !IsVertical() )
920 aNewVisArea.Top() -= ndY;
921 aNewVisArea.Bottom() -= ndY;
923 else
925 aNewVisArea.Top() += ndX;
926 aNewVisArea.Bottom() += ndX;
928 if ( ( nRangeCheck == RGCHK_PAPERSZ1 ) && ( aNewVisArea.Bottom() > (long)pEditEngine->pImpEditEngine->GetTextHeight() ) )
930 // GetTextHeight noch optimieren!
931 long nDiff = pEditEngine->pImpEditEngine->GetTextHeight() - aNewVisArea.Bottom(); // negativ
932 aNewVisArea.Move( 0, nDiff ); // koennte im neg. Bereich landen...
934 if ( ( aNewVisArea.Top() < 0 ) && ( nRangeCheck != RGCHK_NONE ) )
935 aNewVisArea.Move( 0, -aNewVisArea.Top() );
937 // Horizontal:
938 if ( !IsVertical() )
940 aNewVisArea.Left() -= ndX;
941 aNewVisArea.Right() -= ndX;
943 else
945 aNewVisArea.Left() -= ndY;
946 aNewVisArea.Right() -= ndY;
948 if ( ( nRangeCheck == RGCHK_PAPERSZ1 ) && ( aNewVisArea.Right() > (long)pEditEngine->pImpEditEngine->CalcTextWidth( FALSE ) ) )
950 long nDiff = pEditEngine->pImpEditEngine->CalcTextWidth( FALSE ) - aNewVisArea.Right(); // negativ
951 aNewVisArea.Move( nDiff, 0 ); // koennte im neg. Bereich landen...
953 if ( ( aNewVisArea.Left() < 0 ) && ( nRangeCheck != RGCHK_NONE ) )
954 aNewVisArea.Move( -aNewVisArea.Left(), 0 );
956 // Die Differenz muss auf Pixel alignt sein (wegen Scroll!)
957 long nDiffX = !IsVertical() ? ( GetVisDocLeft() - aNewVisArea.Left() ) : -( GetVisDocTop() - aNewVisArea.Top() );
958 long nDiffY = !IsVertical() ? ( GetVisDocTop() - aNewVisArea.Top() ) : ( GetVisDocLeft() - aNewVisArea.Left() );
960 Size aDiffs( nDiffX, nDiffY );
961 aDiffs = pOutWin->LogicToPixel( aDiffs );
962 aDiffs = pOutWin->PixelToLogic( aDiffs );
964 long nRealDiffX = aDiffs.Width();
965 long nRealDiffY = aDiffs.Height();
968 if ( nRealDiffX || nRealDiffY )
970 Cursor* pCrsr = GetCursor();
971 sal_Bool bVisCursor = pCrsr->IsVisible();
972 pCrsr->Hide();
973 pOutWin->Update();
974 if ( !IsVertical() )
975 aVisDocStartPos.Move( -nRealDiffX, -nRealDiffY );
976 else
977 aVisDocStartPos.Move( -nRealDiffY, nRealDiffX );
978 // Das Move um den allignten Wert ergibt nicht unbedingt ein
979 // alligntes Rechteck...
980 // MT 11/00: Align VisArea???
981 aVisDocStartPos = pOutWin->LogicToPixel( aVisDocStartPos );
982 aVisDocStartPos = pOutWin->PixelToLogic( aVisDocStartPos );
983 Rectangle aRec( aOutArea );
984 pOutWin->Scroll( nRealDiffX, nRealDiffY, aRec, sal_True );
985 pOutWin->Update();
986 pCrsr->SetPos( pCrsr->GetPos() + Point( nRealDiffX, nRealDiffY ) );
987 if ( bVisCursor )
989 Rectangle aCursorRec( pCrsr->GetPos(), pCrsr->GetSize() );
990 if ( aOutArea.IsInside( aCursorRec ) )
991 pCrsr->Show();
994 if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() )
996 EENotify aNotify( EE_NOTIFY_TEXTVIEWSCROLLED );
997 aNotify.pEditEngine = pEditEngine;
998 aNotify.pEditView = GetEditViewPtr();
999 pEditEngine->pImpEditEngine->CallNotify( aNotify );
1003 return Pair( nRealDiffX, nRealDiffY );
1006 sal_Bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent, Window* pFrameWin )
1008 BOOL bDone = FALSE;
1010 KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
1011 if ( eFunc != KEYFUNC_DONTKNOW )
1013 switch ( eFunc )
1015 case KEYFUNC_CUT:
1017 if ( !bReadOnly )
1019 Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
1020 CutCopy( aClipBoard, sal_True );
1021 bDone = sal_True;
1024 break;
1025 case KEYFUNC_COPY:
1027 Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
1028 CutCopy( aClipBoard, sal_False );
1029 bDone = TRUE;
1031 break;
1032 case KEYFUNC_PASTE:
1034 if ( !bReadOnly && IsPasteEnabled() )
1036 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE );
1037 Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
1038 Paste( aClipBoard, pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() );
1039 pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_PASTE );
1040 bDone = sal_True;
1043 break;
1044 default:
1045 break;
1049 if( !bDone )
1050 bDone = pEditEngine->PostKeyEvent( rKeyEvent, GetEditViewPtr(), pFrameWin );
1052 return bDone;
1055 sal_Bool ImpEditView::MouseButtonUp( const MouseEvent& rMouseEvent )
1057 if ( pEditEngine->pImpEditEngine->aStatus.NotifyCursorMovements() )
1059 if ( pEditEngine->pImpEditEngine->aStatus.GetPrevParagraph() != pEditEngine->pImpEditEngine->GetEditDoc().GetPos( GetEditSelection().Max().GetNode() ) )
1061 pEditEngine->pImpEditEngine->aStatus.GetStatusWord() = pEditEngine->pImpEditEngine->aStatus.GetStatusWord() | EE_STAT_CRSRLEFTPARA;
1062 pEditEngine->pImpEditEngine->CallStatusHdl();
1065 nTravelXPos = TRAVEL_X_DONTKNOW;
1066 nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW;
1067 nExtraCursorFlags = 0;
1068 bClickedInSelection = sal_False;
1070 if ( rMouseEvent.IsMiddle() && !bReadOnly &&
1071 ( GetWindow()->GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) )
1073 Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetPrimarySelection());
1074 Paste( aClipBoard );
1076 else if ( rMouseEvent.IsLeft() && GetEditSelection().HasRange() )
1078 Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetPrimarySelection());
1079 CutCopy( aClipBoard, FALSE );
1082 return pEditEngine->pImpEditEngine->MouseButtonUp( rMouseEvent, GetEditViewPtr() );
1085 sal_Bool ImpEditView::MouseButtonDown( const MouseEvent& rMouseEvent )
1087 pEditEngine->pImpEditEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown
1088 if ( pEditEngine->pImpEditEngine->aStatus.NotifyCursorMovements() )
1089 pEditEngine->pImpEditEngine->aStatus.GetPrevParagraph() = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( GetEditSelection().Max().GetNode() );
1090 nTravelXPos = TRAVEL_X_DONTKNOW;
1091 nExtraCursorFlags = 0;
1092 nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW;
1093 bClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() );
1094 return pEditEngine->pImpEditEngine->MouseButtonDown( rMouseEvent, GetEditViewPtr() );
1097 sal_Bool ImpEditView::MouseMove( const MouseEvent& rMouseEvent )
1099 return pEditEngine->pImpEditEngine->MouseMove( rMouseEvent, GetEditViewPtr() );
1102 void ImpEditView::Command( const CommandEvent& rCEvt )
1104 pEditEngine->pImpEditEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown
1105 pEditEngine->pImpEditEngine->Command( rCEvt, GetEditViewPtr() );
1109 void ImpEditView::SetInsertMode( sal_Bool bInsert )
1111 if ( bInsert != IsInsertMode() )
1113 SetFlags( nControl, EV_CNTRL_OVERWRITE, !bInsert );
1114 ShowCursor( DoAutoScroll(), sal_False );
1118 sal_Bool ImpEditView::IsWrongSpelledWord( const EditPaM& rPaM, sal_Bool bMarkIfWrong )
1120 sal_Bool bIsWrong = sal_False;
1121 #ifndef SVX_LIGHT
1122 if ( rPaM.GetNode()->GetWrongList() )
1124 EditSelection aSel = pEditEngine->pImpEditEngine->SelectWord( rPaM, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1125 bIsWrong = rPaM.GetNode()->GetWrongList()->HasWrong( aSel.Min().GetIndex(), aSel.Max().GetIndex() );
1126 if ( bIsWrong && bMarkIfWrong )
1128 DrawSelection(); // alte Selektion 'weg-zeichnen'
1129 SetEditSelection( aSel );
1130 DrawSelection();
1133 #endif // !SVX_LIGHT
1134 return bIsWrong;
1137 String ImpEditView::SpellIgnoreOrAddWord( sal_Bool bAdd )
1139 String aWord;
1140 #ifndef SVX_LIGHT
1141 if ( pEditEngine->pImpEditEngine->GetSpeller().is() )
1143 EditPaM aPaM = GetEditSelection().Max();
1144 if ( !HasSelection() )
1146 EditSelection aSel = pEditEngine->pImpEditEngine->SelectWord( aPaM );
1147 aWord = pEditEngine->pImpEditEngine->GetSelected( aSel );
1149 else
1151 aWord = pEditEngine->pImpEditEngine->GetSelected( GetEditSelection() );
1152 // Und deselektieren
1153 DrawSelection(); // alte Selektion 'weg-zeichnen'
1154 SetEditSelection( EditSelection( aPaM, aPaM ) );
1155 DrawSelection();
1158 if ( aWord.Len() )
1160 if ( bAdd )
1162 DBG_ERROR( "Sorry, AddWord not implemented" );
1164 else // Ignore
1166 Reference< XDictionary > xDic( SvxGetIgnoreAllList(), UNO_QUERY );
1167 if (xDic.is())
1168 xDic->add( aWord, sal_False, String() );
1170 const EditDoc& rDoc = pEditEngine->pImpEditEngine->GetEditDoc();
1171 sal_uInt16 nNodes = rDoc.Count();
1172 for ( sal_uInt16 n = 0; n < nNodes; n++ )
1174 ContentNode* pNode = rDoc.GetObject( n );
1175 pNode->GetWrongList()->MarkWrongsInvalid();
1177 pEditEngine->pImpEditEngine->DoOnlineSpelling( aPaM.GetNode() );
1178 pEditEngine->pImpEditEngine->StartOnlineSpellTimer();
1181 #endif // !SVX_LIGHT
1182 return aWord;
1185 void ImpEditView::DeleteSelected()
1187 DrawSelection();
1189 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DELETE );
1191 EditPaM aPaM = pEditEngine->pImpEditEngine->DeleteSelected( GetEditSelection() );
1193 pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_DELETE );
1195 SetEditSelection( EditSelection( aPaM, aPaM ) );
1196 pEditEngine->pImpEditEngine->FormatAndUpdate( GetEditViewPtr() );
1197 ShowCursor( DoAutoScroll(), TRUE );
1200 const SvxFieldItem* ImpEditView::GetField( const Point& rPos, sal_uInt16* pPara, sal_uInt16* pPos ) const
1202 if( !GetOutputArea().IsInside( rPos ) )
1203 return 0;
1205 Point aDocPos( GetDocPos( rPos ) );
1206 EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos, sal_False );
1208 if ( aPaM.GetIndex() == aPaM.GetNode()->Len() )
1210 // Sonst immer, wenn Feld ganz am Schluss und Mouse unter Text
1211 return 0;
1214 const CharAttribArray& rAttrs = aPaM.GetNode()->GetCharAttribs().GetAttribs();
1215 sal_uInt16 nXPos = aPaM.GetIndex();
1216 for ( sal_uInt16 nAttr = rAttrs.Count(); nAttr; )
1218 EditCharAttrib* pAttr = rAttrs[--nAttr];
1219 if ( pAttr->GetStart() == nXPos )
1220 if ( pAttr->Which() == EE_FEATURE_FIELD )
1222 DBG_ASSERT( pAttr->GetItem()->ISA( SvxFieldItem ), "Kein FeldItem..." );
1223 if ( pPara )
1224 *pPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
1225 if ( pPos )
1226 *pPos = pAttr->GetStart();
1227 return (const SvxFieldItem*)pAttr->GetItem();
1230 return NULL;
1233 BOOL ImpEditView::IsBulletArea( const Point& rPos, sal_uInt16* pPara )
1235 if ( pPara )
1236 *pPara = 0xFFFF;
1238 if( !GetOutputArea().IsInside( rPos ) )
1239 return FALSE;
1241 Point aDocPos( GetDocPos( rPos ) );
1242 EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos, sal_False );
1244 if ( aPaM.GetIndex() == 0 )
1246 USHORT nPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
1247 Rectangle aBulletArea = pEditEngine->GetBulletArea( nPara );
1248 long nY = pEditEngine->GetDocPosTopLeft( nPara ).Y();
1249 ParaPortion* pParaPortion = pEditEngine->pImpEditEngine->GetParaPortions().GetObject( nPara );
1250 nY += pParaPortion->GetFirstLineOffset();
1251 if ( ( aDocPos.Y() > ( nY + aBulletArea.Top() ) ) &&
1252 ( aDocPos.Y() < ( nY + aBulletArea.Bottom() ) ) &&
1253 ( aDocPos.X() > ( aBulletArea.Left() ) ) &&
1254 ( aDocPos.X() < ( aBulletArea.Right() ) ) )
1256 if ( pPara )
1257 *pPara = nPara;
1258 return TRUE;
1262 return FALSE;
1265 void ImpEditView::CutCopy( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard, BOOL bCut )
1267 if ( rxClipboard.is() && GetEditSelection().HasRange() )
1269 uno::Reference< datatransfer::XTransferable > xData = pEditEngine->pImpEditEngine->CreateTransferable( GetEditSelection() );
1271 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1275 rxClipboard->setContents( xData, NULL );
1277 // #87756# FlushClipboard, but it would be better to become a TerminateListener to the Desktop and flush on demand...
1278 uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
1279 if( xFlushableClipboard.is() )
1280 xFlushableClipboard->flushClipboard();
1282 catch( const ::com::sun::star::uno::Exception& )
1286 Application::AcquireSolarMutex( nRef );
1288 if ( bCut )
1290 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_CUT );
1291 DeleteSelected();
1292 pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_CUT );
1298 void ImpEditView::Paste( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard, BOOL bUseSpecial )
1300 if ( rxClipboard.is() )
1302 uno::Reference< datatransfer::XTransferable > xDataObj;
1304 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1308 xDataObj = rxClipboard->getContents();
1310 catch( const ::com::sun::star::uno::Exception& )
1314 Application::AcquireSolarMutex( nRef );
1316 if ( xDataObj.is() && EditEngine::HasValidData( xDataObj ) )
1318 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE );
1320 EditSelection aSel( GetEditSelection() );
1321 if ( aSel.HasRange() )
1323 DrawSelection();
1324 aSel = pEditEngine->pImpEditEngine->ImpDeleteSelection( aSel );
1327 PasteOrDropInfos aPasteOrDropInfos;
1328 aPasteOrDropInfos.nAction = EE_ACTION_PASTE;
1329 aPasteOrDropInfos.nStartPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() );
1330 pEditEngine->pImpEditEngine->aBeginPasteOrDropHdl.Call( &aPasteOrDropInfos );
1332 if ( DoSingleLinePaste() )
1334 datatransfer::DataFlavor aFlavor;
1335 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
1336 if ( xDataObj->isDataFlavorSupported( aFlavor ) )
1340 uno::Any aData = xDataObj->getTransferData( aFlavor );
1341 ::rtl::OUString aTmpText;
1342 aData >>= aTmpText;
1343 String aText( aTmpText );
1344 aText.ConvertLineEnd( LINEEND_LF );
1345 aText.SearchAndReplaceAll( LINE_SEP, ' ' );
1346 aSel = pEditEngine->pImpEditEngine->ImpInsertText( aSel, aText );
1348 catch( ... )
1350 ; // #i9286# can happen, even if isDataFlavorSupported returns true...
1354 else
1356 aSel = pEditEngine->pImpEditEngine->InsertText( xDataObj, String(), aSel.Min(), bUseSpecial && pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() );
1359 aPasteOrDropInfos.nEndPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() );
1360 pEditEngine->pImpEditEngine->aEndPasteOrDropHdl.Call( &aPasteOrDropInfos );
1362 pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_PASTE );
1363 SetEditSelection( aSel );
1364 pEditEngine->pImpEditEngine->UpdateSelections();
1365 pEditEngine->pImpEditEngine->FormatAndUpdate( GetEditViewPtr() );
1366 ShowCursor( DoAutoScroll(), TRUE );
1372 BOOL ImpEditView::IsInSelection( const EditPaM& rPaM )
1374 EditSelection aSel = GetEditSelection();
1375 if ( !aSel.HasRange() )
1376 return FALSE;
1378 aSel.Adjust( pEditEngine->pImpEditEngine->GetEditDoc() );
1380 USHORT nStartNode = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() );
1381 USHORT nEndNode = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() );
1382 USHORT nCurNode = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( rPaM.GetNode() );
1384 if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) )
1385 return TRUE;
1387 if ( nStartNode == nEndNode )
1389 if ( nCurNode == nStartNode )
1390 if ( ( rPaM.GetIndex() >= aSel.Min().GetIndex() ) && ( rPaM.GetIndex() < aSel.Max().GetIndex() ) )
1391 return TRUE;
1393 else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.Min().GetIndex() ) )
1394 return TRUE;
1395 else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.Max().GetIndex() ) )
1396 return TRUE;
1398 return FALSE;
1401 void ImpEditView::CreateAnchor()
1403 pEditEngine->pImpEditEngine->bInSelection = TRUE;
1404 GetEditSelection().Min() = GetEditSelection().Max();
1407 void ImpEditView::DeselectAll()
1409 pEditEngine->pImpEditEngine->bInSelection = FALSE;
1410 DrawSelection();
1411 GetEditSelection().Min() = GetEditSelection().Max();
1414 BOOL ImpEditView::IsSelectionAtPoint( const Point& rPosPixel )
1416 if ( pDragAndDropInfo && pDragAndDropInfo->pField )
1417 return TRUE;
1419 Point aMousePos( rPosPixel );
1421 // Logische Einheiten...
1422 aMousePos = GetWindow()->PixelToLogic( aMousePos );
1424 if ( ( !GetOutputArea().IsInside( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() )
1426 return FALSE;
1429 Point aDocPos( GetDocPos( aMousePos ) );
1430 EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos, FALSE );
1431 return IsInSelection( aPaM );
1434 BOOL ImpEditView::SetCursorAtPoint( const Point& rPointPixel )
1436 pEditEngine->pImpEditEngine->CheckIdleFormatter();
1438 Point aMousePos( rPointPixel );
1440 // Logische Einheiten...
1441 aMousePos = GetWindow()->PixelToLogic( aMousePos );
1443 if ( ( !GetOutputArea().IsInside( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() )
1445 return FALSE;
1448 Point aDocPos( GetDocPos( aMousePos ) );
1450 // Kann optimiert werden: Erst innerhalb eines Absatzes die Zeilen
1451 // fuer den PaM durchwuehlen, dann nochmal mit dem PaM fuer das Rect,
1452 // obwohl die Zeile schon bekannt ist....
1453 // Das muss doch nicht sein !
1455 EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos );
1456 BOOL bGotoCursor = DoAutoScroll();
1458 // aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion
1459 EditSelection aTmpNewSel( GetEditSelection().Max(), aPaM );
1461 // --> OD 2005-12-16 #i27299#
1462 // work on copy of current selection and set new selection, if it has changed.
1463 EditSelection aNewEditSelection( GetEditSelection() );
1465 aNewEditSelection.Max() = aPaM;
1466 if ( !pEditEngine->pImpEditEngine->aSelEngine.HasAnchor() )
1468 if ( aNewEditSelection.Min() != aPaM )
1469 pEditEngine->pImpEditEngine->CursorMoved( aNewEditSelection.Min().GetNode() );
1470 aNewEditSelection.Min() = aPaM;
1472 else
1474 DrawSelection( aTmpNewSel );
1477 // set changed text selection
1478 if ( GetEditSelection() != aNewEditSelection )
1480 SetEditSelection( aNewEditSelection );
1482 // <--
1484 BOOL bForceCursor = ( pDragAndDropInfo ? FALSE : TRUE ) && !pEditEngine->pImpEditEngine->IsInSelectionMode();
1485 ShowCursor( bGotoCursor, bForceCursor );
1486 return TRUE;
1490 void ImpEditView::HideDDCursor()
1492 if ( pDragAndDropInfo && pDragAndDropInfo->bVisCursor )
1494 GetWindow()->DrawOutDev( pDragAndDropInfo->aCurSavedCursor.TopLeft(), pDragAndDropInfo->aCurSavedCursor.GetSize(),
1495 Point(0,0), pDragAndDropInfo->aCurSavedCursor.GetSize(),*pDragAndDropInfo->pBackground );
1496 pDragAndDropInfo->bVisCursor = sal_False;
1500 void ImpEditView::ShowDDCursor( const Rectangle& rRect )
1502 if ( !pDragAndDropInfo->bVisCursor )
1504 if ( pOutWin->GetCursor() )
1505 pOutWin->GetCursor()->Hide();
1507 Color aOldFillColor = GetWindow()->GetFillColor();
1508 GetWindow()->SetFillColor( Color(4210752) ); // GRAY BRUSH_50, OLDSV, change to DDCursor!
1510 // Hintergrund sichern...
1511 Rectangle aSaveRec( GetWindow()->LogicToPixel( rRect ) );
1512 // lieber etwas mehr sichern...
1513 aSaveRec.Right() += 1;
1514 aSaveRec.Bottom() += 1;
1516 Size aNewSzPx( aSaveRec.GetSize() );
1517 if ( !pDragAndDropInfo->pBackground )
1519 pDragAndDropInfo->pBackground = new VirtualDevice( *GetWindow() );
1520 MapMode aMapMode( GetWindow()->GetMapMode() );
1521 aMapMode.SetOrigin( Point( 0, 0 ) );
1522 pDragAndDropInfo->pBackground->SetMapMode( aMapMode );
1526 #ifdef DBG_UTIL
1527 Size aCurSzPx( pDragAndDropInfo->pBackground->GetOutputSizePixel() );
1528 if ( ( aCurSzPx.Width() < aNewSzPx.Width() ) ||( aCurSzPx.Height() < aNewSzPx.Height() ) )
1530 sal_Bool bDone = pDragAndDropInfo->pBackground->SetOutputSizePixel( aNewSzPx );
1531 DBG_ASSERT( bDone, "Virtuelles Device kaputt?" );
1533 #endif
1535 aSaveRec = GetWindow()->PixelToLogic( aSaveRec );
1537 pDragAndDropInfo->pBackground->DrawOutDev( Point(0,0), aSaveRec.GetSize(),
1538 aSaveRec.TopLeft(), aSaveRec.GetSize(), *GetWindow() );
1539 pDragAndDropInfo->aCurSavedCursor = aSaveRec;
1541 // Cursor malen...
1542 GetWindow()->DrawRect( rRect );
1544 pDragAndDropInfo->bVisCursor = sal_True;
1545 pDragAndDropInfo->aCurCursor = rRect;
1547 GetWindow()->SetFillColor( aOldFillColor );
1551 void ImpEditView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException)
1553 DBG_ASSERT( !pDragAndDropInfo, "dragGestureRecognized - DragAndDropInfo exist!" );
1555 vos::OGuard aVclGuard( Application::GetSolarMutex() );
1557 Point aMousePosPixel( rDGE.DragOriginX, rDGE.DragOriginY );
1559 EditSelection aCopySel( GetEditSelection() );
1560 aCopySel.Adjust( pEditEngine->pImpEditEngine->GetEditDoc() );
1562 if ( GetEditSelection().HasRange() && bClickedInSelection )
1564 pDragAndDropInfo = new DragAndDropInfo();
1566 else
1568 // Field?!
1569 USHORT nPara, nPos;
1570 Point aMousePos = GetWindow()->PixelToLogic( aMousePosPixel );
1571 const SvxFieldItem* pField = GetField( aMousePos, &nPara, &nPos );
1572 if ( pField )
1574 pDragAndDropInfo = new DragAndDropInfo();
1575 pDragAndDropInfo->pField = pField;
1576 ContentNode* pNode = pEditEngine->pImpEditEngine->GetEditDoc().GetObject( nPara );
1577 aCopySel = EditSelection( EditPaM( pNode, nPos ), EditPaM( pNode, nPos+1 ) );
1578 GetEditSelection() = aCopySel;
1579 DrawSelection();
1580 BOOL bGotoCursor = DoAutoScroll();
1581 BOOL bForceCursor = ( pDragAndDropInfo ? FALSE : TRUE ) && !pEditEngine->pImpEditEngine->IsInSelectionMode();
1582 ShowCursor( bGotoCursor, bForceCursor );
1584 else if ( IsBulletArea( aMousePos, &nPara ) )
1586 pDragAndDropInfo = new DragAndDropInfo();
1587 pDragAndDropInfo->bOutlinerMode = TRUE;
1588 EditPaM aStartPaM( pEditEngine->pImpEditEngine->GetEditDoc().GetObject( nPara ), 0 );
1589 EditPaM aEndPaM( aStartPaM );
1590 const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL );
1591 for ( USHORT n = nPara +1; n < pEditEngine->pImpEditEngine->GetEditDoc().Count(); n++ )
1593 const SfxInt16Item& rL = (const SfxInt16Item&) pEditEngine->GetParaAttrib( n, EE_PARA_OUTLLEVEL );
1594 if ( rL.GetValue() > rLevel.GetValue() )
1596 aEndPaM.SetNode( pEditEngine->pImpEditEngine->GetEditDoc().GetObject( n ) );
1598 else
1600 break;
1603 aEndPaM.GetIndex() = aEndPaM.GetNode()->Len();
1604 SetEditSelection( EditSelection( aStartPaM, aEndPaM ) );
1608 if ( pDragAndDropInfo )
1611 pDragAndDropInfo->bStarterOfDD = sal_True;
1613 // Sensibler Bereich, wo gescrollt werden soll.
1614 Size aSz( 5, 0 );
1615 aSz = GetWindow()->PixelToLogic( aSz );
1616 pDragAndDropInfo->nSensibleRange = (sal_uInt16) aSz.Width();
1617 pDragAndDropInfo->nCursorWidth = (sal_uInt16) aSz.Width() / 2;
1618 pDragAndDropInfo->aBeginDragSel = pEditEngine->pImpEditEngine->CreateESel( aCopySel );
1620 uno::Reference< datatransfer::XTransferable > xData = pEditEngine->pImpEditEngine->CreateTransferable( aCopySel );
1622 sal_Int8 nActions = bReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE;
1624 rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, xData, mxDnDListener );
1625 // Falls Drag&Move in einer Engine, muessen Copy&Del geklammert sein!
1626 GetCursor()->Hide();
1631 void ImpEditView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& rDSDE ) throw (::com::sun::star::uno::RuntimeException)
1633 vos::OGuard aVclGuard( Application::GetSolarMutex() );
1635 DBG_ASSERT( pDragAndDropInfo, "ImpEditView::dragDropEnd: pDragAndDropInfo is NULL!" );
1637 // #123688# Shouldn't happen, but seems to happen...
1638 if ( pDragAndDropInfo )
1640 if ( !bReadOnly && rDSDE.DropSuccess && !pDragAndDropInfo->bOutlinerMode && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) )
1642 if ( pDragAndDropInfo->bStarterOfDD && pDragAndDropInfo->bDroppedInMe )
1644 // DropPos: Wohin wurde gedroppt, unabhaengig von laenge.
1645 ESelection aDropPos( pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos, pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos );
1646 ESelection aToBeDelSel = pDragAndDropInfo->aBeginDragSel;
1647 ESelection aNewSel( pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos,
1648 pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos );
1649 sal_Bool bBeforeSelection = aDropPos.IsLess( pDragAndDropInfo->aBeginDragSel );
1650 sal_uInt16 nParaDiff = pDragAndDropInfo->aBeginDragSel.nEndPara - pDragAndDropInfo->aBeginDragSel.nStartPara;
1651 if ( bBeforeSelection )
1653 // aToBeDelSel anpassen.
1654 DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara >= pDragAndDropInfo->aDropSel.nStartPara, "Doch nicht davor?" );
1655 aToBeDelSel.nStartPara = aToBeDelSel.nStartPara + nParaDiff;
1656 aToBeDelSel.nEndPara = aToBeDelSel.nEndPara + nParaDiff;
1657 // Zeichen korrigieren?
1658 if ( aToBeDelSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara )
1660 sal_uInt16 nMoreChars;
1661 if ( pDragAndDropInfo->aDropSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara )
1662 nMoreChars = pDragAndDropInfo->aDropSel.nEndPos - pDragAndDropInfo->aDropSel.nStartPos;
1663 else
1664 nMoreChars = pDragAndDropInfo->aDropSel.nEndPos;
1665 aToBeDelSel.nStartPos =
1666 aToBeDelSel.nStartPos + nMoreChars;
1667 if ( aToBeDelSel.nStartPara == aToBeDelSel.nEndPara )
1668 aToBeDelSel.nEndPos =
1669 aToBeDelSel.nEndPos + nMoreChars;
1672 else
1674 // aToBeDelSel ist ok, aber Selektion der View
1675 // muss angepasst werden, wenn davor geloescht wird!
1676 DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara <= pDragAndDropInfo->aDropSel.nStartPara, "Doch nicht davor?" );
1677 aNewSel.nStartPara = aNewSel.nStartPara - nParaDiff;
1678 aNewSel.nEndPara = aNewSel.nEndPara - nParaDiff;
1679 // Zeichen korrigieren?
1680 if ( pDragAndDropInfo->aBeginDragSel.nEndPara == pDragAndDropInfo->aDropSel.nStartPara )
1682 sal_uInt16 nLessChars;
1683 if ( pDragAndDropInfo->aBeginDragSel.nStartPara == pDragAndDropInfo->aBeginDragSel.nEndPara )
1684 nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos - pDragAndDropInfo->aBeginDragSel.nStartPos;
1685 else
1686 nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos;
1687 aNewSel.nStartPos = aNewSel.nStartPos - nLessChars;
1688 if ( aNewSel.nStartPara == aNewSel.nEndPara )
1689 aNewSel.nEndPos = aNewSel.nEndPos - nLessChars;
1693 DrawSelection();
1694 EditSelection aDelSel( pEditEngine->pImpEditEngine->CreateSel( aToBeDelSel ) );
1695 DBG_ASSERT( !aDelSel.DbgIsBuggy( pEditEngine->pImpEditEngine->aEditDoc ), "ToBeDel ist buggy!" );
1696 pEditEngine->pImpEditEngine->ImpDeleteSelection( aDelSel );
1697 if ( !bBeforeSelection )
1699 DBG_ASSERT( !pEditEngine->pImpEditEngine->CreateSel( aNewSel ).DbgIsBuggy(pEditEngine->pImpEditEngine->aEditDoc), "Bad" );
1700 SetEditSelection( pEditEngine->pImpEditEngine->CreateSel( aNewSel ) );
1702 pEditEngine->pImpEditEngine->FormatAndUpdate( pEditEngine->pImpEditEngine->GetActiveView() );
1703 DrawSelection();
1705 else
1707 // andere EditEngine...
1708 if ( pEditEngine->pImpEditEngine->ImplHasText() ) // #88630# SC ist removing the content when switching the task
1709 DeleteSelected();
1713 if ( pDragAndDropInfo->bUndoAction )
1714 pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_DRAGANDDROP );
1716 HideDDCursor();
1717 ShowCursor( DoAutoScroll(), TRUE );
1718 delete pDragAndDropInfo;
1719 pDragAndDropInfo = NULL;
1720 pEditEngine->GetEndDropHdl().Call(GetEditViewPtr());
1724 void ImpEditView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
1726 vos::OGuard aVclGuard( Application::GetSolarMutex() );
1728 DBG_ASSERT( pDragAndDropInfo, "Drop - No Drag&Drop info?!" );
1730 if ( pDragAndDropInfo->bDragAccepted )
1732 pEditEngine->GetBeginDropHdl().Call(GetEditViewPtr());
1733 BOOL bChanges = FALSE;
1735 HideDDCursor();
1737 if ( pDragAndDropInfo->bStarterOfDD )
1739 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DRAGANDDROP );
1740 pDragAndDropInfo->bUndoAction = TRUE;
1743 if ( pDragAndDropInfo->bOutlinerMode )
1745 bChanges = TRUE;
1746 GetEditViewPtr()->MoveParagraphs( Range( pDragAndDropInfo->aBeginDragSel.nStartPara, pDragAndDropInfo->aBeginDragSel.nEndPara ), pDragAndDropInfo->nOutlinerDropDest );
1748 else
1750 uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
1751 if ( xDataObj.is() )
1753 bChanges = TRUE;
1754 // Selektion wegmalen...
1755 DrawSelection();
1756 EditPaM aPaM( pDragAndDropInfo->aDropDest );
1758 PasteOrDropInfos aPasteOrDropInfos;
1759 aPasteOrDropInfos.nAction = EE_ACTION_DROP;
1760 aPasteOrDropInfos.nStartPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
1761 pEditEngine->pImpEditEngine->aBeginPasteOrDropHdl.Call( &aPasteOrDropInfos );
1763 EditSelection aNewSel = pEditEngine->pImpEditEngine->InsertText( xDataObj, String(), aPaM, pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() );
1765 aPasteOrDropInfos.nEndPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aNewSel.Max().GetNode() );
1766 pEditEngine->pImpEditEngine->aEndPasteOrDropHdl.Call( &aPasteOrDropInfos );
1768 SetEditSelection( aNewSel );
1769 pEditEngine->pImpEditEngine->FormatAndUpdate( pEditEngine->pImpEditEngine->GetActiveView() );
1770 if ( pDragAndDropInfo->bStarterOfDD )
1772 // Nur dann setzen, wenn in gleicher Engine!
1773 pDragAndDropInfo->aDropSel.nStartPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
1774 pDragAndDropInfo->aDropSel.nStartPos = aPaM.GetIndex();
1775 pDragAndDropInfo->aDropSel.nEndPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aNewSel.Max().GetNode() );
1776 pDragAndDropInfo->aDropSel.nEndPos = aNewSel.Max().GetIndex();
1777 pDragAndDropInfo->bDroppedInMe = sal_True;
1782 if ( bChanges )
1784 rDTDE.Context->acceptDrop( rDTDE.DropAction );
1787 if ( !pDragAndDropInfo->bStarterOfDD )
1789 delete pDragAndDropInfo;
1790 pDragAndDropInfo = NULL;
1793 rDTDE.Context->dropComplete( bChanges );
1797 void ImpEditView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& rDTDEE ) throw (::com::sun::star::uno::RuntimeException)
1799 vos::OGuard aVclGuard( Application::GetSolarMutex() );
1801 if ( !pDragAndDropInfo )
1802 pDragAndDropInfo = new DragAndDropInfo( );
1804 pDragAndDropInfo->bHasValidData = sal_False;
1806 // Check for supported format...
1807 // Only check for text, will also be there if bin or rtf
1808 datatransfer::DataFlavor aTextFlavor;
1809 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aTextFlavor );
1810 const ::com::sun::star::datatransfer::DataFlavor* pFlavors = rDTDEE.SupportedDataFlavors.getConstArray();
1811 int nFlavors = rDTDEE.SupportedDataFlavors.getLength();
1812 for ( int n = 0; n < nFlavors; n++ )
1814 if( TransferableDataHelper::IsEqual( pFlavors[n], aTextFlavor ) )
1816 pDragAndDropInfo->bHasValidData = sal_True;
1817 break;
1821 dragOver( rDTDEE );
1824 void ImpEditView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException)
1826 vos::OGuard aVclGuard( Application::GetSolarMutex() );
1828 HideDDCursor();
1830 if ( !pDragAndDropInfo->bStarterOfDD )
1832 delete pDragAndDropInfo;
1833 pDragAndDropInfo = NULL;
1837 void ImpEditView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
1839 vos::OGuard aVclGuard( Application::GetSolarMutex() );
1841 Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
1842 aMousePos = GetWindow()->PixelToLogic( aMousePos );
1844 sal_Bool bAccept = sal_False;
1846 if ( GetOutputArea().IsInside( aMousePos ) && !bReadOnly )
1848 // sal_Int8 nSupportedActions = bReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE;
1850 if ( pDragAndDropInfo->bHasValidData /* && ( nSupportedActions & rDTDE.DropAction ) MT: Default = 0x80 ?! */ )
1852 bAccept = sal_True;
1854 sal_Bool bAllowScroll = DoAutoScroll();
1855 if ( bAllowScroll )
1857 long nScrollX = 0;
1858 long nScrollY = 0;
1859 // pruefen, ob im sensitiven Bereich
1860 if ( ( (aMousePos.X()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Left() ) && ( ( aMousePos.X() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Left() ) )
1861 nScrollX = GetOutputArea().GetWidth() / SCRLRANGE;
1862 else if ( ( (aMousePos.X()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Right() ) && ( ( aMousePos.X() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Right() ) )
1863 nScrollX = -( GetOutputArea().GetWidth() / SCRLRANGE );
1865 if ( ( (aMousePos.Y()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Top() ) && ( ( aMousePos.Y() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Top() ) )
1866 nScrollY = GetOutputArea().GetHeight() / SCRLRANGE;
1867 else if ( ( (aMousePos.Y()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Bottom() ) && ( ( aMousePos.Y() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Bottom() ) )
1868 nScrollY = -( GetOutputArea().GetHeight() / SCRLRANGE );
1870 if ( nScrollX || nScrollY )
1872 HideDDCursor();
1873 Scroll( nScrollX, nScrollY, RGCHK_PAPERSZ1 );
1877 Point aDocPos( GetDocPos( aMousePos ) );
1878 EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos );
1879 pDragAndDropInfo->aDropDest = aPaM;
1880 if ( pDragAndDropInfo->bOutlinerMode )
1882 USHORT nPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
1883 ParaPortion* pPPortion = pEditEngine->pImpEditEngine->GetParaPortions().SaveGetObject( nPara );
1884 long nDestParaStartY = pEditEngine->pImpEditEngine->GetParaPortions().GetYOffset( pPPortion );
1885 long nRel = aDocPos.Y() - nDestParaStartY;
1886 if ( nRel < ( pPPortion->GetHeight() / 2 ) )
1888 pDragAndDropInfo->nOutlinerDropDest = nPara;
1890 else
1892 pDragAndDropInfo->nOutlinerDropDest = nPara+1;
1895 if( ( pDragAndDropInfo->nOutlinerDropDest >= pDragAndDropInfo->aBeginDragSel.nStartPara ) &&
1896 ( pDragAndDropInfo->nOutlinerDropDest <= (pDragAndDropInfo->aBeginDragSel.nEndPara+1) ) )
1898 bAccept = FALSE;
1901 else if ( HasSelection() )
1903 // es darf nicht in eine Selektion gedroppt werden
1904 EPaM aP = pEditEngine->pImpEditEngine->CreateEPaM( aPaM );
1905 ESelection aDestSel( aP.nPara, aP.nIndex, aP.nPara, aP.nIndex);
1906 ESelection aCurSel = pEditEngine->pImpEditEngine->CreateESel( GetEditSelection() );
1907 aCurSel.Adjust();
1908 if ( !aDestSel.IsLess( aCurSel ) && !aDestSel.IsGreater( aCurSel ) )
1910 bAccept = FALSE;
1913 if ( bAccept )
1915 Rectangle aEditCursor;
1916 if ( pDragAndDropInfo->bOutlinerMode )
1918 long nDDYPos;
1919 if ( pDragAndDropInfo->nOutlinerDropDest < pEditEngine->pImpEditEngine->GetEditDoc().Count() )
1921 ParaPortion* pPPortion = pEditEngine->pImpEditEngine->GetParaPortions().SaveGetObject( pDragAndDropInfo->nOutlinerDropDest );
1922 nDDYPos = pEditEngine->pImpEditEngine->GetParaPortions().GetYOffset( pPPortion );
1924 else
1926 nDDYPos = pEditEngine->pImpEditEngine->GetTextHeight();
1928 Point aStartPos( 0, nDDYPos );
1929 aStartPos = GetWindowPos( aStartPos );
1930 Point aEndPos( GetOutputArea().GetWidth(), nDDYPos );
1931 aEndPos = GetWindowPos( aEndPos );
1932 aEditCursor = GetWindow()->LogicToPixel( Rectangle( aStartPos, aEndPos ) );
1933 if ( !pEditEngine->IsVertical() )
1935 aEditCursor.Top()--;
1936 aEditCursor.Bottom()++;
1938 else
1940 aEditCursor.Left()--;
1941 aEditCursor.Right()++;
1943 aEditCursor = GetWindow()->PixelToLogic( aEditCursor );
1945 else
1947 aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM );
1948 Point aTopLeft( GetWindowPos( aEditCursor.TopLeft() ) );
1949 aEditCursor.SetPos( aTopLeft );
1950 aEditCursor.Right() = aEditCursor.Left() + pDragAndDropInfo->nCursorWidth;
1951 aEditCursor = GetWindow()->LogicToPixel( aEditCursor );
1952 aEditCursor = GetWindow()->PixelToLogic( aEditCursor );
1955 sal_Bool bCursorChanged = !pDragAndDropInfo->bVisCursor || ( pDragAndDropInfo->aCurCursor != aEditCursor );
1956 if ( bCursorChanged )
1958 HideDDCursor();
1959 ShowDDCursor(aEditCursor );
1961 pDragAndDropInfo->bDragAccepted = TRUE;
1962 rDTDE.Context->acceptDrag( rDTDE.DropAction );
1967 if ( !bAccept )
1969 HideDDCursor();
1970 pDragAndDropInfo->bDragAccepted = FALSE;
1971 rDTDE.Context->rejectDrag();
1975 void ImpEditView::AddDragAndDropListeners()
1977 Window* pWindow = GetWindow();
1978 if ( !bActiveDragAndDropListener && pWindow && pWindow->GetDragGestureRecognizer().is() )
1980 vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this );
1981 mxDnDListener = pDnDWrapper;
1983 uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY );
1984 pWindow->GetDragGestureRecognizer()->addDragGestureListener( xDGL );
1985 uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( xDGL, uno::UNO_QUERY );
1986 pWindow->GetDropTarget()->addDropTargetListener( xDTL );
1987 pWindow->GetDropTarget()->setActive( sal_True );
1988 pWindow->GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE );
1990 bActiveDragAndDropListener = TRUE;
1994 void ImpEditView::RemoveDragAndDropListeners()
1996 if ( bActiveDragAndDropListener && GetWindow() && GetWindow()->GetDragGestureRecognizer().is() )
1998 uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY );
1999 GetWindow()->GetDragGestureRecognizer()->removeDragGestureListener( xDGL );
2000 uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( xDGL, uno::UNO_QUERY );
2001 GetWindow()->GetDropTarget()->removeDropTargetListener( xDTL );
2003 if ( mxDnDListener.is() )
2005 uno::Reference< lang::XEventListener> xEL( mxDnDListener, uno::UNO_QUERY );
2006 xEL->disposing( lang::EventObject() ); // #95154# Empty Source means it's the Client
2007 mxDnDListener.clear();
2010 bActiveDragAndDropListener = FALSE;