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