1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: textview.cxx,v $
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_svtools.hxx"
33 #include <svtools/textview.hxx>
34 #include <svtools/texteng.hxx>
35 #include <textdoc.hxx>
36 #include <svtools/textdata.hxx>
37 #include <textdat2.hxx>
39 #include <svtools/undo.hxx>
40 #include <vcl/cursor.hxx>
41 #include <vcl/window.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/sound.hxx>
44 #include <tools/stream.hxx>
46 #include <sot/formats.hxx>
49 #ifndef _COM_SUN_STAR_TEXT_XBREAKITERATOR_HPP_
50 #include <com/sun/star/i18n/XBreakIterator.hpp>
53 #ifndef _COM_SUN_STAR_TEXT_CHARACTERITERATORMODE_HPP_
54 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
57 #ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
58 #include <com/sun/star/i18n/WordType.hpp>
60 #include <cppuhelper/weak.hxx>
61 #include <vcl/unohelp.hxx>
62 #include <com/sun/star/datatransfer/XTransferable.hpp>
63 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
64 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
65 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
67 #ifndef _COM_SUN_STAR_DATATRANSFER_DND_DNDCONSTANS_HPP_
68 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
70 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
71 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
73 #include <vcl/edit.hxx>
76 #include <sot/exchange.hxx>
77 #include <sot/formats.hxx>
79 #include <vos/mutex.hxx>
82 using namespace ::com::sun::star
;
84 class TETextDataObject
: public ::com::sun::star::datatransfer::XTransferable
,
85 public ::cppu::OWeakObject
90 SvMemoryStream maHTMLStream
;
93 TETextDataObject( const String
& rText
);
96 String
& GetText() { return maText
; }
97 SvMemoryStream
& GetHTMLStream() { return maHTMLStream
; }
99 // ::com::sun::star::uno::XInterface
100 ::com::sun::star::uno::Any SAL_CALL
queryInterface( const ::com::sun::star::uno::Type
& rType
) throw(::com::sun::star::uno::RuntimeException
);
101 void SAL_CALL
acquire() throw() { OWeakObject::acquire(); }
102 void SAL_CALL
release() throw() { OWeakObject::release(); }
104 // ::com::sun::star::datatransfer::XTransferable
105 ::com::sun::star::uno::Any SAL_CALL
getTransferData( const ::com::sun::star::datatransfer::DataFlavor
& aFlavor
) throw(::com::sun::star::datatransfer::UnsupportedFlavorException
, ::com::sun::star::io::IOException
, ::com::sun::star::uno::RuntimeException
);
106 ::com::sun::star::uno::Sequence
< ::com::sun::star::datatransfer::DataFlavor
> SAL_CALL
getTransferDataFlavors( ) throw(::com::sun::star::uno::RuntimeException
);
107 sal_Bool SAL_CALL
isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor
& aFlavor
) throw(::com::sun::star::uno::RuntimeException
);
110 TETextDataObject::TETextDataObject( const String
& rText
) : maText( rText
)
114 TETextDataObject::~TETextDataObject()
119 uno::Any
TETextDataObject::queryInterface( const uno::Type
& rType
) throw(uno::RuntimeException
)
121 uno::Any aRet
= ::cppu::queryInterface( rType
, SAL_STATIC_CAST( datatransfer::XTransferable
*, this ) );
122 return (aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
));
125 // datatransfer::XTransferable
126 uno::Any
TETextDataObject::getTransferData( const datatransfer::DataFlavor
& rFlavor
) throw(datatransfer::UnsupportedFlavorException
, io::IOException
, uno::RuntimeException
)
130 ULONG nT
= SotExchange::GetFormat( rFlavor
);
131 if ( nT
== SOT_FORMAT_STRING
)
133 aAny
<<= (::rtl::OUString
)GetText();
135 else if ( nT
== SOT_FORMATSTR_ID_HTML
)
137 GetHTMLStream().Seek( STREAM_SEEK_TO_END
);
138 ULONG nLen
= GetHTMLStream().Tell();
139 GetHTMLStream().Seek(0);
141 uno::Sequence
< sal_Int8
> aSeq( nLen
);
142 memcpy( aSeq
.getArray(), GetHTMLStream().GetData(), nLen
);
147 throw datatransfer::UnsupportedFlavorException();
152 uno::Sequence
< datatransfer::DataFlavor
> TETextDataObject::getTransferDataFlavors( ) throw(uno::RuntimeException
)
154 GetHTMLStream().Seek( STREAM_SEEK_TO_END
);
155 BOOL bHTML
= GetHTMLStream().Tell() > 0;
156 uno::Sequence
< datatransfer::DataFlavor
> aDataFlavors( bHTML
? 2 : 1 );
157 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aDataFlavors
.getArray()[0] );
159 SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_HTML
, aDataFlavors
.getArray()[1] );
163 sal_Bool
TETextDataObject::isDataFlavorSupported( const datatransfer::DataFlavor
& rFlavor
) throw(uno::RuntimeException
)
165 ULONG nT
= SotExchange::GetFormat( rFlavor
);
166 return ( nT
== SOT_FORMAT_STRING
);
169 /*-- 24.06.2004 13:54:36---------------------------------------------------
171 -----------------------------------------------------------------------*/
174 TextEngine
* mpTextEngine
;
177 TextSelection maSelection
;
179 // TextPaM maMBDownPaM;
183 TextDDInfo
* mpDDInfo
;
185 VirtualDevice
* mpVirtDev
;
187 SelectionEngine
* mpSelEngine
;
188 TextSelFunctionSet
* mpSelFuncSet
;
190 ::com::sun::star::uno::Reference
< ::com::sun::star::datatransfer::dnd::XDragSourceListener
> mxDnDListener
;
194 BOOL mbAutoScroll
: 1;
195 BOOL mbInsertMode
: 1;
197 BOOL mbPaintSelection
: 1;
198 BOOL mbAutoIndent
: 1;
199 BOOL mbHighlightSelection
: 1;
200 BOOL mbCursorEnabled
: 1;
201 BOOL mbClickedInSelection
: 1;
202 BOOL mbSupportProtectAttribute
: 1;
203 bool mbCursorAtEndOfLine
;
206 // -------------------------------------------------------------------------
207 // (+) class TextView
208 // -------------------------------------------------------------------------
209 TextView::TextView( TextEngine
* pEng
, Window
* pWindow
) :
210 mpImpl(new ImpTextView
)
212 pWindow
->EnableRTL( FALSE
);
214 mpImpl
->mpWindow
= pWindow
;
215 mpImpl
->mpTextEngine
= pEng
;
216 mpImpl
->mpVirtDev
= NULL
;
218 mpImpl
->mbPaintSelection
= TRUE
;
219 mpImpl
->mbAutoScroll
= TRUE
;
220 mpImpl
->mbInsertMode
= TRUE
;
221 mpImpl
->mbReadOnly
= FALSE
;
222 mpImpl
->mbHighlightSelection
= FALSE
;
223 mpImpl
->mbAutoIndent
= FALSE
;
224 mpImpl
->mbCursorEnabled
= TRUE
;
225 mpImpl
->mbClickedInSelection
= FALSE
;
226 mpImpl
->mbSupportProtectAttribute
= FALSE
;
227 mpImpl
->mbCursorAtEndOfLine
= false;
228 // mbInSelection = FALSE;
230 mpImpl
->mnTravelXPos
= TRAVEL_X_DONTKNOW
;
232 mpImpl
->mpSelFuncSet
= new TextSelFunctionSet( this );
233 mpImpl
->mpSelEngine
= new SelectionEngine( mpImpl
->mpWindow
, mpImpl
->mpSelFuncSet
);
234 mpImpl
->mpSelEngine
->SetSelectionMode( RANGE_SELECTION
);
235 mpImpl
->mpSelEngine
->EnableDrag( TRUE
);
237 mpImpl
->mpCursor
= new Cursor
;
238 mpImpl
->mpCursor
->Show();
239 pWindow
->SetCursor( mpImpl
->mpCursor
);
240 pWindow
->SetInputContext( InputContext( pEng
->GetFont(), INPUTCONTEXT_TEXT
|INPUTCONTEXT_EXTTEXTINPUT
) );
242 if ( pWindow
->GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_INVERT
)
243 mpImpl
->mbHighlightSelection
= TRUE
;
245 pWindow
->SetLineColor();
247 mpImpl
->mpDDInfo
= NULL
;
249 if ( pWindow
->GetDragGestureRecognizer().is() )
251 vcl::unohelper::DragAndDropWrapper
* pDnDWrapper
= new vcl::unohelper::DragAndDropWrapper( this );
252 mpImpl
->mxDnDListener
= pDnDWrapper
;
254 uno::Reference
< datatransfer::dnd::XDragGestureListener
> xDGL( mpImpl
->mxDnDListener
, uno::UNO_QUERY
);
255 pWindow
->GetDragGestureRecognizer()->addDragGestureListener( xDGL
);
256 uno::Reference
< datatransfer::dnd::XDropTargetListener
> xDTL( xDGL
, uno::UNO_QUERY
);
257 pWindow
->GetDropTarget()->addDropTargetListener( xDTL
);
258 pWindow
->GetDropTarget()->setActive( sal_True
);
259 pWindow
->GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE
);
263 TextView::~TextView()
265 delete mpImpl
->mpSelEngine
;
266 delete mpImpl
->mpSelFuncSet
;
267 delete mpImpl
->mpVirtDev
;
269 if ( mpImpl
->mpWindow
->GetCursor() == mpImpl
->mpCursor
)
270 mpImpl
->mpWindow
->SetCursor( 0 );
271 delete mpImpl
->mpCursor
;
272 delete mpImpl
->mpDDInfo
;
276 void TextView::Invalidate()
278 mpImpl
->mpWindow
->Invalidate();
281 void TextView::SetSelection( const TextSelection
& rTextSel
, BOOL bGotoCursor
)
283 // Falls jemand gerade ein leeres Attribut hinterlassen hat,
284 // und dann der Outliner die Selektion manipulitert:
285 if ( !mpImpl
->maSelection
.HasRange() )
286 mpImpl
->mpTextEngine
->CursorMoved( mpImpl
->maSelection
.GetStart().GetPara() );
288 // Wenn nach einem KeyInput die Selection manipuliert wird:
289 mpImpl
->mpTextEngine
->CheckIdleFormatter();
292 TextSelection
aNewSel( rTextSel
);
293 mpImpl
->mpTextEngine
->ValidateSelection( aNewSel
);
294 ImpSetSelection( aNewSel
);
296 ShowCursor( bGotoCursor
);
299 void TextView::SetSelection( const TextSelection
& rTextSel
)
301 SetSelection( rTextSel
, mpImpl
->mbAutoScroll
);
304 const TextSelection
& TextView::GetSelection() const
306 return mpImpl
->maSelection
;
308 TextSelection
& TextView::GetSelection()
310 return mpImpl
->maSelection
;
313 void TextView::DeleteSelected()
317 mpImpl
->mpTextEngine
->UndoActionStart( TEXTUNDO_DELETE
);
318 TextPaM aPaM
= mpImpl
->mpTextEngine
->ImpDeleteText( mpImpl
->maSelection
);
319 mpImpl
->mpTextEngine
->UndoActionEnd( TEXTUNDO_DELETE
);
321 ImpSetSelection( aPaM
);
322 mpImpl
->mpTextEngine
->FormatAndUpdate( this );
326 void TextView::ImpPaint( OutputDevice
* pOut
, const Point
& rStartPos
, Rectangle
const* pPaintArea
, TextSelection
const* pPaintRange
, TextSelection
const* pSelection
)
328 if ( !mpImpl
->mbPaintSelection
)
332 // Richtige Hintergrundfarbe einstellen.
333 // Ich bekomme leider nicht mit, ob sich diese inzwischen geaendert hat.
334 Font aFont
= mpImpl
->mpTextEngine
->GetFont();
335 Color aColor
= pOut
->GetBackground().GetColor();
336 aColor
.SetTransparency( 0 );
337 if ( aColor
!= aFont
.GetFillColor() )
339 if( aFont
.IsTransparent() )
340 aColor
= Color( COL_TRANSPARENT
);
341 aFont
.SetFillColor( aColor
);
342 mpImpl
->mpTextEngine
->maFont
= aFont
;
346 mpImpl
->mpTextEngine
->ImpPaint( pOut
, rStartPos
, pPaintArea
, pPaintRange
, pSelection
);
349 void TextView::Paint( const Rectangle
& rRect
)
351 ImpPaint( rRect
, FALSE
);
354 void TextView::ImpPaint( const Rectangle
& rRect
, BOOL bUseVirtDev
)
356 if ( !mpImpl
->mpTextEngine
->GetUpdateMode() || mpImpl
->mpTextEngine
->IsInUndo() )
359 TextSelection
*pDrawSelection
= NULL
;
360 if ( !mpImpl
->mbHighlightSelection
&& mpImpl
->maSelection
.HasRange() )
361 pDrawSelection
= &mpImpl
->maSelection
;
365 VirtualDevice
* pVDev
= GetVirtualDevice();
367 const Color
& rBackgroundColor
= mpImpl
->mpWindow
->GetBackground().GetColor();
368 if ( pVDev
->GetFillColor() != rBackgroundColor
)
369 pVDev
->SetFillColor( rBackgroundColor
);
370 if ( pVDev
->GetBackground().GetColor() != rBackgroundColor
)
371 pVDev
->SetBackground( rBackgroundColor
);
373 BOOL bVDevValid
= TRUE
;
374 Size
aOutSz( pVDev
->GetOutputSizePixel() );
375 if ( ( aOutSz
.Width() < rRect
.GetWidth() ) ||
376 ( aOutSz
.Height() < rRect
.GetHeight() ) )
378 bVDevValid
= pVDev
->SetOutputSizePixel( rRect
.GetSize() );
382 // Das VirtDev kann bei einem Resize sehr gross werden =>
383 // irgendwann mal kleiner machen!
384 if ( ( aOutSz
.Height() > ( rRect
.GetHeight() + 20 ) ) ||
385 ( aOutSz
.Width() > ( rRect
.GetWidth() + 20 ) ) )
387 bVDevValid
= pVDev
->SetOutputSizePixel( rRect
.GetSize() );
396 ImpPaint( rRect
, FALSE
/* ohne VDev */ );
400 Rectangle
aTmpRec( Point( 0, 0 ), rRect
.GetSize() );
402 Point
aDocPos( mpImpl
->maStartDocPos
.X(), mpImpl
->maStartDocPos
.Y() + rRect
.Top() );
403 Point aStartPos
= ImpGetOutputStartPos( aDocPos
);
404 ImpPaint( pVDev
, aStartPos
, &aTmpRec
, NULL
, pDrawSelection
);
405 mpImpl
->mpWindow
->DrawOutDev( rRect
.TopLeft(), rRect
.GetSize(),
406 Point(0,0), rRect
.GetSize(), *pVDev
);
408 if ( mpImpl
->mbHighlightSelection
)
409 ImpHighlight( mpImpl
->maSelection
);
413 Point aStartPos
= ImpGetOutputStartPos( mpImpl
->maStartDocPos
);
414 ImpPaint( mpImpl
->mpWindow
, aStartPos
, &rRect
, NULL
, pDrawSelection
);
417 if ( mpImpl
->mbHighlightSelection
)
418 ImpHighlight( mpImpl
->maSelection
);
422 void TextView::ImpHighlight( const TextSelection
& rSel
)
424 TextSelection
aSel( rSel
);
426 if ( aSel
.HasRange() && !mpImpl
->mpTextEngine
->IsInUndo() && mpImpl
->mpTextEngine
->GetUpdateMode() )
428 mpImpl
->mpCursor
->Hide();
430 DBG_ASSERT( !mpImpl
->mpTextEngine
->mpIdleFormatter
->IsActive(), "ImpHighlight: Not formatted!" );
432 Rectangle
aVisArea( mpImpl
->maStartDocPos
, mpImpl
->mpWindow
->GetOutputSizePixel() );
434 ULONG nStartPara
= aSel
.GetStart().GetPara();
435 ULONG nEndPara
= aSel
.GetEnd().GetPara();
436 for ( ULONG nPara
= 0; nPara
<= nEndPara
; nPara
++ )
438 long nParaHeight
= (long)mpImpl
->mpTextEngine
->CalcParaHeight( nPara
);
439 if ( ( nPara
>= nStartPara
) && ( ( nY
+ nParaHeight
) > aVisArea
.Top() ) )
441 TEParaPortion
* pTEParaPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( nPara
);
442 USHORT nStartLine
= 0;
443 USHORT nEndLine
= pTEParaPortion
->GetLines().Count() -1;
444 if ( nPara
== nStartPara
)
445 nStartLine
= pTEParaPortion
->GetLineNumber( aSel
.GetStart().GetIndex(), FALSE
);
446 if ( nPara
== nEndPara
)
447 nEndLine
= pTEParaPortion
->GetLineNumber( aSel
.GetEnd().GetIndex(), TRUE
);
449 // ueber die Zeilen iterieren....
450 for ( USHORT nLine
= nStartLine
; nLine
<= nEndLine
; nLine
++ )
452 TextLine
* pLine
= pTEParaPortion
->GetLines().GetObject( nLine
);
453 USHORT nStartIndex
= pLine
->GetStart();
454 USHORT nEndIndex
= pLine
->GetEnd();
455 if ( ( nPara
== nStartPara
) && ( nLine
== nStartLine
) )
456 nStartIndex
= aSel
.GetStart().GetIndex();
457 if ( ( nPara
== nEndPara
) && ( nLine
== nEndLine
) )
458 nEndIndex
= aSel
.GetEnd().GetIndex();
460 // Kann passieren, wenn am Anfang einer umgebrochenen Zeile.
461 if ( nEndIndex
< nStartIndex
)
462 nEndIndex
= nStartIndex
;
464 Rectangle
aTmpRec( mpImpl
->mpTextEngine
->GetEditCursor( TextPaM( nPara
, nStartIndex
), FALSE
) );
466 aTmpRec
.Bottom() += nY
;
467 Point
aTopLeft( aTmpRec
.TopLeft() );
469 aTmpRec
= mpImpl
->mpTextEngine
->GetEditCursor( TextPaM( nPara
, nEndIndex
), TRUE
);
471 aTmpRec
.Bottom() += nY
;
472 Point
aBottomRight( aTmpRec
.BottomRight() );
475 // Nur Painten, wenn im sichtbaren Bereich...
476 if ( ( aTopLeft
.X() < aBottomRight
.X() ) && ( aBottomRight
.Y() >= aVisArea
.Top() ) )
478 Point
aPnt1( GetWindowPos( aTopLeft
) );
479 Point
aPnt2( GetWindowPos( aBottomRight
) );
481 Rectangle
aRect( aPnt1
, aPnt2
);
482 mpImpl
->mpWindow
->Invert( aRect
);
488 if ( nY
>= aVisArea
.Bottom() )
494 void TextView::ImpSetSelection( const TextSelection
& rSelection
)
496 if ( rSelection
!= mpImpl
->maSelection
)
498 mpImpl
->maSelection
= rSelection
;
499 mpImpl
->mpTextEngine
->Broadcast( TextHint( TEXT_HINT_VIEWSELECTIONCHANGED
) );
503 void TextView::ShowSelection()
505 ImpShowHideSelection( TRUE
);
508 void TextView::HideSelection()
510 ImpShowHideSelection( FALSE
);
513 void TextView::ShowSelection( const TextSelection
& rRange
)
515 ImpShowHideSelection( TRUE
, &rRange
);
518 void TextView::ImpShowHideSelection( BOOL bShow
, const TextSelection
* pRange
)
520 const TextSelection
* pRangeOrSelection
= pRange
? pRange
: &mpImpl
->maSelection
;
522 if ( pRangeOrSelection
->HasRange() )
524 if ( mpImpl
->mbHighlightSelection
)
526 ImpHighlight( *pRangeOrSelection
);
530 if( mpImpl
->mpWindow
->IsPaintTransparent() )
531 mpImpl
->mpWindow
->Invalidate();
534 Rectangle
aOutArea( Point( 0, 0 ), mpImpl
->mpWindow
->GetOutputSizePixel() );
535 Point
aStartPos( ImpGetOutputStartPos( mpImpl
->maStartDocPos
) );
536 TextSelection
aRange( *pRangeOrSelection
);
538 BOOL bVisCursor
= mpImpl
->mpCursor
->IsVisible();
539 mpImpl
->mpCursor
->Hide();
540 ImpPaint( mpImpl
->mpWindow
, aStartPos
, &aOutArea
, &aRange
, bShow
? &mpImpl
->maSelection
: NULL
);
542 mpImpl
->mpCursor
->Show();
548 VirtualDevice
* TextView::GetVirtualDevice()
550 if ( !mpImpl
->mpVirtDev
)
552 mpImpl
->mpVirtDev
= new VirtualDevice
;
553 mpImpl
->mpVirtDev
->SetLineColor();
555 return mpImpl
->mpVirtDev
;
558 void TextView::EraseVirtualDevice()
560 delete mpImpl
->mpVirtDev
;
561 mpImpl
->mpVirtDev
= 0;
564 BOOL
TextView::KeyInput( const KeyEvent
& rKeyEvent
)
567 BOOL bModified
= FALSE
;
569 BOOL bEndKey
= FALSE
; // spezielle CursorPosition
570 BOOL bAllowIdle
= TRUE
;
572 // Um zu pruefen ob durch irgendeine Aktion mModified, das lokale
573 // bModified wird z.B. bei Cut/Paste nicht gesetzt, weil dort an anderen
574 // Stellen das updaten erfolgt.
575 BOOL bWasModified
= mpImpl
->mpTextEngine
->IsModified();
576 mpImpl
->mpTextEngine
->SetModified( FALSE
);
578 TextSelection
aCurSel( mpImpl
->maSelection
);
579 TextSelection
aOldSel( aCurSel
);
581 USHORT nCode
= rKeyEvent
.GetKeyCode().GetCode();
582 KeyFuncType eFunc
= rKeyEvent
.GetKeyCode().GetFunction();
583 if ( eFunc
!= KEYFUNC_DONTKNOW
)
589 if ( !mpImpl
->mbReadOnly
)
600 if ( !mpImpl
->mbReadOnly
)
606 if ( !mpImpl
->mbReadOnly
)
612 if ( !mpImpl
->mbReadOnly
)
617 default: // wird dann evtl. unten bearbeitet.
618 eFunc
= KEYFUNC_DONTKNOW
;
621 if ( eFunc
== KEYFUNC_DONTKNOW
)
633 case com::sun::star::awt::Key::MOVE_WORD_FORWARD
:
634 case com::sun::star::awt::Key::SELECT_WORD_FORWARD
:
635 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD
:
636 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD
:
637 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
638 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE
:
639 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
640 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE
:
641 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
642 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
643 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
644 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
645 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
646 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
647 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
648 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
650 if ( ( !rKeyEvent
.GetKeyCode().IsMod2() || ( nCode
== KEY_LEFT
) || ( nCode
== KEY_RIGHT
) )
651 && !( rKeyEvent
.GetKeyCode().IsMod1() && ( nCode
== KEY_PAGEUP
|| nCode
== KEY_PAGEDOWN
) ) )
653 aCurSel
= ImpMoveCursor( rKeyEvent
);
654 if ( aCurSel
.HasRange() ) {
655 uno::Reference
<datatransfer::clipboard::XClipboard
> aSelection(GetWindow()->GetPrimarySelection());
659 if ( nCode
== KEY_END
)
668 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD
:
669 case com::sun::star::awt::Key::DELETE_WORD_FORWARD
:
670 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
671 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE
:
673 if ( !mpImpl
->mbReadOnly
&& !rKeyEvent
.GetKeyCode().IsMod2() )
675 BYTE nDel
= ( nCode
== KEY_DELETE
) ? DEL_RIGHT
: DEL_LEFT
;
676 BYTE nMode
= rKeyEvent
.GetKeyCode().IsMod1() ? DELMODE_RESTOFWORD
: DELMODE_SIMPLE
;
677 if ( ( nMode
== DELMODE_RESTOFWORD
) && rKeyEvent
.GetKeyCode().IsShift() )
678 nMode
= DELMODE_RESTOFCONTENT
;
682 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD
:
684 nMode
= DELMODE_RESTOFWORD
;
686 case com::sun::star::awt::Key::DELETE_WORD_FORWARD
:
688 nMode
= DELMODE_RESTOFWORD
;
690 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
692 nMode
= DELMODE_RESTOFCONTENT
;
694 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE
:
696 nMode
= DELMODE_RESTOFCONTENT
;
701 mpImpl
->mpTextEngine
->UndoActionStart( TEXTUNDO_DELETE
);
702 if(mpImpl
->mbSupportProtectAttribute
)
704 //expand selection to include all protected content - if there is any
705 const TextCharAttrib
* pStartAttr
= mpImpl
->mpTextEngine
->FindCharAttrib(
706 TextPaM(mpImpl
->maSelection
.GetStart().GetPara(),
707 mpImpl
->maSelection
.GetStart().GetIndex()),
708 TEXTATTR_PROTECTED
);
709 const TextCharAttrib
* pEndAttr
= mpImpl
->mpTextEngine
->FindCharAttrib(
710 TextPaM(mpImpl
->maSelection
.GetEnd().GetPara(),
711 mpImpl
->maSelection
.GetEnd().GetIndex()),
712 TEXTATTR_PROTECTED
);
713 if(pStartAttr
&& pStartAttr
->GetStart() < mpImpl
->maSelection
.GetStart().GetIndex())
715 mpImpl
->maSelection
.GetStart().GetIndex() = pStartAttr
->GetStart();
717 if(pEndAttr
&& pEndAttr
->GetEnd() > mpImpl
->maSelection
.GetEnd().GetIndex())
719 mpImpl
->maSelection
.GetEnd().GetIndex() = pEndAttr
->GetEnd();
722 aCurSel
= ImpDelete( nDel
, nMode
);
723 mpImpl
->mpTextEngine
->UndoActionEnd( TEXTUNDO_DELETE
);
733 if ( !mpImpl
->mbReadOnly
&& !rKeyEvent
.GetKeyCode().IsShift() &&
734 !rKeyEvent
.GetKeyCode().IsMod1() && !rKeyEvent
.GetKeyCode().IsMod2() &&
735 ImplCheckTextLen( 'x' ) )
737 aCurSel
= mpImpl
->mpTextEngine
->ImpInsertText( aCurSel
, '\t', !IsInsertMode() );
746 // Shift-RETURN darf nicht geschluckt werden, weil dann keine
747 // mehrzeilige Eingabe in Dialogen/Property-Editor moeglich.
748 if ( !mpImpl
->mbReadOnly
&& !rKeyEvent
.GetKeyCode().IsMod1() &&
749 !rKeyEvent
.GetKeyCode().IsMod2() && ImplCheckTextLen( 'x' ) )
751 mpImpl
->mpTextEngine
->UndoActionStart( TEXTUNDO_INSERT
);
752 aCurSel
= mpImpl
->mpTextEngine
->ImpInsertParaBreak( aCurSel
);
753 if ( mpImpl
->mbAutoIndent
)
755 TextNode
* pPrev
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aCurSel
.GetEnd().GetPara() - 1 );
757 while ( ( n
< pPrev
->GetText().Len() ) && (
758 ( pPrev
->GetText().GetChar( n
) == ' ' ) ||
759 ( pPrev
->GetText().GetChar( n
) == '\t' ) ) )
764 aCurSel
= mpImpl
->mpTextEngine
->ImpInsertText( aCurSel
, pPrev
->GetText().Copy( 0, n
) );
766 mpImpl
->mpTextEngine
->UndoActionEnd( TEXTUNDO_INSERT
);
775 if ( !mpImpl
->mbReadOnly
)
776 SetInsertMode( !IsInsertMode() );
781 if ( TextEngine::IsSimpleCharInput( rKeyEvent
) )
783 xub_Unicode nCharCode
= rKeyEvent
.GetCharCode();
784 if ( !mpImpl
->mbReadOnly
&& ImplCheckTextLen( nCharCode
) ) // sonst trotzdem das Zeichen schlucken...
786 aCurSel
= mpImpl
->mpTextEngine
->ImpInsertText( nCharCode
, aCurSel
, !IsInsertMode(), sal_True
);
796 if ( aCurSel
!= aOldSel
) // Check if changed, maybe other method already changed mpImpl->maSelection, don't overwrite that!
797 ImpSetSelection( aCurSel
);
799 mpImpl
->mpTextEngine
->UpdateSelections();
801 if ( ( nCode
!= KEY_UP
) && ( nCode
!= KEY_DOWN
) )
802 mpImpl
->mnTravelXPos
= TRAVEL_X_DONTKNOW
;
806 // Idle-Formatter nur, wenn AnyInput.
807 if ( bAllowIdle
&& Application::AnyInput( INPUT_KEYBOARD
) )
808 mpImpl
->mpTextEngine
->IdleFormatAndUpdate( this );
810 mpImpl
->mpTextEngine
->FormatAndUpdate( this);
814 // Selection wird jetzt gezielt in ImpMoveCursor gemalt.
815 ImpShowCursor( mpImpl
->mbAutoScroll
, TRUE
, bEndKey
);
818 if ( mpImpl
->mpTextEngine
->IsModified() )
819 mpImpl
->mpTextEngine
->Broadcast( TextHint( TEXT_HINT_MODIFIED
) );
820 else if ( bWasModified
)
821 mpImpl
->mpTextEngine
->SetModified( TRUE
);
826 void TextView::MouseButtonUp( const MouseEvent
& rMouseEvent
)
828 mpImpl
->mbClickedInSelection
= FALSE
;
829 mpImpl
->mnTravelXPos
= TRAVEL_X_DONTKNOW
;
830 mpImpl
->mpSelEngine
->SelMouseButtonUp( rMouseEvent
);
831 if ( rMouseEvent
.IsMiddle() && !IsReadOnly() &&
832 ( GetWindow()->GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION
) )
834 uno::Reference
<datatransfer::clipboard::XClipboard
> aSelection(GetWindow()->GetPrimarySelection());
836 if ( mpImpl
->mpTextEngine
->IsModified() )
837 mpImpl
->mpTextEngine
->Broadcast( TextHint( TEXT_HINT_MODIFIED
) );
839 else if ( rMouseEvent
.IsLeft() && GetSelection().HasRange() )
841 uno::Reference
<datatransfer::clipboard::XClipboard
> aSelection(GetWindow()->GetPrimarySelection());
846 void TextView::MouseButtonDown( const MouseEvent
& rMouseEvent
)
848 mpImpl
->mpTextEngine
->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown
849 mpImpl
->mnTravelXPos
= TRAVEL_X_DONTKNOW
;
850 mpImpl
->mbClickedInSelection
= IsSelectionAtPoint( rMouseEvent
.GetPosPixel() );
852 mpImpl
->mpTextEngine
->SetActiveView( this );
854 mpImpl
->mpSelEngine
->SelMouseButtonDown( rMouseEvent
);
856 // mbu 20.01.2005 - SelMouseButtonDown() possibly triggers a 'selection changed'
857 // notification. The appropriate handler could change the current selection,
858 // which is the case in the MailMerge address block control. To enable select'n'drag
859 // we need to reevaluate the selection after the notification has been fired.
860 mpImpl
->mbClickedInSelection
= IsSelectionAtPoint( rMouseEvent
.GetPosPixel() );
862 // Sonderbehandlungen
863 if ( !rMouseEvent
.IsShift() && ( rMouseEvent
.GetClicks() >= 2 ) )
865 if ( rMouseEvent
.IsMod2() )
868 ImpSetSelection( mpImpl
->maSelection
.GetEnd() );
869 SetCursorAtPoint( rMouseEvent
.GetPosPixel() ); // Wird von SelectionEngine bei MOD2 nicht gesetzt
872 if ( rMouseEvent
.GetClicks() == 2 )
875 if ( mpImpl
->maSelection
.GetEnd().GetIndex() < mpImpl
->mpTextEngine
->GetTextLen( mpImpl
->maSelection
.GetEnd().GetPara() ) )
878 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( mpImpl
->maSelection
.GetEnd().GetPara() );
879 uno::Reference
< i18n::XBreakIterator
> xBI
= mpImpl
->mpTextEngine
->GetBreakIterator();
880 i18n::Boundary aBoundary
= xBI
->getWordBoundary( pNode
->GetText(), mpImpl
->maSelection
.GetEnd().GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
881 TextSelection
aNewSel( mpImpl
->maSelection
);
882 aNewSel
.GetStart().GetIndex() = (USHORT
)aBoundary
.startPos
;
883 aNewSel
.GetEnd().GetIndex() = (USHORT
)aBoundary
.endPos
;
884 if(mpImpl
->mbSupportProtectAttribute
)
886 //expand selection to include all protected content - if there is any
887 const TextCharAttrib
* pStartAttr
= mpImpl
->mpTextEngine
->FindCharAttrib(
888 TextPaM(aNewSel
.GetStart().GetPara(),
889 (USHORT
)aBoundary
.startPos
),
890 TEXTATTR_PROTECTED
);
891 const TextCharAttrib
* pEndAttr
= mpImpl
->mpTextEngine
->FindCharAttrib(
892 TextPaM(aNewSel
.GetEnd().GetPara(),
893 (USHORT
)aBoundary
.endPos
),
894 TEXTATTR_PROTECTED
);
895 if(pStartAttr
&& pStartAttr
->GetStart() < aNewSel
.GetStart().GetIndex())
897 aNewSel
.GetStart().GetIndex() = pStartAttr
->GetStart();
899 if(pEndAttr
&& pEndAttr
->GetEnd() > aNewSel
.GetEnd().GetIndex())
901 aNewSel
.GetEnd().GetIndex() = pEndAttr
->GetEnd();
904 ImpSetSelection( aNewSel
);
906 ShowCursor( TRUE
, TRUE
);
909 else if ( rMouseEvent
.GetClicks() == 3 )
911 // Absatz selektieren
912 if ( mpImpl
->maSelection
.GetStart().GetIndex() || ( mpImpl
->maSelection
.GetEnd().GetIndex() < mpImpl
->mpTextEngine
->GetTextLen( mpImpl
->maSelection
.GetEnd().GetPara() ) ) )
915 TextSelection
aNewSel( mpImpl
->maSelection
);
916 aNewSel
.GetStart().GetIndex() = 0;
917 aNewSel
.GetEnd().GetIndex() = mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( mpImpl
->maSelection
.GetEnd().GetPara() )->GetText().Len();
918 ImpSetSelection( aNewSel
);
920 ShowCursor( TRUE
, TRUE
);
927 void TextView::MouseMove( const MouseEvent
& rMouseEvent
)
929 mpImpl
->mnTravelXPos
= TRAVEL_X_DONTKNOW
;
930 mpImpl
->mpSelEngine
->SelMouseMove( rMouseEvent
);
933 void TextView::Command( const CommandEvent
& rCEvt
)
935 mpImpl
->mpTextEngine
->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown
936 mpImpl
->mpTextEngine
->SetActiveView( this );
938 if ( rCEvt
.GetCommand() == COMMAND_STARTEXTTEXTINPUT
)
941 delete mpImpl
->mpTextEngine
->mpIMEInfos
;
942 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( GetSelection().GetEnd().GetPara() );
943 mpImpl
->mpTextEngine
->mpIMEInfos
= new TEIMEInfos( GetSelection().GetEnd(), pNode
->GetText().Copy( GetSelection().GetEnd().GetIndex() ) );
944 mpImpl
->mpTextEngine
->mpIMEInfos
->bWasCursorOverwrite
= !IsInsertMode();
946 else if ( rCEvt
.GetCommand() == COMMAND_ENDEXTTEXTINPUT
)
948 DBG_ASSERT( mpImpl
->mpTextEngine
->mpIMEInfos
, "COMMAND_ENDEXTTEXTINPUT => Kein Start ?" );
949 if( mpImpl
->mpTextEngine
->mpIMEInfos
)
951 TEParaPortion
* pPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
.GetPara() );
952 pPortion
->MarkSelectionInvalid( mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
.GetIndex(), 0 );
954 BOOL bInsertMode
= !mpImpl
->mpTextEngine
->mpIMEInfos
->bWasCursorOverwrite
;
956 delete mpImpl
->mpTextEngine
->mpIMEInfos
;
957 mpImpl
->mpTextEngine
->mpIMEInfos
= NULL
;
959 mpImpl
->mpTextEngine
->FormatAndUpdate( this );
961 SetInsertMode( bInsertMode
);
963 if ( mpImpl
->mpTextEngine
->IsModified() )
964 mpImpl
->mpTextEngine
->Broadcast( TextHint( TEXT_HINT_MODIFIED
) );
967 else if ( rCEvt
.GetCommand() == COMMAND_EXTTEXTINPUT
)
969 DBG_ASSERT( mpImpl
->mpTextEngine
->mpIMEInfos
, "COMMAND_EXTTEXTINPUT => Kein Start ?" );
970 if( mpImpl
->mpTextEngine
->mpIMEInfos
)
972 const CommandExtTextInputData
* pData
= rCEvt
.GetExtTextInputData();
974 if ( !pData
->IsOnlyCursorChanged() )
976 TextSelection
aSelect( mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
);
977 aSelect
.GetEnd().GetIndex() = aSelect
.GetEnd().GetIndex() + mpImpl
->mpTextEngine
->mpIMEInfos
->nLen
;
978 aSelect
= mpImpl
->mpTextEngine
->ImpDeleteText( aSelect
);
979 aSelect
= mpImpl
->mpTextEngine
->ImpInsertText( aSelect
, pData
->GetText() );
981 if ( mpImpl
->mpTextEngine
->mpIMEInfos
->bWasCursorOverwrite
)
983 USHORT nOldIMETextLen
= mpImpl
->mpTextEngine
->mpIMEInfos
->nLen
;
984 USHORT nNewIMETextLen
= pData
->GetText().Len();
986 if ( ( nOldIMETextLen
> nNewIMETextLen
) &&
987 ( nNewIMETextLen
< mpImpl
->mpTextEngine
->mpIMEInfos
->aOldTextAfterStartPos
.Len() ) )
989 // restore old characters
990 USHORT nRestore
= nOldIMETextLen
- nNewIMETextLen
;
991 TextPaM
aPaM( mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
);
992 aPaM
.GetIndex() = aPaM
.GetIndex() + nNewIMETextLen
;
993 mpImpl
->mpTextEngine
->ImpInsertText( aPaM
, mpImpl
->mpTextEngine
->mpIMEInfos
->aOldTextAfterStartPos
.Copy( nNewIMETextLen
, nRestore
) );
995 else if ( ( nOldIMETextLen
< nNewIMETextLen
) &&
996 ( nOldIMETextLen
< mpImpl
->mpTextEngine
->mpIMEInfos
->aOldTextAfterStartPos
.Len() ) )
999 USHORT nOverwrite
= nNewIMETextLen
- nOldIMETextLen
;
1000 if ( ( nOldIMETextLen
+ nOverwrite
) > mpImpl
->mpTextEngine
->mpIMEInfos
->aOldTextAfterStartPos
.Len() )
1001 nOverwrite
= mpImpl
->mpTextEngine
->mpIMEInfos
->aOldTextAfterStartPos
.Len() - nOldIMETextLen
;
1002 DBG_ASSERT( nOverwrite
&& (nOverwrite
< 0xFF00), "IME Overwrite?!" );
1003 TextPaM
aPaM( mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
);
1004 aPaM
.GetIndex() = aPaM
.GetIndex() + nNewIMETextLen
;
1005 TextSelection
aSel( aPaM
);
1006 aSel
.GetEnd().GetIndex() =
1007 aSel
.GetEnd().GetIndex() + nOverwrite
;
1008 mpImpl
->mpTextEngine
->ImpDeleteText( aSel
);
1012 if ( pData
->GetTextAttr() )
1014 mpImpl
->mpTextEngine
->mpIMEInfos
->CopyAttribs( pData
->GetTextAttr(), pData
->GetText().Len() );
1015 mpImpl
->mpTextEngine
->mpIMEInfos
->bCursor
= pData
->IsCursorVisible();
1019 mpImpl
->mpTextEngine
->mpIMEInfos
->DestroyAttribs();
1022 TEParaPortion
* pPPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
.GetPara() );
1023 pPPortion
->MarkSelectionInvalid( mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
.GetIndex(), 0 );
1024 mpImpl
->mpTextEngine
->FormatAndUpdate( this );
1027 TextSelection aNewSel
= TextPaM( mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
.GetPara(), mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
.GetIndex()+pData
->GetCursorPos() );
1028 SetSelection( aNewSel
);
1029 SetInsertMode( !pData
->IsCursorOverwrite() );
1031 if ( pData
->IsCursorVisible() )
1037 else if ( rCEvt
.GetCommand() == COMMAND_CURSORPOS
)
1039 if ( mpImpl
->mpTextEngine
->mpIMEInfos
&& mpImpl
->mpTextEngine
->mpIMEInfos
->nLen
)
1041 TextPaM
aPaM( GetSelection().GetEnd() );
1042 Rectangle aR1
= mpImpl
->mpTextEngine
->PaMtoEditCursor( aPaM
);
1044 USHORT nInputEnd
= mpImpl
->mpTextEngine
->mpIMEInfos
->aPos
.GetIndex() + mpImpl
->mpTextEngine
->mpIMEInfos
->nLen
;
1046 if ( !mpImpl
->mpTextEngine
->IsFormatted() )
1047 mpImpl
->mpTextEngine
->FormatDoc();
1049 TEParaPortion
* pParaPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( aPaM
.GetPara() );
1050 USHORT nLine
= pParaPortion
->GetLineNumber( aPaM
.GetIndex(), sal_True
);
1051 TextLine
* pLine
= pParaPortion
->GetLines().GetObject( nLine
);
1052 if ( pLine
&& ( nInputEnd
> pLine
->GetEnd() ) )
1053 nInputEnd
= pLine
->GetEnd();
1054 Rectangle aR2
= mpImpl
->mpTextEngine
->PaMtoEditCursor( TextPaM( aPaM
.GetPara(), nInputEnd
) );
1056 long nWidth
= aR2
.Left()-aR1
.Right();
1057 aR1
.Move( -GetStartDocPos().X(), -GetStartDocPos().Y() );
1058 GetWindow()->SetCursorRect( &aR1
, nWidth
);
1062 GetWindow()->SetCursorRect();
1067 mpImpl
->mpSelEngine
->Command( rCEvt
);
1071 void TextView::ShowCursor( BOOL bGotoCursor
, BOOL bForceVisCursor
)
1073 // Die Einstellung hat mehr Gewicht:
1074 if ( !mpImpl
->mbAutoScroll
)
1075 bGotoCursor
= FALSE
;
1076 ImpShowCursor( bGotoCursor
, bForceVisCursor
, FALSE
);
1079 void TextView::HideCursor()
1081 mpImpl
->mpCursor
->Hide();
1084 void TextView::Scroll( long ndX
, long ndY
)
1086 DBG_ASSERT( mpImpl
->mpTextEngine
->IsFormatted(), "Scroll: Nicht formatiert!" );
1091 Point
aNewStartPos( mpImpl
->maStartDocPos
);
1094 aNewStartPos
.Y() -= ndY
;
1095 if ( aNewStartPos
.Y() < 0 )
1096 aNewStartPos
.Y() = 0;
1099 aNewStartPos
.X() -= ndX
;
1100 if ( aNewStartPos
.X() < 0 )
1101 aNewStartPos
.X() = 0;
1103 long nDiffX
= mpImpl
->maStartDocPos
.X() - aNewStartPos
.X();
1104 long nDiffY
= mpImpl
->maStartDocPos
.Y() - aNewStartPos
.Y();
1106 if ( nDiffX
|| nDiffY
)
1108 BOOL bVisCursor
= mpImpl
->mpCursor
->IsVisible();
1109 mpImpl
->mpCursor
->Hide();
1110 mpImpl
->mpWindow
->Update();
1111 mpImpl
->maStartDocPos
= aNewStartPos
;
1113 if ( mpImpl
->mpTextEngine
->IsRightToLeft() )
1115 mpImpl
->mpWindow
->Scroll( nDiffX
, nDiffY
);
1116 mpImpl
->mpWindow
->Update();
1117 mpImpl
->mpCursor
->SetPos( mpImpl
->mpCursor
->GetPos() + Point( nDiffX
, nDiffY
) );
1118 if ( bVisCursor
&& !mpImpl
->mbReadOnly
)
1119 mpImpl
->mpCursor
->Show();
1122 mpImpl
->mpTextEngine
->Broadcast( TextHint( TEXT_HINT_VIEWSCROLLED
) );
1125 void TextView::Undo()
1127 mpImpl
->mpTextEngine
->SetActiveView( this );
1128 mpImpl
->mpTextEngine
->GetUndoManager().Undo( 1 );
1131 void TextView::Redo()
1133 mpImpl
->mpTextEngine
->SetActiveView( this );
1134 mpImpl
->mpTextEngine
->GetUndoManager().Redo( 0 );
1137 void TextView::Cut()
1139 mpImpl
->mpTextEngine
->UndoActionStart( TEXTUNDO_CUT
);
1142 mpImpl
->mpTextEngine
->UndoActionEnd( TEXTUNDO_CUT
);
1145 void TextView::Copy( uno::Reference
< datatransfer::clipboard::XClipboard
>& rxClipboard
)
1147 if ( rxClipboard
.is() )
1149 TETextDataObject
* pDataObj
= new TETextDataObject( GetSelected() );
1151 if ( mpImpl
->mpTextEngine
->HasAttrib( TEXTATTR_HYPERLINK
) ) // Dann auch als HTML
1152 mpImpl
->mpTextEngine
->Write( pDataObj
->GetHTMLStream(), &mpImpl
->maSelection
, TRUE
);
1154 const sal_uInt32 nRef
= Application::ReleaseSolarMutex();
1158 rxClipboard
->setContents( pDataObj
, NULL
);
1160 uno::Reference
< datatransfer::clipboard::XFlushableClipboard
> xFlushableClipboard( rxClipboard
, uno::UNO_QUERY
);
1161 if( xFlushableClipboard
.is() )
1162 xFlushableClipboard
->flushClipboard();
1164 catch( const ::com::sun::star::uno::Exception
& )
1168 Application::AcquireSolarMutex( nRef
);
1172 void TextView::Copy()
1174 uno::Reference
<datatransfer::clipboard::XClipboard
> aClipboard(GetWindow()->GetClipboard());
1178 void TextView::Paste( uno::Reference
< datatransfer::clipboard::XClipboard
>& rxClipboard
)
1180 if ( rxClipboard
.is() )
1182 uno::Reference
< datatransfer::XTransferable
> xDataObj
;
1184 const sal_uInt32 nRef
= Application::ReleaseSolarMutex();
1188 xDataObj
= rxClipboard
->getContents();
1190 catch( const ::com::sun::star::uno::Exception
& )
1194 Application::AcquireSolarMutex( nRef
);
1196 if ( xDataObj
.is() )
1198 datatransfer::DataFlavor aFlavor
;
1199 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
1200 if ( xDataObj
->isDataFlavorSupported( aFlavor
) )
1204 uno::Any aData
= xDataObj
->getTransferData( aFlavor
);
1205 ::rtl::OUString aText
;
1207 bool bWasTruncated
= false;
1208 if( mpImpl
->mpTextEngine
->GetMaxTextLen() != 0 )
1209 bWasTruncated
= ImplTruncateNewText( aText
);
1210 InsertNewText( aText
, FALSE
);
1211 mpImpl
->mpTextEngine
->Broadcast( TextHint( TEXT_HINT_MODIFIED
) );
1214 Edit::ShowTruncationWarning( mpImpl
->mpWindow
);
1216 catch( const ::com::sun::star::datatransfer::UnsupportedFlavorException
& )
1224 void TextView::Paste()
1226 uno::Reference
<datatransfer::clipboard::XClipboard
> aClipboard(GetWindow()->GetClipboard());
1227 Paste( aClipboard
);
1230 String
TextView::GetSelected()
1232 return GetSelected( GetSystemLineEnd() );
1235 String
TextView::GetSelected( LineEnd aSeparator
)
1237 return mpImpl
->mpTextEngine
->GetText( mpImpl
->maSelection
, aSeparator
);
1240 void TextView::SetInsertMode( BOOL bInsert
)
1242 if ( mpImpl
->mbInsertMode
!= bInsert
)
1244 mpImpl
->mbInsertMode
= bInsert
;
1245 ShowCursor( mpImpl
->mbAutoScroll
, FALSE
);
1249 void TextView::SetReadOnly( BOOL bReadOnly
)
1251 if ( mpImpl
->mbReadOnly
!= bReadOnly
)
1253 mpImpl
->mbReadOnly
= bReadOnly
;
1254 if ( !mpImpl
->mbReadOnly
)
1255 ShowCursor( mpImpl
->mbAutoScroll
, FALSE
);
1259 GetWindow()->SetInputContext( InputContext( mpImpl
->mpTextEngine
->GetFont(), bReadOnly
? INPUTCONTEXT_TEXT
|INPUTCONTEXT_EXTTEXTINPUT
: 0 ) );
1263 TextSelection
TextView::ImpMoveCursor( const KeyEvent
& rKeyEvent
)
1265 // Eigentlich nur bei Up/Down noetig, aber was solls.
1266 mpImpl
->mpTextEngine
->CheckIdleFormatter();
1268 TextPaM
aPaM( mpImpl
->maSelection
.GetEnd() );
1269 TextPaM
aOldEnd( aPaM
);
1271 TextDirectionality eTextDirection
= TextDirectionality_LeftToRight_TopToBottom
;
1272 if ( mpImpl
->mpTextEngine
->IsRightToLeft() )
1273 eTextDirection
= TextDirectionality_RightToLeft_TopToBottom
;
1275 KeyEvent aTranslatedKeyEvent
= rKeyEvent
.LogicalTextDirectionality( eTextDirection
);
1277 BOOL bCtrl
= aTranslatedKeyEvent
.GetKeyCode().IsMod1() ? TRUE
: FALSE
;
1278 USHORT nCode
= aTranslatedKeyEvent
.GetKeyCode().GetCode();
1280 bool bSelect
= aTranslatedKeyEvent
.GetKeyCode().IsShift();
1283 case KEY_UP
: aPaM
= CursorUp( aPaM
);
1285 case KEY_DOWN
: aPaM
= CursorDown( aPaM
);
1287 case KEY_HOME
: aPaM
= bCtrl
? CursorStartOfDoc() : CursorStartOfLine( aPaM
);
1289 case KEY_END
: aPaM
= bCtrl
? CursorEndOfDoc() : CursorEndOfLine( aPaM
);
1291 case KEY_PAGEUP
: aPaM
= bCtrl
? CursorStartOfDoc() : PageUp( aPaM
);
1293 case KEY_PAGEDOWN
: aPaM
= bCtrl
? CursorEndOfDoc() : PageDown( aPaM
);
1295 case KEY_LEFT
: aPaM
= bCtrl
? CursorWordLeft( aPaM
) : CursorLeft( aPaM
, aTranslatedKeyEvent
.GetKeyCode().IsMod2() ? (USHORT
)i18n::CharacterIteratorMode::SKIPCHARACTER
: (USHORT
)i18n::CharacterIteratorMode::SKIPCELL
);
1297 case KEY_RIGHT
: aPaM
= bCtrl
? CursorWordRight( aPaM
) : CursorRight( aPaM
, aTranslatedKeyEvent
.GetKeyCode().IsMod2() ? (USHORT
)i18n::CharacterIteratorMode::SKIPCHARACTER
: (USHORT
)i18n::CharacterIteratorMode::SKIPCELL
);
1299 case com::sun::star::awt::Key::SELECT_WORD_FORWARD
:
1300 bSelect
= true; // fallthrough intentional
1301 case com::sun::star::awt::Key::MOVE_WORD_FORWARD
:
1302 aPaM
= CursorWordRight( aPaM
);
1304 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD
:
1305 bSelect
= true; // fallthrough intentional
1306 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD
:
1307 aPaM
= CursorWordLeft( aPaM
);
1309 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
1310 bSelect
= true; // fallthrough intentional
1311 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
1312 aPaM
= CursorStartOfLine( aPaM
);
1314 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE
:
1315 bSelect
= true; // fallthrough intentional
1316 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE
:
1317 aPaM
= CursorEndOfLine( aPaM
);
1319 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
1320 bSelect
= true; // falltthrough intentional
1321 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
1322 aPaM
= CursorStartOfParagraph( aPaM
);
1324 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
1325 bSelect
= true; // falltthrough intentional
1326 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
1327 aPaM
= CursorEndOfParagraph( aPaM
);
1329 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
1330 bSelect
= true; // falltthrough intentional
1331 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
1332 aPaM
= CursorStartOfDoc();
1334 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
1335 bSelect
= true; // falltthrough intentional
1336 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
1337 aPaM
= CursorEndOfDoc();
1341 // Bewirkt evtl. ein CreateAnchor oder Deselection all
1342 mpImpl
->mpSelEngine
->CursorPosChanging( bSelect
, aTranslatedKeyEvent
.GetKeyCode().IsMod1() );
1344 if ( aOldEnd
!= aPaM
)
1346 mpImpl
->mpTextEngine
->CursorMoved( aOldEnd
.GetPara() );
1349 TextSelection
aOldSelection( mpImpl
->maSelection
);
1350 TextSelection
aNewSelection( mpImpl
->maSelection
);
1351 aNewSelection
.GetEnd() = aPaM
;
1354 // Dann wird die Selektion erweitert...
1355 ImpSetSelection( aNewSelection
);
1356 ShowSelection( TextSelection( aOldEnd
, aPaM
) );
1360 aNewSelection
.GetStart() = aPaM
;
1361 ImpSetSelection( aNewSelection
);
1365 return mpImpl
->maSelection
;
1368 void TextView::InsertText( const XubString
& rStr
, BOOL bSelect
)
1370 InsertNewText( rStr
, bSelect
);
1373 void TextView::InsertNewText( const rtl::OUString
& rStr
, BOOL bSelect
)
1376 mpImpl
->mpTextEngine
->UndoActionStart( TEXTUNDO_INSERT
);
1379 break inserted text into chunks that fit into the underlying String
1380 based API (which has a maximum length of 65534 elements
1382 note: this will of course still cause problems for lines longer than those
1383 65534 elements, but those cases will hopefully be few.
1384 In the long run someone should switch the TextEngine to OUString instead of String
1386 sal_Int32 nLen
= rStr
.getLength();
1390 sal_Int32 nChunkLen
= nLen
> 65534 ? 65534 : nLen
;
1391 String
aChunk( rStr
.copy( nPos
, nChunkLen
) );
1393 TextSelection
aNewSel( mpImpl
->maSelection
);
1395 TextPaM aPaM
= mpImpl
->mpTextEngine
->ImpInsertText( mpImpl
->maSelection
, aChunk
);
1400 aNewSel
.GetEnd() = aPaM
;
1407 ImpSetSelection( aNewSel
);
1411 mpImpl
->mpTextEngine
->UndoActionEnd( TEXTUNDO_INSERT
);
1413 mpImpl
->mpTextEngine
->FormatAndUpdate( this );
1417 void TextView::InsertText( const XubString& rStr, BOOL bSelect )
1421 TextSelection aNewSel( mpImpl->maSelection );
1423 mpImpl->mpTextEngine->UndoActionStart( TEXTUNDO_INSERT );
1424 TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, rStr );
1425 mpImpl->mpTextEngine->UndoActionEnd( TEXTUNDO_INSERT );
1430 aNewSel.GetEnd() = aPaM;
1437 ImpSetSelection( aNewSel );
1439 mpImpl->mpTextEngine->FormatAndUpdate( this );
1444 TextPaM
TextView::CursorLeft( const TextPaM
& rPaM
, BOOL bWordMode
)
1446 return bWordMode
? CursorWordLeft( rPaM
) : CursorLeft( rPaM
, (USHORT
)i18n::CharacterIteratorMode::SKIPCELL
);
1448 // Remove (USHORT) typecasts in this file when removing this method!
1452 TextPaM
TextView::CursorRight( const TextPaM
& rPaM
, BOOL bWordMode
)
1454 return bWordMode
? CursorWordRight( rPaM
) : CursorRight( rPaM
, (USHORT
)i18n::CharacterIteratorMode::SKIPCELL
);
1456 // Remove (USHORT) typecasts in this file when removing this method!
1459 TextPaM
TextView::CursorLeft( const TextPaM
& rPaM
, USHORT nCharacterIteratorMode
)
1461 TextPaM
aPaM( rPaM
);
1463 if ( aPaM
.GetIndex() )
1465 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aPaM
.GetPara() );
1466 uno::Reference
< i18n::XBreakIterator
> xBI
= mpImpl
->mpTextEngine
->GetBreakIterator();
1467 sal_Int32 nCount
= 1;
1468 aPaM
.GetIndex() = (USHORT
)xBI
->previousCharacters( pNode
->GetText(), aPaM
.GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), nCharacterIteratorMode
, nCount
, nCount
);
1470 else if ( aPaM
.GetPara() )
1473 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aPaM
.GetPara() );
1474 aPaM
.GetIndex() = pNode
->GetText().Len();
1479 TextPaM
TextView::CursorRight( const TextPaM
& rPaM
, USHORT nCharacterIteratorMode
)
1481 TextPaM
aPaM( rPaM
);
1483 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aPaM
.GetPara() );
1484 if ( aPaM
.GetIndex() < pNode
->GetText().Len() )
1486 uno::Reference
< i18n::XBreakIterator
> xBI
= mpImpl
->mpTextEngine
->GetBreakIterator();
1487 sal_Int32 nCount
= 1;
1488 aPaM
.GetIndex() = (USHORT
)xBI
->nextCharacters( pNode
->GetText(), aPaM
.GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), nCharacterIteratorMode
, nCount
, nCount
);
1490 else if ( aPaM
.GetPara() < ( mpImpl
->mpTextEngine
->mpDoc
->GetNodes().Count()-1) )
1493 aPaM
.GetIndex() = 0;
1500 TextPaM
TextView::CursorWordLeft( const TextPaM
& rPaM
)
1502 TextPaM
aPaM( rPaM
);
1504 if ( aPaM
.GetIndex() )
1506 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aPaM
.GetPara() );
1507 uno::Reference
< i18n::XBreakIterator
> xBI
= mpImpl
->mpTextEngine
->GetBreakIterator();
1508 i18n::Boundary aBoundary
= xBI
->getWordBoundary( pNode
->GetText(), rPaM
.GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
1509 if ( aBoundary
.startPos
>= rPaM
.GetIndex() )
1510 aBoundary
= xBI
->previousWord( pNode
->GetText(), rPaM
.GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1511 aPaM
.GetIndex() = ( aBoundary
.startPos
!= -1 ) ? (USHORT
)aBoundary
.startPos
: 0;
1513 else if ( aPaM
.GetPara() )
1516 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aPaM
.GetPara() );
1517 aPaM
.GetIndex() = pNode
->GetText().Len();
1523 TextPaM
TextView::CursorWordRight( const TextPaM
& rPaM
)
1525 TextPaM
aPaM( rPaM
);
1527 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aPaM
.GetPara() );
1528 if ( aPaM
.GetIndex() < pNode
->GetText().Len() )
1530 uno::Reference
< i18n::XBreakIterator
> xBI
= mpImpl
->mpTextEngine
->GetBreakIterator();
1531 i18n::Boundary aBoundary
= xBI
->nextWord( pNode
->GetText(), aPaM
.GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1532 aPaM
.GetIndex() = (USHORT
)aBoundary
.startPos
;
1534 else if ( aPaM
.GetPara() < ( mpImpl
->mpTextEngine
->mpDoc
->GetNodes().Count()-1) )
1537 aPaM
.GetIndex() = 0;
1543 TextPaM
TextView::ImpDelete( BYTE nMode
, BYTE nDelMode
)
1545 if ( mpImpl
->maSelection
.HasRange() ) // dann nur Sel. loeschen
1546 return mpImpl
->mpTextEngine
->ImpDeleteText( mpImpl
->maSelection
);
1548 TextPaM aStartPaM
= mpImpl
->maSelection
.GetStart();
1549 TextPaM aEndPaM
= aStartPaM
;
1550 if ( nMode
== DEL_LEFT
)
1552 if ( nDelMode
== DELMODE_SIMPLE
)
1554 aEndPaM
= CursorLeft( aEndPaM
, (USHORT
)i18n::CharacterIteratorMode::SKIPCHARACTER
);
1556 else if ( nDelMode
== DELMODE_RESTOFWORD
)
1558 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aEndPaM
.GetPara() );
1559 uno::Reference
< i18n::XBreakIterator
> xBI
= mpImpl
->mpTextEngine
->GetBreakIterator();
1560 i18n::Boundary aBoundary
= xBI
->getWordBoundary( pNode
->GetText(), mpImpl
->maSelection
.GetEnd().GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
1561 if ( aBoundary
.startPos
== mpImpl
->maSelection
.GetEnd().GetIndex() )
1562 aBoundary
= xBI
->previousWord( pNode
->GetText(), mpImpl
->maSelection
.GetEnd().GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1563 // #i63506# startPos is -1 when the paragraph starts with a tab
1564 aEndPaM
.GetIndex() = (aBoundary
.startPos
>= 0) ? (USHORT
)aBoundary
.startPos
: 0;
1566 else // DELMODE_RESTOFCONTENT
1568 if ( aEndPaM
.GetIndex() != 0 )
1569 aEndPaM
.GetIndex() = 0;
1570 else if ( aEndPaM
.GetPara() )
1573 aEndPaM
.GetPara()--;
1574 aEndPaM
.GetIndex() = 0;
1580 if ( nDelMode
== DELMODE_SIMPLE
)
1582 aEndPaM
= CursorRight( aEndPaM
, (USHORT
)i18n::CharacterIteratorMode::SKIPCELL
);
1584 else if ( nDelMode
== DELMODE_RESTOFWORD
)
1586 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aEndPaM
.GetPara() );
1587 uno::Reference
< i18n::XBreakIterator
> xBI
= mpImpl
->mpTextEngine
->GetBreakIterator();
1588 i18n::Boundary aBoundary
= xBI
->nextWord( pNode
->GetText(), mpImpl
->maSelection
.GetEnd().GetIndex(), mpImpl
->mpTextEngine
->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1589 aEndPaM
.GetIndex() = (USHORT
)aBoundary
.startPos
;
1591 else // DELMODE_RESTOFCONTENT
1593 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aEndPaM
.GetPara() );
1594 if ( aEndPaM
.GetIndex() < pNode
->GetText().Len() )
1595 aEndPaM
.GetIndex() = pNode
->GetText().Len();
1596 else if ( aEndPaM
.GetPara() < ( mpImpl
->mpTextEngine
->mpDoc
->GetNodes().Count() - 1 ) )
1599 aEndPaM
.GetPara()++;
1600 TextNode
* pNextNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aEndPaM
.GetPara() );
1601 aEndPaM
.GetIndex() = pNextNode
->GetText().Len();
1606 return mpImpl
->mpTextEngine
->ImpDeleteText( TextSelection( aStartPaM
, aEndPaM
) );
1611 TextPaM
TextView::CursorUp( const TextPaM
& rPaM
)
1613 TextPaM
aPaM( rPaM
);
1616 if ( mpImpl
->mnTravelXPos
== TRAVEL_X_DONTKNOW
)
1618 nX
= mpImpl
->mpTextEngine
->GetEditCursor( rPaM
, FALSE
).Left();
1619 mpImpl
->mnTravelXPos
= (USHORT
)nX
+1;
1622 nX
= mpImpl
->mnTravelXPos
;
1624 TEParaPortion
* pPPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( rPaM
.GetPara() );
1625 USHORT nLine
= pPPortion
->GetLineNumber( rPaM
.GetIndex(), FALSE
);
1626 if ( nLine
) // gleicher Absatz
1628 USHORT nCharPos
= mpImpl
->mpTextEngine
->GetCharPos( rPaM
.GetPara(), nLine
-1, nX
);
1629 aPaM
.GetIndex() = nCharPos
;
1630 // Wenn davor eine autom.Umgebrochene Zeile, und ich muss genau an das
1631 // Ende dieser Zeile, landet der Cursor in der aktuellen Zeile am Anfang
1632 // Siehe Problem: Letztes Zeichen einer autom.umgebr. Zeile = Cursor
1633 TextLine
* pLine
= pPPortion
->GetLines().GetObject( nLine
- 1 );
1634 if ( aPaM
.GetIndex() && ( aPaM
.GetIndex() == pLine
->GetEnd() ) )
1637 else if ( rPaM
.GetPara() ) // vorheriger Absatz
1640 pPPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( aPaM
.GetPara() );
1641 USHORT nL
= pPPortion
->GetLines().Count() - 1;
1642 USHORT nCharPos
= mpImpl
->mpTextEngine
->GetCharPos( aPaM
.GetPara(), nL
, nX
+1 );
1643 aPaM
.GetIndex() = nCharPos
;
1649 TextPaM
TextView::CursorDown( const TextPaM
& rPaM
)
1651 TextPaM
aPaM( rPaM
);
1654 if ( mpImpl
->mnTravelXPos
== TRAVEL_X_DONTKNOW
)
1656 nX
= mpImpl
->mpTextEngine
->GetEditCursor( rPaM
, FALSE
).Left();
1657 mpImpl
->mnTravelXPos
= (USHORT
)nX
+1;
1660 nX
= mpImpl
->mnTravelXPos
;
1662 TEParaPortion
* pPPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( rPaM
.GetPara() );
1663 USHORT nLine
= pPPortion
->GetLineNumber( rPaM
.GetIndex(), FALSE
);
1664 if ( nLine
< ( pPPortion
->GetLines().Count() - 1 ) )
1666 USHORT nCharPos
= mpImpl
->mpTextEngine
->GetCharPos( rPaM
.GetPara(), nLine
+1, nX
);
1667 aPaM
.GetIndex() = nCharPos
;
1669 // Sonderbehandlung siehe CursorUp...
1670 TextLine
* pLine
= pPPortion
->GetLines().GetObject( nLine
+ 1 );
1671 if ( ( aPaM
.GetIndex() == pLine
->GetEnd() ) && ( aPaM
.GetIndex() > pLine
->GetStart() ) && aPaM
.GetIndex() < pPPortion
->GetNode()->GetText().Len() )
1674 else if ( rPaM
.GetPara() < ( mpImpl
->mpTextEngine
->mpDoc
->GetNodes().Count() - 1 ) ) // naechster Absatz
1677 pPPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( aPaM
.GetPara() );
1678 USHORT nCharPos
= mpImpl
->mpTextEngine
->GetCharPos( aPaM
.GetPara(), 0, nX
+1 );
1679 aPaM
.GetIndex() = nCharPos
;
1680 TextLine
* pLine
= pPPortion
->GetLines().GetObject( 0 );
1681 if ( ( aPaM
.GetIndex() == pLine
->GetEnd() ) && ( aPaM
.GetIndex() > pLine
->GetStart() ) && ( pPPortion
->GetLines().Count() > 1 ) )
1688 TextPaM
TextView::CursorStartOfLine( const TextPaM
& rPaM
)
1690 TextPaM
aPaM( rPaM
);
1692 TEParaPortion
* pPPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( rPaM
.GetPara() );
1693 USHORT nLine
= pPPortion
->GetLineNumber( aPaM
.GetIndex(), FALSE
);
1694 TextLine
* pLine
= pPPortion
->GetLines().GetObject( nLine
);
1695 aPaM
.GetIndex() = pLine
->GetStart();
1700 TextPaM
TextView::CursorEndOfLine( const TextPaM
& rPaM
)
1702 TextPaM
aPaM( rPaM
);
1704 TEParaPortion
* pPPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( rPaM
.GetPara() );
1705 USHORT nLine
= pPPortion
->GetLineNumber( aPaM
.GetIndex(), FALSE
);
1706 TextLine
* pLine
= pPPortion
->GetLines().GetObject( nLine
);
1707 aPaM
.GetIndex() = pLine
->GetEnd();
1709 if ( pLine
->GetEnd() > pLine
->GetStart() ) // Leerzeile
1711 xub_Unicode cLastChar
= pPPortion
->GetNode()->GetText().GetChar((USHORT
)(aPaM
.GetIndex()-1) );
1712 if ( ( cLastChar
== ' ' ) && ( aPaM
.GetIndex() != pPPortion
->GetNode()->GetText().Len() ) )
1714 // Bei einem Blank in einer autom. umgebrochenen Zeile macht es Sinn,
1715 // davor zu stehen, da der Anwender hinter das Wort will.
1716 // Wenn diese geaendert wird, Sonderbehandlung fuer Pos1 nach End!
1723 TextPaM
TextView::CursorStartOfParagraph( const TextPaM
& rPaM
)
1725 TextPaM
aPaM( rPaM
);
1726 aPaM
.GetIndex() = 0;
1730 TextPaM
TextView::CursorEndOfParagraph( const TextPaM
& rPaM
)
1732 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( rPaM
.GetPara() );
1733 TextPaM
aPaM( rPaM
);
1734 aPaM
.GetIndex() = pNode
->GetText().Len();
1738 TextPaM
TextView::CursorStartOfDoc()
1740 TextPaM
aPaM( 0, 0 );
1744 TextPaM
TextView::CursorEndOfDoc()
1746 ULONG nNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().Count() - 1;
1747 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( nNode
);
1748 TextPaM
aPaM( nNode
, pNode
->GetText().Len() );
1752 TextPaM
TextView::PageUp( const TextPaM
& rPaM
)
1754 Rectangle aRec
= mpImpl
->mpTextEngine
->PaMtoEditCursor( rPaM
);
1755 Point aTopLeft
= aRec
.TopLeft();
1756 aTopLeft
.Y() -= mpImpl
->mpWindow
->GetOutputSizePixel().Height() * 9/10;
1758 if ( aTopLeft
.Y() < 0 )
1761 TextPaM aPaM
= mpImpl
->mpTextEngine
->GetPaM( aTopLeft
);
1765 TextPaM
TextView::PageDown( const TextPaM
& rPaM
)
1767 Rectangle aRec
= mpImpl
->mpTextEngine
->PaMtoEditCursor( rPaM
);
1768 Point aBottomRight
= aRec
.BottomRight();
1769 aBottomRight
.Y() += mpImpl
->mpWindow
->GetOutputSizePixel().Height() * 9/10;
1770 aBottomRight
.X() += 1;
1771 long nHeight
= mpImpl
->mpTextEngine
->GetTextHeight();
1772 if ( aBottomRight
.Y() > nHeight
)
1773 aBottomRight
.Y() = nHeight
-1;
1775 TextPaM aPaM
= mpImpl
->mpTextEngine
->GetPaM( aBottomRight
);
1779 void TextView::ImpShowCursor( BOOL bGotoCursor
, BOOL bForceVisCursor
, BOOL bSpecial
)
1781 if ( mpImpl
->mpTextEngine
->IsFormatting() )
1783 if ( mpImpl
->mpTextEngine
->GetUpdateMode() == FALSE
)
1785 if ( mpImpl
->mpTextEngine
->IsInUndo() )
1788 mpImpl
->mpTextEngine
->CheckIdleFormatter();
1789 if ( !mpImpl
->mpTextEngine
->IsFormatted() )
1790 mpImpl
->mpTextEngine
->FormatAndUpdate( this );
1793 TextPaM
aPaM( mpImpl
->maSelection
.GetEnd() );
1794 Rectangle aEditCursor
= mpImpl
->mpTextEngine
->PaMtoEditCursor( aPaM
, bSpecial
);
1796 // Remember that we placed the cursor behind the last character of a line
1797 mpImpl
->mbCursorAtEndOfLine
= false;
1800 TEParaPortion
* pParaPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( aPaM
.GetPara() );
1801 mpImpl
->mbCursorAtEndOfLine
=
1802 pParaPortion
->GetLineNumber( aPaM
.GetIndex(), TRUE
) != pParaPortion
->GetLineNumber( aPaM
.GetIndex(), FALSE
);
1805 if ( !IsInsertMode() && !mpImpl
->maSelection
.HasRange() )
1807 TextNode
* pNode
= mpImpl
->mpTextEngine
->mpDoc
->GetNodes().GetObject( aPaM
.GetPara() );
1808 if ( pNode
->GetText().Len() && ( aPaM
.GetIndex() < pNode
->GetText().Len() ) )
1810 // If we are behind a portion, and the next portion has other direction, we must change position...
1811 aEditCursor
.Left() = aEditCursor
.Right() = mpImpl
->mpTextEngine
->GetEditCursor( aPaM
, FALSE
, TRUE
).Left();
1813 TEParaPortion
* pParaPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( aPaM
.GetPara() );
1815 USHORT nTextPortionStart
= 0;
1816 USHORT nTextPortion
= pParaPortion
->GetTextPortions().FindPortion( aPaM
.GetIndex(), nTextPortionStart
, TRUE
);
1817 TETextPortion
* pTextPortion
= pParaPortion
->GetTextPortions().GetObject( nTextPortion
);
1818 if ( pTextPortion
->GetKind() == PORTIONKIND_TAB
)
1820 if ( mpImpl
->mpTextEngine
->IsRightToLeft() )
1824 aEditCursor
.Right() += pTextPortion
->GetWidth();
1828 TextPaM aNext
= CursorRight( TextPaM( aPaM
.GetPara(), aPaM
.GetIndex() ), (USHORT
)i18n::CharacterIteratorMode::SKIPCELL
);
1829 aEditCursor
.Right() = mpImpl
->mpTextEngine
->GetEditCursor( aNext
, TRUE
).Left();
1834 Size aOutSz
= mpImpl
->mpWindow
->GetOutputSizePixel();
1835 if ( aEditCursor
.GetHeight() > aOutSz
.Height() )
1836 aEditCursor
.Bottom() = aEditCursor
.Top() + aOutSz
.Height() - 1;
1838 aEditCursor
.Left() -= 1;
1841 // #i81283# protext maStartDocPos against initialization problems
1842 && aOutSz
.Width() && aOutSz
.Height()
1845 long nVisStartY
= mpImpl
->maStartDocPos
.Y();
1846 long nVisEndY
= mpImpl
->maStartDocPos
.Y() + aOutSz
.Height();
1847 long nVisStartX
= mpImpl
->maStartDocPos
.X();
1848 long nVisEndX
= mpImpl
->maStartDocPos
.X() + aOutSz
.Width();
1849 long nMoreX
= aOutSz
.Width() / 4;
1851 Point
aNewStartPos( mpImpl
->maStartDocPos
);
1853 if ( aEditCursor
.Bottom() > nVisEndY
)
1855 aNewStartPos
.Y() += ( aEditCursor
.Bottom() - nVisEndY
);
1857 else if ( aEditCursor
.Top() < nVisStartY
)
1859 aNewStartPos
.Y() -= ( nVisStartY
- aEditCursor
.Top() );
1862 if ( aEditCursor
.Right() >= nVisEndX
)
1864 aNewStartPos
.X() += ( aEditCursor
.Right() - nVisEndX
);
1866 // Darfs ein bischen mehr sein?
1867 aNewStartPos
.X() += nMoreX
;
1869 else if ( aEditCursor
.Left() <= nVisStartX
)
1871 aNewStartPos
.X() -= ( nVisStartX
- aEditCursor
.Left() );
1873 // Darfs ein bischen mehr sein?
1874 aNewStartPos
.X() -= nMoreX
;
1877 // X kann durch das 'bischen mehr' falsch sein:
1878 // ULONG nMaxTextWidth = mpImpl->mpTextEngine->GetMaxTextWidth();
1879 // if ( !nMaxTextWidth || ( nMaxTextWidth > 0x7FFFFFFF ) )
1880 // nMaxTextWidth = 0x7FFFFFFF;
1881 // long nMaxX = (long)nMaxTextWidth - aOutSz.Width();
1882 long nMaxX
= mpImpl
->mpTextEngine
->CalcTextWidth() - aOutSz
.Width();
1886 if ( aNewStartPos
.X() < 0 )
1887 aNewStartPos
.X() = 0;
1888 else if ( aNewStartPos
.X() > nMaxX
)
1889 aNewStartPos
.X() = nMaxX
;
1891 // Y sollte nicht weiter unten als noetig liegen:
1892 long nYMax
= mpImpl
->mpTextEngine
->GetTextHeight() - aOutSz
.Height();
1895 if ( aNewStartPos
.Y() > nYMax
)
1896 aNewStartPos
.Y() = nYMax
;
1898 if ( aNewStartPos
!= mpImpl
->maStartDocPos
)
1899 Scroll( -(aNewStartPos
.X() - mpImpl
->maStartDocPos
.X()), -(aNewStartPos
.Y() - mpImpl
->maStartDocPos
.Y()) );
1902 if ( aEditCursor
.Right() < aEditCursor
.Left() )
1904 long n
= aEditCursor
.Left();
1905 aEditCursor
.Left() = aEditCursor
.Right();
1906 aEditCursor
.Right() = n
;
1909 Point
aPoint( GetWindowPos( !mpImpl
->mpTextEngine
->IsRightToLeft() ? aEditCursor
.TopLeft() : aEditCursor
.TopRight() ) );
1910 mpImpl
->mpCursor
->SetPos( aPoint
);
1911 mpImpl
->mpCursor
->SetSize( aEditCursor
.GetSize() );
1912 if ( bForceVisCursor
&& mpImpl
->mbCursorEnabled
)
1913 mpImpl
->mpCursor
->Show();
1916 BOOL
TextView::SetCursorAtPoint( const Point
& rPosPixel
)
1918 mpImpl
->mpTextEngine
->CheckIdleFormatter();
1920 Point aDocPos
= GetDocPos( rPosPixel
);
1922 TextPaM aPaM
= mpImpl
->mpTextEngine
->GetPaM( aDocPos
);
1924 // aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion
1925 TextSelection
aTmpNewSel( mpImpl
->maSelection
.GetEnd(), aPaM
);
1926 TextSelection
aNewSel( mpImpl
->maSelection
);
1927 aNewSel
.GetEnd() = aPaM
;
1929 if ( !mpImpl
->mpSelEngine
->HasAnchor() )
1931 if ( mpImpl
->maSelection
.GetStart() != aPaM
)
1932 mpImpl
->mpTextEngine
->CursorMoved( mpImpl
->maSelection
.GetStart().GetPara() );
1933 aNewSel
.GetStart() = aPaM
;
1934 ImpSetSelection( aNewSel
);
1938 ImpSetSelection( aNewSel
);
1939 ShowSelection( aTmpNewSel
);
1942 BOOL bForceCursor
= mpImpl
->mpDDInfo
? FALSE
: TRUE
; // && !mbInSelection
1943 ImpShowCursor( mpImpl
->mbAutoScroll
, bForceCursor
, FALSE
);
1947 BOOL
TextView::IsSelectionAtPoint( const Point
& rPosPixel
)
1949 // if ( !Rectangle( Point(), mpImpl->mpWindow->GetOutputSizePixel() ).IsInside( rPosPixel ) && !mbInSelection )
1952 Point aDocPos
= GetDocPos( rPosPixel
);
1953 TextPaM aPaM
= mpImpl
->mpTextEngine
->GetPaM( aDocPos
, FALSE
);
1954 // Bei Hyperlinks D&D auch ohne Selektion starten.
1955 // BeginDrag wird aber nur gerufen, wenn IsSelectionAtPoint()
1956 // Problem: IsSelectionAtPoint wird bei Command() nicht gerufen,
1957 // wenn vorher im MBDown schon FALSE returnt wurde.
1958 return ( IsInSelection( aPaM
) ||
1959 ( /* mpImpl->mpSelEngine->IsInCommand() && */ mpImpl
->mpTextEngine
->FindAttrib( aPaM
, TEXTATTR_HYPERLINK
) ) );
1962 BOOL
TextView::IsInSelection( const TextPaM
& rPaM
)
1964 TextSelection aSel
= mpImpl
->maSelection
;
1967 ULONG nStartNode
= aSel
.GetStart().GetPara();
1968 ULONG nEndNode
= aSel
.GetEnd().GetPara();
1969 ULONG nCurNode
= rPaM
.GetPara();
1971 if ( ( nCurNode
> nStartNode
) && ( nCurNode
< nEndNode
) )
1974 if ( nStartNode
== nEndNode
)
1976 if ( nCurNode
== nStartNode
)
1977 if ( ( rPaM
.GetIndex() >= aSel
.GetStart().GetIndex() ) && ( rPaM
.GetIndex() < aSel
.GetEnd().GetIndex() ) )
1980 else if ( ( nCurNode
== nStartNode
) && ( rPaM
.GetIndex() >= aSel
.GetStart().GetIndex() ) )
1982 else if ( ( nCurNode
== nEndNode
) && ( rPaM
.GetIndex() < aSel
.GetEnd().GetIndex() ) )
1988 void TextView::ImpHideDDCursor()
1990 if ( mpImpl
->mpDDInfo
&& mpImpl
->mpDDInfo
->mbVisCursor
)
1992 mpImpl
->mpDDInfo
->maCursor
.Hide();
1993 mpImpl
->mpDDInfo
->mbVisCursor
= FALSE
;
1997 void TextView::ImpShowDDCursor()
1999 if ( !mpImpl
->mpDDInfo
->mbVisCursor
)
2001 Rectangle aCursor
= mpImpl
->mpTextEngine
->PaMtoEditCursor( mpImpl
->mpDDInfo
->maDropPos
, TRUE
);
2003 aCursor
.SetPos( GetWindowPos( aCursor
.TopLeft() ) );
2005 mpImpl
->mpDDInfo
->maCursor
.SetWindow( mpImpl
->mpWindow
);
2006 mpImpl
->mpDDInfo
->maCursor
.SetPos( aCursor
.TopLeft() );
2007 mpImpl
->mpDDInfo
->maCursor
.SetSize( aCursor
.GetSize() );
2008 mpImpl
->mpDDInfo
->maCursor
.Show();
2009 mpImpl
->mpDDInfo
->mbVisCursor
= TRUE
;
2013 void TextView::SetPaintSelection( BOOL bPaint
)
2015 if ( bPaint
!= mpImpl
->mbPaintSelection
)
2017 mpImpl
->mbPaintSelection
= bPaint
;
2018 ShowSelection( mpImpl
->maSelection
);
2022 void TextView::SetHighlightSelection( BOOL bSelectByHighlight
)
2024 if ( bSelectByHighlight
!= mpImpl
->mbHighlightSelection
)
2026 // Falls umschalten zwischendurch moeglich...
2027 mpImpl
->mbHighlightSelection
= bSelectByHighlight
;
2031 BOOL
TextView::Read( SvStream
& rInput
)
2033 BOOL bDone
= mpImpl
->mpTextEngine
->Read( rInput
, &mpImpl
->maSelection
);
2038 BOOL
TextView::Write( SvStream
& rOutput
)
2040 return mpImpl
->mpTextEngine
->Read( rOutput
, &mpImpl
->maSelection
);
2043 bool TextView::ImplTruncateNewText( rtl::OUString
& rNewText
) const
2045 bool bTruncated
= false;
2047 if( rNewText
.getLength() > 65534 ) // limit to String API
2049 rNewText
= rNewText
.copy( 0, 65534 );
2053 ULONG nMaxLen
= mpImpl
->mpTextEngine
->GetMaxTextLen();
2054 // 0 means unlimited, there is just the String API limit handled above
2057 ULONG nCurLen
= mpImpl
->mpTextEngine
->GetTextLen();
2059 sal_uInt32 nNewLen
= rNewText
.getLength();
2060 if ( nCurLen
+ nNewLen
> nMaxLen
)
2062 // see how much text will be replaced
2063 ULONG nSelLen
= mpImpl
->mpTextEngine
->GetTextLen( mpImpl
->maSelection
);
2064 if ( nCurLen
+ nNewLen
- nSelLen
> nMaxLen
)
2066 sal_uInt32 nTruncatedLen
= static_cast<sal_uInt32
>(nMaxLen
- (nCurLen
- nSelLen
));
2067 rNewText
= rNewText
.copy( 0, nTruncatedLen
);
2075 BOOL
TextView::ImplCheckTextLen( const String
& rNewText
)
2078 if ( mpImpl
->mpTextEngine
->GetMaxTextLen() )
2080 ULONG n
= mpImpl
->mpTextEngine
->GetTextLen();
2081 n
+= rNewText
.Len();
2082 if ( n
> mpImpl
->mpTextEngine
->GetMaxTextLen() )
2084 // nur dann noch ermitteln, wie viel Text geloescht wird
2085 n
-= mpImpl
->mpTextEngine
->GetTextLen( mpImpl
->maSelection
);
2086 if ( n
> mpImpl
->mpTextEngine
->GetMaxTextLen() )
2088 // Beep hat hier eigentlich nichts verloren, sondern lieber ein Hdl,
2089 // aber so funktioniert es wenigstens in ME, BasicIDE, SourceView
2098 void TextView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent
& rDGE
) throw (::com::sun::star::uno::RuntimeException
)
2100 if ( mpImpl
->mbClickedInSelection
)
2102 vos::OGuard
aVclGuard( Application::GetSolarMutex() );
2104 DBG_ASSERT( mpImpl
->maSelection
.HasRange(), "TextView::dragGestureRecognized: mpImpl->mbClickedInSelection, but no selection?" );
2106 delete mpImpl
->mpDDInfo
;
2107 mpImpl
->mpDDInfo
= new TextDDInfo
;
2108 mpImpl
->mpDDInfo
->mbStarterOfDD
= TRUE
;
2110 TETextDataObject
* pDataObj
= new TETextDataObject( GetSelected() );
2112 if ( mpImpl
->mpTextEngine
->HasAttrib( TEXTATTR_HYPERLINK
) ) // Dann auch als HTML
2113 mpImpl
->mpTextEngine
->Write( pDataObj
->GetHTMLStream(), &mpImpl
->maSelection
, TRUE
);
2117 // D&D eines Hyperlinks.
2118 // Besser waere es im MBDown sich den MBDownPaM zu merken,
2119 // ist dann aber inkompatibel => spaeter mal umstellen.
2120 TextPaM aPaM( mpImpl->mpTextEngine->GetPaM( GetDocPos( GetWindow()->GetPointerPosPixel() ) ) );
2121 const TextCharAttrib* pAttr = mpImpl->mpTextEngine->FindCharAttrib( aPaM, TEXTATTR_HYPERLINK );
2125 aSel.GetStart().GetIndex() = pAttr->GetStart();
2126 aSel.GetEnd().GetIndex() = pAttr->GetEnd();
2128 const TextAttribHyperLink& rLink = (const TextAttribHyperLink&)pAttr->GetAttr();
2129 String aText( rLink.GetDescription() );
2131 aText = mpImpl->mpTextEngine->GetText( aSel );
2132 INetBookmark aBookmark( rLink.GetURL(), aText );
2133 aBookmark.CopyDragServer();
2137 mpImpl
->mpCursor
->Hide();
2139 sal_Int8 nActions
= datatransfer::dnd::DNDConstants::ACTION_COPY
;
2140 if ( !IsReadOnly() )
2141 nActions
|= datatransfer::dnd::DNDConstants::ACTION_MOVE
;
2142 rDGE
.DragSource
->startDrag( rDGE
, nActions
, 0 /*cursor*/, 0 /*image*/, pDataObj
, mpImpl
->mxDnDListener
);
2146 void TextView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent
& ) throw (::com::sun::star::uno::RuntimeException
)
2149 delete mpImpl
->mpDDInfo
;
2150 mpImpl
->mpDDInfo
= NULL
;
2153 void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent
& rDTDE
) throw (::com::sun::star::uno::RuntimeException
)
2155 vos::OGuard
aVclGuard( Application::GetSolarMutex() );
2157 BOOL bChanges
= FALSE
;
2158 if ( !mpImpl
->mbReadOnly
&& mpImpl
->mpDDInfo
)
2162 // Daten fuer das loeschen nach einem DROP_MOVE:
2163 TextSelection
aPrevSel( mpImpl
->maSelection
);
2165 ULONG nPrevParaCount
= mpImpl
->mpTextEngine
->GetParagraphCount();
2166 USHORT nPrevStartParaLen
= mpImpl
->mpTextEngine
->GetTextLen( aPrevSel
.GetStart().GetPara() );
2168 BOOL bStarterOfDD
= FALSE
;
2169 for ( USHORT nView
= mpImpl
->mpTextEngine
->GetViewCount(); nView
&& !bStarterOfDD
; )
2170 bStarterOfDD
= mpImpl
->mpTextEngine
->GetView( --nView
)->mpImpl
->mpDDInfo
? mpImpl
->mpTextEngine
->GetView( nView
)->mpImpl
->mpDDInfo
->mbStarterOfDD
: FALSE
;
2173 ImpSetSelection( mpImpl
->mpDDInfo
->maDropPos
);
2175 mpImpl
->mpTextEngine
->UndoActionStart( TEXTUNDO_DRAGANDDROP
);
2178 uno::Reference
< datatransfer::XTransferable
> xDataObj
= rDTDE
.Transferable
;
2179 if ( xDataObj
.is() )
2181 datatransfer::DataFlavor aFlavor
;
2182 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
2183 if ( xDataObj
->isDataFlavorSupported( aFlavor
) )
2185 uno::Any aData
= xDataObj
->getTransferData( aFlavor
);
2186 ::rtl::OUString aOUString
;
2187 aData
>>= aOUString
;
2189 aText
.ConvertLineEnd( LINEEND_LF
);
2193 if ( aText
.Len() && ( aText
.GetChar( aText
.Len()-1 ) == LINE_SEP
) )
2194 aText
.Erase( aText
.Len()-1 );
2196 TextPaM aTempStart
= mpImpl
->maSelection
.GetStart();
2197 if ( ImplCheckTextLen( aText
) )
2198 ImpSetSelection( mpImpl
->mpTextEngine
->ImpInsertText( mpImpl
->mpDDInfo
->maDropPos
, aText
) );
2199 if(mpImpl
->mbSupportProtectAttribute
)
2201 mpImpl
->mpTextEngine
->SetAttrib( TextAttribProtect(),
2202 aTempStart
.GetPara(),
2203 aTempStart
.GetIndex(),
2204 mpImpl
->maSelection
.GetEnd().GetIndex(), FALSE
);
2207 if ( aPrevSel
.HasRange() &&
2208 !mpImpl
->mbSupportProtectAttribute
&& // don't remove currently selected element
2209 (( rDTDE
.DropAction
& datatransfer::dnd::DNDConstants::ACTION_MOVE
) || !bStarterOfDD
) )
2211 // ggf. Selection anpasssen:
2212 if ( ( mpImpl
->mpDDInfo
->maDropPos
.GetPara() < aPrevSel
.GetStart().GetPara() ) ||
2213 ( ( mpImpl
->mpDDInfo
->maDropPos
.GetPara() == aPrevSel
.GetStart().GetPara() )
2214 && ( mpImpl
->mpDDInfo
->maDropPos
.GetIndex() < aPrevSel
.GetStart().GetIndex() ) ) )
2216 ULONG nNewParasBeforeSelection
=
2217 mpImpl
->mpTextEngine
->GetParagraphCount() - nPrevParaCount
;
2219 aPrevSel
.GetStart().GetPara() += nNewParasBeforeSelection
;
2220 aPrevSel
.GetEnd().GetPara() += nNewParasBeforeSelection
;
2222 if ( mpImpl
->mpDDInfo
->maDropPos
.GetPara() == aPrevSel
.GetStart().GetPara() )
2225 mpImpl
->mpTextEngine
->GetTextLen( aPrevSel
.GetStart().GetPara() ) - nPrevStartParaLen
;
2227 aPrevSel
.GetStart().GetIndex() =
2228 aPrevSel
.GetStart().GetIndex() + nNewChars
;
2229 if ( aPrevSel
.GetStart().GetPara() == aPrevSel
.GetEnd().GetPara() )
2230 aPrevSel
.GetEnd().GetIndex() =
2231 aPrevSel
.GetEnd().GetIndex() + nNewChars
;
2236 // aktuelle Selektion anpassen
2237 TextPaM aPaM
= mpImpl
->maSelection
.GetStart();
2238 aPaM
.GetPara() -= ( aPrevSel
.GetEnd().GetPara() - aPrevSel
.GetStart().GetPara() );
2239 if ( aPrevSel
.GetEnd().GetPara() == mpImpl
->mpDDInfo
->maDropPos
.GetPara() )
2242 aPaM
.GetIndex() - aPrevSel
.GetEnd().GetIndex();
2243 if ( aPrevSel
.GetStart().GetPara() == mpImpl
->mpDDInfo
->maDropPos
.GetPara() )
2245 aPaM
.GetIndex() + aPrevSel
.GetStart().GetIndex();
2247 ImpSetSelection( aPaM
);
2250 mpImpl
->mpTextEngine
->ImpDeleteText( aPrevSel
);
2253 mpImpl
->mpTextEngine
->UndoActionEnd( TEXTUNDO_DRAGANDDROP
);
2255 delete mpImpl
->mpDDInfo
;
2256 mpImpl
->mpDDInfo
= 0;
2258 mpImpl
->mpTextEngine
->FormatAndUpdate( this );
2260 mpImpl
->mpTextEngine
->Broadcast( TextHint( TEXT_HINT_MODIFIED
) );
2262 rDTDE
.Context
->dropComplete( bChanges
);
2265 void TextView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent
& ) throw (::com::sun::star::uno::RuntimeException
)
2269 void TextView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent
& ) throw (::com::sun::star::uno::RuntimeException
)
2271 vos::OGuard
aVclGuard( Application::GetSolarMutex() );
2275 void TextView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent
& rDTDE
) throw (::com::sun::star::uno::RuntimeException
)
2277 vos::OGuard
aVclGuard( Application::GetSolarMutex() );
2279 if ( !mpImpl
->mpDDInfo
)
2280 mpImpl
->mpDDInfo
= new TextDDInfo
;
2282 TextPaM aPrevDropPos
= mpImpl
->mpDDInfo
->maDropPos
;
2283 Point
aMousePos( rDTDE
.LocationX
, rDTDE
.LocationY
);
2284 Point aDocPos
= GetDocPos( aMousePos
);
2285 mpImpl
->mpDDInfo
->maDropPos
= mpImpl
->mpTextEngine
->GetPaM( aDocPos
);
2288 Size aOutSize = mpImpl->mpWindow->GetOutputSizePixel();
2289 if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) ||
2290 ( aMousePos.Y() < 0 ) || ( aMousePos.Y() > aOutSize.Height() ) )
2293 // No, I will not receive events for this...
2297 sal_Bool bProtected
= sal_False
;
2298 if(mpImpl
->mbSupportProtectAttribute
)
2300 const TextCharAttrib
* pStartAttr
= mpImpl
->mpTextEngine
->FindCharAttrib(
2301 mpImpl
->mpDDInfo
->maDropPos
,
2302 TEXTATTR_PROTECTED
);
2303 bProtected
= pStartAttr
!= 0 &&
2304 pStartAttr
->GetStart() != mpImpl
->mpDDInfo
->maDropPos
.GetIndex() &&
2305 pStartAttr
->GetEnd() != mpImpl
->mpDDInfo
->maDropPos
.GetIndex();
2307 // Don't drop in selection or in read only engine
2308 if ( IsReadOnly() || IsInSelection( mpImpl
->mpDDInfo
->maDropPos
) || bProtected
)
2311 rDTDE
.Context
->rejectDrag();
2315 // Alten Cursor wegzeichnen...
2316 if ( !mpImpl
->mpDDInfo
->mbVisCursor
|| ( aPrevDropPos
!= mpImpl
->mpDDInfo
->maDropPos
) )
2321 rDTDE
.Context
->acceptDrag( rDTDE
.DropAction
);
2325 Point
TextView::ImpGetOutputStartPos( const Point
& rStartDocPos
) const
2327 Point
aStartPos( -rStartDocPos
.X(), -rStartDocPos
.Y() );
2328 if ( mpImpl
->mpTextEngine
->IsRightToLeft() )
2330 Size aSz
= mpImpl
->mpWindow
->GetOutputSizePixel();
2331 aStartPos
.X() = rStartDocPos
.X() + aSz
.Width() - 1; // -1: Start is 0
2336 Point
TextView::GetDocPos( const Point
& rWindowPos
) const
2338 // Fensterposition => Dokumentposition
2342 aPoint
.Y() = rWindowPos
.Y() + mpImpl
->maStartDocPos
.Y();
2344 if ( !mpImpl
->mpTextEngine
->IsRightToLeft() )
2346 aPoint
.X() = rWindowPos
.X() + mpImpl
->maStartDocPos
.X();
2350 Size aSz
= mpImpl
->mpWindow
->GetOutputSizePixel();
2351 aPoint
.X() = ( aSz
.Width() - 1 ) - rWindowPos
.X() + mpImpl
->maStartDocPos
.X();
2357 Point
TextView::GetWindowPos( const Point
& rDocPos
) const
2359 // Dokumentposition => Fensterposition
2363 aPoint
.Y() = rDocPos
.Y() - mpImpl
->maStartDocPos
.Y();
2365 if ( !mpImpl
->mpTextEngine
->IsRightToLeft() )
2367 aPoint
.X() = rDocPos
.X() - mpImpl
->maStartDocPos
.X();
2371 Size aSz
= mpImpl
->mpWindow
->GetOutputSizePixel();
2372 aPoint
.X() = ( aSz
.Width() - 1 ) - ( rDocPos
.X() - mpImpl
->maStartDocPos
.X() );
2378 sal_Int32
TextView::GetLineNumberOfCursorInSelection() const
2381 sal_Int32 nLineNo
= -1;
2382 if( mpImpl
->mbCursorEnabled
)
2384 TextPaM aPaM
= GetSelection().GetEnd();
2385 TEParaPortion
* pPPortion
= mpImpl
->mpTextEngine
->mpTEParaPortions
->GetObject( aPaM
.GetPara() );
2386 nLineNo
= pPPortion
->GetLineNumber( aPaM
.GetIndex(), FALSE
);
2387 if( mpImpl
->mbCursorAtEndOfLine
)
2394 // -------------------------------------------------------------------------
2395 // (+) class TextSelFunctionSet
2396 // -------------------------------------------------------------------------
2397 TextSelFunctionSet::TextSelFunctionSet( TextView
* pView
)
2402 void __EXPORT
TextSelFunctionSet::BeginDrag()
2406 void __EXPORT
TextSelFunctionSet::CreateAnchor()
2408 // TextSelection aSel( mpView->GetSelection() );
2409 // aSel.GetStart() = aSel.GetEnd();
2410 // mpView->SetSelection( aSel );
2412 // Es darf kein ShowCursor folgen:
2413 mpView
->HideSelection();
2414 mpView
->ImpSetSelection( mpView
->mpImpl
->maSelection
.GetEnd() );
2417 BOOL __EXPORT
TextSelFunctionSet::SetCursorAtPoint( const Point
& rPointPixel
, BOOL
)
2419 return mpView
->SetCursorAtPoint( rPointPixel
);
2422 BOOL __EXPORT
TextSelFunctionSet::IsSelectionAtPoint( const Point
& rPointPixel
)
2424 return mpView
->IsSelectionAtPoint( rPointPixel
);
2427 void __EXPORT
TextSelFunctionSet::DeselectAll()
2432 void __EXPORT
TextSelFunctionSet::DeselectAtPoint( const Point
& )
2434 // Nur bei Mehrfachselektion
2437 void __EXPORT
TextSelFunctionSet::DestroyAnchor()
2439 // Nur bei Mehrfachselektion
2441 TextEngine
* TextView::GetTextEngine() const
2442 { return mpImpl
->mpTextEngine
; }
2443 Window
* TextView::GetWindow() const
2444 { return mpImpl
->mpWindow
; }
2445 void TextView::EnableCursor( BOOL bEnable
)
2446 { mpImpl
->mbCursorEnabled
= bEnable
; }
2447 BOOL
TextView::IsCursorEnabled() const
2448 { return mpImpl
->mbCursorEnabled
; }
2449 void TextView::SetStartDocPos( const Point
& rPos
)
2450 { mpImpl
->maStartDocPos
= rPos
; }
2451 const Point
& TextView::GetStartDocPos() const
2452 { return mpImpl
->maStartDocPos
; }
2453 void TextView::SetAutoIndentMode( BOOL bAutoIndent
)
2454 { mpImpl
->mbAutoIndent
= bAutoIndent
; }
2455 BOOL
TextView::IsAutoIndentMode() const
2456 { return mpImpl
->mbAutoIndent
; }
2457 BOOL
TextView::IsReadOnly() const
2458 { return mpImpl
->mbReadOnly
; }
2459 void TextView::SetAutoScroll( BOOL bAutoScroll
)
2460 { mpImpl
->mbAutoScroll
= bAutoScroll
; }
2461 BOOL
TextView::IsAutoScroll() const
2462 { return mpImpl
->mbAutoScroll
; }
2463 BOOL
TextView::IsPaintSelection() const
2464 { return mpImpl
->mbPaintSelection
; }
2465 BOOL
TextView::IsHighlightSelection() const
2466 { return mpImpl
->mbHighlightSelection
; }
2467 BOOL
TextView::HasSelection() const
2468 { return mpImpl
->maSelection
.HasRange(); }
2469 BOOL
TextView::IsInsertMode() const
2470 { return mpImpl
->mbInsertMode
; }
2471 void TextView::SupportProtectAttribute(sal_Bool bSupport
)
2472 { mpImpl
->mbSupportProtectAttribute
= bSupport
;}