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