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