xref: /aoo4110/main/svtools/source/edit/textview.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 #include <svtools/textview.hxx>
27 #include <svtools/texteng.hxx>
28 #include <textdoc.hxx>
29 #include <svtools/textdata.hxx>
30 #include <textdat2.hxx>
31 
32 #include <svl/undo.hxx>
33 #include <vcl/cursor.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/sound.hxx>
37 #include <tools/stream.hxx>
38 
39 #include <sot/formats.hxx>
40 #include <svl/urlbmk.hxx>
41 
42 #ifndef _COM_SUN_STAR_TEXT_XBREAKITERATOR_HPP_
43 #include <com/sun/star/i18n/XBreakIterator.hpp>
44 #endif
45 
46 #ifndef _COM_SUN_STAR_TEXT_CHARACTERITERATORMODE_HPP_
47 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
48 #endif
49 
50 #ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
51 #include <com/sun/star/i18n/WordType.hpp>
52 #endif
53 #include <cppuhelper/weak.hxx>
54 #include <vcl/unohelp.hxx>
55 #include <com/sun/star/datatransfer/XTransferable.hpp>
56 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
57 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 
60 #ifndef _COM_SUN_STAR_DATATRANSFER_DND_DNDCONSTANS_HPP_
61 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
62 #endif
63 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
64 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
65 
66 #include <vcl/edit.hxx>
67 
68 
69 #include <sot/exchange.hxx>
70 #include <sot/formats.hxx>
71 
72 #include <vos/mutex.hxx>
73 
74 
75 using namespace ::com::sun::star;
76 
77 class TETextDataObject :	public ::com::sun::star::datatransfer::XTransferable,
78 						public ::cppu::OWeakObject
79 
80 {
81 private:
82 	String			maText;
83 	SvMemoryStream	maHTMLStream;
84 
85 public:
86 					TETextDataObject( const String& rText );
87 					~TETextDataObject();
88 
GetText()89 	String&			GetText() { return maText; }
GetHTMLStream()90 	SvMemoryStream&	GetHTMLStream() { return maHTMLStream; }
91 
92 	// ::com::sun::star::uno::XInterface
93     ::com::sun::star::uno::Any					SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);
acquire()94 	void										SAL_CALL acquire() throw()	{ OWeakObject::acquire(); }
release()95 	void										SAL_CALL release() throw()	{ OWeakObject::release(); }
96 
97 	// ::com::sun::star::datatransfer::XTransferable
98     ::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);
99     ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors(  ) throw(::com::sun::star::uno::RuntimeException);
100     sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw(::com::sun::star::uno::RuntimeException);
101 };
102 
TETextDataObject(const String & rText)103 TETextDataObject::TETextDataObject( const String& rText ) : maText( rText )
104 {
105 }
106 
~TETextDataObject()107 TETextDataObject::~TETextDataObject()
108 {
109 }
110 
111 // uno::XInterface
queryInterface(const uno::Type & rType)112 uno::Any TETextDataObject::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException)
113 {
114 	uno::Any aRet = ::cppu::queryInterface( rType, SAL_STATIC_CAST( datatransfer::XTransferable*, this ) );
115 	return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
116 }
117 
118 // datatransfer::XTransferable
getTransferData(const datatransfer::DataFlavor & rFlavor)119 uno::Any TETextDataObject::getTransferData( const datatransfer::DataFlavor& rFlavor ) throw(datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
120 {
121 	uno::Any aAny;
122 
123 	sal_uLong nT = SotExchange::GetFormat( rFlavor );
124 	if ( nT == SOT_FORMAT_STRING )
125 	{
126 		aAny <<= (::rtl::OUString)GetText();
127 	}
128 	else if ( nT == SOT_FORMATSTR_ID_HTML )
129 	{
130 		GetHTMLStream().Seek( STREAM_SEEK_TO_END );
131 		sal_uLong nLen = GetHTMLStream().Tell();
132 		GetHTMLStream().Seek(0);
133 
134 		uno::Sequence< sal_Int8 > aSeq( nLen );
135 		memcpy( aSeq.getArray(), GetHTMLStream().GetData(), nLen );
136 		aAny <<= aSeq;
137 	}
138     else
139     {
140         throw datatransfer::UnsupportedFlavorException();
141     }
142 	return aAny;
143 }
144 
getTransferDataFlavors()145 uno::Sequence< datatransfer::DataFlavor > TETextDataObject::getTransferDataFlavors(  ) throw(uno::RuntimeException)
146 {
147 	GetHTMLStream().Seek( STREAM_SEEK_TO_END );
148 	sal_Bool bHTML = GetHTMLStream().Tell() > 0;
149 	uno::Sequence< datatransfer::DataFlavor > aDataFlavors( bHTML ? 2 : 1 );
150 	SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aDataFlavors.getArray()[0] );
151 	if ( bHTML )
152 		SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_HTML, aDataFlavors.getArray()[1] );
153 	return aDataFlavors;
154 }
155 
isDataFlavorSupported(const datatransfer::DataFlavor & rFlavor)156 sal_Bool TETextDataObject::isDataFlavorSupported( const datatransfer::DataFlavor& rFlavor ) throw(uno::RuntimeException)
157 {
158 	sal_uLong nT = SotExchange::GetFormat( rFlavor );
159 	return ( nT == SOT_FORMAT_STRING );
160 }
161 
162 /*-- 24.06.2004 13:54:36---------------------------------------------------
163 
164   -----------------------------------------------------------------------*/
165 struct ImpTextView
166 {
167     TextEngine*         mpTextEngine;
168 
169     Window*             mpWindow;
170     TextSelection       maSelection;
171     Point               maStartDocPos;
172 //    TextPaM             maMBDownPaM;
173 
174     Cursor*             mpCursor;
175 
176     TextDDInfo*         mpDDInfo;
177 
178     VirtualDevice*      mpVirtDev;
179 
180     SelectionEngine*    mpSelEngine;
181     TextSelFunctionSet* mpSelFuncSet;
182 
183     ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener > mxDnDListener;
184 
185     sal_uInt16              mnTravelXPos;
186 
187     sal_Bool                mbAutoScroll            : 1;
188     sal_Bool                mbInsertMode            : 1;
189     sal_Bool                mbReadOnly              : 1;
190     sal_Bool                mbPaintSelection        : 1;
191     sal_Bool                mbAutoIndent            : 1;
192     sal_Bool                mbHighlightSelection    : 1;
193     sal_Bool                mbCursorEnabled         : 1;
194     sal_Bool                mbClickedInSelection    : 1;
195     sal_Bool                mbSupportProtectAttribute : 1;
196     bool                mbCursorAtEndOfLine;
197 };
198 
199 // -------------------------------------------------------------------------
200 // (+) class TextView
201 // -------------------------------------------------------------------------
TextView(TextEngine * pEng,Window * pWindow)202 TextView::TextView( TextEngine* pEng, Window* pWindow ) :
203     mpImpl(new ImpTextView)
204 {
205     pWindow->EnableRTL( sal_False );
206 
207     mpImpl->mpWindow = pWindow;
208     mpImpl->mpTextEngine = pEng;
209     mpImpl->mpVirtDev = NULL;
210 
211     mpImpl->mbPaintSelection = sal_True;
212     mpImpl->mbAutoScroll = sal_True;
213     mpImpl->mbInsertMode = sal_True;
214     mpImpl->mbReadOnly = sal_False;
215     mpImpl->mbHighlightSelection = sal_False;
216     mpImpl->mbAutoIndent = sal_False;
217     mpImpl->mbCursorEnabled = sal_True;
218     mpImpl->mbClickedInSelection = sal_False;
219     mpImpl->mbSupportProtectAttribute = sal_False;
220     mpImpl->mbCursorAtEndOfLine = false;
221 //	mbInSelection = sal_False;
222 
223     mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
224 
225     mpImpl->mpSelFuncSet = new TextSelFunctionSet( this );
226     mpImpl->mpSelEngine = new SelectionEngine( mpImpl->mpWindow, mpImpl->mpSelFuncSet );
227     mpImpl->mpSelEngine->SetSelectionMode( RANGE_SELECTION );
228     mpImpl->mpSelEngine->EnableDrag( sal_True );
229 
230     mpImpl->mpCursor = new Cursor;
231     mpImpl->mpCursor->Show();
232     pWindow->SetCursor( mpImpl->mpCursor );
233     pWindow->SetInputContext( InputContext( pEng->GetFont(), INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT ) );
234 
235 	if ( pWindow->GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_INVERT )
236         mpImpl->mbHighlightSelection = sal_True;
237 
238 	pWindow->SetLineColor();
239 
240     mpImpl->mpDDInfo = NULL;
241 
242     if ( pWindow->GetDragGestureRecognizer().is() )
243     {
244         vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this );
245         mpImpl->mxDnDListener = pDnDWrapper;
246 
247         uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mpImpl->mxDnDListener, uno::UNO_QUERY );
248         pWindow->GetDragGestureRecognizer()->addDragGestureListener( xDGL );
249         uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( xDGL, uno::UNO_QUERY );
250         pWindow->GetDropTarget()->addDropTargetListener( xDTL );
251         pWindow->GetDropTarget()->setActive( sal_True );
252         pWindow->GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE );
253     }
254 }
255 
~TextView()256 TextView::~TextView()
257 {
258     delete mpImpl->mpSelEngine;
259     delete mpImpl->mpSelFuncSet;
260     delete mpImpl->mpVirtDev;
261 
262     if ( mpImpl->mpWindow->GetCursor() == mpImpl->mpCursor )
263         mpImpl->mpWindow->SetCursor( 0 );
264     delete mpImpl->mpCursor;
265     delete mpImpl->mpDDInfo;
266     delete mpImpl;
267 }
268 
Invalidate()269 void TextView::Invalidate()
270 {
271     mpImpl->mpWindow->Invalidate();
272 }
273 
SetSelection(const TextSelection & rTextSel,sal_Bool bGotoCursor)274 void TextView::SetSelection( const TextSelection& rTextSel, sal_Bool bGotoCursor )
275 {
276 	// Falls jemand gerade ein leeres Attribut hinterlassen hat,
277 	// und dann der Outliner die Selektion manipulitert:
278     if ( !mpImpl->maSelection.HasRange() )
279         mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() );
280 
281 	// Wenn nach einem KeyInput die Selection manipuliert wird:
282     mpImpl->mpTextEngine->CheckIdleFormatter();
283 
284 	HideSelection();
285     TextSelection aNewSel( rTextSel );
286     mpImpl->mpTextEngine->ValidateSelection( aNewSel );
287 	ImpSetSelection( aNewSel );
288 	ShowSelection();
289 	ShowCursor( bGotoCursor );
290 }
291 
SetSelection(const TextSelection & rTextSel)292 void TextView::SetSelection( const TextSelection& rTextSel )
293 {
294     SetSelection( rTextSel, mpImpl->mbAutoScroll );
295 }
296 
GetSelection() const297 const TextSelection& TextView::GetSelection() const
298 {
299     return mpImpl->maSelection;
300 }
GetSelection()301 TextSelection&      TextView::GetSelection()
302 {
303     return mpImpl->maSelection;
304 }
305 
DeleteSelected()306 void TextView::DeleteSelected()
307 {
308 //	HideSelection();
309 
310     mpImpl->mpTextEngine->UndoActionStart();
311     TextPaM aPaM = mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
312     mpImpl->mpTextEngine->UndoActionEnd();
313 
314 	ImpSetSelection( aPaM );
315     mpImpl->mpTextEngine->FormatAndUpdate( this );
316 	ShowCursor();
317 }
318 
ImpPaint(OutputDevice * pOut,const Point & rStartPos,Rectangle const * pPaintArea,TextSelection const * pPaintRange,TextSelection const * pSelection)319 void TextView::ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange, TextSelection const* pSelection )
320 {
321     if ( !mpImpl->mbPaintSelection )
322 		pSelection = NULL;
323 	else
324 	{
325 		// Richtige Hintergrundfarbe einstellen.
326 		// Ich bekomme leider nicht mit, ob sich diese inzwischen geaendert hat.
327         Font aFont = mpImpl->mpTextEngine->GetFont();
328 		Color aColor = pOut->GetBackground().GetColor();
329 		aColor.SetTransparency( 0 );
330 		if ( aColor != aFont.GetFillColor() )
331 		{
332             if( aFont.IsTransparent() )
333                 aColor = Color( COL_TRANSPARENT );
334 			aFont.SetFillColor( aColor );
335             mpImpl->mpTextEngine->maFont = aFont;
336 		}
337 	}
338 
339     mpImpl->mpTextEngine->ImpPaint( pOut, rStartPos, pPaintArea, pPaintRange, pSelection );
340 }
341 
Paint(const Rectangle & rRect)342 void TextView::Paint( const Rectangle& rRect )
343 {
344 	ImpPaint( rRect, sal_False );
345 }
346 
ImpPaint(const Rectangle & rRect,sal_Bool bUseVirtDev)347 void TextView::ImpPaint( const Rectangle& rRect, sal_Bool bUseVirtDev )
348 {
349     if ( !mpImpl->mpTextEngine->GetUpdateMode() || mpImpl->mpTextEngine->IsInUndo() )
350 		return;
351 
352 	TextSelection *pDrawSelection = NULL;
353     if ( !mpImpl->mbHighlightSelection && mpImpl->maSelection.HasRange() )
354         pDrawSelection = &mpImpl->maSelection;
355 
356 	if ( bUseVirtDev )
357 	{
358 		VirtualDevice* pVDev = GetVirtualDevice();
359 
360         const Color& rBackgroundColor = mpImpl->mpWindow->GetBackground().GetColor();
361 		if ( pVDev->GetFillColor() != rBackgroundColor )
362 			pVDev->SetFillColor( rBackgroundColor );
363 		if ( pVDev->GetBackground().GetColor() != rBackgroundColor )
364 			pVDev->SetBackground( rBackgroundColor );
365 
366 		sal_Bool bVDevValid = sal_True;
367 		Size aOutSz( pVDev->GetOutputSizePixel() );
368 		if ( (	aOutSz.Width() < rRect.GetWidth() ) ||
369 			 (	aOutSz.Height() < rRect.GetHeight() ) )
370 		{
371 			bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() );
372 		}
373 		else
374 		{
375 			// Das VirtDev kann bei einem Resize sehr gross werden =>
376 			// irgendwann mal kleiner machen!
377 			if ( ( aOutSz.Height() > ( rRect.GetHeight() + 20 ) ) ||
378 				 ( aOutSz.Width() > ( rRect.GetWidth() + 20 ) ) )
379 			{
380 				bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() );
381 			}
382 			else
383 			{
384 				pVDev->Erase();
385 			}
386 		}
387 		if ( !bVDevValid )
388 		{
389 			ImpPaint( rRect, sal_False /* ohne VDev */ );
390 			return;
391 		}
392 
393 		Rectangle aTmpRec( Point( 0, 0 ), rRect.GetSize() );
394 
395         Point aDocPos( mpImpl->maStartDocPos.X(), mpImpl->maStartDocPos.Y() + rRect.Top() );
396         Point aStartPos = ImpGetOutputStartPos( aDocPos );
397 		ImpPaint( pVDev, aStartPos, &aTmpRec, NULL, pDrawSelection );
398         mpImpl->mpWindow->DrawOutDev( rRect.TopLeft(), rRect.GetSize(),
399 								Point(0,0), rRect.GetSize(), *pVDev );
400 //		ShowSelection();
401         if ( mpImpl->mbHighlightSelection )
402             ImpHighlight( mpImpl->maSelection );
403 	}
404 	else
405 	{
406         Point aStartPos = ImpGetOutputStartPos( mpImpl->maStartDocPos );
407         ImpPaint( mpImpl->mpWindow, aStartPos, &rRect, NULL, pDrawSelection );
408 
409 //		ShowSelection();
410         if ( mpImpl->mbHighlightSelection )
411             ImpHighlight( mpImpl->maSelection );
412 	}
413 }
414 
ImpHighlight(const TextSelection & rSel)415 void TextView::ImpHighlight( const TextSelection& rSel )
416 {
417 	TextSelection aSel( rSel );
418 	aSel.Justify();
419     if ( aSel.HasRange() && !mpImpl->mpTextEngine->IsInUndo() && mpImpl->mpTextEngine->GetUpdateMode() )
420 	{
421         mpImpl->mpCursor->Hide();
422 
423         DBG_ASSERT( !mpImpl->mpTextEngine->mpIdleFormatter->IsActive(), "ImpHighlight: Not formatted!" );
424 
425         Rectangle aVisArea( mpImpl->maStartDocPos, mpImpl->mpWindow->GetOutputSizePixel() );
426 		long nY = 0;
427 		sal_uLong nStartPara = aSel.GetStart().GetPara();
428 		sal_uLong nEndPara = aSel.GetEnd().GetPara();
429 		for ( sal_uLong nPara = 0; nPara <= nEndPara; nPara++ )
430 		{
431             long nParaHeight = (long)mpImpl->mpTextEngine->CalcParaHeight( nPara );
432 			if ( ( nPara >= nStartPara ) && ( ( nY + nParaHeight ) > aVisArea.Top() ) )
433 			{
434                 TEParaPortion* pTEParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( nPara );
435 				sal_uInt16 nStartLine = 0;
436 				sal_uInt16 nEndLine = pTEParaPortion->GetLines().Count() -1;
437 				if ( nPara == nStartPara )
438 					nStartLine = pTEParaPortion->GetLineNumber( aSel.GetStart().GetIndex(), sal_False );
439 				if ( nPara == nEndPara )
440 					nEndLine = pTEParaPortion->GetLineNumber( aSel.GetEnd().GetIndex(), sal_True );
441 
442 				// ueber die Zeilen iterieren....
443 				for ( sal_uInt16 nLine = nStartLine; nLine <= nEndLine; nLine++ )
444 				{
445 					TextLine* pLine = pTEParaPortion->GetLines().GetObject( nLine );
446 					sal_uInt16 nStartIndex = pLine->GetStart();
447 					sal_uInt16 nEndIndex = pLine->GetEnd();
448 					if ( ( nPara == nStartPara ) && ( nLine == nStartLine ) )
449 						nStartIndex = aSel.GetStart().GetIndex();
450 					if ( ( nPara == nEndPara ) && ( nLine == nEndLine ) )
451 						nEndIndex = aSel.GetEnd().GetIndex();
452 
453 					// Kann passieren, wenn am Anfang einer umgebrochenen Zeile.
454 					if ( nEndIndex < nStartIndex )
455 						nEndIndex = nStartIndex;
456 
457                     Rectangle aTmpRec( mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nStartIndex ), sal_False ) );
458 					aTmpRec.Top() += nY;
459 					aTmpRec.Bottom() += nY;
460 					Point aTopLeft( aTmpRec.TopLeft() );
461 
462                     aTmpRec = mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nEndIndex ), sal_True );
463 					aTmpRec.Top() += nY;
464 					aTmpRec.Bottom() += nY;
465 					Point aBottomRight( aTmpRec.BottomRight() );
466 					aBottomRight.X()--;
467 
468 					// Nur Painten, wenn im sichtbaren Bereich...
469 					if ( ( aTopLeft.X() < aBottomRight.X() ) && ( aBottomRight.Y() >= aVisArea.Top() ) )
470 					{
471 						Point aPnt1( GetWindowPos( aTopLeft ) );
472 						Point aPnt2( GetWindowPos( aBottomRight ) );
473 
474 						Rectangle aRect( aPnt1, aPnt2 );
475                         mpImpl->mpWindow->Invert( aRect );
476 					}
477 				}
478 			}
479 			nY += nParaHeight;
480 
481 			if ( nY >= aVisArea.Bottom() )
482 				break;
483 		}
484 	}
485 }
486 
ImpSetSelection(const TextSelection & rSelection)487 void TextView::ImpSetSelection( const TextSelection& rSelection )
488 {
489     if ( rSelection != mpImpl->maSelection )
490     {
491         mpImpl->maSelection = rSelection;
492         mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSELECTIONCHANGED ) );
493     }
494 }
495 
ShowSelection()496 void TextView::ShowSelection()
497 {
498     ImpShowHideSelection( sal_True );
499 }
500 
HideSelection()501 void TextView::HideSelection()
502 {
503     ImpShowHideSelection( sal_False );
504 }
505 
ShowSelection(const TextSelection & rRange)506 void TextView::ShowSelection( const TextSelection& rRange )
507 {
508     ImpShowHideSelection( sal_True, &rRange );
509 }
510 
ImpShowHideSelection(sal_Bool bShow,const TextSelection * pRange)511 void TextView::ImpShowHideSelection( sal_Bool bShow, const TextSelection* pRange )
512 {
513     const TextSelection* pRangeOrSelection = pRange ? pRange : &mpImpl->maSelection;
514 
515 	if ( pRangeOrSelection->HasRange() )
516 	{
517         if ( mpImpl->mbHighlightSelection )
518         {
519 			ImpHighlight( *pRangeOrSelection );
520         }
521 		else
522 		{
523             if( mpImpl->mpWindow->IsPaintTransparent() )
524                 mpImpl->mpWindow->Invalidate();
525             else
526             {
527                 Rectangle aOutArea( Point( 0, 0 ), mpImpl->mpWindow->GetOutputSizePixel() );
528                 Point aStartPos( ImpGetOutputStartPos( mpImpl->maStartDocPos ) );
529                 TextSelection aRange( *pRangeOrSelection );
530                 aRange.Justify();
531                 sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible();
532                 mpImpl->mpCursor->Hide();
533                 ImpPaint( mpImpl->mpWindow, aStartPos, &aOutArea, &aRange, bShow ? &mpImpl->maSelection : NULL );
534                 if ( bVisCursor )
535                     mpImpl->mpCursor->Show();
536             }
537 		}
538 	}
539 }
540 
GetVirtualDevice()541 VirtualDevice* TextView::GetVirtualDevice()
542 {
543     if ( !mpImpl->mpVirtDev )
544 	{
545         mpImpl->mpVirtDev = new VirtualDevice;
546         mpImpl->mpVirtDev->SetLineColor();
547 	}
548     return mpImpl->mpVirtDev;
549 }
550 
EraseVirtualDevice()551 void TextView::EraseVirtualDevice()
552 {
553     delete mpImpl->mpVirtDev;
554     mpImpl->mpVirtDev = 0;
555 }
556 
KeyInput(const KeyEvent & rKeyEvent)557 sal_Bool TextView::KeyInput( const KeyEvent& rKeyEvent )
558 {
559 	sal_Bool bDone 		= sal_True;
560 	sal_Bool bModified	= sal_False;
561 	sal_Bool bMoved		= sal_False;
562 	sal_Bool bEndKey	= sal_False;	// spezielle CursorPosition
563 	sal_Bool bAllowIdle = sal_True;
564 
565 	// Um zu pruefen ob durch irgendeine Aktion mModified, das lokale
566 	// bModified wird z.B. bei Cut/Paste nicht gesetzt, weil dort an anderen
567 	// Stellen das updaten erfolgt.
568     sal_Bool bWasModified = mpImpl->mpTextEngine->IsModified();
569     mpImpl->mpTextEngine->SetModified( sal_False );
570 
571     TextSelection aCurSel( mpImpl->maSelection );
572 	TextSelection aOldSel( aCurSel );
573 
574 	sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode();
575 	KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
576 	if ( eFunc != KEYFUNC_DONTKNOW )
577 	{
578 		switch ( eFunc )
579 		{
580 			case KEYFUNC_CUT:
581 			{
582                 if ( !mpImpl->mbReadOnly )
583 					Cut();
584 			}
585 			break;
586 			case KEYFUNC_COPY:
587 			{
588 				Copy();
589 			}
590 			break;
591 			case KEYFUNC_PASTE:
592 			{
593                 if ( !mpImpl->mbReadOnly )
594 					Paste();
595 			}
596 			break;
597 			case KEYFUNC_UNDO:
598 			{
599                 if ( !mpImpl->mbReadOnly )
600 					Undo();
601 			}
602 			break;
603 			case KEYFUNC_REDO:
604 			{
605                 if ( !mpImpl->mbReadOnly )
606 					Redo();
607 			}
608 			break;
609 
610 			default:	// wird dann evtl. unten bearbeitet.
611 						eFunc = KEYFUNC_DONTKNOW;
612 		}
613 	}
614 	if ( eFunc == KEYFUNC_DONTKNOW )
615 	{
616 		switch ( nCode )
617 		{
618 			case KEY_UP:
619 			case KEY_DOWN:
620 			case KEY_LEFT:
621 			case KEY_RIGHT:
622 			case KEY_HOME:
623 			case KEY_END:
624 			case KEY_PAGEUP:
625 			case KEY_PAGEDOWN:
626             case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
627             case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
628             case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
629             case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
630             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
631             case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
632             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
633             case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
634             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
635             case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
636             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
637             case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
638             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
639             case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
640             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
641             case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
642 			{
643 				if ( ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) )
644                       && !( rKeyEvent.GetKeyCode().IsMod1() && ( nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN ) ) )
645 				{
646 					aCurSel = ImpMoveCursor( rKeyEvent );
647                     if ( aCurSel.HasRange() ) {
648                         uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
649                         Copy( aSelection );
650                     }
651 					bMoved = sal_True;
652 					if ( nCode == KEY_END )
653 						bEndKey = sal_True;
654 				}
655 				else
656 					bDone = sal_False;
657 			}
658 			break;
659 			case KEY_BACKSPACE:
660 			case KEY_DELETE:
661             case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
662             case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
663             case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
664             case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
665 			{
666                 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod2() )
667 				{
668 					sal_uInt8 nDel = ( nCode == KEY_DELETE ) ? DEL_RIGHT : DEL_LEFT;
669 					sal_uInt8 nMode = rKeyEvent.GetKeyCode().IsMod1() ? DELMODE_RESTOFWORD : DELMODE_SIMPLE;
670 					if ( ( nMode == DELMODE_RESTOFWORD ) && rKeyEvent.GetKeyCode().IsShift() )
671 						nMode = DELMODE_RESTOFCONTENT;
672 
673                     switch( nCode )
674                     {
675                     case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
676                         nDel = DEL_LEFT;
677                         nMode = DELMODE_RESTOFWORD;
678                         break;
679                     case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
680                         nDel = DEL_RIGHT;
681                         nMode = DELMODE_RESTOFWORD;
682                         break;
683                     case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
684                         nDel = DEL_LEFT;
685                         nMode = DELMODE_RESTOFCONTENT;
686                         break;
687                     case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
688                         nDel = DEL_RIGHT;
689                         nMode = DELMODE_RESTOFCONTENT;
690                         break;
691                     default: break;
692                     }
693 
694                     mpImpl->mpTextEngine->UndoActionStart();
695                     if(mpImpl->mbSupportProtectAttribute)
696                     {
697                         //expand selection to include all protected content - if there is any
698                         const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
699                                     TextPaM(mpImpl->maSelection.GetStart().GetPara(),
700                                     mpImpl->maSelection.GetStart().GetIndex()),
701                                     TEXTATTR_PROTECTED );
702                         const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib(
703                                     TextPaM(mpImpl->maSelection.GetEnd().GetPara(),
704                                     mpImpl->maSelection.GetEnd().GetIndex()),
705                                     TEXTATTR_PROTECTED );
706                         if(pStartAttr && pStartAttr->GetStart() < mpImpl->maSelection.GetStart().GetIndex())
707                         {
708                             mpImpl->maSelection.GetStart().GetIndex() = pStartAttr->GetStart();
709                         }
710                         if(pEndAttr && pEndAttr->GetEnd() > mpImpl->maSelection.GetEnd().GetIndex())
711                         {
712                             mpImpl->maSelection.GetEnd().GetIndex() = pEndAttr->GetEnd();
713                         }
714                     }
715                     aCurSel = ImpDelete( nDel, nMode );
716                     mpImpl->mpTextEngine->UndoActionEnd();
717 					bModified = sal_True;
718 					bAllowIdle = sal_False;
719 				}
720 				else
721 					bDone = sal_False;
722 			}
723 			break;
724 			case KEY_TAB:
725 			{
726                 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsShift() &&
727 						!rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() &&
728 						ImplCheckTextLen( 'x' ) )
729 				{
730                     aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, '\t', !IsInsertMode() );
731 					bModified = sal_True;
732 				}
733 				else
734 					bDone = sal_False;
735 			}
736 			break;
737 			case KEY_RETURN:
738 			{
739 				// Shift-RETURN darf nicht geschluckt werden, weil dann keine
740 				// mehrzeilige Eingabe in Dialogen/Property-Editor moeglich.
741                 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod1() &&
742 						!rKeyEvent.GetKeyCode().IsMod2() && ImplCheckTextLen( 'x' ) )
743 				{
744                     mpImpl->mpTextEngine->UndoActionStart();
745                     aCurSel = mpImpl->mpTextEngine->ImpInsertParaBreak( aCurSel );
746                     if ( mpImpl->mbAutoIndent )
747 					{
748                         TextNode* pPrev = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aCurSel.GetEnd().GetPara() - 1 );
749 						sal_uInt16 n = 0;
750 						while ( ( n < pPrev->GetText().Len() ) && (
751 									( pPrev->GetText().GetChar( n ) == ' ' ) ||
752 									( pPrev->GetText().GetChar( n ) == '\t' ) ) )
753 						{
754 							n++;
755 						}
756 						if ( n )
757                             aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, pPrev->GetText().Copy( 0, n ) );
758 					}
759                     mpImpl->mpTextEngine->UndoActionEnd();
760 					bModified = sal_True;
761 				}
762 				else
763 					bDone = sal_False;
764 			}
765 			break;
766 			case KEY_INSERT:
767 			{
768                 if ( !mpImpl->mbReadOnly )
769 					SetInsertMode( !IsInsertMode() );
770 			}
771 			break;
772 			default:
773 			{
774 				if ( TextEngine::IsSimpleCharInput( rKeyEvent ) )
775 				{
776 					xub_Unicode nCharCode = rKeyEvent.GetCharCode();
777                     if ( !mpImpl->mbReadOnly && ImplCheckTextLen( nCharCode ) )    // sonst trotzdem das Zeichen schlucken...
778 					{
779                         aCurSel = mpImpl->mpTextEngine->ImpInsertText( nCharCode, aCurSel, !IsInsertMode(), sal_True );
780 						bModified = sal_True;
781 					}
782 				}
783 				else
784 					bDone = sal_False;
785 			}
786 		}
787 	}
788 
789     if ( aCurSel != aOldSel )   // Check if changed, maybe other method already changed mpImpl->maSelection, don't overwrite that!
790         ImpSetSelection( aCurSel );
791 
792     mpImpl->mpTextEngine->UpdateSelections();
793 
794 	if ( ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) )
795         mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
796 
797 	if ( bModified )
798 	{
799 		// Idle-Formatter nur, wenn AnyInput.
800 		if ( bAllowIdle && Application::AnyInput( INPUT_KEYBOARD) )
801             mpImpl->mpTextEngine->IdleFormatAndUpdate( this );
802 		else
803             mpImpl->mpTextEngine->FormatAndUpdate( this);
804 	}
805 	else if ( bMoved )
806 	{
807 		// Selection wird jetzt gezielt in ImpMoveCursor gemalt.
808         ImpShowCursor( mpImpl->mbAutoScroll, sal_True, bEndKey );
809 	}
810 
811     if ( mpImpl->mpTextEngine->IsModified() )
812         mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
813 	else if ( bWasModified )
814         mpImpl->mpTextEngine->SetModified( sal_True );
815 
816 	return bDone;
817 }
818 
MouseButtonUp(const MouseEvent & rMouseEvent)819 void TextView::MouseButtonUp( const MouseEvent& rMouseEvent )
820 {
821     mpImpl->mbClickedInSelection = sal_False;
822     mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
823     mpImpl->mpSelEngine->SelMouseButtonUp( rMouseEvent );
824     if ( rMouseEvent.IsMiddle() && !IsReadOnly() &&
825          ( GetWindow()->GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) )
826     {
827         uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
828         Paste( aSelection );
829         if ( mpImpl->mpTextEngine->IsModified() )
830             mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
831     }
832     else if ( rMouseEvent.IsLeft() && GetSelection().HasRange() )
833     {
834         uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
835         Copy( aSelection );
836     }
837 }
838 
MouseButtonDown(const MouseEvent & rMouseEvent)839 void TextView::MouseButtonDown( const MouseEvent& rMouseEvent )
840 {
841     mpImpl->mpTextEngine->CheckIdleFormatter();    // Falls schnelles Tippen und MouseButtonDown
842     mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
843     mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() );
844 
845     mpImpl->mpTextEngine->SetActiveView( this );
846 
847     mpImpl->mpSelEngine->SelMouseButtonDown( rMouseEvent );
848 
849 	// mbu 20.01.2005 - SelMouseButtonDown() possibly triggers a 'selection changed'
850 	// notification. The appropriate handler could change the current selection,
851 	// which is the case in the MailMerge address block control. To enable select'n'drag
852 	// we need to reevaluate the selection after the notification has been fired.
853     mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() );
854 
855 	// Sonderbehandlungen
856 	if ( !rMouseEvent.IsShift() && ( rMouseEvent.GetClicks() >= 2 ) )
857 	{
858 		if ( rMouseEvent.IsMod2() )
859 		{
860 			HideSelection();
861             ImpSetSelection( mpImpl->maSelection.GetEnd() );
862 			SetCursorAtPoint( rMouseEvent.GetPosPixel() );	// Wird von SelectionEngine bei MOD2 nicht gesetzt
863 		}
864 
865 		if ( rMouseEvent.GetClicks() == 2 )
866 		{
867 			// Wort selektieren
868             if ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) )
869 			{
870 				HideSelection();
871                 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject(  mpImpl->maSelection.GetEnd().GetPara() );
872                 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
873                 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
874                 TextSelection aNewSel( mpImpl->maSelection );
875 				aNewSel.GetStart().GetIndex() = (sal_uInt16)aBoundary.startPos;
876 				aNewSel.GetEnd().GetIndex() = (sal_uInt16)aBoundary.endPos;
877                 if(mpImpl->mbSupportProtectAttribute)
878                 {
879                     //expand selection to include all protected content - if there is any
880                     const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
881                                 TextPaM(aNewSel.GetStart().GetPara(),
882                                 (sal_uInt16)aBoundary.startPos),
883                                 TEXTATTR_PROTECTED );
884                     const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib(
885                                 TextPaM(aNewSel.GetEnd().GetPara(),
886                                 (sal_uInt16)aBoundary.endPos),
887                                 TEXTATTR_PROTECTED );
888                     if(pStartAttr && pStartAttr->GetStart() < aNewSel.GetStart().GetIndex())
889                     {
890                         aNewSel.GetStart().GetIndex() = pStartAttr->GetStart();
891                     }
892                     if(pEndAttr && pEndAttr->GetEnd() > aNewSel.GetEnd().GetIndex())
893                     {
894                         aNewSel.GetEnd().GetIndex() = pEndAttr->GetEnd();
895                     }
896                 }
897                 ImpSetSelection( aNewSel );
898 				ShowSelection();
899 				ShowCursor( sal_True, sal_True );
900 			}
901 		}
902 		else if ( rMouseEvent.GetClicks() == 3 )
903 		{
904 			// Absatz selektieren
905             if ( mpImpl->maSelection.GetStart().GetIndex() || ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) ) )
906 			{
907 				HideSelection();
908                 TextSelection aNewSel( mpImpl->maSelection );
909 				aNewSel.GetStart().GetIndex() = 0;
910                 aNewSel.GetEnd().GetIndex() = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( mpImpl->maSelection.GetEnd().GetPara() )->GetText().Len();
911                 ImpSetSelection( aNewSel );
912 				ShowSelection();
913 				ShowCursor( sal_True, sal_True );
914 			}
915 		}
916 	}
917 }
918 
919 
MouseMove(const MouseEvent & rMouseEvent)920 void TextView::MouseMove( const MouseEvent& rMouseEvent )
921 {
922     mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
923     mpImpl->mpSelEngine->SelMouseMove( rMouseEvent );
924 }
925 
Command(const CommandEvent & rCEvt)926 void TextView::Command( const CommandEvent& rCEvt )
927 {
928     mpImpl->mpTextEngine->CheckIdleFormatter();    // Falls schnelles Tippen und MouseButtonDown
929     mpImpl->mpTextEngine->SetActiveView( this );
930 
931 	if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT )
932 	{
933 		DeleteSelected();
934         delete mpImpl->mpTextEngine->mpIMEInfos;
935         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( GetSelection().GetEnd().GetPara() );
936         mpImpl->mpTextEngine->mpIMEInfos = new TEIMEInfos( GetSelection().GetEnd(), pNode->GetText().Copy( GetSelection().GetEnd().GetIndex() ) );
937         mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite = !IsInsertMode();
938 	}
939 	else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
940 	{
941         DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_ENDEXTTEXTINPUT => Kein Start ?" );
942         if( mpImpl->mpTextEngine->mpIMEInfos )
943 		{
944             TEParaPortion* pPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() );
945             pPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 );
946 
947             sal_Bool bInsertMode = !mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite;
948 
949             delete mpImpl->mpTextEngine->mpIMEInfos;
950             mpImpl->mpTextEngine->mpIMEInfos = NULL;
951 
952             mpImpl->mpTextEngine->FormatAndUpdate( this );
953 
954 			SetInsertMode( bInsertMode );
955 
956             if ( mpImpl->mpTextEngine->IsModified() )
957                 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
958 		}
959 	}
960 	else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT )
961 	{
962         DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_EXTTEXTINPUT => Kein Start ?" );
963         if( mpImpl->mpTextEngine->mpIMEInfos )
964 		{
965 			const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
966 
967 			if ( !pData->IsOnlyCursorChanged() )
968 			{
969                 TextSelection aSelect( mpImpl->mpTextEngine->mpIMEInfos->aPos );
970                 aSelect.GetEnd().GetIndex() = aSelect.GetEnd().GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen;
971                 aSelect = mpImpl->mpTextEngine->ImpDeleteText( aSelect );
972                 aSelect = mpImpl->mpTextEngine->ImpInsertText( aSelect, pData->GetText() );
973 
974                 if ( mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite )
975                 {
976                     sal_uInt16 nOldIMETextLen = mpImpl->mpTextEngine->mpIMEInfos->nLen;
977                     sal_uInt16 nNewIMETextLen = pData->GetText().Len();
978 
979                     if ( ( nOldIMETextLen > nNewIMETextLen ) &&
980                          ( nNewIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) )
981                     {
982                         // restore old characters
983                         sal_uInt16 nRestore = nOldIMETextLen - nNewIMETextLen;
984                         TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos );
985                         aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
986                         mpImpl->mpTextEngine->ImpInsertText( aPaM, mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ) );
987                     }
988                     else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
989                               ( nOldIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) )
990                     {
991                         // overwrite
992                         sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen;
993                         if ( ( nOldIMETextLen + nOverwrite ) > mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() )
994                             nOverwrite = mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen;
995                         DBG_ASSERT( nOverwrite && (nOverwrite < 0xFF00), "IME Overwrite?!" );
996                         TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos );
997                         aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
998                         TextSelection aSel( aPaM );
999                         aSel.GetEnd().GetIndex() =
1000                             aSel.GetEnd().GetIndex() + nOverwrite;
1001                         mpImpl->mpTextEngine->ImpDeleteText( aSel );
1002                     }
1003                 }
1004 
1005 			    if ( pData->GetTextAttr() )
1006 			    {
1007                     mpImpl->mpTextEngine->mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() );
1008                     mpImpl->mpTextEngine->mpIMEInfos->bCursor = pData->IsCursorVisible();
1009 			    }
1010 			    else
1011 			    {
1012                     mpImpl->mpTextEngine->mpIMEInfos->DestroyAttribs();
1013 			    }
1014 
1015                 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() );
1016                 pPPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 );
1017                 mpImpl->mpTextEngine->FormatAndUpdate( this );
1018             }
1019 
1020             TextSelection aNewSel = TextPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara(), mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() );
1021 			SetSelection( aNewSel );
1022 			SetInsertMode( !pData->IsCursorOverwrite() );
1023 
1024 			if ( pData->IsCursorVisible() )
1025 				ShowCursor();
1026 			else
1027 				HideCursor();
1028 		}
1029 	}
1030 	else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
1031 	{
1032         if ( mpImpl->mpTextEngine->mpIMEInfos && mpImpl->mpTextEngine->mpIMEInfos->nLen )
1033 		{
1034 			TextPaM aPaM( GetSelection().GetEnd() );
1035             Rectangle aR1 = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM );
1036 
1037             sal_uInt16 nInputEnd = mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen;
1038 
1039             if ( !mpImpl->mpTextEngine->IsFormatted() )
1040                 mpImpl->mpTextEngine->FormatDoc();
1041 
1042             TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1043 			sal_uInt16 nLine = pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True );
1044 			TextLine* pLine = pParaPortion->GetLines().GetObject( nLine );
1045 			if ( pLine && ( nInputEnd > pLine->GetEnd() ) )
1046 				nInputEnd = pLine->GetEnd();
1047             Rectangle aR2 = mpImpl->mpTextEngine->PaMtoEditCursor( TextPaM( aPaM.GetPara(), nInputEnd ) );
1048 
1049 			long nWidth = aR2.Left()-aR1.Right();
1050 			aR1.Move( -GetStartDocPos().X(), -GetStartDocPos().Y() );
1051 			GetWindow()->SetCursorRect( &aR1, nWidth );
1052 		}
1053 		else
1054 		{
1055 			GetWindow()->SetCursorRect();
1056 		}
1057 	}
1058 	else
1059 	{
1060         mpImpl->mpSelEngine->Command( rCEvt );
1061 	}
1062 }
1063 
ShowCursor(sal_Bool bGotoCursor,sal_Bool bForceVisCursor)1064 void TextView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor )
1065 {
1066 	// Die Einstellung hat mehr Gewicht:
1067     if ( !mpImpl->mbAutoScroll )
1068 		bGotoCursor = sal_False;
1069 	ImpShowCursor( bGotoCursor, bForceVisCursor, sal_False );
1070 }
1071 
HideCursor()1072 void TextView::HideCursor()
1073 {
1074     mpImpl->mpCursor->Hide();
1075 }
1076 
Scroll(long ndX,long ndY)1077 void TextView::Scroll( long ndX, long ndY )
1078 {
1079     DBG_ASSERT( mpImpl->mpTextEngine->IsFormatted(), "Scroll: Nicht formatiert!" );
1080 
1081 	if ( !ndX && !ndY )
1082 		return;
1083 
1084     Point aNewStartPos( mpImpl->maStartDocPos );
1085 
1086 	// Vertical:
1087 	aNewStartPos.Y() -= ndY;
1088 	if ( aNewStartPos.Y() < 0 )
1089 		aNewStartPos.Y() = 0;
1090 
1091 	// Horizontal:
1092 	aNewStartPos.X() -= ndX;
1093 	if ( aNewStartPos.X() < 0 )
1094 		aNewStartPos.X() = 0;
1095 
1096     long nDiffX = mpImpl->maStartDocPos.X() - aNewStartPos.X();
1097     long nDiffY = mpImpl->maStartDocPos.Y() - aNewStartPos.Y();
1098 
1099 	if ( nDiffX || nDiffY )
1100 	{
1101         sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible();
1102         mpImpl->mpCursor->Hide();
1103         mpImpl->mpWindow->Update();
1104         mpImpl->maStartDocPos = aNewStartPos;
1105 
1106         if ( mpImpl->mpTextEngine->IsRightToLeft() )
1107             nDiffX = -nDiffX;
1108         mpImpl->mpWindow->Scroll( nDiffX, nDiffY );
1109         mpImpl->mpWindow->Update();
1110         mpImpl->mpCursor->SetPos( mpImpl->mpCursor->GetPos() + Point( nDiffX, nDiffY ) );
1111         if ( bVisCursor && !mpImpl->mbReadOnly )
1112             mpImpl->mpCursor->Show();
1113 	}
1114 
1115     mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSCROLLED ) );
1116 }
1117 
Undo()1118 void TextView::Undo()
1119 {
1120     mpImpl->mpTextEngine->SetActiveView( this );
1121     mpImpl->mpTextEngine->GetUndoManager().Undo();
1122 }
1123 
Redo()1124 void TextView::Redo()
1125 {
1126     mpImpl->mpTextEngine->SetActiveView( this );
1127     mpImpl->mpTextEngine->GetUndoManager().Redo();
1128 }
1129 
Cut()1130 void TextView::Cut()
1131 {
1132     mpImpl->mpTextEngine->UndoActionStart();
1133 	Copy();
1134 	DeleteSelected();
1135     mpImpl->mpTextEngine->UndoActionEnd();
1136 }
1137 
Copy(uno::Reference<datatransfer::clipboard::XClipboard> & rxClipboard)1138 void TextView::Copy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1139 {
1140 	if ( rxClipboard.is() )
1141 	{
1142 		TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
1143 
1144         if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) )  // Dann auch als HTML
1145             mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True );
1146 
1147 		const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1148 
1149         try
1150 		{
1151 		    rxClipboard->setContents( pDataObj, NULL );
1152 
1153             uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
1154 		    if( xFlushableClipboard.is() )
1155 			    xFlushableClipboard->flushClipboard();
1156 		}
1157 		catch( const ::com::sun::star::uno::Exception& )
1158 		{
1159 		}
1160 
1161 		Application::AcquireSolarMutex( nRef );
1162 	}
1163 }
1164 
Copy()1165 void TextView::Copy()
1166 {
1167     uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
1168     Copy( aClipboard );
1169 }
1170 
Paste(uno::Reference<datatransfer::clipboard::XClipboard> & rxClipboard)1171 void TextView::Paste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1172 {
1173 	if ( rxClipboard.is() )
1174 	{
1175         uno::Reference< datatransfer::XTransferable > xDataObj;
1176 
1177         const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1178 
1179         try
1180 		{
1181 		    xDataObj = rxClipboard->getContents();
1182 		}
1183 		catch( const ::com::sun::star::uno::Exception& )
1184 		{
1185 		}
1186 
1187         Application::AcquireSolarMutex( nRef );
1188 
1189         if ( xDataObj.is() )
1190 		{
1191 			datatransfer::DataFlavor aFlavor;
1192 			SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
1193 			if ( xDataObj->isDataFlavorSupported( aFlavor ) )
1194 			{
1195                 try
1196                 {
1197                     uno::Any aData = xDataObj->getTransferData( aFlavor );
1198                     ::rtl::OUString aText;
1199                     aData >>= aText;
1200                     bool bWasTruncated = false;
1201                     if( mpImpl->mpTextEngine->GetMaxTextLen() != 0 )
1202                         bWasTruncated = ImplTruncateNewText( aText );
1203                     InsertNewText( aText, sal_False );
1204                     mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
1205 
1206                     if( bWasTruncated )
1207                         Edit::ShowTruncationWarning( mpImpl->mpWindow );
1208                 }
1209                 catch( const ::com::sun::star::datatransfer::UnsupportedFlavorException& )
1210                 {
1211                 }
1212 			}
1213 		}
1214 	}
1215 }
1216 
Paste()1217 void TextView::Paste()
1218 {
1219     uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
1220     Paste( aClipboard );
1221 }
1222 
GetSelected()1223 String TextView::GetSelected()
1224 {
1225     return GetSelected( GetSystemLineEnd() );
1226 }
1227 
GetSelected(LineEnd aSeparator)1228 String TextView::GetSelected( LineEnd aSeparator )
1229 {
1230     return mpImpl->mpTextEngine->GetText( mpImpl->maSelection, aSeparator );
1231 }
1232 
SetInsertMode(sal_Bool bInsert)1233 void TextView::SetInsertMode( sal_Bool bInsert )
1234 {
1235     if ( mpImpl->mbInsertMode != bInsert )
1236 	{
1237         mpImpl->mbInsertMode = bInsert;
1238         ShowCursor( mpImpl->mbAutoScroll, sal_False );
1239 	}
1240 }
1241 
SetReadOnly(sal_Bool bReadOnly)1242 void TextView::SetReadOnly( sal_Bool bReadOnly )
1243 {
1244     if ( mpImpl->mbReadOnly != bReadOnly )
1245 	{
1246         mpImpl->mbReadOnly = bReadOnly;
1247         if ( !mpImpl->mbReadOnly )
1248             ShowCursor( mpImpl->mbAutoScroll, sal_False );
1249 		else
1250 			HideCursor();
1251 
1252         GetWindow()->SetInputContext( InputContext( mpImpl->mpTextEngine->GetFont(), bReadOnly ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) );
1253 	}
1254 }
1255 
ImpMoveCursor(const KeyEvent & rKeyEvent)1256 TextSelection TextView::ImpMoveCursor( const KeyEvent& rKeyEvent )
1257 {
1258 	// Eigentlich nur bei Up/Down noetig, aber was solls.
1259     mpImpl->mpTextEngine->CheckIdleFormatter();
1260 
1261     TextPaM aPaM( mpImpl->maSelection.GetEnd() );
1262 	TextPaM aOldEnd( aPaM );
1263 
1264     TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom;
1265     if ( mpImpl->mpTextEngine->IsRightToLeft() )
1266         eTextDirection = TextDirectionality_RightToLeft_TopToBottom;
1267 
1268     KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection );
1269 
1270     sal_Bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? sal_True : sal_False;
1271 	sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode();
1272 
1273     bool bSelect = aTranslatedKeyEvent.GetKeyCode().IsShift();
1274 	switch ( nCode )
1275 	{
1276 		case KEY_UP:		aPaM = CursorUp( aPaM );
1277 							break;
1278 		case KEY_DOWN:		aPaM = CursorDown( aPaM );
1279 							break;
1280 		case KEY_HOME:		aPaM = bCtrl ? CursorStartOfDoc() : CursorStartOfLine( aPaM );
1281 							break;
1282 		case KEY_END:		aPaM = bCtrl ? CursorEndOfDoc() : CursorEndOfLine( aPaM );
1283 							break;
1284 		case KEY_PAGEUP:	aPaM = bCtrl ? CursorStartOfDoc() : PageUp( aPaM );
1285 							break;
1286 		case KEY_PAGEDOWN:	aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM );
1287 							break;
1288 		case KEY_LEFT:		aPaM = bCtrl ? CursorWordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1289 							break;
1290 		case KEY_RIGHT: 	aPaM = bCtrl ? CursorWordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1291 							break;
1292         case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
1293                             bSelect = true; // fallthrough intentional
1294         case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
1295                             aPaM = CursorWordRight( aPaM );
1296                             break;
1297         case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
1298                             bSelect = true; // fallthrough intentional
1299         case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
1300                             aPaM = CursorWordLeft( aPaM );
1301                             break;
1302         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1303                             bSelect = true; // fallthrough intentional
1304         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1305                             aPaM = CursorStartOfLine( aPaM );
1306                             break;
1307         case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
1308                             bSelect = true; // fallthrough intentional
1309         case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
1310                             aPaM = CursorEndOfLine( aPaM );
1311                             break;
1312         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1313                             bSelect = true; // falltthrough intentional
1314         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1315                             aPaM = CursorStartOfParagraph( aPaM );
1316                             break;
1317         case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1318                             bSelect = true; // falltthrough intentional
1319         case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1320                             aPaM = CursorEndOfParagraph( aPaM );
1321                             break;
1322         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1323                             bSelect = true; // falltthrough intentional
1324         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1325                             aPaM = CursorStartOfDoc();
1326                             break;
1327         case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1328                             bSelect = true; // falltthrough intentional
1329         case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1330                             aPaM = CursorEndOfDoc();
1331                             break;
1332 	}
1333 
1334 	// Bewirkt evtl. ein CreateAnchor oder Deselection all
1335     mpImpl->mpSelEngine->CursorPosChanging( bSelect, aTranslatedKeyEvent.GetKeyCode().IsMod1() );
1336 
1337 	if ( aOldEnd != aPaM )
1338 	{
1339         mpImpl->mpTextEngine->CursorMoved( aOldEnd.GetPara() );
1340 
1341 
1342         TextSelection aOldSelection( mpImpl->maSelection );
1343         TextSelection aNewSelection( mpImpl->maSelection );
1344 		aNewSelection.GetEnd() = aPaM;
1345 		if ( bSelect )
1346 		{
1347 			// Dann wird die Selektion erweitert...
1348             ImpSetSelection( aNewSelection );
1349 			ShowSelection( TextSelection( aOldEnd, aPaM ) );
1350 		}
1351 		else
1352 		{
1353 			aNewSelection.GetStart() = aPaM;
1354             ImpSetSelection( aNewSelection );
1355 		}
1356 	}
1357 
1358     return mpImpl->maSelection;
1359 }
1360 
InsertText(const XubString & rStr,sal_Bool bSelect)1361 void TextView::InsertText( const XubString& rStr, sal_Bool bSelect )
1362 {
1363     InsertNewText( rStr, bSelect );
1364 }
1365 
InsertNewText(const rtl::OUString & rStr,sal_Bool bSelect)1366 void TextView::InsertNewText( const rtl::OUString& rStr, sal_Bool bSelect )
1367 {
1368 //	HideSelection();
1369     mpImpl->mpTextEngine->UndoActionStart();
1370 
1371     /* #i87633#
1372     break inserted text into chunks that fit into the underlying String
1373     based API (which has a maximum length of 65534 elements
1374 
1375     note: this will of course still cause problems for lines longer than those
1376     65534 elements, but those cases will hopefully be few.
1377     In the long run someone should switch the TextEngine to OUString instead of String
1378     */
1379     sal_Int32 nLen = rStr.getLength();
1380     sal_Int32 nPos = 0;
1381     do
1382     {
1383         sal_Int32 nChunkLen = nLen > 65534 ? 65534 : nLen;
1384         String aChunk( rStr.copy( nPos, nChunkLen ) );
1385 
1386         TextSelection aNewSel( mpImpl->maSelection );
1387 
1388         TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, aChunk );
1389 
1390         if ( bSelect )
1391         {
1392             aNewSel.Justify();
1393             aNewSel.GetEnd() = aPaM;
1394         }
1395         else
1396         {
1397             aNewSel = aPaM;
1398         }
1399 
1400         ImpSetSelection( aNewSel );
1401         nLen -= nChunkLen;
1402         nPos += nChunkLen;
1403     } while( nLen );
1404     mpImpl->mpTextEngine->UndoActionEnd();
1405 
1406     mpImpl->mpTextEngine->FormatAndUpdate( this );
1407 }
1408 
1409 /*
1410 void TextView::InsertText( const XubString& rStr, sal_Bool bSelect )
1411 {
1412 //	HideSelection();
1413 
1414     TextSelection aNewSel( mpImpl->maSelection );
1415 
1416     mpImpl->mpTextEngine->UndoActionStart();
1417     TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, rStr );
1418     mpImpl->mpTextEngine->UndoActionEnd();
1419 
1420 	if ( bSelect )
1421 	{
1422 		aNewSel.Justify();
1423 		aNewSel.GetEnd() = aPaM;
1424 	}
1425 	else
1426     {
1427 		aNewSel = aPaM;
1428     }
1429 
1430     ImpSetSelection( aNewSel );
1431 
1432     mpImpl->mpTextEngine->FormatAndUpdate( this );
1433 }
1434 */
1435 
1436 // OLD
CursorLeft(const TextPaM & rPaM,sal_Bool bWordMode)1437 TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_Bool bWordMode )
1438 {
1439     return bWordMode ? CursorWordLeft( rPaM ) : CursorLeft( rPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1440 
1441     // Remove (sal_uInt16) typecasts in this file when removing this method!
1442 }
1443 
1444 // OLD
CursorRight(const TextPaM & rPaM,sal_Bool bWordMode)1445 TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_Bool bWordMode )
1446 {
1447     return bWordMode ? CursorWordRight( rPaM ) : CursorRight( rPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1448 
1449     // Remove (sal_uInt16) typecasts in this file when removing this method!
1450 }
1451 
CursorLeft(const TextPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1452 TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1453 {
1454 	TextPaM aPaM( rPaM );
1455 
1456 	if ( aPaM.GetIndex() )
1457 	{
1458         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1459         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1460 		sal_Int32 nCount = 1;
1461         aPaM.GetIndex() = (sal_uInt16)xBI->previousCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
1462 	}
1463 	else if ( aPaM.GetPara() )
1464 	{
1465 		aPaM.GetPara()--;
1466         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1467 		aPaM.GetIndex() = pNode->GetText().Len();
1468 	}
1469 	return aPaM;
1470 }
1471 
CursorRight(const TextPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1472 TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1473 {
1474 	TextPaM aPaM( rPaM );
1475 
1476     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1477 	if ( aPaM.GetIndex() < pNode->GetText().Len() )
1478 	{
1479         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1480 		sal_Int32 nCount = 1;
1481         aPaM.GetIndex() = (sal_uInt16)xBI->nextCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
1482 	}
1483     else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
1484 	{
1485 		aPaM.GetPara()++;
1486 		aPaM.GetIndex() = 0;
1487 	}
1488 
1489 	return aPaM;
1490 }
1491 
1492 
CursorWordLeft(const TextPaM & rPaM)1493 TextPaM TextView::CursorWordLeft( const TextPaM& rPaM )
1494 {
1495 	TextPaM aPaM( rPaM );
1496 
1497 	if ( aPaM.GetIndex() )
1498 	{
1499         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1500         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1501         i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1502 		if ( aBoundary.startPos >= rPaM.GetIndex() )
1503             aBoundary = xBI->previousWord( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1504 		aPaM.GetIndex() = ( aBoundary.startPos != -1 ) ? (sal_uInt16)aBoundary.startPos : 0;
1505 	}
1506 	else if ( aPaM.GetPara() )
1507 	{
1508 		aPaM.GetPara()--;
1509         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1510 		aPaM.GetIndex() = pNode->GetText().Len();
1511 	}
1512 	return aPaM;
1513 }
1514 
1515 
CursorWordRight(const TextPaM & rPaM)1516 TextPaM TextView::CursorWordRight( const TextPaM& rPaM )
1517 {
1518 	TextPaM aPaM( rPaM );
1519 
1520     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1521 	if ( aPaM.GetIndex() < pNode->GetText().Len() )
1522 	{
1523         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1524         i18n::Boundary aBoundary = xBI->nextWord(  pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1525 		aPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
1526 	}
1527     else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
1528 	{
1529 		aPaM.GetPara()++;
1530 		aPaM.GetIndex() = 0;
1531 	}
1532 
1533 	return aPaM;
1534 }
1535 
ImpDelete(sal_uInt8 nMode,sal_uInt8 nDelMode)1536 TextPaM TextView::ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode )
1537 {
1538     if ( mpImpl->maSelection.HasRange() )  // dann nur Sel. loeschen
1539         return mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
1540 
1541     TextPaM aStartPaM = mpImpl->maSelection.GetStart();
1542 	TextPaM aEndPaM = aStartPaM;
1543 	if ( nMode == DEL_LEFT )
1544 	{
1545 		if ( nDelMode == DELMODE_SIMPLE )
1546 		{
1547 			aEndPaM = CursorLeft( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER );
1548 		}
1549 		else if ( nDelMode == DELMODE_RESTOFWORD )
1550 		{
1551             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject(  aEndPaM.GetPara() );
1552             uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1553             i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1554             if ( aBoundary.startPos == mpImpl->maSelection.GetEnd().GetIndex() )
1555                 aBoundary = xBI->previousWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1556 			// #i63506# startPos is -1 when the paragraph starts with a tab
1557 			aEndPaM.GetIndex() = (aBoundary.startPos >= 0) ? (sal_uInt16)aBoundary.startPos : 0;
1558 		}
1559 		else	// DELMODE_RESTOFCONTENT
1560 		{
1561 			if ( aEndPaM.GetIndex() != 0 )
1562 				aEndPaM.GetIndex() = 0;
1563 			else if ( aEndPaM.GetPara() )
1564 			{
1565 				// Absatz davor
1566 				aEndPaM.GetPara()--;
1567 				aEndPaM.GetIndex() = 0;
1568 			}
1569 		}
1570 	}
1571 	else
1572 	{
1573 		if ( nDelMode == DELMODE_SIMPLE )
1574 		{
1575 			aEndPaM = CursorRight( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1576 		}
1577 		else if ( nDelMode == DELMODE_RESTOFWORD )
1578 		{
1579             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject(  aEndPaM.GetPara() );
1580             uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1581             i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1582 			aEndPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
1583 		}
1584 		else	// DELMODE_RESTOFCONTENT
1585 		{
1586             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1587 			if ( aEndPaM.GetIndex() < pNode->GetText().Len() )
1588 				aEndPaM.GetIndex() = pNode->GetText().Len();
1589             else if ( aEndPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) )
1590 			{
1591 				// Absatz danach
1592 				aEndPaM.GetPara()++;
1593                 TextNode* pNextNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1594 				aEndPaM.GetIndex() = pNextNode->GetText().Len();
1595 			}
1596 		}
1597 	}
1598 
1599     return mpImpl->mpTextEngine->ImpDeleteText( TextSelection( aStartPaM, aEndPaM ) );
1600 }
1601 
1602 
1603 
CursorUp(const TextPaM & rPaM)1604 TextPaM TextView::CursorUp( const TextPaM& rPaM )
1605 {
1606 	TextPaM aPaM( rPaM );
1607 
1608 	long nX;
1609     if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
1610 	{
1611         nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left();
1612         mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
1613 	}
1614 	else
1615         nX = mpImpl->mnTravelXPos;
1616 
1617     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1618 	sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False );
1619 	if ( nLine )	// gleicher Absatz
1620 	{
1621         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine-1, nX );
1622 		aPaM.GetIndex() = nCharPos;
1623 		// Wenn davor eine autom.Umgebrochene Zeile, und ich muss genau an das
1624 		// Ende dieser Zeile, landet der Cursor in der aktuellen Zeile am Anfang
1625 		// Siehe Problem: Letztes Zeichen einer autom.umgebr. Zeile = Cursor
1626 		TextLine* pLine = pPPortion->GetLines().GetObject( nLine - 1 );
1627 		if ( aPaM.GetIndex() && ( aPaM.GetIndex() == pLine->GetEnd() ) )
1628 			aPaM.GetIndex()--;
1629 	}
1630 	else if ( rPaM.GetPara() )	// vorheriger Absatz
1631 	{
1632 		aPaM.GetPara()--;
1633         pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1634 		sal_uInt16 nL = pPPortion->GetLines().Count() - 1;
1635         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), nL, nX+1 );
1636 		aPaM.GetIndex() = nCharPos;
1637 	}
1638 
1639 	return aPaM;
1640 }
1641 
CursorDown(const TextPaM & rPaM)1642 TextPaM TextView::CursorDown( const TextPaM& rPaM )
1643 {
1644 	TextPaM aPaM( rPaM );
1645 
1646 	long nX;
1647     if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
1648 	{
1649         nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left();
1650         mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
1651 	}
1652 	else
1653         nX = mpImpl->mnTravelXPos;
1654 
1655     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1656 	sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False );
1657 	if ( nLine < ( pPPortion->GetLines().Count() - 1 ) )
1658 	{
1659         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine+1, nX );
1660 		aPaM.GetIndex() = nCharPos;
1661 
1662 		// Sonderbehandlung siehe CursorUp...
1663 		TextLine* pLine = pPPortion->GetLines().GetObject( nLine + 1 );
1664 		if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && aPaM.GetIndex() < pPPortion->GetNode()->GetText().Len() )
1665 			aPaM.GetIndex()--;
1666 	}
1667     else if ( rPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) )   // naechster Absatz
1668 	{
1669 		aPaM.GetPara()++;
1670         pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1671         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), 0, nX+1 );
1672 		aPaM.GetIndex() = nCharPos;
1673 		TextLine* pLine = pPPortion->GetLines().GetObject( 0 );
1674 		if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && ( pPPortion->GetLines().Count() > 1 ) )
1675 			aPaM.GetIndex()--;
1676 	}
1677 
1678 	return aPaM;
1679 }
1680 
CursorStartOfLine(const TextPaM & rPaM)1681 TextPaM TextView::CursorStartOfLine( const TextPaM& rPaM )
1682 {
1683 	TextPaM aPaM( rPaM );
1684 
1685     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1686 	sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1687 	TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
1688 	aPaM.GetIndex() = pLine->GetStart();
1689 
1690 	return aPaM;
1691 }
1692 
CursorEndOfLine(const TextPaM & rPaM)1693 TextPaM TextView::CursorEndOfLine( const TextPaM& rPaM )
1694 {
1695 	TextPaM aPaM( rPaM );
1696 
1697     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1698 	sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1699 	TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
1700 	aPaM.GetIndex() = pLine->GetEnd();
1701 
1702 	if ( pLine->GetEnd() > pLine->GetStart() )	// Leerzeile
1703 	{
1704 		xub_Unicode cLastChar = pPPortion->GetNode()->GetText().GetChar((sal_uInt16)(aPaM.GetIndex()-1) );
1705 		if ( ( cLastChar == ' ' ) && ( aPaM.GetIndex() != pPPortion->GetNode()->GetText().Len() ) )
1706 		{
1707 			// Bei einem Blank in einer autom. umgebrochenen Zeile macht es Sinn,
1708 			// davor zu stehen, da der Anwender hinter das Wort will.
1709 			// Wenn diese geaendert wird, Sonderbehandlung fuer Pos1 nach End!
1710 			aPaM.GetIndex()--;
1711 		}
1712 	}
1713 	return aPaM;
1714 }
1715 
CursorStartOfParagraph(const TextPaM & rPaM)1716 TextPaM TextView::CursorStartOfParagraph( const TextPaM& rPaM )
1717 {
1718 	TextPaM aPaM( rPaM );
1719 	aPaM.GetIndex() = 0;
1720 	return aPaM;
1721 }
1722 
CursorEndOfParagraph(const TextPaM & rPaM)1723 TextPaM TextView::CursorEndOfParagraph( const TextPaM& rPaM )
1724 {
1725     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( rPaM.GetPara() );
1726 	TextPaM aPaM( rPaM );
1727 	aPaM.GetIndex() = pNode->GetText().Len();
1728 	return aPaM;
1729 }
1730 
CursorStartOfDoc()1731 TextPaM TextView::CursorStartOfDoc()
1732 {
1733 	TextPaM aPaM( 0, 0 );
1734 	return aPaM;
1735 }
1736 
CursorEndOfDoc()1737 TextPaM TextView::CursorEndOfDoc()
1738 {
1739     sal_uLong nNode = mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1;
1740     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( nNode );
1741 	TextPaM aPaM( nNode, pNode->GetText().Len() );
1742 	return aPaM;
1743 }
1744 
PageUp(const TextPaM & rPaM)1745 TextPaM TextView::PageUp( const TextPaM& rPaM )
1746 {
1747     Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
1748 	Point aTopLeft = aRec.TopLeft();
1749     aTopLeft.Y() -= mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
1750 	aTopLeft.X() += 1;
1751 	if ( aTopLeft.Y() < 0 )
1752 		aTopLeft.Y() = 0;
1753 
1754     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aTopLeft );
1755 	return aPaM;
1756 }
1757 
PageDown(const TextPaM & rPaM)1758 TextPaM TextView::PageDown( const TextPaM& rPaM )
1759 {
1760     Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
1761 	Point aBottomRight = aRec.BottomRight();
1762     aBottomRight.Y() += mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
1763 	aBottomRight.X() += 1;
1764     long nHeight = mpImpl->mpTextEngine->GetTextHeight();
1765 	if ( aBottomRight.Y() > nHeight )
1766 		aBottomRight.Y() = nHeight-1;
1767 
1768     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aBottomRight );
1769 	return aPaM;
1770 }
1771 
ImpShowCursor(sal_Bool bGotoCursor,sal_Bool bForceVisCursor,sal_Bool bSpecial)1772 void TextView::ImpShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, sal_Bool bSpecial )
1773 {
1774     if ( mpImpl->mpTextEngine->IsFormatting() )
1775 		return;
1776     if ( mpImpl->mpTextEngine->GetUpdateMode() == sal_False )
1777 		return;
1778     if ( mpImpl->mpTextEngine->IsInUndo() )
1779 		return;
1780 
1781     mpImpl->mpTextEngine->CheckIdleFormatter();
1782     if ( !mpImpl->mpTextEngine->IsFormatted() )
1783         mpImpl->mpTextEngine->FormatAndUpdate( this );
1784 
1785 
1786     TextPaM aPaM( mpImpl->maSelection.GetEnd() );
1787     Rectangle aEditCursor = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM, bSpecial );
1788 
1789     // Remember that we placed the cursor behind the last character of a line
1790     mpImpl->mbCursorAtEndOfLine = false;
1791     if( bSpecial )
1792     {
1793         TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1794         mpImpl->mbCursorAtEndOfLine =
1795             pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True ) != pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1796     }
1797 
1798     if ( !IsInsertMode() && !mpImpl->maSelection.HasRange() )
1799 	{
1800         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1801 		if ( pNode->GetText().Len() && ( aPaM.GetIndex() < pNode->GetText().Len() ) )
1802 		{
1803             // If we are behind a portion, and the next portion has other direction, we must change position...
1804             aEditCursor.Left() = aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aPaM, sal_False, sal_True ).Left();
1805 
1806             TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1807 
1808             sal_uInt16 nTextPortionStart = 0;
1809             sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, sal_True );
1810             TETextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
1811             if ( pTextPortion->GetKind() == PORTIONKIND_TAB )
1812             {
1813                 if ( mpImpl->mpTextEngine->IsRightToLeft() )
1814                 {
1815 
1816                 }
1817 		        aEditCursor.Right() += pTextPortion->GetWidth();
1818             }
1819             else
1820             {
1821                 TextPaM aNext = CursorRight( TextPaM( aPaM.GetPara(), aPaM.GetIndex() ), (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1822                 aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aNext, sal_True ).Left();
1823             }
1824 		}
1825 	}
1826 
1827     Size aOutSz = mpImpl->mpWindow->GetOutputSizePixel();
1828 	if ( aEditCursor.GetHeight() > aOutSz.Height() )
1829 		aEditCursor.Bottom() = aEditCursor.Top() + aOutSz.Height() - 1;
1830 
1831     aEditCursor.Left() -= 1;
1832 
1833 	if ( bGotoCursor
1834         // #i81283# protext maStartDocPos against initialization problems
1835         && aOutSz.Width() && aOutSz.Height()
1836     )
1837 	{
1838         long nVisStartY = mpImpl->maStartDocPos.Y();
1839         long nVisEndY = mpImpl->maStartDocPos.Y() + aOutSz.Height();
1840         long nVisStartX = mpImpl->maStartDocPos.X();
1841         long nVisEndX = mpImpl->maStartDocPos.X() + aOutSz.Width();
1842 		long nMoreX = aOutSz.Width() / 4;
1843 
1844         Point aNewStartPos( mpImpl->maStartDocPos );
1845 
1846 		if ( aEditCursor.Bottom() > nVisEndY )
1847 		{
1848 			aNewStartPos.Y() += ( aEditCursor.Bottom() - nVisEndY );
1849 		}
1850 		else if ( aEditCursor.Top() < nVisStartY )
1851 		{
1852 			aNewStartPos.Y() -= ( nVisStartY - aEditCursor.Top() );
1853 		}
1854 
1855 		if ( aEditCursor.Right() >= nVisEndX )
1856 		{
1857 			aNewStartPos.X() += ( aEditCursor.Right() - nVisEndX );
1858 
1859 			// Darfs ein bischen mehr sein?
1860 			aNewStartPos.X() += nMoreX;
1861 		}
1862 		else if ( aEditCursor.Left() <= nVisStartX )
1863 		{
1864 			aNewStartPos.X() -= ( nVisStartX - aEditCursor.Left() );
1865 
1866 			// Darfs ein bischen mehr sein?
1867 			aNewStartPos.X() -= nMoreX;
1868 		}
1869 
1870 		// X kann durch das 'bischen mehr' falsch sein:
1871 //      sal_uLong nMaxTextWidth = mpImpl->mpTextEngine->GetMaxTextWidth();
1872 //		if ( !nMaxTextWidth || ( nMaxTextWidth > 0x7FFFFFFF ) )
1873 //			nMaxTextWidth = 0x7FFFFFFF;
1874 //		long nMaxX = (long)nMaxTextWidth - aOutSz.Width();
1875         long nMaxX = mpImpl->mpTextEngine->CalcTextWidth() - aOutSz.Width();
1876 		if ( nMaxX < 0 )
1877 			nMaxX = 0;
1878 
1879 		if ( aNewStartPos.X() < 0 )
1880 			aNewStartPos.X() = 0;
1881 		else if ( aNewStartPos.X() > nMaxX )
1882 			aNewStartPos.X() = nMaxX;
1883 
1884 		// Y sollte nicht weiter unten als noetig liegen:
1885         long nYMax = mpImpl->mpTextEngine->GetTextHeight() - aOutSz.Height();
1886 		if ( nYMax < 0 )
1887 			nYMax = 0;
1888 		if ( aNewStartPos.Y() > nYMax )
1889 			aNewStartPos.Y() = nYMax;
1890 
1891         if ( aNewStartPos != mpImpl->maStartDocPos )
1892             Scroll( -(aNewStartPos.X() - mpImpl->maStartDocPos.X()), -(aNewStartPos.Y() - mpImpl->maStartDocPos.Y()) );
1893 	}
1894 
1895     if ( aEditCursor.Right() < aEditCursor.Left() )
1896     {
1897         long n = aEditCursor.Left();
1898         aEditCursor.Left() = aEditCursor.Right();
1899         aEditCursor.Right() = n;
1900     }
1901 
1902     Point aPoint( GetWindowPos( !mpImpl->mpTextEngine->IsRightToLeft() ? aEditCursor.TopLeft() : aEditCursor.TopRight() ) );
1903     mpImpl->mpCursor->SetPos( aPoint );
1904     mpImpl->mpCursor->SetSize( aEditCursor.GetSize() );
1905     if ( bForceVisCursor && mpImpl->mbCursorEnabled )
1906         mpImpl->mpCursor->Show();
1907 }
1908 
SetCursorAtPoint(const Point & rPosPixel)1909 sal_Bool TextView::SetCursorAtPoint( const Point& rPosPixel )
1910 {
1911     mpImpl->mpTextEngine->CheckIdleFormatter();
1912 
1913 	Point aDocPos = GetDocPos( rPosPixel );
1914 
1915     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos );
1916 
1917 	// aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion
1918     TextSelection aTmpNewSel( mpImpl->maSelection.GetEnd(), aPaM );
1919     TextSelection aNewSel( mpImpl->maSelection );
1920 	aNewSel.GetEnd() = aPaM;
1921 
1922     if ( !mpImpl->mpSelEngine->HasAnchor() )
1923 	{
1924         if ( mpImpl->maSelection.GetStart() != aPaM )
1925             mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() );
1926 		aNewSel.GetStart() = aPaM;
1927         ImpSetSelection( aNewSel );
1928 	}
1929 	else
1930 	{
1931         ImpSetSelection( aNewSel );
1932 		ShowSelection( aTmpNewSel );
1933 	}
1934 
1935     sal_Bool bForceCursor =  mpImpl->mpDDInfo ? sal_False : sal_True; // && !mbInSelection
1936     ImpShowCursor( mpImpl->mbAutoScroll, bForceCursor, sal_False );
1937 	return sal_True;
1938 }
1939 
IsSelectionAtPoint(const Point & rPosPixel)1940 sal_Bool TextView::IsSelectionAtPoint( const Point& rPosPixel )
1941 {
1942 //  if ( !Rectangle( Point(), mpImpl->mpWindow->GetOutputSizePixel() ).IsInside( rPosPixel ) && !mbInSelection )
1943 //		return sal_False;
1944 
1945 	Point aDocPos = GetDocPos( rPosPixel );
1946     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos, sal_False );
1947 	// Bei Hyperlinks D&D auch ohne Selektion starten.
1948 	// BeginDrag wird aber nur gerufen, wenn IsSelectionAtPoint()
1949 	// Problem: IsSelectionAtPoint wird bei Command() nicht gerufen,
1950 	// wenn vorher im MBDown schon sal_False returnt wurde.
1951 	return ( IsInSelection( aPaM ) ||
1952             ( /* mpImpl->mpSelEngine->IsInCommand() && */ mpImpl->mpTextEngine->FindAttrib( aPaM, TEXTATTR_HYPERLINK ) ) );
1953 }
1954 
IsInSelection(const TextPaM & rPaM)1955 sal_Bool TextView::IsInSelection( const TextPaM& rPaM )
1956 {
1957     TextSelection aSel = mpImpl->maSelection;
1958 	aSel.Justify();
1959 
1960 	sal_uLong nStartNode = aSel.GetStart().GetPara();
1961 	sal_uLong nEndNode = aSel.GetEnd().GetPara();
1962 	sal_uLong nCurNode = rPaM.GetPara();
1963 
1964 	if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) )
1965 		return sal_True;
1966 
1967 	if ( nStartNode == nEndNode )
1968 	{
1969 		if ( nCurNode == nStartNode )
1970 			if ( ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
1971 				return sal_True;
1972 	}
1973 	else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) )
1974 		return sal_True;
1975 	else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
1976 		return sal_True;
1977 
1978 	return sal_False;
1979 }
1980 
ImpHideDDCursor()1981 void TextView::ImpHideDDCursor()
1982 {
1983     if ( mpImpl->mpDDInfo && mpImpl->mpDDInfo->mbVisCursor )
1984 	{
1985         mpImpl->mpDDInfo->maCursor.Hide();
1986         mpImpl->mpDDInfo->mbVisCursor = sal_False;
1987 	}
1988 }
1989 
ImpShowDDCursor()1990 void TextView::ImpShowDDCursor()
1991 {
1992     if ( !mpImpl->mpDDInfo->mbVisCursor )
1993 	{
1994         Rectangle aCursor = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpDDInfo->maDropPos, sal_True );
1995 		aCursor.Right()++;
1996 		aCursor.SetPos( GetWindowPos( aCursor.TopLeft() ) );
1997 
1998         mpImpl->mpDDInfo->maCursor.SetWindow( mpImpl->mpWindow );
1999         mpImpl->mpDDInfo->maCursor.SetPos( aCursor.TopLeft() );
2000         mpImpl->mpDDInfo->maCursor.SetSize( aCursor.GetSize() );
2001         mpImpl->mpDDInfo->maCursor.Show();
2002         mpImpl->mpDDInfo->mbVisCursor = sal_True;
2003 	}
2004 }
2005 
SetPaintSelection(sal_Bool bPaint)2006 void TextView::SetPaintSelection( sal_Bool bPaint )
2007 {
2008     if ( bPaint != mpImpl->mbPaintSelection )
2009 	{
2010         mpImpl->mbPaintSelection = bPaint;
2011         ShowSelection( mpImpl->maSelection );
2012 	}
2013 }
2014 
SetHighlightSelection(sal_Bool bSelectByHighlight)2015 void TextView::SetHighlightSelection( sal_Bool bSelectByHighlight )
2016 {
2017     if ( bSelectByHighlight != mpImpl->mbHighlightSelection )
2018 	{
2019 		// Falls umschalten zwischendurch moeglich...
2020         mpImpl->mbHighlightSelection = bSelectByHighlight;
2021 	}
2022 }
2023 
Read(SvStream & rInput)2024 sal_Bool TextView::Read( SvStream& rInput )
2025 {
2026     sal_Bool bDone = mpImpl->mpTextEngine->Read( rInput, &mpImpl->maSelection );
2027 	ShowCursor();
2028 	return bDone;
2029 }
2030 
Write(SvStream & rOutput)2031 sal_Bool TextView::Write( SvStream& rOutput )
2032 {
2033     return mpImpl->mpTextEngine->Read( rOutput, &mpImpl->maSelection );
2034 }
2035 
ImplTruncateNewText(rtl::OUString & rNewText) const2036 bool TextView::ImplTruncateNewText( rtl::OUString& rNewText ) const
2037 {
2038 	bool bTruncated = false;
2039 
2040     if( rNewText.getLength() > 65534 ) // limit to String API
2041     {
2042         rNewText = rNewText.copy( 0, 65534 );
2043         bTruncated = true;
2044     }
2045 
2046     sal_uLong nMaxLen = mpImpl->mpTextEngine->GetMaxTextLen();
2047     // 0 means unlimited, there is just the String API limit handled above
2048     if( nMaxLen != 0 )
2049     {
2050         sal_uLong nCurLen = mpImpl->mpTextEngine->GetTextLen();
2051 
2052         sal_uInt32 nNewLen = rNewText.getLength();
2053         if ( nCurLen + nNewLen > nMaxLen )
2054         {
2055             // see how much text will be replaced
2056             sal_uLong nSelLen = mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
2057             if ( nCurLen + nNewLen - nSelLen > nMaxLen )
2058             {
2059                 sal_uInt32 nTruncatedLen = static_cast<sal_uInt32>(nMaxLen - (nCurLen - nSelLen));
2060                 rNewText = rNewText.copy( 0, nTruncatedLen );
2061                 bTruncated = true;
2062             }
2063         }
2064     }
2065 	return bTruncated;
2066 }
2067 
ImplCheckTextLen(const String & rNewText)2068 sal_Bool TextView::ImplCheckTextLen( const String& rNewText )
2069 {
2070 	sal_Bool bOK = sal_True;
2071     if ( mpImpl->mpTextEngine->GetMaxTextLen() )
2072 	{
2073         sal_uLong n = mpImpl->mpTextEngine->GetTextLen();
2074 		n += rNewText.Len();
2075         if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
2076 		{
2077 			// nur dann noch ermitteln, wie viel Text geloescht wird
2078             n -= mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
2079             if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
2080 			{
2081 				// Beep hat hier eigentlich nichts verloren, sondern lieber ein Hdl,
2082 				// aber so funktioniert es wenigstens in ME, BasicIDE, SourceView
2083 				Sound::Beep();
2084 				bOK = sal_False;
2085 			}
2086 		}
2087 	}
2088 	return bOK;
2089 }
2090 
dragGestureRecognized(const::com::sun::star::datatransfer::dnd::DragGestureEvent & rDGE)2091 void TextView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException)
2092 {
2093     if ( mpImpl->mbClickedInSelection )
2094     {
2095 	    vos::OGuard aVclGuard( Application::GetSolarMutex() );
2096 
2097         DBG_ASSERT( mpImpl->maSelection.HasRange(), "TextView::dragGestureRecognized: mpImpl->mbClickedInSelection, but no selection?" );
2098 
2099         delete mpImpl->mpDDInfo;
2100         mpImpl->mpDDInfo = new TextDDInfo;
2101         mpImpl->mpDDInfo->mbStarterOfDD = sal_True;
2102 
2103 	    TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
2104 
2105         if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) )  // Dann auch als HTML
2106             mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True );
2107 
2108 
2109         /*
2110 	    // D&D eines Hyperlinks.
2111 	    // Besser waere es im MBDown sich den MBDownPaM zu merken,
2112 	    // ist dann aber inkompatibel => spaeter mal umstellen.
2113         TextPaM aPaM( mpImpl->mpTextEngine->GetPaM( GetDocPos( GetWindow()->GetPointerPosPixel() ) ) );
2114         const TextCharAttrib* pAttr = mpImpl->mpTextEngine->FindCharAttrib( aPaM, TEXTATTR_HYPERLINK );
2115 	    if ( pAttr )
2116 	    {
2117 		    aSel = aPaM;
2118 		    aSel.GetStart().GetIndex() = pAttr->GetStart();
2119 		    aSel.GetEnd().GetIndex() = pAttr->GetEnd();
2120 
2121 		    const TextAttribHyperLink& rLink = (const TextAttribHyperLink&)pAttr->GetAttr();
2122 		    String aText( rLink.GetDescription() );
2123 		    if ( !aText.Len() )
2124                 aText = mpImpl->mpTextEngine->GetText( aSel );
2125 		    INetBookmark aBookmark( rLink.GetURL(), aText );
2126 		    aBookmark.CopyDragServer();
2127 	    }
2128         */
2129 
2130         mpImpl->mpCursor->Hide();
2131 
2132         sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY;
2133         if ( !IsReadOnly() )
2134             nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE;
2135         rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mpImpl->mxDnDListener );
2136     }
2137 }
2138 
dragDropEnd(const::com::sun::star::datatransfer::dnd::DragSourceDropEvent &)2139 void TextView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& ) throw (::com::sun::star::uno::RuntimeException)
2140 {
2141     ImpHideDDCursor();
2142     delete mpImpl->mpDDInfo;
2143     mpImpl->mpDDInfo = NULL;
2144 }
2145 
drop(const::com::sun::star::datatransfer::dnd::DropTargetDropEvent & rDTDE)2146 void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
2147 {
2148 	vos::OGuard aVclGuard( Application::GetSolarMutex() );
2149 
2150 	sal_Bool bChanges = sal_False;
2151     if ( !mpImpl->mbReadOnly && mpImpl->mpDDInfo )
2152 	{
2153 		ImpHideDDCursor();
2154 
2155 		// Daten fuer das loeschen nach einem DROP_MOVE:
2156         TextSelection aPrevSel( mpImpl->maSelection );
2157 		aPrevSel.Justify();
2158         sal_uLong nPrevParaCount = mpImpl->mpTextEngine->GetParagraphCount();
2159         sal_uInt16 nPrevStartParaLen = mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() );
2160 
2161 		sal_Bool bStarterOfDD = sal_False;
2162         for ( sal_uInt16 nView = mpImpl->mpTextEngine->GetViewCount(); nView && !bStarterOfDD; )
2163             bStarterOfDD = mpImpl->mpTextEngine->GetView( --nView )->mpImpl->mpDDInfo ? mpImpl->mpTextEngine->GetView( nView )->mpImpl->mpDDInfo->mbStarterOfDD : sal_False;
2164 
2165 		HideSelection();
2166         ImpSetSelection( mpImpl->mpDDInfo->maDropPos );
2167 
2168         mpImpl->mpTextEngine->UndoActionStart();
2169 
2170 		String aText;
2171 		uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
2172 		if ( xDataObj.is() )
2173 		{
2174 		    datatransfer::DataFlavor aFlavor;
2175 		    SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
2176 		    if ( xDataObj->isDataFlavorSupported( aFlavor ) )
2177 		    {
2178 			    uno::Any aData = xDataObj->getTransferData( aFlavor );
2179 			    ::rtl::OUString aOUString;
2180 			    aData >>= aOUString;
2181                 aText = aOUString;
2182 		        aText.ConvertLineEnd( LINEEND_LF );
2183 		    }
2184         }
2185 
2186 		if ( aText.Len() && ( aText.GetChar( aText.Len()-1 ) == LINE_SEP ) )
2187 			aText.Erase( aText.Len()-1 );
2188 
2189 		TextPaM aTempStart = mpImpl->maSelection.GetStart();
2190         if ( ImplCheckTextLen( aText ) )
2191             ImpSetSelection( mpImpl->mpTextEngine->ImpInsertText( mpImpl->mpDDInfo->maDropPos, aText ) );
2192         if(mpImpl->mbSupportProtectAttribute)
2193         {
2194             mpImpl->mpTextEngine->SetAttrib( TextAttribProtect(),
2195                 aTempStart.GetPara(),
2196                 aTempStart.GetIndex(),
2197                 mpImpl->maSelection.GetEnd().GetIndex(), sal_False );
2198         }
2199 
2200         if ( aPrevSel.HasRange() &&
2201                 !mpImpl->mbSupportProtectAttribute && // don't remove currently selected element
2202                 (( rDTDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) || !bStarterOfDD) )
2203 		{
2204 			// ggf. Selection anpasssen:
2205             if ( ( mpImpl->mpDDInfo->maDropPos.GetPara() < aPrevSel.GetStart().GetPara() ) ||
2206                  ( ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
2207                         && ( mpImpl->mpDDInfo->maDropPos.GetIndex() < aPrevSel.GetStart().GetIndex() ) ) )
2208 			{
2209 				sal_uLong nNewParasBeforeSelection =
2210                     mpImpl->mpTextEngine->GetParagraphCount() -    nPrevParaCount;
2211 
2212 				aPrevSel.GetStart().GetPara() += nNewParasBeforeSelection;
2213 				aPrevSel.GetEnd().GetPara() += nNewParasBeforeSelection;
2214 
2215                 if ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
2216 				{
2217 					sal_uInt16 nNewChars =
2218                         mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ) - nPrevStartParaLen;
2219 
2220 					aPrevSel.GetStart().GetIndex() =
2221                         aPrevSel.GetStart().GetIndex() + nNewChars;
2222 					if ( aPrevSel.GetStart().GetPara() == aPrevSel.GetEnd().GetPara() )
2223 						aPrevSel.GetEnd().GetIndex() =
2224                             aPrevSel.GetEnd().GetIndex() + nNewChars;
2225 				}
2226 			}
2227 			else
2228 			{
2229 				// aktuelle Selektion anpassen
2230                 TextPaM aPaM = mpImpl->maSelection.GetStart();
2231 				aPaM.GetPara() -= ( aPrevSel.GetEnd().GetPara() - aPrevSel.GetStart().GetPara() );
2232                 if ( aPrevSel.GetEnd().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
2233 				{
2234 					aPaM.GetIndex() =
2235                         aPaM.GetIndex() - aPrevSel.GetEnd().GetIndex();
2236                     if ( aPrevSel.GetStart().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
2237 						aPaM.GetIndex() =
2238                             aPaM.GetIndex() + aPrevSel.GetStart().GetIndex();
2239 				}
2240 				ImpSetSelection( aPaM );
2241 
2242 			}
2243             mpImpl->mpTextEngine->ImpDeleteText( aPrevSel );
2244 		}
2245 
2246         mpImpl->mpTextEngine->UndoActionEnd();
2247 
2248         delete mpImpl->mpDDInfo;
2249         mpImpl->mpDDInfo = 0;
2250 
2251         mpImpl->mpTextEngine->FormatAndUpdate( this );
2252 
2253         mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
2254     }
2255     rDTDE.Context->dropComplete( bChanges );
2256 }
2257 
dragEnter(const::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent &)2258 void TextView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& ) throw (::com::sun::star::uno::RuntimeException)
2259 {
2260 }
2261 
dragExit(const::com::sun::star::datatransfer::dnd::DropTargetEvent &)2262 void TextView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException)
2263 {
2264 	vos::OGuard aVclGuard( Application::GetSolarMutex() );
2265     ImpHideDDCursor();
2266 }
2267 
dragOver(const::com::sun::star::datatransfer::dnd::DropTargetDragEvent & rDTDE)2268 void TextView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
2269 {
2270 	vos::OGuard aVclGuard( Application::GetSolarMutex() );
2271 
2272     if ( !mpImpl->mpDDInfo )
2273         mpImpl->mpDDInfo = new TextDDInfo;
2274 
2275     TextPaM aPrevDropPos = mpImpl->mpDDInfo->maDropPos;
2276 	Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
2277 	Point aDocPos = GetDocPos( aMousePos );
2278     mpImpl->mpDDInfo->maDropPos = mpImpl->mpTextEngine->GetPaM( aDocPos );
2279 
2280 /*
2281     Size aOutSize = mpImpl->mpWindow->GetOutputSizePixel();
2282 	if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) ||
2283 		 ( aMousePos.Y() < 0 ) || ( aMousePos.Y() > aOutSize.Height() ) )
2284 	{
2285 		// Scroll?
2286 		// No, I will not receive events for this...
2287 	}
2288 */
2289 
2290     sal_Bool bProtected = sal_False;
2291     if(mpImpl->mbSupportProtectAttribute)
2292     {
2293         const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
2294                     mpImpl->mpDDInfo->maDropPos,
2295                     TEXTATTR_PROTECTED );
2296         bProtected = pStartAttr != 0 &&
2297                 pStartAttr->GetStart() != mpImpl->mpDDInfo->maDropPos.GetIndex() &&
2298                 pStartAttr->GetEnd() != mpImpl->mpDDInfo->maDropPos.GetIndex();
2299     }
2300     // Don't drop in selection or in read only engine
2301     if ( IsReadOnly() || IsInSelection( mpImpl->mpDDInfo->maDropPos ) || bProtected)
2302 	{
2303 		ImpHideDDCursor();
2304         rDTDE.Context->rejectDrag();
2305 	}
2306     else
2307     {
2308 	    // Alten Cursor wegzeichnen...
2309         if ( !mpImpl->mpDDInfo->mbVisCursor || ( aPrevDropPos != mpImpl->mpDDInfo->maDropPos ) )
2310 	    {
2311 		    ImpHideDDCursor();
2312 		    ImpShowDDCursor();
2313 	    }
2314         rDTDE.Context->acceptDrag( rDTDE.DropAction );
2315     }
2316 }
2317 
ImpGetOutputStartPos(const Point & rStartDocPos) const2318 Point TextView::ImpGetOutputStartPos( const Point& rStartDocPos ) const
2319 {
2320 	Point aStartPos( -rStartDocPos.X(), -rStartDocPos.Y() );
2321     if ( mpImpl->mpTextEngine->IsRightToLeft() )
2322     {
2323         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2324 		aStartPos.X() = rStartDocPos.X() + aSz.Width() - 1; // -1: Start is 0
2325     }
2326     return aStartPos;
2327 }
2328 
GetDocPos(const Point & rWindowPos) const2329 Point TextView::GetDocPos( const Point& rWindowPos ) const
2330 {
2331 	// Fensterposition => Dokumentposition
2332 
2333 	Point aPoint;
2334 
2335     aPoint.Y() = rWindowPos.Y() + mpImpl->maStartDocPos.Y();
2336 
2337     if ( !mpImpl->mpTextEngine->IsRightToLeft() )
2338     {
2339         aPoint.X() = rWindowPos.X() + mpImpl->maStartDocPos.X();
2340     }
2341     else
2342     {
2343         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2344         aPoint.X() = ( aSz.Width() - 1 ) - rWindowPos.X() + mpImpl->maStartDocPos.X();
2345     }
2346 
2347 	return aPoint;
2348 }
2349 
GetWindowPos(const Point & rDocPos) const2350 Point TextView::GetWindowPos( const Point& rDocPos ) const
2351 {
2352 	// Dokumentposition => Fensterposition
2353 
2354 	Point aPoint;
2355 
2356     aPoint.Y() = rDocPos.Y() - mpImpl->maStartDocPos.Y();
2357 
2358     if ( !mpImpl->mpTextEngine->IsRightToLeft() )
2359     {
2360         aPoint.X() = rDocPos.X() - mpImpl->maStartDocPos.X();
2361     }
2362     else
2363     {
2364         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2365         aPoint.X() = ( aSz.Width() - 1 ) - ( rDocPos.X() - mpImpl->maStartDocPos.X() );
2366     }
2367 
2368 	return aPoint;
2369 }
2370 
GetLineNumberOfCursorInSelection() const2371 sal_Int32 TextView::GetLineNumberOfCursorInSelection() const
2372 {
2373  // PROGRESS
2374     sal_Int32 nLineNo = -1;
2375     if( mpImpl->mbCursorEnabled )
2376     {
2377         TextPaM aPaM = GetSelection().GetEnd();
2378         TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
2379         nLineNo = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
2380         if( mpImpl->mbCursorAtEndOfLine )
2381             --nLineNo;
2382     }
2383     return nLineNo;
2384 }
2385 
2386 
2387 // -------------------------------------------------------------------------
2388 // (+) class TextSelFunctionSet
2389 // -------------------------------------------------------------------------
TextSelFunctionSet(TextView * pView)2390 TextSelFunctionSet::TextSelFunctionSet( TextView* pView )
2391 {
2392 	mpView = pView;
2393 }
2394 
BeginDrag()2395 void __EXPORT TextSelFunctionSet::BeginDrag()
2396 {
2397 }
2398 
CreateAnchor()2399 void __EXPORT TextSelFunctionSet::CreateAnchor()
2400 {
2401 //	TextSelection aSel( mpView->GetSelection() );
2402 //	aSel.GetStart() = aSel.GetEnd();
2403 //	mpView->SetSelection( aSel );
2404 
2405 	// Es darf kein ShowCursor folgen:
2406 	mpView->HideSelection();
2407     mpView->ImpSetSelection( mpView->mpImpl->maSelection.GetEnd() );
2408 }
2409 
SetCursorAtPoint(const Point & rPointPixel,sal_Bool)2410 sal_Bool __EXPORT TextSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool )
2411 {
2412 	return mpView->SetCursorAtPoint( rPointPixel );
2413 }
2414 
IsSelectionAtPoint(const Point & rPointPixel)2415 sal_Bool __EXPORT TextSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
2416 {
2417 	return mpView->IsSelectionAtPoint( rPointPixel );
2418 }
2419 
DeselectAll()2420 void __EXPORT TextSelFunctionSet::DeselectAll()
2421 {
2422 	CreateAnchor();
2423 }
2424 
DeselectAtPoint(const Point &)2425 void __EXPORT TextSelFunctionSet::DeselectAtPoint( const Point& )
2426 {
2427 	// Nur bei Mehrfachselektion
2428 }
2429 
DestroyAnchor()2430 void __EXPORT TextSelFunctionSet::DestroyAnchor()
2431 {
2432 	// Nur bei Mehrfachselektion
2433 }
GetTextEngine() const2434 TextEngine*         TextView::GetTextEngine() const
2435 { return mpImpl->mpTextEngine; }
GetWindow() const2436 Window*             TextView::GetWindow() const
2437 { return mpImpl->mpWindow; }
EnableCursor(sal_Bool bEnable)2438 void                TextView::EnableCursor( sal_Bool bEnable )
2439 { mpImpl->mbCursorEnabled = bEnable; }
IsCursorEnabled() const2440 sal_Bool                TextView::IsCursorEnabled() const
2441 { return mpImpl->mbCursorEnabled; }
SetStartDocPos(const Point & rPos)2442 void                TextView::SetStartDocPos( const Point& rPos )
2443 { mpImpl->maStartDocPos = rPos; }
GetStartDocPos() const2444 const Point&        TextView::GetStartDocPos() const
2445 { return mpImpl->maStartDocPos; }
SetAutoIndentMode(sal_Bool bAutoIndent)2446 void                TextView::SetAutoIndentMode( sal_Bool bAutoIndent )
2447 { mpImpl->mbAutoIndent = bAutoIndent; }
IsAutoIndentMode() const2448 sal_Bool                TextView::IsAutoIndentMode() const
2449 { return mpImpl->mbAutoIndent; }
IsReadOnly() const2450 sal_Bool                TextView::IsReadOnly() const
2451 { return mpImpl->mbReadOnly; }
SetAutoScroll(sal_Bool bAutoScroll)2452 void                TextView::SetAutoScroll( sal_Bool bAutoScroll )
2453 { mpImpl->mbAutoScroll = bAutoScroll; }
IsAutoScroll() const2454 sal_Bool                TextView::IsAutoScroll() const
2455 { return mpImpl->mbAutoScroll; }
IsPaintSelection() const2456 sal_Bool                TextView::IsPaintSelection() const
2457 { return mpImpl->mbPaintSelection; }
IsHighlightSelection() const2458 sal_Bool                TextView::IsHighlightSelection() const
2459 { return mpImpl->mbHighlightSelection; }
HasSelection() const2460 sal_Bool                TextView::HasSelection() const
2461 { return mpImpl->maSelection.HasRange(); }
IsInsertMode() const2462 sal_Bool                TextView::IsInsertMode() const
2463 { return mpImpl->mbInsertMode; }
SupportProtectAttribute(sal_Bool bSupport)2464 void                TextView::SupportProtectAttribute(sal_Bool bSupport)
2465 { mpImpl->mbSupportProtectAttribute = bSupport;}
2466 
2467