xref: /trunk/main/svtools/source/edit/textview.cxx (revision af7a586e)
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             if ( nWidth == 0 ) {
1052                 Rectangle aR3 = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpTextEngine->mpIMEInfos->aPos );
1053                 nWidth = -(aR1.Left() - aR3.Left());
1054             }
1055 			GetWindow()->SetCursorRect( &aR1, nWidth );
1056 		}
1057 		else
1058 		{
1059 			GetWindow()->SetCursorRect();
1060 		}
1061 	}
1062 	else
1063 	{
1064         mpImpl->mpSelEngine->Command( rCEvt );
1065 	}
1066 }
1067 
ShowCursor(sal_Bool bGotoCursor,sal_Bool bForceVisCursor)1068 void TextView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor )
1069 {
1070 	// Die Einstellung hat mehr Gewicht:
1071     if ( !mpImpl->mbAutoScroll )
1072 		bGotoCursor = sal_False;
1073 	ImpShowCursor( bGotoCursor, bForceVisCursor, sal_False );
1074 }
1075 
HideCursor()1076 void TextView::HideCursor()
1077 {
1078     mpImpl->mpCursor->Hide();
1079 }
1080 
Scroll(long ndX,long ndY)1081 void TextView::Scroll( long ndX, long ndY )
1082 {
1083     DBG_ASSERT( mpImpl->mpTextEngine->IsFormatted(), "Scroll: Nicht formatiert!" );
1084 
1085 	if ( !ndX && !ndY )
1086 		return;
1087 
1088     Point aNewStartPos( mpImpl->maStartDocPos );
1089 
1090 	// Vertical:
1091 	aNewStartPos.Y() -= ndY;
1092 	if ( aNewStartPos.Y() < 0 )
1093 		aNewStartPos.Y() = 0;
1094 
1095 	// Horizontal:
1096 	aNewStartPos.X() -= ndX;
1097 	if ( aNewStartPos.X() < 0 )
1098 		aNewStartPos.X() = 0;
1099 
1100     long nDiffX = mpImpl->maStartDocPos.X() - aNewStartPos.X();
1101     long nDiffY = mpImpl->maStartDocPos.Y() - aNewStartPos.Y();
1102 
1103 	if ( nDiffX || nDiffY )
1104 	{
1105         sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible();
1106         mpImpl->mpCursor->Hide();
1107         mpImpl->mpWindow->Update();
1108         mpImpl->maStartDocPos = aNewStartPos;
1109 
1110         if ( mpImpl->mpTextEngine->IsRightToLeft() )
1111             nDiffX = -nDiffX;
1112         mpImpl->mpWindow->Scroll( nDiffX, nDiffY );
1113         mpImpl->mpWindow->Update();
1114         mpImpl->mpCursor->SetPos( mpImpl->mpCursor->GetPos() + Point( nDiffX, nDiffY ) );
1115         if ( bVisCursor && !mpImpl->mbReadOnly )
1116             mpImpl->mpCursor->Show();
1117 	}
1118 
1119     mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSCROLLED ) );
1120 }
1121 
Undo()1122 void TextView::Undo()
1123 {
1124     mpImpl->mpTextEngine->SetActiveView( this );
1125     mpImpl->mpTextEngine->GetUndoManager().Undo();
1126 }
1127 
Redo()1128 void TextView::Redo()
1129 {
1130     mpImpl->mpTextEngine->SetActiveView( this );
1131     mpImpl->mpTextEngine->GetUndoManager().Redo();
1132 }
1133 
Cut()1134 void TextView::Cut()
1135 {
1136     mpImpl->mpTextEngine->UndoActionStart();
1137 	Copy();
1138 	DeleteSelected();
1139     mpImpl->mpTextEngine->UndoActionEnd();
1140 }
1141 
Copy(uno::Reference<datatransfer::clipboard::XClipboard> & rxClipboard)1142 void TextView::Copy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1143 {
1144 	if ( rxClipboard.is() )
1145 	{
1146 		TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
1147 
1148         if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) )  // Dann auch als HTML
1149             mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True );
1150 
1151 		const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1152 
1153         try
1154 		{
1155 		    rxClipboard->setContents( pDataObj, NULL );
1156 
1157             uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
1158 		    if( xFlushableClipboard.is() )
1159 			    xFlushableClipboard->flushClipboard();
1160 		}
1161 		catch( const ::com::sun::star::uno::Exception& )
1162 		{
1163 		}
1164 
1165 		Application::AcquireSolarMutex( nRef );
1166 	}
1167 }
1168 
Copy()1169 void TextView::Copy()
1170 {
1171     uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
1172     Copy( aClipboard );
1173 }
1174 
Paste(uno::Reference<datatransfer::clipboard::XClipboard> & rxClipboard)1175 void TextView::Paste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1176 {
1177 	if ( rxClipboard.is() )
1178 	{
1179         uno::Reference< datatransfer::XTransferable > xDataObj;
1180 
1181         const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1182 
1183         try
1184 		{
1185 		    xDataObj = rxClipboard->getContents();
1186 		}
1187 		catch( const ::com::sun::star::uno::Exception& )
1188 		{
1189 		}
1190 
1191         Application::AcquireSolarMutex( nRef );
1192 
1193         if ( xDataObj.is() )
1194 		{
1195 			datatransfer::DataFlavor aFlavor;
1196 			SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
1197 			if ( xDataObj->isDataFlavorSupported( aFlavor ) )
1198 			{
1199                 try
1200                 {
1201                     uno::Any aData = xDataObj->getTransferData( aFlavor );
1202                     ::rtl::OUString aText;
1203                     aData >>= aText;
1204                     bool bWasTruncated = false;
1205                     if( mpImpl->mpTextEngine->GetMaxTextLen() != 0 )
1206                         bWasTruncated = ImplTruncateNewText( aText );
1207                     InsertNewText( aText, sal_False );
1208                     mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
1209 
1210                     if( bWasTruncated )
1211                         Edit::ShowTruncationWarning( mpImpl->mpWindow );
1212                 }
1213                 catch( const ::com::sun::star::datatransfer::UnsupportedFlavorException& )
1214                 {
1215                 }
1216 			}
1217 		}
1218 	}
1219 }
1220 
Paste()1221 void TextView::Paste()
1222 {
1223     uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
1224     Paste( aClipboard );
1225 }
1226 
GetSelected()1227 String TextView::GetSelected()
1228 {
1229     return GetSelected( GetSystemLineEnd() );
1230 }
1231 
GetSelected(LineEnd aSeparator)1232 String TextView::GetSelected( LineEnd aSeparator )
1233 {
1234     return mpImpl->mpTextEngine->GetText( mpImpl->maSelection, aSeparator );
1235 }
1236 
SetInsertMode(sal_Bool bInsert)1237 void TextView::SetInsertMode( sal_Bool bInsert )
1238 {
1239     if ( mpImpl->mbInsertMode != bInsert )
1240 	{
1241         mpImpl->mbInsertMode = bInsert;
1242         ShowCursor( mpImpl->mbAutoScroll, sal_False );
1243 	}
1244 }
1245 
SetReadOnly(sal_Bool bReadOnly)1246 void TextView::SetReadOnly( sal_Bool bReadOnly )
1247 {
1248     if ( mpImpl->mbReadOnly != bReadOnly )
1249 	{
1250         mpImpl->mbReadOnly = bReadOnly;
1251         if ( !mpImpl->mbReadOnly )
1252             ShowCursor( mpImpl->mbAutoScroll, sal_False );
1253 		else
1254 			HideCursor();
1255 
1256         GetWindow()->SetInputContext( InputContext( mpImpl->mpTextEngine->GetFont(), bReadOnly ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) );
1257 	}
1258 }
1259 
ImpMoveCursor(const KeyEvent & rKeyEvent)1260 TextSelection TextView::ImpMoveCursor( const KeyEvent& rKeyEvent )
1261 {
1262 	// Eigentlich nur bei Up/Down noetig, aber was solls.
1263     mpImpl->mpTextEngine->CheckIdleFormatter();
1264 
1265     TextPaM aPaM( mpImpl->maSelection.GetEnd() );
1266 	TextPaM aOldEnd( aPaM );
1267 
1268     TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom;
1269     if ( mpImpl->mpTextEngine->IsRightToLeft() )
1270         eTextDirection = TextDirectionality_RightToLeft_TopToBottom;
1271 
1272     KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection );
1273 
1274     sal_Bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? sal_True : sal_False;
1275 	sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode();
1276 
1277     bool bSelect = aTranslatedKeyEvent.GetKeyCode().IsShift();
1278 	switch ( nCode )
1279 	{
1280 		case KEY_UP:		aPaM = CursorUp( aPaM );
1281 							break;
1282 		case KEY_DOWN:		aPaM = CursorDown( aPaM );
1283 							break;
1284 		case KEY_HOME:		aPaM = bCtrl ? CursorStartOfDoc() : CursorStartOfLine( aPaM );
1285 							break;
1286 		case KEY_END:		aPaM = bCtrl ? CursorEndOfDoc() : CursorEndOfLine( aPaM );
1287 							break;
1288 		case KEY_PAGEUP:	aPaM = bCtrl ? CursorStartOfDoc() : PageUp( aPaM );
1289 							break;
1290 		case KEY_PAGEDOWN:	aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM );
1291 							break;
1292 		case KEY_LEFT:		aPaM = bCtrl ? CursorWordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1293 							break;
1294 		case KEY_RIGHT: 	aPaM = bCtrl ? CursorWordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1295 							break;
1296         case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
1297                             bSelect = true; // fallthrough intentional
1298         case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
1299                             aPaM = CursorWordRight( aPaM );
1300                             break;
1301         case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
1302                             bSelect = true; // fallthrough intentional
1303         case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
1304                             aPaM = CursorWordLeft( aPaM );
1305                             break;
1306         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1307                             bSelect = true; // fallthrough intentional
1308         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1309                             aPaM = CursorStartOfLine( aPaM );
1310                             break;
1311         case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
1312                             bSelect = true; // fallthrough intentional
1313         case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
1314                             aPaM = CursorEndOfLine( aPaM );
1315                             break;
1316         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1317                             bSelect = true; // falltthrough intentional
1318         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1319                             aPaM = CursorStartOfParagraph( aPaM );
1320                             break;
1321         case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1322                             bSelect = true; // falltthrough intentional
1323         case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1324                             aPaM = CursorEndOfParagraph( aPaM );
1325                             break;
1326         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1327                             bSelect = true; // falltthrough intentional
1328         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1329                             aPaM = CursorStartOfDoc();
1330                             break;
1331         case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1332                             bSelect = true; // falltthrough intentional
1333         case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1334                             aPaM = CursorEndOfDoc();
1335                             break;
1336 	}
1337 
1338 	// Bewirkt evtl. ein CreateAnchor oder Deselection all
1339     mpImpl->mpSelEngine->CursorPosChanging( bSelect, aTranslatedKeyEvent.GetKeyCode().IsMod1() );
1340 
1341 	if ( aOldEnd != aPaM )
1342 	{
1343         mpImpl->mpTextEngine->CursorMoved( aOldEnd.GetPara() );
1344 
1345 
1346         TextSelection aOldSelection( mpImpl->maSelection );
1347         TextSelection aNewSelection( mpImpl->maSelection );
1348 		aNewSelection.GetEnd() = aPaM;
1349 		if ( bSelect )
1350 		{
1351 			// Dann wird die Selektion erweitert...
1352             ImpSetSelection( aNewSelection );
1353 			ShowSelection( TextSelection( aOldEnd, aPaM ) );
1354 		}
1355 		else
1356 		{
1357 			aNewSelection.GetStart() = aPaM;
1358             ImpSetSelection( aNewSelection );
1359 		}
1360 	}
1361 
1362     return mpImpl->maSelection;
1363 }
1364 
InsertText(const XubString & rStr,sal_Bool bSelect)1365 void TextView::InsertText( const XubString& rStr, sal_Bool bSelect )
1366 {
1367     InsertNewText( rStr, bSelect );
1368 }
1369 
InsertNewText(const rtl::OUString & rStr,sal_Bool bSelect)1370 void TextView::InsertNewText( const rtl::OUString& rStr, sal_Bool bSelect )
1371 {
1372 //	HideSelection();
1373     mpImpl->mpTextEngine->UndoActionStart();
1374 
1375     /* #i87633#
1376     break inserted text into chunks that fit into the underlying String
1377     based API (which has a maximum length of 65534 elements
1378 
1379     note: this will of course still cause problems for lines longer than those
1380     65534 elements, but those cases will hopefully be few.
1381     In the long run someone should switch the TextEngine to OUString instead of String
1382     */
1383     sal_Int32 nLen = rStr.getLength();
1384     sal_Int32 nPos = 0;
1385     do
1386     {
1387         sal_Int32 nChunkLen = nLen > 65534 ? 65534 : nLen;
1388         String aChunk( rStr.copy( nPos, nChunkLen ) );
1389 
1390         TextSelection aNewSel( mpImpl->maSelection );
1391 
1392         TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, aChunk );
1393 
1394         if ( bSelect )
1395         {
1396             aNewSel.Justify();
1397             aNewSel.GetEnd() = aPaM;
1398         }
1399         else
1400         {
1401             aNewSel = aPaM;
1402         }
1403 
1404         ImpSetSelection( aNewSel );
1405         nLen -= nChunkLen;
1406         nPos += nChunkLen;
1407     } while( nLen );
1408     mpImpl->mpTextEngine->UndoActionEnd();
1409 
1410     mpImpl->mpTextEngine->FormatAndUpdate( this );
1411 }
1412 
1413 /*
1414 void TextView::InsertText( const XubString& rStr, sal_Bool bSelect )
1415 {
1416 //	HideSelection();
1417 
1418     TextSelection aNewSel( mpImpl->maSelection );
1419 
1420     mpImpl->mpTextEngine->UndoActionStart();
1421     TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, rStr );
1422     mpImpl->mpTextEngine->UndoActionEnd();
1423 
1424 	if ( bSelect )
1425 	{
1426 		aNewSel.Justify();
1427 		aNewSel.GetEnd() = aPaM;
1428 	}
1429 	else
1430     {
1431 		aNewSel = aPaM;
1432     }
1433 
1434     ImpSetSelection( aNewSel );
1435 
1436     mpImpl->mpTextEngine->FormatAndUpdate( this );
1437 }
1438 */
1439 
1440 // OLD
CursorLeft(const TextPaM & rPaM,sal_Bool bWordMode)1441 TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_Bool bWordMode )
1442 {
1443     return bWordMode ? CursorWordLeft( rPaM ) : CursorLeft( rPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1444 
1445     // Remove (sal_uInt16) typecasts in this file when removing this method!
1446 }
1447 
1448 // OLD
CursorRight(const TextPaM & rPaM,sal_Bool bWordMode)1449 TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_Bool bWordMode )
1450 {
1451     return bWordMode ? CursorWordRight( rPaM ) : CursorRight( rPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1452 
1453     // Remove (sal_uInt16) typecasts in this file when removing this method!
1454 }
1455 
CursorLeft(const TextPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1456 TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1457 {
1458 	TextPaM aPaM( rPaM );
1459 
1460 	if ( aPaM.GetIndex() )
1461 	{
1462         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1463         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1464 		sal_Int32 nCount = 1;
1465         aPaM.GetIndex() = (sal_uInt16)xBI->previousCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
1466 	}
1467 	else if ( aPaM.GetPara() )
1468 	{
1469 		aPaM.GetPara()--;
1470         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1471 		aPaM.GetIndex() = pNode->GetText().Len();
1472 	}
1473 	return aPaM;
1474 }
1475 
CursorRight(const TextPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1476 TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1477 {
1478 	TextPaM aPaM( rPaM );
1479 
1480     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1481 	if ( aPaM.GetIndex() < pNode->GetText().Len() )
1482 	{
1483         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1484 		sal_Int32 nCount = 1;
1485         aPaM.GetIndex() = (sal_uInt16)xBI->nextCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
1486 	}
1487     else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
1488 	{
1489 		aPaM.GetPara()++;
1490 		aPaM.GetIndex() = 0;
1491 	}
1492 
1493 	return aPaM;
1494 }
1495 
1496 
CursorWordLeft(const TextPaM & rPaM)1497 TextPaM TextView::CursorWordLeft( const TextPaM& rPaM )
1498 {
1499 	TextPaM aPaM( rPaM );
1500 
1501 	if ( aPaM.GetIndex() )
1502 	{
1503         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1504         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1505         i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1506 		if ( aBoundary.startPos >= rPaM.GetIndex() )
1507             aBoundary = xBI->previousWord( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1508 		aPaM.GetIndex() = ( aBoundary.startPos != -1 ) ? (sal_uInt16)aBoundary.startPos : 0;
1509 	}
1510 	else if ( aPaM.GetPara() )
1511 	{
1512 		aPaM.GetPara()--;
1513         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1514 		aPaM.GetIndex() = pNode->GetText().Len();
1515 	}
1516 	return aPaM;
1517 }
1518 
1519 
CursorWordRight(const TextPaM & rPaM)1520 TextPaM TextView::CursorWordRight( const TextPaM& rPaM )
1521 {
1522 	TextPaM aPaM( rPaM );
1523 
1524     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1525 	if ( aPaM.GetIndex() < pNode->GetText().Len() )
1526 	{
1527         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1528         i18n::Boundary aBoundary = xBI->nextWord(  pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1529 		aPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
1530 	}
1531     else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
1532 	{
1533 		aPaM.GetPara()++;
1534 		aPaM.GetIndex() = 0;
1535 	}
1536 
1537 	return aPaM;
1538 }
1539 
ImpDelete(sal_uInt8 nMode,sal_uInt8 nDelMode)1540 TextPaM TextView::ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode )
1541 {
1542     if ( mpImpl->maSelection.HasRange() )  // dann nur Sel. loeschen
1543         return mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
1544 
1545     TextPaM aStartPaM = mpImpl->maSelection.GetStart();
1546 	TextPaM aEndPaM = aStartPaM;
1547 	if ( nMode == DEL_LEFT )
1548 	{
1549 		if ( nDelMode == DELMODE_SIMPLE )
1550 		{
1551 			aEndPaM = CursorLeft( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER );
1552 		}
1553 		else if ( nDelMode == DELMODE_RESTOFWORD )
1554 		{
1555             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject(  aEndPaM.GetPara() );
1556             uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1557             i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1558             if ( aBoundary.startPos == mpImpl->maSelection.GetEnd().GetIndex() )
1559                 aBoundary = xBI->previousWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1560 			// #i63506# startPos is -1 when the paragraph starts with a tab
1561 			aEndPaM.GetIndex() = (aBoundary.startPos >= 0) ? (sal_uInt16)aBoundary.startPos : 0;
1562 		}
1563 		else	// DELMODE_RESTOFCONTENT
1564 		{
1565 			if ( aEndPaM.GetIndex() != 0 )
1566 				aEndPaM.GetIndex() = 0;
1567 			else if ( aEndPaM.GetPara() )
1568 			{
1569 				// Absatz davor
1570 				aEndPaM.GetPara()--;
1571 				aEndPaM.GetIndex() = 0;
1572 			}
1573 		}
1574 	}
1575 	else
1576 	{
1577 		if ( nDelMode == DELMODE_SIMPLE )
1578 		{
1579 			aEndPaM = CursorRight( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1580 		}
1581 		else if ( nDelMode == DELMODE_RESTOFWORD )
1582 		{
1583             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject(  aEndPaM.GetPara() );
1584             uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1585             i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1586 			aEndPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
1587 		}
1588 		else	// DELMODE_RESTOFCONTENT
1589 		{
1590             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1591 			if ( aEndPaM.GetIndex() < pNode->GetText().Len() )
1592 				aEndPaM.GetIndex() = pNode->GetText().Len();
1593             else if ( aEndPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) )
1594 			{
1595 				// Absatz danach
1596 				aEndPaM.GetPara()++;
1597                 TextNode* pNextNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1598 				aEndPaM.GetIndex() = pNextNode->GetText().Len();
1599 			}
1600 		}
1601 	}
1602 
1603     return mpImpl->mpTextEngine->ImpDeleteText( TextSelection( aStartPaM, aEndPaM ) );
1604 }
1605 
1606 
1607 
CursorUp(const TextPaM & rPaM)1608 TextPaM TextView::CursorUp( const TextPaM& rPaM )
1609 {
1610 	TextPaM aPaM( rPaM );
1611 
1612 	long nX;
1613     if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
1614 	{
1615         nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left();
1616         mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
1617 	}
1618 	else
1619         nX = mpImpl->mnTravelXPos;
1620 
1621     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1622 	sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False );
1623 	if ( nLine )	// gleicher Absatz
1624 	{
1625         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine-1, nX );
1626 		aPaM.GetIndex() = nCharPos;
1627 		// Wenn davor eine autom.Umgebrochene Zeile, und ich muss genau an das
1628 		// Ende dieser Zeile, landet der Cursor in der aktuellen Zeile am Anfang
1629 		// Siehe Problem: Letztes Zeichen einer autom.umgebr. Zeile = Cursor
1630 		TextLine* pLine = pPPortion->GetLines().GetObject( nLine - 1 );
1631 		if ( aPaM.GetIndex() && ( aPaM.GetIndex() == pLine->GetEnd() ) )
1632 			aPaM.GetIndex()--;
1633 	}
1634 	else if ( rPaM.GetPara() )	// vorheriger Absatz
1635 	{
1636 		aPaM.GetPara()--;
1637         pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1638 		sal_uInt16 nL = pPPortion->GetLines().Count() - 1;
1639         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), nL, nX+1 );
1640 		aPaM.GetIndex() = nCharPos;
1641 	}
1642 
1643 	return aPaM;
1644 }
1645 
CursorDown(const TextPaM & rPaM)1646 TextPaM TextView::CursorDown( const TextPaM& rPaM )
1647 {
1648 	TextPaM aPaM( rPaM );
1649 
1650 	long nX;
1651     if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
1652 	{
1653         nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left();
1654         mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
1655 	}
1656 	else
1657         nX = mpImpl->mnTravelXPos;
1658 
1659     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1660 	sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False );
1661 	if ( nLine < ( pPPortion->GetLines().Count() - 1 ) )
1662 	{
1663         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine+1, nX );
1664 		aPaM.GetIndex() = nCharPos;
1665 
1666 		// Sonderbehandlung siehe CursorUp...
1667 		TextLine* pLine = pPPortion->GetLines().GetObject( nLine + 1 );
1668 		if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && aPaM.GetIndex() < pPPortion->GetNode()->GetText().Len() )
1669 			aPaM.GetIndex()--;
1670 	}
1671     else if ( rPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) )   // naechster Absatz
1672 	{
1673 		aPaM.GetPara()++;
1674         pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1675         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), 0, nX+1 );
1676 		aPaM.GetIndex() = nCharPos;
1677 		TextLine* pLine = pPPortion->GetLines().GetObject( 0 );
1678 		if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && ( pPPortion->GetLines().Count() > 1 ) )
1679 			aPaM.GetIndex()--;
1680 	}
1681 
1682 	return aPaM;
1683 }
1684 
CursorStartOfLine(const TextPaM & rPaM)1685 TextPaM TextView::CursorStartOfLine( const TextPaM& rPaM )
1686 {
1687 	TextPaM aPaM( rPaM );
1688 
1689     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1690 	sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1691 	TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
1692 	aPaM.GetIndex() = pLine->GetStart();
1693 
1694 	return aPaM;
1695 }
1696 
CursorEndOfLine(const TextPaM & rPaM)1697 TextPaM TextView::CursorEndOfLine( const TextPaM& rPaM )
1698 {
1699 	TextPaM aPaM( rPaM );
1700 
1701     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1702 	sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1703 	TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
1704 	aPaM.GetIndex() = pLine->GetEnd();
1705 
1706 	if ( pLine->GetEnd() > pLine->GetStart() )	// Leerzeile
1707 	{
1708 		xub_Unicode cLastChar = pPPortion->GetNode()->GetText().GetChar((sal_uInt16)(aPaM.GetIndex()-1) );
1709 		if ( ( cLastChar == ' ' ) && ( aPaM.GetIndex() != pPPortion->GetNode()->GetText().Len() ) )
1710 		{
1711 			// Bei einem Blank in einer autom. umgebrochenen Zeile macht es Sinn,
1712 			// davor zu stehen, da der Anwender hinter das Wort will.
1713 			// Wenn diese geaendert wird, Sonderbehandlung fuer Pos1 nach End!
1714 			aPaM.GetIndex()--;
1715 		}
1716 	}
1717 	return aPaM;
1718 }
1719 
CursorStartOfParagraph(const TextPaM & rPaM)1720 TextPaM TextView::CursorStartOfParagraph( const TextPaM& rPaM )
1721 {
1722 	TextPaM aPaM( rPaM );
1723 	aPaM.GetIndex() = 0;
1724 	return aPaM;
1725 }
1726 
CursorEndOfParagraph(const TextPaM & rPaM)1727 TextPaM TextView::CursorEndOfParagraph( const TextPaM& rPaM )
1728 {
1729     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( rPaM.GetPara() );
1730 	TextPaM aPaM( rPaM );
1731 	aPaM.GetIndex() = pNode->GetText().Len();
1732 	return aPaM;
1733 }
1734 
CursorStartOfDoc()1735 TextPaM TextView::CursorStartOfDoc()
1736 {
1737 	TextPaM aPaM( 0, 0 );
1738 	return aPaM;
1739 }
1740 
CursorEndOfDoc()1741 TextPaM TextView::CursorEndOfDoc()
1742 {
1743     sal_uLong nNode = mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1;
1744     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( nNode );
1745 	TextPaM aPaM( nNode, pNode->GetText().Len() );
1746 	return aPaM;
1747 }
1748 
PageUp(const TextPaM & rPaM)1749 TextPaM TextView::PageUp( const TextPaM& rPaM )
1750 {
1751     Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
1752 	Point aTopLeft = aRec.TopLeft();
1753     aTopLeft.Y() -= mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
1754 	aTopLeft.X() += 1;
1755 	if ( aTopLeft.Y() < 0 )
1756 		aTopLeft.Y() = 0;
1757 
1758     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aTopLeft );
1759 	return aPaM;
1760 }
1761 
PageDown(const TextPaM & rPaM)1762 TextPaM TextView::PageDown( const TextPaM& rPaM )
1763 {
1764     Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
1765 	Point aBottomRight = aRec.BottomRight();
1766     aBottomRight.Y() += mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
1767 	aBottomRight.X() += 1;
1768     long nHeight = mpImpl->mpTextEngine->GetTextHeight();
1769 	if ( aBottomRight.Y() > nHeight )
1770 		aBottomRight.Y() = nHeight-1;
1771 
1772     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aBottomRight );
1773 	return aPaM;
1774 }
1775 
ImpShowCursor(sal_Bool bGotoCursor,sal_Bool bForceVisCursor,sal_Bool bSpecial)1776 void TextView::ImpShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, sal_Bool bSpecial )
1777 {
1778     if ( mpImpl->mpTextEngine->IsFormatting() )
1779 		return;
1780     if ( mpImpl->mpTextEngine->GetUpdateMode() == sal_False )
1781 		return;
1782     if ( mpImpl->mpTextEngine->IsInUndo() )
1783 		return;
1784 
1785     mpImpl->mpTextEngine->CheckIdleFormatter();
1786     if ( !mpImpl->mpTextEngine->IsFormatted() )
1787         mpImpl->mpTextEngine->FormatAndUpdate( this );
1788 
1789 
1790     TextPaM aPaM( mpImpl->maSelection.GetEnd() );
1791     Rectangle aEditCursor = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM, bSpecial );
1792 
1793     // Remember that we placed the cursor behind the last character of a line
1794     mpImpl->mbCursorAtEndOfLine = false;
1795     if( bSpecial )
1796     {
1797         TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1798         mpImpl->mbCursorAtEndOfLine =
1799             pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True ) != pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1800     }
1801 
1802     if ( !IsInsertMode() && !mpImpl->maSelection.HasRange() )
1803 	{
1804         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1805 		if ( pNode->GetText().Len() && ( aPaM.GetIndex() < pNode->GetText().Len() ) )
1806 		{
1807             // If we are behind a portion, and the next portion has other direction, we must change position...
1808             aEditCursor.Left() = aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aPaM, sal_False, sal_True ).Left();
1809 
1810             TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1811 
1812             sal_uInt16 nTextPortionStart = 0;
1813             sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, sal_True );
1814             TETextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
1815             if ( pTextPortion->GetKind() == PORTIONKIND_TAB )
1816             {
1817                 if ( mpImpl->mpTextEngine->IsRightToLeft() )
1818                 {
1819 
1820                 }
1821 		        aEditCursor.Right() += pTextPortion->GetWidth();
1822             }
1823             else
1824             {
1825                 TextPaM aNext = CursorRight( TextPaM( aPaM.GetPara(), aPaM.GetIndex() ), (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1826                 aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aNext, sal_True ).Left();
1827             }
1828 		}
1829 	}
1830 
1831     Size aOutSz = mpImpl->mpWindow->GetOutputSizePixel();
1832 	if ( aEditCursor.GetHeight() > aOutSz.Height() )
1833 		aEditCursor.Bottom() = aEditCursor.Top() + aOutSz.Height() - 1;
1834 
1835     aEditCursor.Left() -= 1;
1836 
1837 	if ( bGotoCursor
1838         // #i81283# protext maStartDocPos against initialization problems
1839         && aOutSz.Width() && aOutSz.Height()
1840     )
1841 	{
1842         long nVisStartY = mpImpl->maStartDocPos.Y();
1843         long nVisEndY = mpImpl->maStartDocPos.Y() + aOutSz.Height();
1844         long nVisStartX = mpImpl->maStartDocPos.X();
1845         long nVisEndX = mpImpl->maStartDocPos.X() + aOutSz.Width();
1846 		long nMoreX = aOutSz.Width() / 4;
1847 
1848         Point aNewStartPos( mpImpl->maStartDocPos );
1849 
1850 		if ( aEditCursor.Bottom() > nVisEndY )
1851 		{
1852 			aNewStartPos.Y() += ( aEditCursor.Bottom() - nVisEndY );
1853 		}
1854 		else if ( aEditCursor.Top() < nVisStartY )
1855 		{
1856 			aNewStartPos.Y() -= ( nVisStartY - aEditCursor.Top() );
1857 		}
1858 
1859 		if ( aEditCursor.Right() >= nVisEndX )
1860 		{
1861 			aNewStartPos.X() += ( aEditCursor.Right() - nVisEndX );
1862 
1863 			// Darfs ein bischen mehr sein?
1864 			aNewStartPos.X() += nMoreX;
1865 		}
1866 		else if ( aEditCursor.Left() <= nVisStartX )
1867 		{
1868 			aNewStartPos.X() -= ( nVisStartX - aEditCursor.Left() );
1869 
1870 			// Darfs ein bischen mehr sein?
1871 			aNewStartPos.X() -= nMoreX;
1872 		}
1873 
1874 		// X kann durch das 'bischen mehr' falsch sein:
1875 //      sal_uLong nMaxTextWidth = mpImpl->mpTextEngine->GetMaxTextWidth();
1876 //		if ( !nMaxTextWidth || ( nMaxTextWidth > 0x7FFFFFFF ) )
1877 //			nMaxTextWidth = 0x7FFFFFFF;
1878 //		long nMaxX = (long)nMaxTextWidth - aOutSz.Width();
1879         long nMaxX = mpImpl->mpTextEngine->CalcTextWidth() - aOutSz.Width();
1880 		if ( nMaxX < 0 )
1881 			nMaxX = 0;
1882 
1883 		if ( aNewStartPos.X() < 0 )
1884 			aNewStartPos.X() = 0;
1885 		else if ( aNewStartPos.X() > nMaxX )
1886 			aNewStartPos.X() = nMaxX;
1887 
1888 		// Y sollte nicht weiter unten als noetig liegen:
1889         long nYMax = mpImpl->mpTextEngine->GetTextHeight() - aOutSz.Height();
1890 		if ( nYMax < 0 )
1891 			nYMax = 0;
1892 		if ( aNewStartPos.Y() > nYMax )
1893 			aNewStartPos.Y() = nYMax;
1894 
1895         if ( aNewStartPos != mpImpl->maStartDocPos )
1896             Scroll( -(aNewStartPos.X() - mpImpl->maStartDocPos.X()), -(aNewStartPos.Y() - mpImpl->maStartDocPos.Y()) );
1897 	}
1898 
1899     if ( aEditCursor.Right() < aEditCursor.Left() )
1900     {
1901         long n = aEditCursor.Left();
1902         aEditCursor.Left() = aEditCursor.Right();
1903         aEditCursor.Right() = n;
1904     }
1905 
1906     Point aPoint( GetWindowPos( !mpImpl->mpTextEngine->IsRightToLeft() ? aEditCursor.TopLeft() : aEditCursor.TopRight() ) );
1907     mpImpl->mpCursor->SetPos( aPoint );
1908     mpImpl->mpCursor->SetSize( aEditCursor.GetSize() );
1909     if ( bForceVisCursor && mpImpl->mbCursorEnabled )
1910         mpImpl->mpCursor->Show();
1911 }
1912 
SetCursorAtPoint(const Point & rPosPixel)1913 sal_Bool TextView::SetCursorAtPoint( const Point& rPosPixel )
1914 {
1915     mpImpl->mpTextEngine->CheckIdleFormatter();
1916 
1917 	Point aDocPos = GetDocPos( rPosPixel );
1918 
1919     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos );
1920 
1921 	// aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion
1922     TextSelection aTmpNewSel( mpImpl->maSelection.GetEnd(), aPaM );
1923     TextSelection aNewSel( mpImpl->maSelection );
1924 	aNewSel.GetEnd() = aPaM;
1925 
1926     if ( !mpImpl->mpSelEngine->HasAnchor() )
1927 	{
1928         if ( mpImpl->maSelection.GetStart() != aPaM )
1929             mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() );
1930 		aNewSel.GetStart() = aPaM;
1931         ImpSetSelection( aNewSel );
1932 	}
1933 	else
1934 	{
1935         ImpSetSelection( aNewSel );
1936 		ShowSelection( aTmpNewSel );
1937 	}
1938 
1939     sal_Bool bForceCursor =  mpImpl->mpDDInfo ? sal_False : sal_True; // && !mbInSelection
1940     ImpShowCursor( mpImpl->mbAutoScroll, bForceCursor, sal_False );
1941 	return sal_True;
1942 }
1943 
IsSelectionAtPoint(const Point & rPosPixel)1944 sal_Bool TextView::IsSelectionAtPoint( const Point& rPosPixel )
1945 {
1946 //  if ( !Rectangle( Point(), mpImpl->mpWindow->GetOutputSizePixel() ).IsInside( rPosPixel ) && !mbInSelection )
1947 //		return sal_False;
1948 
1949 	Point aDocPos = GetDocPos( rPosPixel );
1950     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos, sal_False );
1951 	// Bei Hyperlinks D&D auch ohne Selektion starten.
1952 	// BeginDrag wird aber nur gerufen, wenn IsSelectionAtPoint()
1953 	// Problem: IsSelectionAtPoint wird bei Command() nicht gerufen,
1954 	// wenn vorher im MBDown schon sal_False returnt wurde.
1955 	return ( IsInSelection( aPaM ) ||
1956             ( /* mpImpl->mpSelEngine->IsInCommand() && */ mpImpl->mpTextEngine->FindAttrib( aPaM, TEXTATTR_HYPERLINK ) ) );
1957 }
1958 
IsInSelection(const TextPaM & rPaM)1959 sal_Bool TextView::IsInSelection( const TextPaM& rPaM )
1960 {
1961     TextSelection aSel = mpImpl->maSelection;
1962 	aSel.Justify();
1963 
1964 	sal_uLong nStartNode = aSel.GetStart().GetPara();
1965 	sal_uLong nEndNode = aSel.GetEnd().GetPara();
1966 	sal_uLong nCurNode = rPaM.GetPara();
1967 
1968 	if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) )
1969 		return sal_True;
1970 
1971 	if ( nStartNode == nEndNode )
1972 	{
1973 		if ( nCurNode == nStartNode )
1974 			if ( ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
1975 				return sal_True;
1976 	}
1977 	else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) )
1978 		return sal_True;
1979 	else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
1980 		return sal_True;
1981 
1982 	return sal_False;
1983 }
1984 
ImpHideDDCursor()1985 void TextView::ImpHideDDCursor()
1986 {
1987     if ( mpImpl->mpDDInfo && mpImpl->mpDDInfo->mbVisCursor )
1988 	{
1989         mpImpl->mpDDInfo->maCursor.Hide();
1990         mpImpl->mpDDInfo->mbVisCursor = sal_False;
1991 	}
1992 }
1993 
ImpShowDDCursor()1994 void TextView::ImpShowDDCursor()
1995 {
1996     if ( !mpImpl->mpDDInfo->mbVisCursor )
1997 	{
1998         Rectangle aCursor = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpDDInfo->maDropPos, sal_True );
1999 		aCursor.Right()++;
2000 		aCursor.SetPos( GetWindowPos( aCursor.TopLeft() ) );
2001 
2002         mpImpl->mpDDInfo->maCursor.SetWindow( mpImpl->mpWindow );
2003         mpImpl->mpDDInfo->maCursor.SetPos( aCursor.TopLeft() );
2004         mpImpl->mpDDInfo->maCursor.SetSize( aCursor.GetSize() );
2005         mpImpl->mpDDInfo->maCursor.Show();
2006         mpImpl->mpDDInfo->mbVisCursor = sal_True;
2007 	}
2008 }
2009 
SetPaintSelection(sal_Bool bPaint)2010 void TextView::SetPaintSelection( sal_Bool bPaint )
2011 {
2012     if ( bPaint != mpImpl->mbPaintSelection )
2013 	{
2014         mpImpl->mbPaintSelection = bPaint;
2015         ShowSelection( mpImpl->maSelection );
2016 	}
2017 }
2018 
SetHighlightSelection(sal_Bool bSelectByHighlight)2019 void TextView::SetHighlightSelection( sal_Bool bSelectByHighlight )
2020 {
2021     if ( bSelectByHighlight != mpImpl->mbHighlightSelection )
2022 	{
2023 		// Falls umschalten zwischendurch moeglich...
2024         mpImpl->mbHighlightSelection = bSelectByHighlight;
2025 	}
2026 }
2027 
Read(SvStream & rInput)2028 sal_Bool TextView::Read( SvStream& rInput )
2029 {
2030     sal_Bool bDone = mpImpl->mpTextEngine->Read( rInput, &mpImpl->maSelection );
2031 	ShowCursor();
2032 	return bDone;
2033 }
2034 
Write(SvStream & rOutput)2035 sal_Bool TextView::Write( SvStream& rOutput )
2036 {
2037     return mpImpl->mpTextEngine->Read( rOutput, &mpImpl->maSelection );
2038 }
2039 
ImplTruncateNewText(rtl::OUString & rNewText) const2040 bool TextView::ImplTruncateNewText( rtl::OUString& rNewText ) const
2041 {
2042 	bool bTruncated = false;
2043 
2044     if( rNewText.getLength() > 65534 ) // limit to String API
2045     {
2046         rNewText = rNewText.copy( 0, 65534 );
2047         bTruncated = true;
2048     }
2049 
2050     sal_uLong nMaxLen = mpImpl->mpTextEngine->GetMaxTextLen();
2051     // 0 means unlimited, there is just the String API limit handled above
2052     if( nMaxLen != 0 )
2053     {
2054         sal_uLong nCurLen = mpImpl->mpTextEngine->GetTextLen();
2055 
2056         sal_uInt32 nNewLen = rNewText.getLength();
2057         if ( nCurLen + nNewLen > nMaxLen )
2058         {
2059             // see how much text will be replaced
2060             sal_uLong nSelLen = mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
2061             if ( nCurLen + nNewLen - nSelLen > nMaxLen )
2062             {
2063                 sal_uInt32 nTruncatedLen = static_cast<sal_uInt32>(nMaxLen - (nCurLen - nSelLen));
2064                 rNewText = rNewText.copy( 0, nTruncatedLen );
2065                 bTruncated = true;
2066             }
2067         }
2068     }
2069 	return bTruncated;
2070 }
2071 
ImplCheckTextLen(const String & rNewText)2072 sal_Bool TextView::ImplCheckTextLen( const String& rNewText )
2073 {
2074 	sal_Bool bOK = sal_True;
2075     if ( mpImpl->mpTextEngine->GetMaxTextLen() )
2076 	{
2077         sal_uLong n = mpImpl->mpTextEngine->GetTextLen();
2078 		n += rNewText.Len();
2079         if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
2080 		{
2081 			// nur dann noch ermitteln, wie viel Text geloescht wird
2082             n -= mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
2083             if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
2084 			{
2085 				// Beep hat hier eigentlich nichts verloren, sondern lieber ein Hdl,
2086 				// aber so funktioniert es wenigstens in ME, BasicIDE, SourceView
2087 				Sound::Beep();
2088 				bOK = sal_False;
2089 			}
2090 		}
2091 	}
2092 	return bOK;
2093 }
2094 
dragGestureRecognized(const::com::sun::star::datatransfer::dnd::DragGestureEvent & rDGE)2095 void TextView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException)
2096 {
2097     if ( mpImpl->mbClickedInSelection )
2098     {
2099 	    vos::OGuard aVclGuard( Application::GetSolarMutex() );
2100 
2101         DBG_ASSERT( mpImpl->maSelection.HasRange(), "TextView::dragGestureRecognized: mpImpl->mbClickedInSelection, but no selection?" );
2102 
2103         delete mpImpl->mpDDInfo;
2104         mpImpl->mpDDInfo = new TextDDInfo;
2105         mpImpl->mpDDInfo->mbStarterOfDD = sal_True;
2106 
2107 	    TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
2108 
2109         if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) )  // Dann auch als HTML
2110             mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True );
2111 
2112 
2113         /*
2114 	    // D&D eines Hyperlinks.
2115 	    // Besser waere es im MBDown sich den MBDownPaM zu merken,
2116 	    // ist dann aber inkompatibel => spaeter mal umstellen.
2117         TextPaM aPaM( mpImpl->mpTextEngine->GetPaM( GetDocPos( GetWindow()->GetPointerPosPixel() ) ) );
2118         const TextCharAttrib* pAttr = mpImpl->mpTextEngine->FindCharAttrib( aPaM, TEXTATTR_HYPERLINK );
2119 	    if ( pAttr )
2120 	    {
2121 		    aSel = aPaM;
2122 		    aSel.GetStart().GetIndex() = pAttr->GetStart();
2123 		    aSel.GetEnd().GetIndex() = pAttr->GetEnd();
2124 
2125 		    const TextAttribHyperLink& rLink = (const TextAttribHyperLink&)pAttr->GetAttr();
2126 		    String aText( rLink.GetDescription() );
2127 		    if ( !aText.Len() )
2128                 aText = mpImpl->mpTextEngine->GetText( aSel );
2129 		    INetBookmark aBookmark( rLink.GetURL(), aText );
2130 		    aBookmark.CopyDragServer();
2131 	    }
2132         */
2133 
2134         mpImpl->mpCursor->Hide();
2135 
2136         sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY;
2137         if ( !IsReadOnly() )
2138             nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE;
2139         rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mpImpl->mxDnDListener );
2140     }
2141 }
2142 
dragDropEnd(const::com::sun::star::datatransfer::dnd::DragSourceDropEvent &)2143 void TextView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& ) throw (::com::sun::star::uno::RuntimeException)
2144 {
2145     ImpHideDDCursor();
2146     delete mpImpl->mpDDInfo;
2147     mpImpl->mpDDInfo = NULL;
2148 }
2149 
drop(const::com::sun::star::datatransfer::dnd::DropTargetDropEvent & rDTDE)2150 void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
2151 {
2152 	vos::OGuard aVclGuard( Application::GetSolarMutex() );
2153 
2154 	sal_Bool bChanges = sal_False;
2155     if ( !mpImpl->mbReadOnly && mpImpl->mpDDInfo )
2156 	{
2157 		ImpHideDDCursor();
2158 
2159 		// Daten fuer das loeschen nach einem DROP_MOVE:
2160         TextSelection aPrevSel( mpImpl->maSelection );
2161 		aPrevSel.Justify();
2162         sal_uLong nPrevParaCount = mpImpl->mpTextEngine->GetParagraphCount();
2163         sal_uInt16 nPrevStartParaLen = mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() );
2164 
2165 		sal_Bool bStarterOfDD = sal_False;
2166         for ( sal_uInt16 nView = mpImpl->mpTextEngine->GetViewCount(); nView && !bStarterOfDD; )
2167             bStarterOfDD = mpImpl->mpTextEngine->GetView( --nView )->mpImpl->mpDDInfo ? mpImpl->mpTextEngine->GetView( nView )->mpImpl->mpDDInfo->mbStarterOfDD : sal_False;
2168 
2169 		HideSelection();
2170         ImpSetSelection( mpImpl->mpDDInfo->maDropPos );
2171 
2172         mpImpl->mpTextEngine->UndoActionStart();
2173 
2174 		String aText;
2175 		uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
2176 		if ( xDataObj.is() )
2177 		{
2178 		    datatransfer::DataFlavor aFlavor;
2179 		    SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
2180 		    if ( xDataObj->isDataFlavorSupported( aFlavor ) )
2181 		    {
2182 			    uno::Any aData = xDataObj->getTransferData( aFlavor );
2183 			    ::rtl::OUString aOUString;
2184 			    aData >>= aOUString;
2185                 aText = aOUString;
2186 		        aText.ConvertLineEnd( LINEEND_LF );
2187 		    }
2188         }
2189 
2190 		if ( aText.Len() && ( aText.GetChar( aText.Len()-1 ) == LINE_SEP ) )
2191 			aText.Erase( aText.Len()-1 );
2192 
2193 		TextPaM aTempStart = mpImpl->maSelection.GetStart();
2194         if ( ImplCheckTextLen( aText ) )
2195             ImpSetSelection( mpImpl->mpTextEngine->ImpInsertText( mpImpl->mpDDInfo->maDropPos, aText ) );
2196         if(mpImpl->mbSupportProtectAttribute)
2197         {
2198             mpImpl->mpTextEngine->SetAttrib( TextAttribProtect(),
2199                 aTempStart.GetPara(),
2200                 aTempStart.GetIndex(),
2201                 mpImpl->maSelection.GetEnd().GetIndex(), sal_False );
2202         }
2203 
2204         if ( aPrevSel.HasRange() &&
2205                 !mpImpl->mbSupportProtectAttribute && // don't remove currently selected element
2206                 (( rDTDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) || !bStarterOfDD) )
2207 		{
2208 			// ggf. Selection anpasssen:
2209             if ( ( mpImpl->mpDDInfo->maDropPos.GetPara() < aPrevSel.GetStart().GetPara() ) ||
2210                  ( ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
2211                         && ( mpImpl->mpDDInfo->maDropPos.GetIndex() < aPrevSel.GetStart().GetIndex() ) ) )
2212 			{
2213 				sal_uLong nNewParasBeforeSelection =
2214                     mpImpl->mpTextEngine->GetParagraphCount() -    nPrevParaCount;
2215 
2216 				aPrevSel.GetStart().GetPara() += nNewParasBeforeSelection;
2217 				aPrevSel.GetEnd().GetPara() += nNewParasBeforeSelection;
2218 
2219                 if ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
2220 				{
2221 					sal_uInt16 nNewChars =
2222                         mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ) - nPrevStartParaLen;
2223 
2224 					aPrevSel.GetStart().GetIndex() =
2225                         aPrevSel.GetStart().GetIndex() + nNewChars;
2226 					if ( aPrevSel.GetStart().GetPara() == aPrevSel.GetEnd().GetPara() )
2227 						aPrevSel.GetEnd().GetIndex() =
2228                             aPrevSel.GetEnd().GetIndex() + nNewChars;
2229 				}
2230 			}
2231 			else
2232 			{
2233 				// aktuelle Selektion anpassen
2234                 TextPaM aPaM = mpImpl->maSelection.GetStart();
2235 				aPaM.GetPara() -= ( aPrevSel.GetEnd().GetPara() - aPrevSel.GetStart().GetPara() );
2236                 if ( aPrevSel.GetEnd().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
2237 				{
2238 					aPaM.GetIndex() =
2239                         aPaM.GetIndex() - aPrevSel.GetEnd().GetIndex();
2240                     if ( aPrevSel.GetStart().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
2241 						aPaM.GetIndex() =
2242                             aPaM.GetIndex() + aPrevSel.GetStart().GetIndex();
2243 				}
2244 				ImpSetSelection( aPaM );
2245 
2246 			}
2247             mpImpl->mpTextEngine->ImpDeleteText( aPrevSel );
2248 		}
2249 
2250         mpImpl->mpTextEngine->UndoActionEnd();
2251 
2252         delete mpImpl->mpDDInfo;
2253         mpImpl->mpDDInfo = 0;
2254 
2255         mpImpl->mpTextEngine->FormatAndUpdate( this );
2256 
2257         mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
2258     }
2259     rDTDE.Context->dropComplete( bChanges );
2260 }
2261 
dragEnter(const::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent &)2262 void TextView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& ) throw (::com::sun::star::uno::RuntimeException)
2263 {
2264 }
2265 
dragExit(const::com::sun::star::datatransfer::dnd::DropTargetEvent &)2266 void TextView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException)
2267 {
2268 	vos::OGuard aVclGuard( Application::GetSolarMutex() );
2269     ImpHideDDCursor();
2270 }
2271 
dragOver(const::com::sun::star::datatransfer::dnd::DropTargetDragEvent & rDTDE)2272 void TextView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
2273 {
2274 	vos::OGuard aVclGuard( Application::GetSolarMutex() );
2275 
2276     if ( !mpImpl->mpDDInfo )
2277         mpImpl->mpDDInfo = new TextDDInfo;
2278 
2279     TextPaM aPrevDropPos = mpImpl->mpDDInfo->maDropPos;
2280 	Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
2281 	Point aDocPos = GetDocPos( aMousePos );
2282     mpImpl->mpDDInfo->maDropPos = mpImpl->mpTextEngine->GetPaM( aDocPos );
2283 
2284 /*
2285     Size aOutSize = mpImpl->mpWindow->GetOutputSizePixel();
2286 	if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) ||
2287 		 ( aMousePos.Y() < 0 ) || ( aMousePos.Y() > aOutSize.Height() ) )
2288 	{
2289 		// Scroll?
2290 		// No, I will not receive events for this...
2291 	}
2292 */
2293 
2294     sal_Bool bProtected = sal_False;
2295     if(mpImpl->mbSupportProtectAttribute)
2296     {
2297         const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
2298                     mpImpl->mpDDInfo->maDropPos,
2299                     TEXTATTR_PROTECTED );
2300         bProtected = pStartAttr != 0 &&
2301                 pStartAttr->GetStart() != mpImpl->mpDDInfo->maDropPos.GetIndex() &&
2302                 pStartAttr->GetEnd() != mpImpl->mpDDInfo->maDropPos.GetIndex();
2303     }
2304     // Don't drop in selection or in read only engine
2305     if ( IsReadOnly() || IsInSelection( mpImpl->mpDDInfo->maDropPos ) || bProtected)
2306 	{
2307 		ImpHideDDCursor();
2308         rDTDE.Context->rejectDrag();
2309 	}
2310     else
2311     {
2312 	    // Alten Cursor wegzeichnen...
2313         if ( !mpImpl->mpDDInfo->mbVisCursor || ( aPrevDropPos != mpImpl->mpDDInfo->maDropPos ) )
2314 	    {
2315 		    ImpHideDDCursor();
2316 		    ImpShowDDCursor();
2317 	    }
2318         rDTDE.Context->acceptDrag( rDTDE.DropAction );
2319     }
2320 }
2321 
ImpGetOutputStartPos(const Point & rStartDocPos) const2322 Point TextView::ImpGetOutputStartPos( const Point& rStartDocPos ) const
2323 {
2324 	Point aStartPos( -rStartDocPos.X(), -rStartDocPos.Y() );
2325     if ( mpImpl->mpTextEngine->IsRightToLeft() )
2326     {
2327         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2328 		aStartPos.X() = rStartDocPos.X() + aSz.Width() - 1; // -1: Start is 0
2329     }
2330     return aStartPos;
2331 }
2332 
GetDocPos(const Point & rWindowPos) const2333 Point TextView::GetDocPos( const Point& rWindowPos ) const
2334 {
2335 	// Fensterposition => Dokumentposition
2336 
2337 	Point aPoint;
2338 
2339     aPoint.Y() = rWindowPos.Y() + mpImpl->maStartDocPos.Y();
2340 
2341     if ( !mpImpl->mpTextEngine->IsRightToLeft() )
2342     {
2343         aPoint.X() = rWindowPos.X() + mpImpl->maStartDocPos.X();
2344     }
2345     else
2346     {
2347         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2348         aPoint.X() = ( aSz.Width() - 1 ) - rWindowPos.X() + mpImpl->maStartDocPos.X();
2349     }
2350 
2351 	return aPoint;
2352 }
2353 
GetWindowPos(const Point & rDocPos) const2354 Point TextView::GetWindowPos( const Point& rDocPos ) const
2355 {
2356 	// Dokumentposition => Fensterposition
2357 
2358 	Point aPoint;
2359 
2360     aPoint.Y() = rDocPos.Y() - mpImpl->maStartDocPos.Y();
2361 
2362     if ( !mpImpl->mpTextEngine->IsRightToLeft() )
2363     {
2364         aPoint.X() = rDocPos.X() - mpImpl->maStartDocPos.X();
2365     }
2366     else
2367     {
2368         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2369         aPoint.X() = ( aSz.Width() - 1 ) - ( rDocPos.X() - mpImpl->maStartDocPos.X() );
2370     }
2371 
2372 	return aPoint;
2373 }
2374 
GetLineNumberOfCursorInSelection() const2375 sal_Int32 TextView::GetLineNumberOfCursorInSelection() const
2376 {
2377  // PROGRESS
2378     sal_Int32 nLineNo = -1;
2379     if( mpImpl->mbCursorEnabled )
2380     {
2381         TextPaM aPaM = GetSelection().GetEnd();
2382         TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
2383         nLineNo = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
2384         if( mpImpl->mbCursorAtEndOfLine )
2385             --nLineNo;
2386     }
2387     return nLineNo;
2388 }
2389 
2390 
2391 // -------------------------------------------------------------------------
2392 // (+) class TextSelFunctionSet
2393 // -------------------------------------------------------------------------
TextSelFunctionSet(TextView * pView)2394 TextSelFunctionSet::TextSelFunctionSet( TextView* pView )
2395 {
2396 	mpView = pView;
2397 }
2398 
BeginDrag()2399 void __EXPORT TextSelFunctionSet::BeginDrag()
2400 {
2401 }
2402 
CreateAnchor()2403 void __EXPORT TextSelFunctionSet::CreateAnchor()
2404 {
2405 //	TextSelection aSel( mpView->GetSelection() );
2406 //	aSel.GetStart() = aSel.GetEnd();
2407 //	mpView->SetSelection( aSel );
2408 
2409 	// Es darf kein ShowCursor folgen:
2410 	mpView->HideSelection();
2411     mpView->ImpSetSelection( mpView->mpImpl->maSelection.GetEnd() );
2412 }
2413 
SetCursorAtPoint(const Point & rPointPixel,sal_Bool)2414 sal_Bool __EXPORT TextSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool )
2415 {
2416 	return mpView->SetCursorAtPoint( rPointPixel );
2417 }
2418 
IsSelectionAtPoint(const Point & rPointPixel)2419 sal_Bool __EXPORT TextSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
2420 {
2421 	return mpView->IsSelectionAtPoint( rPointPixel );
2422 }
2423 
DeselectAll()2424 void __EXPORT TextSelFunctionSet::DeselectAll()
2425 {
2426 	CreateAnchor();
2427 }
2428 
DeselectAtPoint(const Point &)2429 void __EXPORT TextSelFunctionSet::DeselectAtPoint( const Point& )
2430 {
2431 	// Nur bei Mehrfachselektion
2432 }
2433 
DestroyAnchor()2434 void __EXPORT TextSelFunctionSet::DestroyAnchor()
2435 {
2436 	// Nur bei Mehrfachselektion
2437 }
GetTextEngine() const2438 TextEngine*         TextView::GetTextEngine() const
2439 { return mpImpl->mpTextEngine; }
GetWindow() const2440 Window*             TextView::GetWindow() const
2441 { return mpImpl->mpWindow; }
EnableCursor(sal_Bool bEnable)2442 void                TextView::EnableCursor( sal_Bool bEnable )
2443 { mpImpl->mbCursorEnabled = bEnable; }
IsCursorEnabled() const2444 sal_Bool                TextView::IsCursorEnabled() const
2445 { return mpImpl->mbCursorEnabled; }
SetStartDocPos(const Point & rPos)2446 void                TextView::SetStartDocPos( const Point& rPos )
2447 { mpImpl->maStartDocPos = rPos; }
GetStartDocPos() const2448 const Point&        TextView::GetStartDocPos() const
2449 { return mpImpl->maStartDocPos; }
SetAutoIndentMode(sal_Bool bAutoIndent)2450 void                TextView::SetAutoIndentMode( sal_Bool bAutoIndent )
2451 { mpImpl->mbAutoIndent = bAutoIndent; }
IsAutoIndentMode() const2452 sal_Bool                TextView::IsAutoIndentMode() const
2453 { return mpImpl->mbAutoIndent; }
IsReadOnly() const2454 sal_Bool                TextView::IsReadOnly() const
2455 { return mpImpl->mbReadOnly; }
SetAutoScroll(sal_Bool bAutoScroll)2456 void                TextView::SetAutoScroll( sal_Bool bAutoScroll )
2457 { mpImpl->mbAutoScroll = bAutoScroll; }
IsAutoScroll() const2458 sal_Bool                TextView::IsAutoScroll() const
2459 { return mpImpl->mbAutoScroll; }
IsPaintSelection() const2460 sal_Bool                TextView::IsPaintSelection() const
2461 { return mpImpl->mbPaintSelection; }
IsHighlightSelection() const2462 sal_Bool                TextView::IsHighlightSelection() const
2463 { return mpImpl->mbHighlightSelection; }
HasSelection() const2464 sal_Bool                TextView::HasSelection() const
2465 { return mpImpl->maSelection.HasRange(); }
IsInsertMode() const2466 sal_Bool                TextView::IsInsertMode() const
2467 { return mpImpl->mbInsertMode; }
SupportProtectAttribute(sal_Bool bSupport)2468 void                TextView::SupportProtectAttribute(sal_Bool bSupport)
2469 { mpImpl->mbSupportProtectAttribute = bSupport;}
2470 
2471