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