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