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