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