xref: /core/editeng/source/editeng/editeng.cxx (revision 8feca893)
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 <utility>
22 
23 #include <comphelper/lok.hxx>
24 #include <config_global.h>
25 #include <vcl/weld.hxx>
26 #include <vcl/svapp.hxx>
27 
28 #include <svtools/ctrltool.hxx>
29 
30 #include <editeng/svxfont.hxx>
31 #include "impedit.hxx"
32 #include <editeng/editeng.hxx>
33 #include <editeng/editview.hxx>
34 #include <editeng/editstat.hxx>
35 #include "editdbg.hxx"
36 #include <eerdll2.hxx>
37 #include <editeng/eerdll.hxx>
38 #include <editeng/editrids.hrc>
39 #include <editeng.hxx>
40 #include <editeng/acorrcfg.hxx>
41 #include <editeng/flditem.hxx>
42 #include <editeng/txtrange.hxx>
43 #include <editeng/cmapitem.hxx>
44 #include <vcl/graph.hxx>
45 
46 #include <editeng/autokernitem.hxx>
47 #include <editeng/contouritem.hxx>
48 #include <editeng/colritem.hxx>
49 #include <editeng/crossedoutitem.hxx>
50 #include <editeng/escapementitem.hxx>
51 #include <editeng/fhgtitem.hxx>
52 #include <editeng/fontitem.hxx>
53 #include <editeng/kernitem.hxx>
54 #include <editeng/lrspitem.hxx>
55 #include <editeng/postitem.hxx>
56 #include <editeng/shdditem.hxx>
57 #include <editeng/udlnitem.hxx>
58 #include <editeng/wghtitem.hxx>
59 #include <editeng/wrlmitem.hxx>
60 #include <editeng/brushitem.hxx>
61 #include <editeng/langitem.hxx>
62 #include <editeng/emphasismarkitem.hxx>
63 #include <editeng/charscaleitem.hxx>
64 #include <editeng/charreliefitem.hxx>
65 
66 #include <sot/exchange.hxx>
67 #include <sot/formats.hxx>
68 
69 #include <editeng/numitem.hxx>
70 #include <editeng/bulletitem.hxx>
71 #include <editeng/unolingu.hxx>
72 #include <linguistic/lngprops.hxx>
73 #include <i18nlangtag/mslangid.hxx>
74 #include <rtl/strbuf.hxx>
75 #include <sal/log.hxx>
76 #include <vcl/help.hxx>
77 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
78 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
79 
80 #include <svl/srchdefs.hxx>
81 
82 #if OSL_DEBUG_LEVEL > 1
83 #include <editeng/frmdiritem.hxx>
84 #endif
85 #include <basegfx/polygon/b2dpolygon.hxx>
86 
87 using namespace ::com::sun::star;
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::linguistic2;
90 
91 
92 #if (OSL_DEBUG_LEVEL > 1) || defined ( DBG_UTIL )
93 static bool bDebugPaint = false;
94 #endif
95 
96 static SfxItemPool* pGlobalPool=nullptr;
97 
98 EditEngine::EditEngine( SfxItemPool* pItemPool )
99 {
100     pImpEditEngine.reset( new ImpEditEngine( this, pItemPool ) );
101 }
102 
103 EditEngine::~EditEngine()
104 {
105 }
106 
107 void EditEngine::EnableUndo( bool bEnable )
108 {
109     pImpEditEngine->EnableUndo( bEnable );
110 }
111 
112 bool EditEngine::IsUndoEnabled()
113 {
114     return pImpEditEngine->IsUndoEnabled();
115 }
116 
117 bool EditEngine::IsInUndo()
118 {
119     return pImpEditEngine->IsInUndo();
120 }
121 
122 SfxUndoManager& EditEngine::GetUndoManager()
123 {
124     return pImpEditEngine->GetUndoManager();
125 }
126 
127 SfxUndoManager* EditEngine::SetUndoManager(SfxUndoManager* pNew)
128 {
129     return pImpEditEngine->SetUndoManager(pNew);
130 }
131 
132 void EditEngine::UndoActionStart( sal_uInt16 nId )
133 {
134     DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Calling UndoActionStart in Undomode!" );
135     if ( !pImpEditEngine->IsInUndo() )
136         pImpEditEngine->UndoActionStart( nId );
137 }
138 
139 void EditEngine::UndoActionStart(sal_uInt16 nId, const ESelection& rSel)
140 {
141     pImpEditEngine->UndoActionStart(nId, rSel);
142 }
143 
144 void EditEngine::UndoActionEnd()
145 {
146     DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Calling UndoActionEnd in Undomode!" );
147     if ( !pImpEditEngine->IsInUndo() )
148         pImpEditEngine->UndoActionEnd();
149 }
150 
151 bool EditEngine::HasTriedMergeOnLastAddUndo() const
152 {
153     return pImpEditEngine->mbLastTryMerge;
154 }
155 
156 void EditEngine::SetRefDevice( OutputDevice* pRefDev )
157 {
158     pImpEditEngine->SetRefDevice( pRefDev );
159 }
160 
161 OutputDevice* EditEngine::GetRefDevice() const
162 {
163     return pImpEditEngine->GetRefDevice();
164 }
165 
166 void EditEngine::SetRefMapMode( const MapMode& rMapMode )
167 {
168     pImpEditEngine->SetRefMapMode( rMapMode );
169 }
170 
171 MapMode const & EditEngine::GetRefMapMode()
172 {
173     return pImpEditEngine->GetRefMapMode();
174 }
175 
176 void EditEngine::SetBackgroundColor( const Color& rColor )
177 {
178     pImpEditEngine->SetBackgroundColor( rColor );
179 }
180 
181 Color const & EditEngine::GetBackgroundColor() const
182 {
183     return pImpEditEngine->GetBackgroundColor();
184 }
185 
186 Color EditEngine::GetAutoColor() const
187 {
188     return pImpEditEngine->GetAutoColor();
189 }
190 
191 void EditEngine::EnableAutoColor( bool b )
192 {
193     pImpEditEngine->EnableAutoColor( b );
194 }
195 
196 void EditEngine::ForceAutoColor( bool b )
197 {
198     pImpEditEngine->ForceAutoColor( b );
199 }
200 
201 bool EditEngine::IsForceAutoColor() const
202 {
203     return pImpEditEngine->IsForceAutoColor();
204 }
205 
206 const SfxItemSet& EditEngine::GetEmptyItemSet()
207 {
208     return pImpEditEngine->GetEmptyItemSet();
209 }
210 
211 void EditEngine::Draw( OutputDevice* pOutDev, const tools::Rectangle& rOutRect )
212 {
213     Draw( pOutDev, rOutRect, Point( 0, 0 ) );
214 }
215 
216 void EditEngine::Draw( OutputDevice* pOutDev, const Point& rStartPos, short nOrientation )
217 {
218     // Create with 2 points, as with positive points it will end up with
219     // LONGMAX as Size, Bottom and Right in the range > LONGMAX.
220     tools::Rectangle aBigRect( -0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF );
221     if( pOutDev->GetConnectMetaFile() )
222         pOutDev->Push();
223     Point aStartPos( rStartPos );
224     if ( IsVertical() )
225     {
226         aStartPos.AdjustX(GetPaperSize().Width() );
227         aStartPos = Rotate( aStartPos, nOrientation, rStartPos );
228     }
229     pImpEditEngine->Paint( pOutDev, aBigRect, aStartPos, false, nOrientation );
230     if( pOutDev->GetConnectMetaFile() )
231         pOutDev->Pop();
232 }
233 
234 void EditEngine::Draw( OutputDevice* pOutDev, const tools::Rectangle& rOutRect, const Point& rStartDocPos )
235 {
236     Draw( pOutDev, rOutRect, rStartDocPos, true );
237 }
238 
239 void EditEngine::Draw( OutputDevice* pOutDev, const tools::Rectangle& rOutRect, const Point& rStartDocPos, bool bClip )
240 {
241 #if defined( DBG_UTIL ) || (OSL_DEBUG_LEVEL > 1)
242     if ( bDebugPaint )
243         EditDbg::ShowEditEngineData( this, false );
244 #endif
245 
246     // Align to the pixel boundary, so that it becomes exactly the same
247     // as Paint ()
248     tools::Rectangle aOutRect( pOutDev->LogicToPixel( rOutRect ) );
249     aOutRect = pOutDev->PixelToLogic( aOutRect );
250 
251     Point aStartPos;
252     if ( !IsVertical() )
253     {
254         aStartPos.setX( aOutRect.Left() - rStartDocPos.X() );
255         aStartPos.setY( aOutRect.Top() - rStartDocPos.Y() );
256     }
257     else
258     {
259         aStartPos.setX( aOutRect.Right() + rStartDocPos.Y() );
260         aStartPos.setY( aOutRect.Top() - rStartDocPos.X() );
261     }
262 
263     bool bClipRegion = pOutDev->IsClipRegion();
264     bool bMetafile = pOutDev->GetConnectMetaFile();
265     vcl::Region aOldRegion = pOutDev->GetClipRegion();
266 
267     // If one existed => intersection!
268     // Use Push/pop for creating the Meta file
269     if ( bMetafile )
270         pOutDev->Push();
271 
272     // Always use the Intersect method, it is a must for Metafile!
273     if ( bClip )
274     {
275         // Clip only if necessary...
276         if ( rStartDocPos.X() || rStartDocPos.Y() ||
277              ( rOutRect.GetHeight() < static_cast<long>(GetTextHeight()) ) ||
278              ( rOutRect.GetWidth() < static_cast<long>(CalcTextWidth()) ) )
279         {
280             // Some printer drivers cause problems if characters graze the
281             // ClipRegion, therefore rather add a pixel more ...
282             tools::Rectangle aClipRect( aOutRect );
283             if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
284             {
285                 Size aPixSz( 1, 0 );
286                 aPixSz = pOutDev->PixelToLogic( aPixSz );
287                 aClipRect.AdjustRight(aPixSz.Width() );
288                 aClipRect.AdjustBottom(aPixSz.Width() );
289             }
290             pOutDev->IntersectClipRegion( aClipRect );
291         }
292     }
293 
294     pImpEditEngine->Paint( pOutDev, aOutRect, aStartPos );
295 
296     if ( bMetafile )
297         pOutDev->Pop();
298     else if ( bClipRegion )
299         pOutDev->SetClipRegion( aOldRegion );
300     else
301         pOutDev->SetClipRegion();
302 }
303 
304 void EditEngine::InsertView(EditView* pEditView, size_t nIndex)
305 {
306 
307     if ( nIndex > pImpEditEngine->GetEditViews().size() )
308         nIndex = pImpEditEngine->GetEditViews().size();
309 
310     ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews();
311     rViews.insert(rViews.begin()+nIndex, pEditView);
312 
313     EditSelection aStartSel = pImpEditEngine->GetEditDoc().GetStartPaM();
314     pEditView->pImpEditView->SetEditSelection( aStartSel );
315     if ( !pImpEditEngine->GetActiveView() )
316         pImpEditEngine->SetActiveView( pEditView );
317 
318     pEditView->pImpEditView->AddDragAndDropListeners();
319 }
320 
321 EditView* EditEngine::RemoveView( EditView* pView )
322 {
323 
324     pView->HideCursor();
325     EditView* pRemoved = nullptr;
326     ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews();
327     ImpEditEngine::ViewsType::iterator it = std::find(rViews.begin(), rViews.end(), pView);
328 
329     DBG_ASSERT( it != rViews.end(), "RemoveView with invalid index" );
330     if (it != rViews.end())
331     {
332         pRemoved = *it;
333         rViews.erase(it);
334         if ( pImpEditEngine->GetActiveView() == pView )
335         {
336             pImpEditEngine->SetActiveView( nullptr );
337             pImpEditEngine->GetSelEngine().SetCurView( nullptr );
338         }
339         pView->pImpEditView->RemoveDragAndDropListeners();
340 
341     }
342     return pRemoved;
343 }
344 
345 void EditEngine::RemoveView(size_t nIndex)
346 {
347     ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews();
348     if (nIndex >= rViews.size())
349         return;
350 
351     EditView* pView = rViews[nIndex];
352     if ( pView )
353         RemoveView( pView );
354 }
355 
356 EditView* EditEngine::GetView(size_t nIndex) const
357 {
358     return pImpEditEngine->GetEditViews()[nIndex];
359 }
360 
361 size_t EditEngine::GetViewCount() const
362 {
363     return pImpEditEngine->GetEditViews().size();
364 }
365 
366 bool EditEngine::HasView( EditView* pView ) const
367 {
368     ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews();
369     return std::find(rViews.begin(), rViews.end(), pView) != rViews.end();
370 }
371 
372 EditView* EditEngine::GetActiveView() const
373 {
374     return pImpEditEngine->GetActiveView();
375 }
376 
377 void EditEngine::SetActiveView(EditView* pView)
378 {
379     pImpEditEngine->SetActiveView(pView);
380 }
381 
382 void EditEngine::SetDefTab( sal_uInt16 nDefTab )
383 {
384     pImpEditEngine->GetEditDoc().SetDefTab( nDefTab );
385     if ( pImpEditEngine->IsFormatted() )
386     {
387         pImpEditEngine->FormatFullDoc();
388         pImpEditEngine->UpdateViews();
389     }
390 }
391 
392 void EditEngine::SetPaperSize( const Size& rNewSize )
393 {
394 
395     Size aOldSize( pImpEditEngine->GetPaperSize() );
396     pImpEditEngine->SetValidPaperSize( rNewSize );
397     Size aNewSize( pImpEditEngine->GetPaperSize() );
398 
399     bool bAutoPageSize = pImpEditEngine->GetStatus().AutoPageSize();
400     if ( bAutoPageSize || ( aNewSize.Width() != aOldSize.Width() ) )
401     {
402         for (EditView* pView : pImpEditEngine->aEditViews)
403         {
404             if ( bAutoPageSize )
405                 pView->pImpEditView->RecalcOutputArea();
406             else if ( pView->pImpEditView->DoAutoSize() )
407             {
408                 pView->pImpEditView->ResetOutputArea( tools::Rectangle(
409                     pView->pImpEditView->GetOutputArea().TopLeft(), aNewSize ) );
410             }
411         }
412 
413         if ( bAutoPageSize || pImpEditEngine->IsFormatted() )
414         {
415             // Changing the width has no effect for AutoPageSize, as this is
416             // determined by the text width.
417             // Optimization first after Vobis delivery was enabled ...
418             pImpEditEngine->FormatFullDoc();
419 
420             pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() );
421 
422             if ( pImpEditEngine->GetUpdateMode() && pImpEditEngine->GetActiveView() )
423                 pImpEditEngine->pActiveView->ShowCursor( false, false );
424         }
425     }
426 }
427 
428 const Size& EditEngine::GetPaperSize() const
429 {
430     return pImpEditEngine->GetPaperSize();
431 }
432 
433 void EditEngine::SetVertical( bool bVertical, bool bTopToBottom )
434 {
435     pImpEditEngine->SetVertical( bVertical, bTopToBottom);
436 }
437 
438 bool EditEngine::IsVertical() const
439 {
440     return pImpEditEngine->IsVertical();
441 }
442 
443 bool EditEngine::IsTopToBottom() const
444 {
445     return pImpEditEngine->IsTopToBottom();
446 }
447 
448 void EditEngine::SetFixedCellHeight( bool bUseFixedCellHeight )
449 {
450     pImpEditEngine->SetFixedCellHeight( bUseFixedCellHeight );
451 }
452 
453 void EditEngine::SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir )
454 {
455     pImpEditEngine->SetDefaultHorizontalTextDirection( eHTextDir );
456 }
457 
458 EEHorizontalTextDirection EditEngine::GetDefaultHorizontalTextDirection() const
459 {
460     return pImpEditEngine->GetDefaultHorizontalTextDirection();
461 }
462 
463 SvtScriptType EditEngine::GetScriptType( const ESelection& rSelection ) const
464 {
465     EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) );
466     return pImpEditEngine->GetItemScriptType( aSel );
467 }
468 
469 LanguageType EditEngine::GetLanguage(const EditPaM& rPaM) const
470 {
471     return pImpEditEngine->GetLanguage(rPaM);
472 }
473 
474 LanguageType EditEngine::GetLanguage( sal_Int32 nPara, sal_Int32 nPos ) const
475 {
476     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
477     DBG_ASSERT( pNode, "GetLanguage - nPara is invalid!" );
478     return pNode ? pImpEditEngine->GetLanguage( EditPaM( pNode, nPos ) ) : LANGUAGE_DONTKNOW;
479 }
480 
481 
482 void EditEngine::TransliterateText( const ESelection& rSelection, TransliterationFlags nTransliterationMode )
483 {
484     pImpEditEngine->TransliterateText( pImpEditEngine->CreateSel( rSelection ), nTransliterationMode );
485 }
486 
487 EditSelection EditEngine::TransliterateText(const EditSelection& rSelection, TransliterationFlags nTransliterationMode)
488 {
489     return pImpEditEngine->TransliterateText(rSelection, nTransliterationMode);
490 }
491 
492 void EditEngine::SetAsianCompressionMode( CharCompressType n )
493 {
494     pImpEditEngine->SetAsianCompressionMode( n );
495 }
496 
497 void EditEngine::SetKernAsianPunctuation( bool b )
498 {
499     pImpEditEngine->SetKernAsianPunctuation( b );
500 }
501 
502 void EditEngine::SetAddExtLeading( bool b )
503 {
504     pImpEditEngine->SetAddExtLeading( b );
505 }
506 
507 void EditEngine::SetPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon )
508 {
509     SetPolygon( rPolyPolygon, nullptr );
510 }
511 
512 void EditEngine::SetPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DPolyPolygon* pLinePolyPolygon)
513 {
514     bool bSimple(false);
515 
516     if(pLinePolyPolygon && 1 == rPolyPolygon.count())
517     {
518         if(rPolyPolygon.getB2DPolygon(0).isClosed())
519         {
520             // open polygon
521             bSimple = true;
522         }
523     }
524 
525     TextRanger* pRanger = new TextRanger( rPolyPolygon, pLinePolyPolygon, 30, 2, 2, bSimple, true );
526     pImpEditEngine->SetTextRanger( std::unique_ptr<TextRanger>(pRanger) );
527     pImpEditEngine->SetPaperSize( pRanger->GetBoundRect().GetSize() );
528 }
529 
530 void EditEngine::ClearPolygon()
531 {
532     pImpEditEngine->SetTextRanger( nullptr );
533 }
534 
535 const Size& EditEngine::GetMinAutoPaperSize() const
536 {
537     return pImpEditEngine->GetMinAutoPaperSize();
538 }
539 
540 void EditEngine::SetMinAutoPaperSize( const Size& rSz )
541 {
542     pImpEditEngine->SetMinAutoPaperSize( rSz );
543 }
544 
545 const Size& EditEngine::GetMaxAutoPaperSize() const
546 {
547     return pImpEditEngine->GetMaxAutoPaperSize();
548 }
549 
550 void EditEngine::SetMaxAutoPaperSize( const Size& rSz )
551 {
552     pImpEditEngine->SetMaxAutoPaperSize( rSz );
553 }
554 
555 OUString EditEngine::GetText( LineEnd eEnd ) const
556 {
557     return pImpEditEngine->GetEditDoc().GetText( eEnd );
558 }
559 
560 OUString EditEngine::GetText( const ESelection& rESelection ) const
561 {
562     EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) );
563     return pImpEditEngine->GetSelected( aSel );
564 }
565 
566 sal_uInt32 EditEngine::GetTextLen() const
567 {
568     return pImpEditEngine->GetEditDoc().GetTextLen();
569 }
570 
571 sal_Int32 EditEngine::GetParagraphCount() const
572 {
573     return pImpEditEngine->aEditDoc.Count();
574 }
575 
576 sal_Int32 EditEngine::GetLineCount( sal_Int32 nParagraph ) const
577 {
578     if ( !pImpEditEngine->IsFormatted() )
579         pImpEditEngine->FormatDoc();
580     return pImpEditEngine->GetLineCount( nParagraph );
581 }
582 
583 sal_Int32 EditEngine::GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) const
584 {
585     if ( !pImpEditEngine->IsFormatted() )
586         pImpEditEngine->FormatDoc();
587     return pImpEditEngine->GetLineLen( nParagraph, nLine );
588 }
589 
590 void EditEngine::GetLineBoundaries( /*out*/sal_Int32& rStart, /*out*/sal_Int32& rEnd, sal_Int32 nParagraph, sal_Int32 nLine ) const
591 {
592     if ( !pImpEditEngine->IsFormatted() )
593         pImpEditEngine->FormatDoc();
594     return pImpEditEngine->GetLineBoundaries( rStart, rEnd, nParagraph, nLine );
595 }
596 
597 sal_Int32 EditEngine::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const
598 {
599     if ( !pImpEditEngine->IsFormatted() )
600         pImpEditEngine->FormatDoc();
601     return pImpEditEngine->GetLineNumberAtIndex( nPara, nIndex );
602 }
603 
604 sal_uInt32 EditEngine::GetLineHeight( sal_Int32 nParagraph )
605 {
606     // If someone calls GetLineHeight() with an empty Engine.
607     if ( !pImpEditEngine->IsFormatted() )
608         pImpEditEngine->FormatDoc();
609     return pImpEditEngine->GetLineHeight( nParagraph, 0 );
610 }
611 
612 tools::Rectangle EditEngine::GetParaBounds( sal_Int32 nPara )
613 {
614     if ( !pImpEditEngine->IsFormatted() )
615         pImpEditEngine->FormatDoc();
616 
617     Point aPnt = GetDocPosTopLeft( nPara );
618 
619     if( IsVertical() )
620     {
621         sal_Int32 nTextHeight = pImpEditEngine->GetTextHeight();
622         sal_Int32 nParaWidth = pImpEditEngine->CalcParaWidth( nPara, true );
623         sal_uLong nParaHeight = pImpEditEngine->GetParaHeight( nPara );
624 
625         return tools::Rectangle( nTextHeight - aPnt.Y() - nParaHeight, 0, nTextHeight - aPnt.Y(), nParaWidth );
626     }
627     else
628     {
629         sal_Int32 nParaWidth = pImpEditEngine->CalcParaWidth( nPara, true );
630         sal_uLong nParaHeight = pImpEditEngine->GetParaHeight( nPara );
631 
632         return tools::Rectangle( 0, aPnt.Y(), nParaWidth, aPnt.Y() + nParaHeight );
633     }
634 }
635 
636 sal_uInt32 EditEngine::GetTextHeight( sal_Int32 nParagraph ) const
637 {
638     if ( !pImpEditEngine->IsFormatted() )
639         pImpEditEngine->FormatDoc();
640 
641     sal_uInt32 nHeight = pImpEditEngine->GetParaHeight( nParagraph );
642     return nHeight;
643 }
644 
645 OUString EditEngine::GetWord( sal_Int32 nPara, sal_Int32 nIndex )
646 {
647     ESelection aESel( nPara, nIndex, nPara, nIndex );
648     EditSelection aSel( pImpEditEngine->CreateSel( aESel ) );
649     aSel = pImpEditEngine->SelectWord( aSel );
650     return pImpEditEngine->GetSelected( aSel );
651 }
652 
653 ESelection EditEngine::GetWord( const ESelection& rSelection, sal_uInt16 nWordType  ) const
654 {
655     // ImpEditEngine-Iteration-Methods should be const!
656     EditEngine* pE = const_cast<EditEngine*>(this);
657 
658     EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) );
659     aSel = pE->pImpEditEngine->SelectWord( aSel, nWordType );
660     return pE->pImpEditEngine->CreateESel( aSel );
661 }
662 
663 void EditEngine::CursorMoved(const ContentNode* pPrevNode)
664 {
665     pImpEditEngine->CursorMoved(pPrevNode);
666 }
667 
668 void EditEngine::CheckIdleFormatter()
669 {
670     pImpEditEngine->CheckIdleFormatter();
671 }
672 
673 bool EditEngine::IsIdleFormatterActive() const
674 {
675     return pImpEditEngine->aIdleFormatter.IsActive();
676 }
677 
678 ParaPortion* EditEngine::FindParaPortion(ContentNode const * pNode)
679 {
680     return pImpEditEngine->FindParaPortion(pNode);
681 }
682 
683 const ParaPortion* EditEngine::FindParaPortion(ContentNode const * pNode) const
684 {
685     return pImpEditEngine->FindParaPortion(pNode);
686 }
687 
688 const ParaPortion* EditEngine::GetPrevVisPortion(const ParaPortion* pCurPortion) const
689 {
690     return pImpEditEngine->GetPrevVisPortion(pCurPortion);
691 }
692 
693 SvtScriptType EditEngine::GetScriptType(const EditSelection& rSel) const
694 {
695     return pImpEditEngine->GetItemScriptType(rSel);
696 }
697 
698 void EditEngine::RemoveParaPortion(sal_Int32 nNode)
699 {
700     pImpEditEngine->GetParaPortions().Remove(nNode);
701 }
702 
703 void EditEngine::SetCallParaInsertedOrDeleted(bool b)
704 {
705     pImpEditEngine->SetCallParaInsertedOrDeleted(b);
706 }
707 
708 bool EditEngine::IsCallParaInsertedOrDeleted() const
709 {
710     return pImpEditEngine->IsCallParaInsertedOrDeleted();
711 }
712 
713 void EditEngine::AppendDeletedNodeInfo(DeletedNodeInfo* pInfo)
714 {
715     pImpEditEngine->aDeletedNodes.push_back(std::unique_ptr<DeletedNodeInfo>(pInfo));
716 }
717 
718 void EditEngine::UpdateSelections()
719 {
720     pImpEditEngine->UpdateSelections();
721 }
722 
723 void EditEngine::InsertContent(ContentNode* pNode, sal_Int32 nPos)
724 {
725     pImpEditEngine->InsertContent(pNode, nPos);
726 }
727 
728 EditPaM EditEngine::SplitContent(sal_Int32 nNode, sal_Int32 nSepPos)
729 {
730     return pImpEditEngine->SplitContent(nNode, nSepPos);
731 }
732 
733 EditPaM EditEngine::ConnectContents(sal_Int32 nLeftNode, bool bBackward)
734 {
735     return pImpEditEngine->ConnectContents(nLeftNode, bBackward);
736 }
737 
738 void EditEngine::InsertFeature(const EditSelection& rEditSelection, const SfxPoolItem& rItem)
739 {
740     pImpEditEngine->ImpInsertFeature(rEditSelection, rItem);
741 }
742 
743 EditSelection EditEngine::MoveParagraphs(const Range& rParagraphs, sal_Int32 nNewPos)
744 {
745     return pImpEditEngine->MoveParagraphs(rParagraphs, nNewPos, nullptr);
746 }
747 
748 void EditEngine::RemoveCharAttribs(sal_Int32 nPara, sal_uInt16 nWhich, bool bRemoveFeatures)
749 {
750     pImpEditEngine->RemoveCharAttribs(nPara, nWhich, bRemoveFeatures);
751 }
752 
753 void EditEngine::RemoveCharAttribs(const EditSelection& rSel, bool bRemoveParaAttribs, sal_uInt16 nWhich)
754 {
755     pImpEditEngine->RemoveCharAttribs(rSel, bRemoveParaAttribs, nWhich);
756 }
757 
758 EditEngine::ViewsType& EditEngine::GetEditViews()
759 {
760     return pImpEditEngine->GetEditViews();
761 }
762 
763 const EditEngine::ViewsType& EditEngine::GetEditViews() const
764 {
765     return pImpEditEngine->GetEditViews();
766 }
767 
768 void EditEngine::SetUndoMode(bool b)
769 {
770     pImpEditEngine->SetUndoMode(b);
771 }
772 
773 void EditEngine::FormatAndUpdate(EditView* pCurView, bool bCalledFromUndo)
774 {
775     pImpEditEngine->FormatAndUpdate(pCurView, bCalledFromUndo);
776 }
777 
778 void EditEngine::Undo(EditView* pView)
779 {
780     pImpEditEngine->Undo(pView);
781 }
782 
783 void EditEngine::Redo(EditView* pView)
784 {
785     pImpEditEngine->Redo(pView);
786 }
787 
788 uno::Reference<datatransfer::XTransferable> EditEngine::CreateTransferable(const EditSelection& rSelection)
789 {
790     return pImpEditEngine->CreateTransferable(rSelection);
791 }
792 
793 void EditEngine::ParaAttribsToCharAttribs(ContentNode* pNode)
794 {
795     pImpEditEngine->ParaAttribsToCharAttribs(pNode);
796 }
797 
798 EditPaM EditEngine::CreateEditPaM(const EPaM& rEPaM)
799 {
800     return pImpEditEngine->CreateEditPaM(rEPaM);
801 }
802 
803 EditPaM EditEngine::ConnectParagraphs(
804         ContentNode* pLeft, ContentNode* pRight, bool bBackward)
805 {
806     return pImpEditEngine->ImpConnectParagraphs(pLeft, pRight, bBackward);
807 }
808 
809 EditPaM EditEngine::InsertField(const EditSelection& rEditSelection, const SvxFieldItem& rFld)
810 {
811     return pImpEditEngine->InsertField(rEditSelection, rFld);
812 }
813 
814 EditPaM EditEngine::InsertText(const EditSelection& aCurEditSelection, const OUString& rStr)
815 {
816     return pImpEditEngine->InsertText(aCurEditSelection, rStr);
817 }
818 
819 EditSelection EditEngine::InsertText(const EditTextObject& rTextObject, const EditSelection& rSel)
820 {
821     return pImpEditEngine->InsertText(rTextObject, rSel);
822 }
823 
824 EditSelection EditEngine::InsertText(
825     uno::Reference<datatransfer::XTransferable > const & rxDataObj,
826     const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial)
827 {
828     return pImpEditEngine->PasteText(rxDataObj, rBaseURL, rPaM, bUseSpecial);
829 }
830 
831 EditPaM EditEngine::EndOfWord(const EditPaM& rPaM)
832 {
833     return pImpEditEngine->EndOfWord(rPaM);
834 }
835 
836 EditPaM EditEngine::GetPaM(const Point& aDocPos, bool bSmart)
837 {
838     return pImpEditEngine->GetPaM(aDocPos, bSmart);
839 }
840 
841 EditSelection EditEngine::SelectWord(
842         const EditSelection& rCurSelection, sal_Int16 nWordType)
843 {
844     return pImpEditEngine->SelectWord(rCurSelection, nWordType);
845 }
846 
847 long EditEngine::GetXPos(
848         const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nIndex, bool bPreferPortionStart) const
849 {
850     return pImpEditEngine->GetXPos(pParaPortion, pLine, nIndex, bPreferPortionStart);
851 }
852 
853 Range EditEngine::GetLineXPosStartEnd(
854         const ParaPortion* pParaPortion, const EditLine* pLine) const
855 {
856     return pImpEditEngine->GetLineXPosStartEnd(pParaPortion, pLine);
857 }
858 
859 bool EditEngine::IsFormatted() const
860 {
861     return pImpEditEngine->IsFormatted();
862 }
863 
864 EditPaM EditEngine::CursorLeft(const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode)
865 {
866     return pImpEditEngine->CursorLeft(rPaM, nCharacterIteratorMode);
867 }
868 
869 EditPaM EditEngine::CursorRight(const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode)
870 {
871     return pImpEditEngine->CursorRight(rPaM, nCharacterIteratorMode);
872 }
873 
874 InternalEditStatus& EditEngine::GetInternalEditStatus()
875 {
876     return pImpEditEngine->GetStatus();
877 }
878 
879 EditDoc& EditEngine::GetEditDoc()
880 {
881     return pImpEditEngine->GetEditDoc();
882 }
883 
884 const EditDoc& EditEngine::GetEditDoc() const
885 {
886     return pImpEditEngine->GetEditDoc();
887 }
888 
889 void EditEngine::dumpAsXmlEditDoc(xmlTextWriterPtr pWriter) const
890 {
891     pImpEditEngine->GetEditDoc().dumpAsXml(pWriter);
892 }
893 
894 ParaPortionList& EditEngine::GetParaPortions()
895 {
896     return pImpEditEngine->GetParaPortions();
897 }
898 
899 const ParaPortionList& EditEngine::GetParaPortions() const
900 {
901     return pImpEditEngine->GetParaPortions();
902 }
903 
904 void EditEngine::SeekCursor(ContentNode* pNode, sal_Int32 nPos, SvxFont& rFont)
905 {
906     pImpEditEngine->SeekCursor(pNode, nPos, rFont);
907 }
908 
909 EditPaM EditEngine::DeleteSelection(const EditSelection& rSel)
910 {
911     return pImpEditEngine->ImpDeleteSelection(rSel);
912 }
913 
914 ESelection EditEngine::CreateESelection(const EditSelection& rSel)
915 {
916     return pImpEditEngine->CreateESel(rSel);
917 }
918 
919 EditSelection EditEngine::CreateSelection(const ESelection& rSel)
920 {
921     return pImpEditEngine->CreateSel(rSel);
922 }
923 
924 const SfxItemSet& EditEngine::GetBaseParaAttribs(sal_Int32 nPara) const
925 {
926     return pImpEditEngine->GetParaAttribs(nPara);
927 }
928 
929 void EditEngine::SetParaAttribsOnly(sal_Int32 nPara, const SfxItemSet& rSet)
930 {
931     pImpEditEngine->SetParaAttribs(nPara, rSet);
932 }
933 
934 void EditEngine::SetAttribs(const EditSelection& rSel, const SfxItemSet& rSet, SetAttribsMode nSpecial)
935 {
936     pImpEditEngine->SetAttribs(rSel, rSet, nSpecial);
937 }
938 
939 OUString EditEngine::GetSelected(const EditSelection& rSel) const
940 {
941     return pImpEditEngine->GetSelected(rSel);
942 }
943 
944 EditPaM EditEngine::DeleteSelected(const EditSelection& rSel)
945 {
946     return pImpEditEngine->DeleteSelected(rSel);
947 }
948 
949 void EditEngine::HandleBeginPasteOrDrop(PasteOrDropInfos& rInfos)
950 {
951     pImpEditEngine->aBeginPasteOrDropHdl.Call(rInfos);
952 }
953 
954 void EditEngine::HandleEndPasteOrDrop(PasteOrDropInfos& rInfos)
955 {
956     pImpEditEngine->aEndPasteOrDropHdl.Call(rInfos);
957 }
958 
959 bool EditEngine::HasText() const
960 {
961     return pImpEditEngine->ImplHasText();
962 }
963 
964 const EditSelectionEngine& EditEngine::GetSelectionEngine() const
965 {
966     return pImpEditEngine->aSelEngine;
967 }
968 
969 void EditEngine::SetInSelectionMode(bool b)
970 {
971     pImpEditEngine->bInSelection = b;
972 }
973 
974 bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, vcl::Window const * pFrameWin )
975 {
976     DBG_ASSERT( pEditView, "no View - no cookie !" );
977 
978     bool bDone = true;
979 
980     bool bModified  = false;
981     bool bMoved     = false;
982     bool bAllowIdle = true;
983     bool bReadOnly  = pEditView->IsReadOnly();
984 
985     GetCursorFlags nNewCursorFlags = GetCursorFlags::NONE;
986     bool bSetCursorFlags = true;
987 
988     EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
989     DBG_ASSERT( !aCurSel.IsInvalid(), "Blinde Selection in EditEngine::PostKeyEvent" );
990 
991     OUString aAutoText( pImpEditEngine->GetAutoCompleteText() );
992     if (!pImpEditEngine->GetAutoCompleteText().isEmpty())
993         pImpEditEngine->SetAutoCompleteText(OUString(), true);
994 
995     sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode();
996     KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
997     if ( eFunc != KeyFuncType::DONTKNOW )
998     {
999         switch ( eFunc )
1000         {
1001             case KeyFuncType::UNDO:
1002             {
1003                 if ( !bReadOnly )
1004                     pEditView->Undo();
1005                 return true;
1006             }
1007             case KeyFuncType::REDO:
1008             {
1009                 if ( !bReadOnly )
1010                     pEditView->Redo();
1011                 return true;
1012             }
1013 
1014             default:    // is then possible edited below.
1015                         eFunc = KeyFuncType::DONTKNOW;
1016         }
1017     }
1018 
1019     if ( eFunc == KeyFuncType::DONTKNOW )
1020     {
1021         switch ( nCode )
1022         {
1023            #if defined( DBG_UTIL ) || (OSL_DEBUG_LEVEL > 1)
1024             case KEY_F1:
1025             {
1026                 if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
1027                 {
1028                     sal_Int32 nParas = GetParagraphCount();
1029                     Point aPos;
1030                     Point aViewStart( pEditView->GetOutputArea().TopLeft() );
1031                     long n20 = 40 * pImpEditEngine->nOnePixelInRef;
1032                     for ( sal_Int32 n = 0; n < nParas; n++ )
1033                     {
1034                         long nH = GetTextHeight( n );
1035                         Point P1( aViewStart.X() + n20 + n20*(n%2), aViewStart.Y() + aPos.Y() );
1036                         Point P2( P1 );
1037                         P2.AdjustX(n20 );
1038                         P2.AdjustY(nH );
1039                         pEditView->GetWindow()->SetLineColor();
1040                         pEditView->GetWindow()->SetFillColor( (n%2) ? COL_YELLOW : COL_LIGHTGREEN );
1041                         pEditView->GetWindow()->DrawRect( tools::Rectangle( P1, P2 ) );
1042                         aPos.AdjustY(nH );
1043                     }
1044                 }
1045                 bDone = false;
1046             }
1047             break;
1048             case KEY_F11:
1049             {
1050                 if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
1051                 {
1052                     bDebugPaint = !bDebugPaint;
1053                     OStringBuffer aInfo("DebugPaint: ");
1054                     aInfo.append(bDebugPaint ? "On" : "Off");
1055                     std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pEditView->GetWindow()->GetFrameWeld(),
1056                                                                   VclMessageType::Info, VclButtonsType::Ok,
1057                                                                   OStringToOUString(aInfo.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US)));
1058                     xInfoBox->run();
1059 
1060                 }
1061                 bDone = false;
1062             }
1063             break;
1064             case KEY_F12:
1065             {
1066                 if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
1067                 {
1068                     EditDbg::ShowEditEngineData( this );
1069                 }
1070                 bDone = false;
1071             }
1072             break;
1073            #endif
1074             case KEY_UP:
1075             case KEY_DOWN:
1076             case KEY_LEFT:
1077             case KEY_RIGHT:
1078             case KEY_HOME:
1079             case KEY_END:
1080             case KEY_PAGEUP:
1081             case KEY_PAGEDOWN:
1082             case css::awt::Key::MOVE_WORD_FORWARD:
1083             case css::awt::Key::SELECT_WORD_FORWARD:
1084             case css::awt::Key::MOVE_WORD_BACKWARD:
1085             case css::awt::Key::SELECT_WORD_BACKWARD:
1086             case css::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1087             case css::awt::Key::MOVE_TO_END_OF_LINE:
1088             case css::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1089             case css::awt::Key::SELECT_TO_END_OF_LINE:
1090             case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1091             case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1092             case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1093             case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1094             case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1095             case css::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1096             case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1097             case css::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1098             {
1099                 if ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) )
1100                 {
1101                     if ( pImpEditEngine->DoVisualCursorTraveling() && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) /* || ( nCode == KEY_HOME ) || ( nCode == KEY_END ) */ ) )
1102                         bSetCursorFlags = false;    // Will be manipulated within visual cursor move
1103 
1104                     aCurSel = pImpEditEngine->MoveCursor( rKeyEvent, pEditView );
1105 
1106                     if ( aCurSel.HasRange() ) {
1107                         if (vcl::Window* pWindow = pEditView->GetWindow()) {
1108                             Reference<css::datatransfer::clipboard::XClipboard> aSelection(pWindow->GetPrimarySelection());
1109                             pEditView->pImpEditView->CutCopy( aSelection, false );
1110                         }
1111                     }
1112 
1113                     bMoved = true;
1114                     if ( nCode == KEY_HOME )
1115                         nNewCursorFlags |= GetCursorFlags::StartOfLine;
1116                     else if ( nCode == KEY_END )
1117                         nNewCursorFlags |= GetCursorFlags::EndOfLine;
1118 
1119                 }
1120 #if OSL_DEBUG_LEVEL > 1
1121                 GetLanguage( pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() ), aCurSel.Max().GetIndex() );
1122 #endif
1123             }
1124             break;
1125             case KEY_BACKSPACE:
1126             case KEY_DELETE:
1127             case css::awt::Key::DELETE_WORD_BACKWARD:
1128             case css::awt::Key::DELETE_WORD_FORWARD:
1129             case css::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH:
1130             case css::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
1131             {
1132                 if ( !bReadOnly && !rKeyEvent.GetKeyCode().IsMod2() )
1133                 {
1134                     // check if we are behind a bullet and using the backspace key
1135                     ContentNode *pNode = aCurSel.Min().GetNode();
1136                     const SvxNumberFormat *pFmt = pImpEditEngine->GetNumberFormat( pNode );
1137                     if (pFmt && nCode == KEY_BACKSPACE &&
1138                         !aCurSel.HasRange() && aCurSel.Min().GetIndex() == 0)
1139                     {
1140                         // if the bullet is still visible, just make it invisible.
1141                         // Otherwise continue as usual.
1142 
1143 
1144                         sal_Int32 nPara = pImpEditEngine->GetEditDoc().GetPos( pNode );
1145                         SfxBoolItem aBulletState( pImpEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) );
1146 
1147                         if ( aBulletState.GetValue() )
1148                         {
1149 
1150                             aBulletState.SetValue( false );
1151                             SfxItemSet aSet( pImpEditEngine->GetParaAttribs( nPara ) );
1152                             aSet.Put( aBulletState );
1153                             pImpEditEngine->SetParaAttribs( nPara, aSet );
1154 
1155                             // have this and the following paragraphs formatted and repainted.
1156                             // (not painting a numbering in the list may cause the following
1157                             // numberings to have different numbers than before and thus the
1158                             // length may have changed as well )
1159                             pImpEditEngine->FormatAndUpdate( pImpEditEngine->GetActiveView() );
1160 
1161                             break;
1162                         }
1163                     }
1164 
1165                     sal_uInt8 nDel = 0;
1166                     DeleteMode nMode = DeleteMode::Simple;
1167                     switch( nCode )
1168                     {
1169                     case css::awt::Key::DELETE_WORD_BACKWARD:
1170                         nMode = DeleteMode::RestOfWord;
1171                         nDel = DEL_LEFT;
1172                         break;
1173                     case css::awt::Key::DELETE_WORD_FORWARD:
1174                         nMode = DeleteMode::RestOfWord;
1175                         nDel = DEL_RIGHT;
1176                         break;
1177                     case css::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH:
1178                         nMode = DeleteMode::RestOfContent;
1179                         nDel = DEL_LEFT;
1180                         break;
1181                     case css::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
1182                         nMode = DeleteMode::RestOfContent;
1183                         nDel = DEL_RIGHT;
1184                         break;
1185                     default:
1186                         nDel = ( nCode == KEY_DELETE ) ? DEL_RIGHT : DEL_LEFT;
1187                         nMode = rKeyEvent.GetKeyCode().IsMod1() ? DeleteMode::RestOfWord : DeleteMode::Simple;
1188                         if ( ( nMode == DeleteMode::RestOfWord ) && rKeyEvent.GetKeyCode().IsShift() )
1189                             nMode = DeleteMode::RestOfContent;
1190                         break;
1191                     }
1192 
1193                     pEditView->pImpEditView->DrawSelectionXOR();
1194                     pImpEditEngine->UndoActionStart( EDITUNDO_DELETE );
1195                     aCurSel = pImpEditEngine->DeleteLeftOrRight( aCurSel, nDel, nMode );
1196                     pImpEditEngine->UndoActionEnd();
1197                     bModified = true;
1198                     bAllowIdle = false;
1199                 }
1200             }
1201             break;
1202             case KEY_TAB:
1203             {
1204                 if ( !bReadOnly && !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
1205                 {
1206                     bool bShift = rKeyEvent.GetKeyCode().IsShift();
1207                     if ( !bShift )
1208                     {
1209                         bool bSel = pEditView->HasSelection();
1210                         if ( bSel )
1211                             pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
1212                         if ( pImpEditEngine->GetStatus().DoAutoCorrect() )
1213                             aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin );
1214                         aCurSel = pImpEditEngine->InsertTab( aCurSel );
1215                         if ( bSel )
1216                             pImpEditEngine->UndoActionEnd();
1217                         bModified = true;
1218                     }
1219                 }
1220                 else
1221                     bDone = false;
1222             }
1223             break;
1224             case KEY_RETURN:
1225             {
1226                 if ( !bReadOnly )
1227                 {
1228                     pEditView->pImpEditView->DrawSelectionXOR();
1229                     if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
1230                     {
1231                         pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
1232                         if ( rKeyEvent.GetKeyCode().IsShift() )
1233                         {
1234                             aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin );
1235                             aCurSel = pImpEditEngine->InsertLineBreak( aCurSel );
1236                         }
1237                         else
1238                         {
1239                             if (aAutoText.isEmpty())
1240                             {
1241                                 if ( pImpEditEngine->GetStatus().DoAutoCorrect() )
1242                                     aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin );
1243                                 aCurSel = pImpEditEngine->InsertParaBreak( aCurSel );
1244                             }
1245                             else
1246                             {
1247                                 DBG_ASSERT( !aCurSel.HasRange(), "Selection on complete?!" );
1248                                 EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) );
1249                                 aCurSel = pImpEditEngine->InsertText(
1250                                                 EditSelection( aStart, aCurSel.Max() ), aAutoText );
1251                                 pImpEditEngine->SetAutoCompleteText( OUString(), true );
1252                             }
1253                         }
1254                         pImpEditEngine->UndoActionEnd();
1255                         bModified = true;
1256                     }
1257                 }
1258             }
1259             break;
1260             case KEY_INSERT:
1261             {
1262                 if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
1263                     pEditView->SetInsertMode( !pEditView->IsInsertMode() );
1264             }
1265             break;
1266             default:
1267             {
1268                 #if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL)
1269                     if ( ( nCode == KEY_W ) && rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
1270                     {
1271                         SfxItemSet aAttribs = pEditView->GetAttribs();
1272                         const SvxFrameDirectionItem& rCurrentWritingMode = (const SvxFrameDirectionItem&)aAttribs.Get( EE_PARA_WRITINGDIR );
1273                         SvxFrameDirectionItem aNewItem( SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR );
1274                         if ( rCurrentWritingMode.GetValue() != SvxFrameDirection::Horizontal_RL_TB )
1275                             aNewItem.SetValue( SvxFrameDirection::Horizontal_RL_TB );
1276                         aAttribs.Put( aNewItem );
1277                         pEditView->SetAttribs( aAttribs );
1278                     }
1279                 #endif
1280                 if ( !bReadOnly && IsSimpleCharInput( rKeyEvent ) )
1281                 {
1282                     sal_Unicode nCharCode = rKeyEvent.GetCharCode();
1283                     pEditView->pImpEditView->DrawSelectionXOR();
1284                     // Autocorrection?
1285                     if ( ( pImpEditEngine->GetStatus().DoAutoCorrect() ) &&
1286                         ( SvxAutoCorrect::IsAutoCorrectChar( nCharCode ) ||
1287                           pImpEditEngine->IsNbspRunNext() ) )
1288                     {
1289                         aCurSel = pImpEditEngine->AutoCorrect(
1290                             aCurSel, nCharCode, !pEditView->IsInsertMode(), pFrameWin );
1291                     }
1292                     else
1293                     {
1294                         aCurSel = pImpEditEngine->InsertTextUserInput( aCurSel, nCharCode, !pEditView->IsInsertMode() );
1295                     }
1296                     // AutoComplete ???
1297                     if ( pImpEditEngine->GetStatus().DoAutoComplete() && ( nCharCode != ' ' ) )
1298                     {
1299                         // Only at end of word...
1300                         sal_Int32 nIndex = aCurSel.Max().GetIndex();
1301                         if ( ( nIndex >= aCurSel.Max().GetNode()->Len() ) ||
1302                              ( pImpEditEngine->aWordDelimiters.indexOf( aCurSel.Max().GetNode()->GetChar( nIndex ) ) != -1 ) )
1303                         {
1304                             EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) );
1305                             OUString aWord = pImpEditEngine->GetSelected( EditSelection( aStart, aCurSel.Max() ) );
1306                             if ( aWord.getLength() >= 3 )
1307                             {
1308                                 OUString aComplete;
1309 
1310                                 LanguageType eLang = pImpEditEngine->GetLanguage( EditPaM( aStart.GetNode(), aStart.GetIndex()+1));
1311                                 LanguageTag aLanguageTag( eLang);
1312 
1313                                 if (!pImpEditEngine->xLocaleDataWrapper.isInitialized())
1314                                     pImpEditEngine->xLocaleDataWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), aLanguageTag);
1315                                 else
1316                                     pImpEditEngine->xLocaleDataWrapper.changeLocale( aLanguageTag);
1317 
1318                                 if (!pImpEditEngine->xTransliterationWrapper.isInitialized())
1319                                     pImpEditEngine->xTransliterationWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), eLang);
1320                                 else
1321                                     pImpEditEngine->xTransliterationWrapper.changeLocale( eLang);
1322 
1323                                 const ::utl::TransliterationWrapper* pTransliteration = pImpEditEngine->xTransliterationWrapper.get();
1324                                 Sequence< i18n::CalendarItem2 > xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarDays();
1325                                 sal_Int32 nCount = xItem.getLength();
1326                                 const i18n::CalendarItem2* pArr = xItem.getArray();
1327                                 for( sal_Int32 n = 0; n <= nCount; ++n )
1328                                 {
1329                                     const OUString& rDay = pArr[n].FullName;
1330                                     if( pTransliteration->isMatch( aWord, rDay) )
1331                                     {
1332                                         aComplete = rDay;
1333                                         break;
1334                                     }
1335                                 }
1336 
1337                                 if ( aComplete.isEmpty() )
1338                                 {
1339                                     xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarMonths();
1340                                     sal_Int32 nMonthCount = xItem.getLength();
1341                                     const i18n::CalendarItem2* pMonthArr = xItem.getArray();
1342                                     for( sal_Int32 n = 0; n <= nMonthCount; ++n )
1343                                     {
1344                                         const OUString& rMon = pMonthArr[n].FullName;
1345                                         if( pTransliteration->isMatch( aWord, rMon) )
1346                                         {
1347                                             aComplete = rMon;
1348                                             break;
1349                                         }
1350                                     }
1351                                 }
1352 
1353                                 if( !aComplete.isEmpty() && ( ( aWord.getLength() + 1 ) < aComplete.getLength() ) )
1354                                 {
1355                                     pImpEditEngine->SetAutoCompleteText( aComplete, false );
1356                                     Point aPos = pImpEditEngine->PaMtoEditCursor( aCurSel.Max() ).TopLeft();
1357                                     aPos = pEditView->pImpEditView->GetWindowPos( aPos );
1358                                     aPos = pEditView->pImpEditView->GetWindow()->LogicToPixel( aPos );
1359                                     aPos = pEditView->GetWindow()->OutputToScreenPixel( aPos );
1360                                     aPos.AdjustY( -3 );
1361                                     Help::ShowQuickHelp( pEditView->GetWindow(), tools::Rectangle( aPos, Size( 1, 1 ) ), aComplete, QuickHelpFlags::Bottom|QuickHelpFlags::Left );
1362                                 }
1363                             }
1364                         }
1365                     }
1366                     bModified = true;
1367                 }
1368                 else
1369                     bDone = false;
1370             }
1371         }
1372     }
1373 
1374     pEditView->pImpEditView->SetEditSelection( aCurSel );
1375     if (comphelper::LibreOfficeKit::isActive())
1376     {
1377         pEditView->pImpEditView->DrawSelectionXOR();
1378     }
1379     pImpEditEngine->UpdateSelections();
1380 
1381     if ( ( !IsVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ) ||
1382          ( IsVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) ))
1383     {
1384         pEditView->pImpEditView->nTravelXPos = TRAVEL_X_DONTKNOW;
1385     }
1386 
1387     if ( /* ( nCode != KEY_HOME ) && ( nCode != KEY_END ) && */
1388         ( !IsVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) ) ||
1389          ( IsVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ))
1390     {
1391         pEditView->pImpEditView->SetCursorBidiLevel( CURSOR_BIDILEVEL_DONTKNOW );
1392     }
1393 
1394     if ( bSetCursorFlags )
1395         pEditView->pImpEditView->nExtraCursorFlags = nNewCursorFlags;
1396 
1397     if ( bModified )
1398     {
1399         DBG_ASSERT( !bReadOnly, "ReadOnly but modified???" );
1400         // Idle-Formatter only when AnyInput.
1401         if ( bAllowIdle && pImpEditEngine->GetStatus().UseIdleFormatter()
1402                 && Application::AnyInput( VclInputFlags::KEYBOARD) )
1403             pImpEditEngine->IdleFormatAndUpdate( pEditView );
1404         else
1405             pImpEditEngine->FormatAndUpdate( pEditView );
1406     }
1407     else if ( bMoved )
1408     {
1409         bool bGotoCursor = pEditView->pImpEditView->DoAutoScroll();
1410         pEditView->pImpEditView->ShowCursor( bGotoCursor, true );
1411         pImpEditEngine->CallStatusHdl();
1412     }
1413 
1414     return bDone;
1415 }
1416 
1417 sal_uInt32 EditEngine::GetTextHeight() const
1418 {
1419 
1420     if ( !pImpEditEngine->IsFormatted() )
1421         pImpEditEngine->FormatDoc();
1422 
1423     sal_uInt32 nHeight = !IsVertical() ? pImpEditEngine->GetTextHeight() : pImpEditEngine->CalcTextWidth( true );
1424     return nHeight;
1425 }
1426 
1427 sal_uInt32 EditEngine::GetTextHeightNTP() const
1428 {
1429 
1430     if ( !pImpEditEngine->IsFormatted() )
1431         pImpEditEngine->FormatDoc();
1432 
1433     if ( IsVertical() )
1434         return pImpEditEngine->CalcTextWidth( true );
1435 
1436     return pImpEditEngine->GetTextHeightNTP();
1437 }
1438 
1439 sal_uInt32 EditEngine::CalcTextWidth()
1440 {
1441 
1442     if ( !pImpEditEngine->IsFormatted() )
1443         pImpEditEngine->FormatDoc();
1444 
1445     sal_uInt32 nWidth = !IsVertical() ? pImpEditEngine->CalcTextWidth( true ) : pImpEditEngine->GetTextHeight();
1446     return nWidth;
1447 }
1448 
1449 void EditEngine::SetUpdateMode( bool bUpdate )
1450 {
1451     pImpEditEngine->SetUpdateMode( bUpdate );
1452     if ( pImpEditEngine->pActiveView )
1453         pImpEditEngine->pActiveView->ShowCursor( false, false, /*bActivate=*/true );
1454 }
1455 
1456 bool EditEngine::GetUpdateMode() const
1457 {
1458     return pImpEditEngine->GetUpdateMode();
1459 }
1460 
1461 void EditEngine::Clear()
1462 {
1463     pImpEditEngine->Clear();
1464 }
1465 
1466 void EditEngine::SetText( const OUString& rText )
1467 {
1468     pImpEditEngine->SetText( rText );
1469     if ( !rText.isEmpty() )
1470         pImpEditEngine->FormatAndUpdate();
1471 }
1472 
1473 ErrCode EditEngine::Read( SvStream& rInput, const OUString& rBaseURL, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs /* = NULL */ )
1474 {
1475     bool bUndoEnabled = pImpEditEngine->IsUndoEnabled();
1476     pImpEditEngine->EnableUndo( false );
1477     pImpEditEngine->SetText( OUString() );
1478     EditPaM aPaM( pImpEditEngine->GetEditDoc().GetStartPaM() );
1479     pImpEditEngine->Read( rInput, rBaseURL, eFormat, EditSelection( aPaM, aPaM ), pHTTPHeaderAttrs );
1480     pImpEditEngine->EnableUndo( bUndoEnabled );
1481     return rInput.GetError();
1482 }
1483 
1484 void EditEngine::Write( SvStream& rOutput, EETextFormat eFormat )
1485 {
1486     EditPaM aStartPaM( pImpEditEngine->GetEditDoc().GetStartPaM() );
1487     EditPaM aEndPaM( pImpEditEngine->GetEditDoc().GetEndPaM() );
1488     pImpEditEngine->Write( rOutput, eFormat, EditSelection( aStartPaM, aEndPaM ) );
1489 }
1490 
1491 std::unique_ptr<EditTextObject> EditEngine::CreateTextObject()
1492 {
1493     return pImpEditEngine->CreateTextObject();
1494 }
1495 
1496 std::unique_ptr<EditTextObject> EditEngine::CreateTextObject( const ESelection& rESelection )
1497 {
1498     EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) );
1499     return pImpEditEngine->CreateTextObject( aSel );
1500 }
1501 
1502 std::unique_ptr<EditTextObject> EditEngine::GetEmptyTextObject() const
1503 {
1504     return pImpEditEngine->GetEmptyTextObject();
1505 }
1506 
1507 
1508 void EditEngine::SetText( const EditTextObject& rTextObject )
1509 {
1510     pImpEditEngine->SetText( rTextObject );
1511     pImpEditEngine->FormatAndUpdate();
1512 }
1513 
1514 void EditEngine::ShowParagraph( sal_Int32 nParagraph, bool bShow )
1515 {
1516     pImpEditEngine->ShowParagraph( nParagraph, bShow );
1517 }
1518 
1519 void EditEngine::SetNotifyHdl( const Link<EENotify&,void>& rLink )
1520 {
1521     pImpEditEngine->SetNotifyHdl( rLink );
1522 }
1523 
1524 Link<EENotify&,void> const & EditEngine::GetNotifyHdl() const
1525 {
1526     return pImpEditEngine->GetNotifyHdl();
1527 }
1528 
1529 void EditEngine::SetStatusEventHdl( const Link<EditStatus&, void>& rLink )
1530 {
1531     pImpEditEngine->SetStatusEventHdl( rLink );
1532 }
1533 
1534 Link<EditStatus&, void> const & EditEngine::GetStatusEventHdl() const
1535 {
1536     return pImpEditEngine->GetStatusEventHdl();
1537 }
1538 
1539 void EditEngine::SetHtmlImportHdl( const Link<HtmlImportInfo&,void>& rLink )
1540 {
1541     pImpEditEngine->aHtmlImportHdl = rLink;
1542 }
1543 
1544 const Link<HtmlImportInfo&,void>& EditEngine::GetHtmlImportHdl() const
1545 {
1546     return pImpEditEngine->aHtmlImportHdl;
1547 }
1548 
1549 void EditEngine::SetRtfImportHdl( const Link<RtfImportInfo&,void>& rLink )
1550 {
1551     pImpEditEngine->aRtfImportHdl = rLink;
1552 }
1553 
1554 const Link<RtfImportInfo&,void>& EditEngine::GetRtfImportHdl() const
1555 {
1556     return pImpEditEngine->aRtfImportHdl;
1557 }
1558 
1559 void EditEngine::SetBeginMovingParagraphsHdl( const Link<MoveParagraphsInfo&,void>& rLink )
1560 {
1561     pImpEditEngine->aBeginMovingParagraphsHdl = rLink;
1562 }
1563 
1564 void EditEngine::SetEndMovingParagraphsHdl( const Link<MoveParagraphsInfo&,void>& rLink )
1565 {
1566     pImpEditEngine->aEndMovingParagraphsHdl = rLink;
1567 }
1568 
1569 void EditEngine::SetBeginPasteOrDropHdl( const Link<PasteOrDropInfos&,void>& rLink )
1570 {
1571 
1572     pImpEditEngine->aBeginPasteOrDropHdl = rLink;
1573 }
1574 
1575 void EditEngine::SetEndPasteOrDropHdl( const Link<PasteOrDropInfos&,void>& rLink )
1576 {
1577     pImpEditEngine->aEndPasteOrDropHdl = rLink;
1578 }
1579 
1580 std::unique_ptr<EditTextObject> EditEngine::CreateTextObject( sal_Int32 nPara, sal_Int32 nParas )
1581 {
1582     DBG_ASSERT( 0 <= nPara && nPara < pImpEditEngine->GetEditDoc().Count(), "CreateTextObject: Startpara out of Range" );
1583     DBG_ASSERT( nParas <= pImpEditEngine->GetEditDoc().Count() - nPara, "CreateTextObject: Endpara out of Range" );
1584 
1585     ContentNode* pStartNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
1586     ContentNode* pEndNode = pImpEditEngine->GetEditDoc().GetObject( nPara+nParas-1 );
1587     DBG_ASSERT( pStartNode, "Start-Paragraph does not exist: CreateTextObject" );
1588     DBG_ASSERT( pEndNode, "End-Paragraph does not exist: CreateTextObject" );
1589 
1590     if ( pStartNode && pEndNode )
1591     {
1592         EditSelection aTmpSel;
1593         aTmpSel.Min() = EditPaM( pStartNode, 0 );
1594         aTmpSel.Max() = EditPaM( pEndNode, pEndNode->Len() );
1595         return pImpEditEngine->CreateTextObject( aTmpSel );
1596     }
1597     return nullptr;
1598 }
1599 
1600 void EditEngine::RemoveParagraph( sal_Int32 nPara )
1601 {
1602     DBG_ASSERT( pImpEditEngine->GetEditDoc().Count() > 1, "The first paragraph should not be deleted!" );
1603     if( pImpEditEngine->GetEditDoc().Count() <= 1 )
1604         return;
1605 
1606     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
1607     const ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara );
1608     DBG_ASSERT( pPortion && pNode, "Paragraph not found: RemoveParagraph" );
1609     if ( pNode && pPortion )
1610     {
1611         // No Undo encapsulation needed.
1612         pImpEditEngine->ImpRemoveParagraph( nPara );
1613         pImpEditEngine->InvalidateFromParagraph( nPara );
1614         pImpEditEngine->UpdateSelections();
1615         pImpEditEngine->FormatAndUpdate();
1616     }
1617 }
1618 
1619 sal_Int32 EditEngine::GetTextLen( sal_Int32 nPara ) const
1620 {
1621     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
1622     DBG_ASSERT( pNode, "Paragraph not found: GetTextLen" );
1623     if ( pNode )
1624         return pNode->Len();
1625     return 0;
1626 }
1627 
1628 OUString EditEngine::GetText( sal_Int32 nPara ) const
1629 {
1630     OUString aStr;
1631     if ( 0 <= nPara && nPara < pImpEditEngine->GetEditDoc().Count() )
1632         aStr = pImpEditEngine->GetEditDoc().GetParaAsString( nPara );
1633     return aStr;
1634 }
1635 
1636 void EditEngine::SetModifyHdl( const Link<LinkParamNone*,void>& rLink )
1637 {
1638     pImpEditEngine->SetModifyHdl( rLink );
1639 }
1640 
1641 Link<LinkParamNone*,void> const & EditEngine::GetModifyHdl() const
1642 {
1643     return pImpEditEngine->GetModifyHdl();
1644 }
1645 
1646 
1647 void EditEngine::ClearModifyFlag()
1648 {
1649     pImpEditEngine->SetModifyFlag( false );
1650 }
1651 
1652 void EditEngine::SetModified()
1653 {
1654     pImpEditEngine->SetModifyFlag( true );
1655 }
1656 
1657 bool EditEngine::IsModified() const
1658 {
1659     return pImpEditEngine->IsModified();
1660 }
1661 
1662 bool EditEngine::IsInSelectionMode() const
1663 {
1664     return ( pImpEditEngine->IsInSelectionMode() ||
1665                 pImpEditEngine->GetSelEngine().IsInSelection() );
1666 }
1667 
1668 void EditEngine::InsertParagraph( sal_Int32 nPara, const EditTextObject& rTxtObj )
1669 {
1670     if ( nPara > GetParagraphCount() )
1671     {
1672         SAL_WARN_IF( nPara != EE_PARA_APPEND, "editeng", "Paragraph number too large, but not EE_PARA_APPEND!" );
1673         nPara = GetParagraphCount();
1674     }
1675 
1676     pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
1677 
1678     // No Undo compounding needed.
1679     EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) );
1680     // When InsertParagraph from the outside, no hard attributes
1681     // should be taken over!
1682     pImpEditEngine->RemoveCharAttribs( nPara );
1683     pImpEditEngine->InsertText( rTxtObj, EditSelection( aPaM, aPaM ) );
1684 
1685     pImpEditEngine->UndoActionEnd();
1686 
1687     pImpEditEngine->FormatAndUpdate();
1688 }
1689 
1690 void EditEngine::InsertParagraph(sal_Int32 nPara, const OUString& rTxt)
1691 {
1692     if ( nPara > GetParagraphCount() )
1693     {
1694         SAL_WARN_IF( nPara != EE_PARA_APPEND, "editeng", "Paragraph number too large, but not EE_PARA_APPEND!" );
1695         nPara = GetParagraphCount();
1696     }
1697 
1698     pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
1699     EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) );
1700     // When InsertParagraph from the outside, no hard attributes
1701     // should be taken over!
1702     pImpEditEngine->RemoveCharAttribs( nPara );
1703     pImpEditEngine->UndoActionEnd();
1704     pImpEditEngine->ImpInsertText( EditSelection( aPaM, aPaM ), rTxt );
1705     pImpEditEngine->FormatAndUpdate();
1706 }
1707 
1708 void EditEngine::SetText(sal_Int32 nPara, const OUString& rTxt)
1709 {
1710     std::unique_ptr<EditSelection> pSel = pImpEditEngine->SelectParagraph( nPara );
1711     if ( pSel )
1712     {
1713         pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
1714         pImpEditEngine->ImpInsertText( *pSel, rTxt );
1715         pImpEditEngine->UndoActionEnd();
1716         pImpEditEngine->FormatAndUpdate();
1717     }
1718 }
1719 
1720 void EditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
1721 {
1722     pImpEditEngine->SetParaAttribs( nPara, rSet );
1723     pImpEditEngine->FormatAndUpdate();
1724 }
1725 
1726 const SfxItemSet& EditEngine::GetParaAttribs( sal_Int32 nPara ) const
1727 {
1728     return pImpEditEngine->GetParaAttribs( nPara );
1729 }
1730 
1731 bool EditEngine::HasParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const
1732 {
1733     return pImpEditEngine->HasParaAttrib( nPara, nWhich );
1734 }
1735 
1736 const SfxPoolItem& EditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich )
1737 {
1738     return pImpEditEngine->GetParaAttrib( nPara, nWhich );
1739 }
1740 
1741 void EditEngine::SetCharAttribs(sal_Int32 nPara, const SfxItemSet& rSet)
1742 {
1743     EditSelection aSel(pImpEditEngine->ConvertSelection(nPara, 0, nPara, GetTextLen(nPara)));
1744     pImpEditEngine->SetAttribs(aSel, rSet);
1745     pImpEditEngine->FormatAndUpdate();
1746 }
1747 
1748 void EditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const
1749 {
1750     pImpEditEngine->GetCharAttribs( nPara, rLst );
1751 }
1752 
1753 SfxItemSet EditEngine::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib )
1754 {
1755     EditSelection aSel( pImpEditEngine->
1756         ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
1757     return pImpEditEngine->GetAttribs( aSel, nOnlyHardAttrib );
1758 }
1759 
1760 SfxItemSet EditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags ) const
1761 {
1762     return pImpEditEngine->GetAttribs( nPara, nStart, nEnd, nFlags );
1763 }
1764 
1765 void EditEngine::RemoveAttribs( const ESelection& rSelection, bool bRemoveParaAttribs, sal_uInt16 nWhich )
1766 {
1767 
1768     pImpEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS );
1769     EditSelection aSel( pImpEditEngine->ConvertSelection( rSelection.nStartPara, rSelection.nStartPos, rSelection.nEndPara, rSelection.nEndPos ) );
1770     pImpEditEngine->RemoveCharAttribs( aSel, bRemoveParaAttribs, nWhich  );
1771     pImpEditEngine->UndoActionEnd();
1772     pImpEditEngine->FormatAndUpdate();
1773 }
1774 
1775 vcl::Font EditEngine::GetStandardFont( sal_Int32 nPara )
1776 {
1777     return GetStandardSvxFont( nPara );
1778 }
1779 
1780 SvxFont EditEngine::GetStandardSvxFont( sal_Int32 nPara )
1781 {
1782     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
1783     return pNode->GetCharAttribs().GetDefFont();
1784 }
1785 
1786 void EditEngine::StripPortions()
1787 {
1788     ScopedVclPtrInstance< VirtualDevice > aTmpDev;
1789     tools::Rectangle aBigRect( Point( 0, 0 ), Size( 0x7FFFFFFF, 0x7FFFFFFF ) );
1790     if ( IsVertical() )
1791     {
1792         if( IsTopToBottom() )
1793         {
1794             aBigRect.SetRight( 0 );
1795             aBigRect.SetLeft( -0x7FFFFFFF );
1796         }
1797         else
1798         {
1799             aBigRect.SetTop( -0x7FFFFFFF );
1800             aBigRect.SetBottom( 0 );
1801         }
1802     }
1803     pImpEditEngine->Paint( aTmpDev.get(), aBigRect, Point(), true );
1804 }
1805 
1806 void EditEngine::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList )
1807 {
1808     if ( !pImpEditEngine->IsFormatted() )
1809         pImpEditEngine->FormatFullDoc();
1810 
1811     const ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara );
1812     if ( pParaPortion )
1813     {
1814         sal_Int32 nEnd = 0;
1815         sal_Int32 nTextPortions = pParaPortion->GetTextPortions().Count();
1816         for ( sal_Int32 n = 0; n < nTextPortions; n++ )
1817         {
1818             nEnd = nEnd + pParaPortion->GetTextPortions()[n].GetLen();
1819             rList.push_back( nEnd );
1820         }
1821     }
1822 }
1823 
1824 void EditEngine::SetFlatMode( bool bFlat)
1825 {
1826     pImpEditEngine->SetFlatMode( bFlat );
1827 }
1828 
1829 bool EditEngine::IsFlatMode() const
1830 {
1831     return !( pImpEditEngine->aStatus.UseCharAttribs() );
1832 }
1833 
1834 void EditEngine::SetControlWord( EEControlBits nWord )
1835 {
1836 
1837     if ( nWord != pImpEditEngine->aStatus.GetControlWord() )
1838     {
1839         EEControlBits nPrev = pImpEditEngine->aStatus.GetControlWord();
1840         pImpEditEngine->aStatus.GetControlWord() = nWord;
1841 
1842         EEControlBits nChanges = nPrev ^ nWord;
1843         if ( pImpEditEngine->IsFormatted() )
1844         {
1845             // possibly reformat:
1846             if ( ( nChanges & EEControlBits::USECHARATTRIBS ) ||
1847                  ( nChanges & EEControlBits::ONECHARPERLINE ) ||
1848                  ( nChanges & EEControlBits::STRETCHING ) ||
1849                  ( nChanges & EEControlBits::OUTLINER ) ||
1850                  ( nChanges & EEControlBits::NOCOLORS ) ||
1851                  ( nChanges & EEControlBits::OUTLINER2 ) )
1852             {
1853                 if ( nChanges & EEControlBits::USECHARATTRIBS )
1854                 {
1855                     pImpEditEngine->GetEditDoc().CreateDefFont( true );
1856                 }
1857 
1858                 pImpEditEngine->FormatFullDoc();
1859                 pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() );
1860             }
1861         }
1862 
1863         bool bSpellingChanged = bool(nChanges & EEControlBits::ONLINESPELLING);
1864 
1865         if ( bSpellingChanged )
1866         {
1867             pImpEditEngine->StopOnlineSpellTimer();
1868             if (nWord & EEControlBits::ONLINESPELLING)
1869             {
1870                 // Create WrongList, start timer...
1871                 sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count();
1872                 for ( sal_Int32 n = 0; n < nNodes; n++ )
1873                 {
1874                     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n );
1875                     pNode->CreateWrongList();
1876                 }
1877                 if (pImpEditEngine->IsFormatted())
1878                     pImpEditEngine->StartOnlineSpellTimer();
1879             }
1880             else
1881             {
1882                 long nY = 0;
1883                 sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count();
1884                 for ( sal_Int32 n = 0; n < nNodes; n++ )
1885                 {
1886                     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n );
1887                     const ParaPortion* pPortion = pImpEditEngine->GetParaPortions()[n];
1888                     bool bWrongs = false;
1889                     if (pNode->GetWrongList() != nullptr)
1890                         bWrongs = !pNode->GetWrongList()->empty();
1891                     pNode->DestroyWrongList();
1892                     if ( bWrongs )
1893                     {
1894                         pImpEditEngine->aInvalidRect.SetLeft( 0 );
1895                         pImpEditEngine->aInvalidRect.SetRight( pImpEditEngine->GetPaperSize().Width() );
1896                         pImpEditEngine->aInvalidRect.SetTop( nY+1 );
1897                         pImpEditEngine->aInvalidRect.SetBottom( nY+pPortion->GetHeight()-1 );
1898                         pImpEditEngine->UpdateViews( pImpEditEngine->pActiveView );
1899                     }
1900                     nY += pPortion->GetHeight();
1901                 }
1902             }
1903         }
1904     }
1905 }
1906 
1907 EEControlBits EditEngine::GetControlWord() const
1908 {
1909     return pImpEditEngine->aStatus.GetControlWord();
1910 }
1911 
1912 long EditEngine::GetFirstLineStartX( sal_Int32 nParagraph )
1913 {
1914 
1915     long nX = 0;
1916     const ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nParagraph );
1917     if ( pPPortion )
1918     {
1919         DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetFirstLineStartX: Doc not formatted - unable to format!" );
1920         if ( !pImpEditEngine->IsFormatted() )
1921             pImpEditEngine->FormatDoc();
1922         const EditLine& rFirstLine = pPPortion->GetLines()[0];
1923         nX = rFirstLine.GetStartPosX();
1924     }
1925     return nX;
1926 }
1927 
1928 Point EditEngine::GetDocPos( const Point& rPaperPos ) const
1929 {
1930     Point aDocPos( rPaperPos );
1931     if ( IsVertical() )
1932     {
1933         if ( IsTopToBottom() )
1934         {
1935             aDocPos.setX( rPaperPos.Y() );
1936             aDocPos.setY( GetPaperSize().Width() - rPaperPos.X() );
1937         }
1938         else
1939         {
1940             aDocPos.setX( rPaperPos.Y() );
1941             aDocPos.setY( rPaperPos.X() );
1942         }
1943     }
1944     return aDocPos;
1945 }
1946 
1947 Point EditEngine::GetDocPosTopLeft( sal_Int32 nParagraph )
1948 {
1949     const ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nParagraph );
1950     DBG_ASSERT( pPPortion, "Paragraph not found: GetWindowPosTopLeft" );
1951     Point aPoint;
1952     if ( pPPortion )
1953     {
1954 
1955         // If someone calls GetLineHeight() with an empty Engine.
1956         DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetDocPosTopLeft: Doc not formatted - unable to format!" );
1957         if ( !pImpEditEngine->IsFormatted() )
1958             pImpEditEngine->FormatAndUpdate();
1959         if ( pPPortion->GetLines().Count() )
1960         {
1961             // Correct it if large Bullet.
1962             const EditLine& rFirstLine = pPPortion->GetLines()[0];
1963             aPoint.setX( rFirstLine.GetStartPosX() );
1964         }
1965         else
1966         {
1967             const SvxLRSpaceItem& rLRItem = pImpEditEngine->GetLRSpaceItem( pPPortion->GetNode() );
1968 // TL_NF_LR         aPoint.X() = pImpEditEngine->GetXValue( (short)(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOfst()) );
1969             sal_Int32 nSpaceBefore = 0;
1970             pImpEditEngine->GetSpaceBeforeAndMinLabelWidth( pPPortion->GetNode(), &nSpaceBefore );
1971             short nX = static_cast<short>(rLRItem.GetTextLeft()
1972                             + rLRItem.GetTextFirstLineOfst()
1973                             + nSpaceBefore);
1974             aPoint.setX( pImpEditEngine->GetXValue( nX
1975                              ) );
1976         }
1977         aPoint.setY( pImpEditEngine->GetParaPortions().GetYOffset( pPPortion ) );
1978     }
1979     return aPoint;
1980 }
1981 
1982 const SvxNumberFormat* EditEngine::GetNumberFormat( sal_Int32 ) const
1983 {
1984     // derived objects may override this function to give access to
1985     // bullet information (see Outliner)
1986     return nullptr;
1987 }
1988 
1989 bool EditEngine::IsRightToLeft( sal_Int32 nPara ) const
1990 {
1991     return pImpEditEngine->IsRightToLeft( nPara );
1992 }
1993 
1994 bool EditEngine::IsTextPos( const Point& rPaperPos, sal_uInt16 nBorder )
1995 {
1996 
1997     if ( !pImpEditEngine->IsFormatted() )
1998         pImpEditEngine->FormatDoc();
1999 
2000     bool bTextPos = false;
2001     // take unrotated positions for calculation here
2002     Point aDocPos = GetDocPos( rPaperPos );
2003 
2004     if ( ( aDocPos.Y() > 0  ) && ( aDocPos.Y() < static_cast<long>(pImpEditEngine->GetTextHeight()) ) )
2005     {
2006         EditPaM aPaM = pImpEditEngine->GetPaM( aDocPos, false );
2007         if ( aPaM.GetNode() )
2008         {
2009             const ParaPortion* pParaPortion = pImpEditEngine->FindParaPortion( aPaM.GetNode() );
2010             DBG_ASSERT( pParaPortion, "ParaPortion?" );
2011 
2012             sal_Int32 nLine = pParaPortion->GetLineNumber( aPaM.GetIndex() );
2013             const EditLine& rLine = pParaPortion->GetLines()[nLine];
2014             Range aLineXPosStartEnd = pImpEditEngine->GetLineXPosStartEnd( pParaPortion, &rLine );
2015             if ( ( aDocPos.X() >= aLineXPosStartEnd.Min() - nBorder ) &&
2016                  ( aDocPos.X() <= aLineXPosStartEnd.Max() + nBorder ) )
2017             {
2018                  bTextPos = true;
2019             }
2020         }
2021     }
2022     return bTextPos;
2023 }
2024 
2025 void EditEngine::SetEditTextObjectPool( SfxItemPool* pPool )
2026 {
2027     pImpEditEngine->SetEditTextObjectPool( pPool );
2028 }
2029 
2030 SfxItemPool* EditEngine::GetEditTextObjectPool() const
2031 {
2032     return pImpEditEngine->GetEditTextObjectPool();
2033 }
2034 
2035 void EditEngine::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
2036 {
2037 
2038     EditSelection aSel( pImpEditEngine->
2039         ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
2040 
2041     pImpEditEngine->SetAttribs( aSel, rSet );
2042 }
2043 
2044 void EditEngine::QuickMarkInvalid( const ESelection& rSel )
2045 {
2046     DBG_ASSERT( rSel.nStartPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: Start out of Range!" );
2047     DBG_ASSERT( rSel.nEndPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: End out of Range!" );
2048     for ( sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
2049     {
2050         ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara );
2051         if ( pPortion )
2052             pPortion->MarkSelectionInvalid( 0 );
2053     }
2054 }
2055 
2056 void EditEngine::QuickInsertText(const OUString& rText, const ESelection& rSel)
2057 {
2058 
2059     EditSelection aSel( pImpEditEngine->
2060         ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
2061 
2062     pImpEditEngine->ImpInsertText( aSel, rText );
2063 }
2064 
2065 void EditEngine::QuickDelete( const ESelection& rSel )
2066 {
2067 
2068     EditSelection aSel( pImpEditEngine->
2069         ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
2070 
2071     pImpEditEngine->ImpDeleteSelection( aSel );
2072 }
2073 
2074 void EditEngine::QuickMarkToBeRepainted( sal_Int32 nPara )
2075 {
2076     ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara );
2077     if ( pPortion )
2078         pPortion->SetMustRepaint( true );
2079 }
2080 
2081 void EditEngine::QuickInsertLineBreak( const ESelection& rSel )
2082 {
2083 
2084     EditSelection aSel( pImpEditEngine->
2085         ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
2086 
2087     pImpEditEngine->InsertLineBreak( aSel );
2088 }
2089 
2090 void EditEngine::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
2091 {
2092 
2093     EditSelection aSel( pImpEditEngine->
2094         ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
2095 
2096     pImpEditEngine->ImpInsertFeature( aSel, rFld );
2097 }
2098 
2099 void EditEngine::QuickFormatDoc( bool bFull )
2100 {
2101     if ( bFull )
2102         pImpEditEngine->FormatFullDoc();
2103     else
2104         pImpEditEngine->FormatDoc();
2105 
2106     // Don't pass active view, maybe selection is not updated yet...
2107     pImpEditEngine->UpdateViews();
2108 }
2109 
2110 void EditEngine::SetStyleSheet(const EditSelection& aSel, SfxStyleSheet* pStyle)
2111 {
2112     pImpEditEngine->SetStyleSheet(aSel, pStyle);
2113 }
2114 
2115 void EditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle )
2116 {
2117     pImpEditEngine->SetStyleSheet( nPara, pStyle );
2118 }
2119 
2120 const SfxStyleSheet* EditEngine::GetStyleSheet( sal_Int32 nPara ) const
2121 {
2122     return pImpEditEngine->GetStyleSheet( nPara );
2123 }
2124 
2125 SfxStyleSheet* EditEngine::GetStyleSheet( sal_Int32 nPara )
2126 {
2127     return pImpEditEngine->GetStyleSheet( nPara );
2128 }
2129 
2130 void EditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
2131 {
2132     pImpEditEngine->SetStyleSheetPool( pSPool );
2133 }
2134 
2135 SfxStyleSheetPool* EditEngine::GetStyleSheetPool()
2136 {
2137     return pImpEditEngine->GetStyleSheetPool();
2138 }
2139 
2140 void EditEngine::SetWordDelimiters( const OUString& rDelimiters )
2141 {
2142     pImpEditEngine->aWordDelimiters = rDelimiters;
2143     if (pImpEditEngine->aWordDelimiters.indexOf(CH_FEATURE) == -1)
2144         pImpEditEngine->aWordDelimiters += OUStringLiteral1(CH_FEATURE);
2145 }
2146 
2147 const OUString& EditEngine::GetWordDelimiters() const
2148 {
2149     return pImpEditEngine->aWordDelimiters;
2150 }
2151 
2152 void EditEngine::EraseVirtualDevice()
2153 {
2154     pImpEditEngine->EraseVirtualDevice();
2155 }
2156 
2157 void EditEngine::SetSpeller( Reference< XSpellChecker1 > const &xSpeller )
2158 {
2159     pImpEditEngine->SetSpeller( xSpeller );
2160 }
2161 
2162 Reference< XSpellChecker1 > const & EditEngine::GetSpeller()
2163 {
2164     return pImpEditEngine->GetSpeller();
2165 }
2166 
2167 void EditEngine::SetHyphenator( Reference< XHyphenator > const & xHyph )
2168 {
2169     pImpEditEngine->SetHyphenator( xHyph );
2170 }
2171 
2172 void EditEngine::GetAllMisspellRanges( std::vector<editeng::MisspellRanges>& rRanges ) const
2173 {
2174     pImpEditEngine->GetAllMisspellRanges(rRanges);
2175 }
2176 
2177 void EditEngine::SetAllMisspellRanges( const std::vector<editeng::MisspellRanges>& rRanges )
2178 {
2179     pImpEditEngine->SetAllMisspellRanges(rRanges);
2180 }
2181 
2182 void EditEngine::SetForbiddenCharsTable(const std::shared_ptr<SvxForbiddenCharactersTable>& xForbiddenChars)
2183 {
2184     ImpEditEngine::SetForbiddenCharsTable( xForbiddenChars );
2185 }
2186 
2187 void EditEngine::SetDefaultLanguage( LanguageType eLang )
2188 {
2189     pImpEditEngine->SetDefaultLanguage( eLang );
2190 }
2191 
2192 LanguageType EditEngine::GetDefaultLanguage() const
2193 {
2194     return pImpEditEngine->GetDefaultLanguage();
2195 }
2196 
2197 bool EditEngine::SpellNextDocument()
2198 {
2199     return false;
2200 }
2201 
2202 EESpellState EditEngine::HasSpellErrors()
2203 {
2204     if ( !pImpEditEngine->GetSpeller().is()  )
2205         return EESpellState::NoSpeller;
2206 
2207     return pImpEditEngine->HasSpellErrors();
2208 }
2209 
2210 void EditEngine::ClearSpellErrors()
2211 {
2212     pImpEditEngine->ClearSpellErrors();
2213 }
2214 
2215 bool EditEngine::SpellSentence(EditView const & rView, svx::SpellPortions& rToFill )
2216 {
2217     return pImpEditEngine->SpellSentence( rView, rToFill );
2218 }
2219 
2220 void EditEngine::PutSpellingToSentenceStart( EditView const & rEditView )
2221 {
2222     pImpEditEngine->PutSpellingToSentenceStart( rEditView );
2223 }
2224 
2225 void EditEngine::ApplyChangedSentence(EditView const & rEditView, const svx::SpellPortions& rNewPortions, bool bRecheck )
2226 {
2227     pImpEditEngine->ApplyChangedSentence( rEditView, rNewPortions, bRecheck  );
2228 }
2229 
2230 bool EditEngine::HasConvertibleTextPortion( LanguageType nLang )
2231 {
2232     return pImpEditEngine->HasConvertibleTextPortion( nLang );
2233 }
2234 
2235 bool EditEngine::ConvertNextDocument()
2236 {
2237     return false;
2238 }
2239 
2240 bool EditEngine::HasText( const SvxSearchItem& rSearchItem )
2241 {
2242     return pImpEditEngine->HasText( rSearchItem );
2243 }
2244 
2245 void EditEngine::SetGlobalCharStretching( sal_uInt16 nX, sal_uInt16 nY )
2246 {
2247     pImpEditEngine->SetCharStretching( nX, nY );
2248 }
2249 
2250 void EditEngine::GetGlobalCharStretching( sal_uInt16& rX, sal_uInt16& rY ) const
2251 {
2252     pImpEditEngine->GetCharStretching( rX, rY );
2253 }
2254 
2255 bool EditEngine::ShouldCreateBigTextObject() const
2256 {
2257     sal_Int32 nTextPortions = 0;
2258     sal_Int32 nParas = pImpEditEngine->GetEditDoc().Count();
2259     for ( sal_Int32 nPara = 0; nPara < nParas; nPara++  )
2260     {
2261         ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions()[nPara];
2262         nTextPortions = nTextPortions + pParaPortion->GetTextPortions().Count();
2263     }
2264     return nTextPortions >= pImpEditEngine->GetBigTextObjectStart();
2265 }
2266 
2267 sal_uInt16 EditEngine::GetFieldCount( sal_Int32 nPara ) const
2268 {
2269     sal_uInt16 nFields = 0;
2270     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
2271     if ( pNode )
2272     {
2273         for (auto const& attrib : pNode->GetCharAttribs().GetAttribs())
2274         {
2275             if (attrib->Which() == EE_FEATURE_FIELD)
2276                 ++nFields;
2277         }
2278     }
2279 
2280     return nFields;
2281 }
2282 
2283 EFieldInfo EditEngine::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const
2284 {
2285     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
2286     if ( pNode )
2287     {
2288         sal_uInt16 nCurrentField = 0;
2289         for (auto const& attrib : pNode->GetCharAttribs().GetAttribs())
2290         {
2291             const EditCharAttrib& rAttr = *attrib;
2292             if (rAttr.Which() == EE_FEATURE_FIELD)
2293             {
2294                 if ( nCurrentField == nField )
2295                 {
2296                     const SvxFieldItem* p = static_cast<const SvxFieldItem*>(rAttr.GetItem());
2297                     EFieldInfo aInfo(*p, nPara, rAttr.GetStart());
2298                     aInfo.aCurrentText = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue();
2299                     return aInfo;
2300                 }
2301 
2302                 ++nCurrentField;
2303             }
2304         }
2305     }
2306     return EFieldInfo();
2307 }
2308 
2309 
2310 bool EditEngine::UpdateFields()
2311 {
2312     bool bChanges = pImpEditEngine->UpdateFields();
2313     if ( bChanges )
2314         pImpEditEngine->FormatAndUpdate();
2315     return bChanges;
2316 }
2317 
2318 bool EditEngine::UpdateFieldsOnly()
2319 {
2320     return pImpEditEngine->UpdateFields();
2321 }
2322 
2323 void EditEngine::RemoveFields( const std::function<bool ( const SvxFieldData* )>& isFieldData )
2324 {
2325     pImpEditEngine->UpdateFields();
2326 
2327     sal_Int32 nParas = pImpEditEngine->GetEditDoc().Count();
2328     for ( sal_Int32 nPara = 0; nPara < nParas; nPara++  )
2329     {
2330         ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
2331         const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
2332         for (size_t nAttr = rAttrs.size(); nAttr; )
2333         {
2334             const EditCharAttrib& rAttr = *rAttrs[--nAttr].get();
2335             if (rAttr.Which() == EE_FEATURE_FIELD)
2336             {
2337                 const SvxFieldData* pFldData = static_cast<const SvxFieldItem*>(rAttr.GetItem())->GetField();
2338                 if ( pFldData && ( isFieldData( pFldData )  ) )
2339                 {
2340                     DBG_ASSERT( dynamic_cast<const SvxFieldItem*>(rAttr.GetItem()), "no field item..." );
2341                     EditSelection aSel( EditPaM(pNode, rAttr.GetStart()), EditPaM(pNode, rAttr.GetEnd()) );
2342                     OUString aFieldText = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue();
2343                     pImpEditEngine->ImpInsertText( aSel, aFieldText );
2344                 }
2345             }
2346         }
2347     }
2348 }
2349 
2350 bool EditEngine::HasOnlineSpellErrors() const
2351 {
2352     sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count();
2353     for ( sal_Int32 n = 0; n < nNodes; n++ )
2354     {
2355         ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n );
2356         if ( pNode->GetWrongList() && !pNode->GetWrongList()->empty() )
2357             return true;
2358     }
2359     return false;
2360 }
2361 
2362 void EditEngine::CompleteOnlineSpelling()
2363 {
2364     if ( pImpEditEngine->GetStatus().DoOnlineSpelling() )
2365     {
2366         if( !pImpEditEngine->IsFormatted() )
2367             pImpEditEngine->FormatAndUpdate();
2368 
2369         pImpEditEngine->StopOnlineSpellTimer();
2370         pImpEditEngine->DoOnlineSpelling( nullptr, true, false );
2371     }
2372 }
2373 
2374 sal_Int32 EditEngine::FindParagraph( long nDocPosY )
2375 {
2376     return pImpEditEngine->GetParaPortions().FindParagraph( nDocPosY );
2377 }
2378 
2379 EPosition EditEngine::FindDocPosition( const Point& rDocPos ) const
2380 {
2381     EPosition aPos;
2382     // From the point of the API, this is const....
2383     EditPaM aPaM = const_cast<EditEngine*>(this)->pImpEditEngine->GetPaM( rDocPos, false );
2384     if ( aPaM.GetNode() )
2385     {
2386         aPos.nPara = pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
2387         aPos.nIndex = aPaM.GetIndex();
2388     }
2389     return aPos;
2390 }
2391 
2392 tools::Rectangle EditEngine::GetCharacterBounds( const EPosition& rPos ) const
2393 {
2394     tools::Rectangle aBounds;
2395     ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( rPos.nPara );
2396 
2397     // Check against index, not paragraph
2398     if ( pNode && ( rPos.nIndex < pNode->Len() ) )
2399     {
2400         aBounds = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex ), GetCursorFlags::TextOnly );
2401         tools::Rectangle aR2 = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex+1 ), GetCursorFlags::TextOnly|GetCursorFlags::EndOfLine );
2402         if ( aR2.Right() > aBounds.Right() )
2403             aBounds.SetRight( aR2.Right() );
2404     }
2405     return aBounds;
2406 }
2407 
2408 ParagraphInfos EditEngine::GetParagraphInfos( sal_Int32 nPara )
2409 {
2410 
2411     // This only works if not already in the format ...
2412     if ( !pImpEditEngine->IsFormatted() )
2413         pImpEditEngine->FormatDoc();
2414 
2415     ParagraphInfos aInfos;
2416     aInfos.bValid = pImpEditEngine->IsFormatted();
2417     if ( pImpEditEngine->IsFormatted() )
2418     {
2419         const ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions()[nPara];
2420         const EditLine* pLine = (pParaPortion && pParaPortion->GetLines().Count()) ?
2421                 &pParaPortion->GetLines()[0] : nullptr;
2422         DBG_ASSERT( pParaPortion && pLine, "GetParagraphInfos - Paragraph out of range" );
2423         if ( pParaPortion && pLine )
2424         {
2425             aInfos.nFirstLineHeight = pLine->GetHeight();
2426             aInfos.nFirstLineTextHeight = pLine->GetTxtHeight();
2427             aInfos.nFirstLineMaxAscent = pLine->GetMaxAscent();
2428         }
2429     }
2430     return aInfos;
2431 }
2432 
2433 css::uno::Reference< css::datatransfer::XTransferable >
2434                     EditEngine::CreateTransferable( const ESelection& rSelection ) const
2435 {
2436     EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) );
2437     return pImpEditEngine->CreateTransferable( aSel );
2438 }
2439 
2440 
2441 // ======================    Virtual Methods    ========================
2442 
2443 void EditEngine::DrawingText( const Point&, const OUString&, sal_Int32, sal_Int32,
2444                               const long*, const SvxFont&, sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/,
2445                               const EEngineData::WrongSpellVector*, const SvxFieldData*, bool, bool,
2446                               const css::lang::Locale*, const Color&, const Color&)
2447 
2448 {
2449 }
2450 
2451 void EditEngine::DrawingTab( const Point& /*rStartPos*/, long /*nWidth*/,
2452                              const OUString& /*rChar*/, const SvxFont& /*rFont*/,
2453                              sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/, bool /*bEndOfLine*/,
2454                              bool /*bEndOfParagraph*/, const Color& /*rOverlineColor*/,
2455                              const Color& /*rTextLineColor*/)
2456 {
2457 }
2458 
2459 void EditEngine::PaintingFirstLine( sal_Int32, const Point&, long, const Point&, short, OutputDevice* )
2460 {
2461 }
2462 
2463 void EditEngine::ParagraphInserted( sal_Int32 nPara )
2464 {
2465 
2466     if ( GetNotifyHdl().IsSet() )
2467     {
2468         EENotify aNotify( EE_NOTIFY_PARAGRAPHINSERTED );
2469         aNotify.nParagraph = nPara;
2470         pImpEditEngine->GetNotifyHdl().Call( aNotify );
2471     }
2472 }
2473 
2474 void EditEngine::ParagraphDeleted( sal_Int32 nPara )
2475 {
2476 
2477     if ( GetNotifyHdl().IsSet() )
2478     {
2479         EENotify aNotify( EE_NOTIFY_PARAGRAPHREMOVED );
2480         aNotify.nParagraph = nPara;
2481         pImpEditEngine->GetNotifyHdl().Call( aNotify );
2482     }
2483 }
2484 void EditEngine::ParagraphConnected( sal_Int32 /*nLeftParagraph*/, sal_Int32 /*nRightParagraph*/ )
2485 {
2486 }
2487 
2488 void EditEngine::ParaAttribsChanged( sal_Int32 /* nParagraph */ )
2489 {
2490 }
2491 
2492 void EditEngine::StyleSheetChanged( SfxStyleSheet* /* pStyle */ )
2493 {
2494 }
2495 
2496 void EditEngine::ParagraphHeightChanged( sal_Int32 nPara )
2497 {
2498 
2499     if ( GetNotifyHdl().IsSet() )
2500     {
2501         EENotify aNotify( EE_NOTIFY_TextHeightChanged );
2502         aNotify.nParagraph = nPara;
2503         pImpEditEngine->GetNotifyHdl().Call( aNotify );
2504     }
2505 }
2506 
2507 OUString EditEngine::GetUndoComment( sal_uInt16 nId ) const
2508 {
2509     OUString aComment;
2510     switch ( nId )
2511     {
2512         case EDITUNDO_REMOVECHARS:
2513         case EDITUNDO_CONNECTPARAS:
2514         case EDITUNDO_DELCONTENT:
2515         case EDITUNDO_DELETE:
2516         case EDITUNDO_CUT:
2517             aComment = EditResId(RID_EDITUNDO_DEL);
2518         break;
2519         case EDITUNDO_MOVEPARAGRAPHS:
2520         case EDITUNDO_MOVEPARAS:
2521         case EDITUNDO_DRAGANDDROP:
2522             aComment = EditResId(RID_EDITUNDO_MOVE);
2523         break;
2524         case EDITUNDO_INSERTFEATURE:
2525         case EDITUNDO_SPLITPARA:
2526         case EDITUNDO_INSERTCHARS:
2527         case EDITUNDO_PASTE:
2528         case EDITUNDO_INSERT:
2529         case EDITUNDO_READ:
2530             aComment = EditResId(RID_EDITUNDO_INSERT);
2531         break;
2532         case EDITUNDO_REPLACEALL:
2533             aComment = EditResId(RID_EDITUNDO_REPLACE);
2534         break;
2535         case EDITUNDO_ATTRIBS:
2536         case EDITUNDO_PARAATTRIBS:
2537             aComment = EditResId(RID_EDITUNDO_SETATTRIBS);
2538         break;
2539         case EDITUNDO_RESETATTRIBS:
2540             aComment = EditResId(RID_EDITUNDO_RESETATTRIBS);
2541         break;
2542         case EDITUNDO_STYLESHEET:
2543             aComment = EditResId(RID_EDITUNDO_SETSTYLE);
2544         break;
2545         case EDITUNDO_TRANSLITERATE:
2546             aComment = EditResId(RID_EDITUNDO_TRANSLITERATE);
2547         break;
2548         case EDITUNDO_INDENTBLOCK:
2549         case EDITUNDO_UNINDENTBLOCK:
2550             aComment = EditResId(RID_EDITUNDO_INDENT);
2551         break;
2552     }
2553     return aComment;
2554 }
2555 
2556 tools::Rectangle EditEngine::GetBulletArea( sal_Int32 )
2557 {
2558     return tools::Rectangle( Point(), Point() );
2559 }
2560 
2561 OUString EditEngine::CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, boost::optional<Color>&, boost::optional<Color>& )
2562 {
2563     return OUString(' ');
2564 }
2565 
2566 void EditEngine::FieldClicked( const SvxFieldItem&, sal_Int32, sal_Int32 )
2567 {
2568 }
2569 
2570 
2571 // ======================     Static Methods     =======================
2572 
2573 SfxItemPool* EditEngine::CreatePool()
2574 {
2575     SfxItemPool* pPool = new EditEngineItemPool();
2576     return pPool;
2577 }
2578 
2579 SfxItemPool& EditEngine::GetGlobalItemPool()
2580 {
2581     if ( !pGlobalPool )
2582         pGlobalPool = CreatePool();
2583     return *pGlobalPool;
2584 }
2585 
2586 void EditEngine::SetFontInfoInItemSet( SfxItemSet& rSet, const vcl::Font& rFont )
2587 {
2588     SvxFont aSvxFont( rFont );
2589     SetFontInfoInItemSet( rSet, aSvxFont );
2590 
2591 }
2592 
2593 void EditEngine::SetFontInfoInItemSet( SfxItemSet& rSet, const SvxFont& rFont )
2594 {
2595     rSet.Put( SvxLanguageItem( rFont.GetLanguage(), EE_CHAR_LANGUAGE ) );
2596     rSet.Put( SvxFontItem( rFont.GetFamilyType(), rFont.GetFamilyName(), OUString(), rFont.GetPitch(), rFont.GetCharSet(), EE_CHAR_FONTINFO ) );
2597     rSet.Put( SvxFontHeightItem( rFont.GetFontSize().Height(), 100, EE_CHAR_FONTHEIGHT )  );
2598     rSet.Put( SvxCharScaleWidthItem( 100, EE_CHAR_FONTWIDTH ) );
2599     rSet.Put( SvxShadowedItem( rFont.IsShadow(), EE_CHAR_SHADOW )  );
2600     rSet.Put( SvxEscapementItem( rFont.GetEscapement(), rFont.GetPropr(), EE_CHAR_ESCAPEMENT )  );
2601     rSet.Put( SvxWeightItem( rFont.GetWeight(), EE_CHAR_WEIGHT )  );
2602     rSet.Put( SvxColorItem( rFont.GetColor(), EE_CHAR_COLOR )  );
2603     rSet.Put( SvxBackgroundColorItem( rFont.GetFillColor(), EE_CHAR_BKGCOLOR )  );
2604     rSet.Put( SvxUnderlineItem( rFont.GetUnderline(), EE_CHAR_UNDERLINE )  );
2605     rSet.Put( SvxOverlineItem( rFont.GetOverline(), EE_CHAR_OVERLINE )  );
2606     rSet.Put( SvxCrossedOutItem( rFont.GetStrikeout(), EE_CHAR_STRIKEOUT )  );
2607     rSet.Put( SvxCaseMapItem( rFont.GetCaseMap(), EE_CHAR_CASEMAP )  );
2608     rSet.Put( SvxPostureItem( rFont.GetItalic(), EE_CHAR_ITALIC )  );
2609     rSet.Put( SvxContourItem( rFont.IsOutline(), EE_CHAR_OUTLINE )  );
2610     rSet.Put( SvxAutoKernItem( rFont.IsKerning(), EE_CHAR_PAIRKERNING ) );
2611     rSet.Put( SvxKerningItem( rFont.GetFixKerning(), EE_CHAR_KERNING ) );
2612     rSet.Put( SvxWordLineModeItem( rFont.IsWordLineMode(), EE_CHAR_WLM ) );
2613     rSet.Put( SvxEmphasisMarkItem( rFont.GetEmphasisMark(), EE_CHAR_EMPHASISMARK ) );
2614     rSet.Put( SvxCharReliefItem( rFont.GetRelief(), EE_CHAR_RELIEF ) );
2615 }
2616 
2617 vcl::Font EditEngine::CreateFontFromItemSet( const SfxItemSet& rItemSet, SvtScriptType nScriptType )
2618 {
2619     SvxFont aFont;
2620     CreateFont( aFont, rItemSet, true, nScriptType );
2621 #if HAVE_GCC_BUG_87150
2622     return aFont;
2623 #else
2624     return std::move(aFont);
2625 #endif
2626 }
2627 
2628 SvxFont EditEngine::CreateSvxFontFromItemSet( const SfxItemSet& rItemSet )
2629 {
2630     SvxFont aFont;
2631     CreateFont( aFont, rItemSet );
2632     return aFont;
2633 }
2634 
2635 bool EditEngine::DoesKeyMoveCursor( const KeyEvent& rKeyEvent )
2636 {
2637     bool bDoesMove = false;
2638 
2639     switch ( rKeyEvent.GetKeyCode().GetCode() )
2640     {
2641         case KEY_UP:
2642         case KEY_DOWN:
2643         case KEY_LEFT:
2644         case KEY_RIGHT:
2645         case KEY_HOME:
2646         case KEY_END:
2647         case KEY_PAGEUP:
2648         case KEY_PAGEDOWN:
2649         {
2650             if ( !rKeyEvent.GetKeyCode().IsMod2() )
2651                 bDoesMove = true;
2652         }
2653         break;
2654     }
2655     return bDoesMove;
2656 }
2657 
2658 bool EditEngine::DoesKeyChangeText( const KeyEvent& rKeyEvent )
2659 {
2660     bool bDoesChange = false;
2661 
2662     KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
2663     if ( eFunc != KeyFuncType::DONTKNOW )
2664     {
2665         switch ( eFunc )
2666         {
2667             case KeyFuncType::UNDO:
2668             case KeyFuncType::REDO:
2669             case KeyFuncType::CUT:
2670             case KeyFuncType::PASTE: bDoesChange = true;
2671             break;
2672             default:    // is then possibly edited below.
2673                         eFunc = KeyFuncType::DONTKNOW;
2674         }
2675     }
2676     if ( eFunc == KeyFuncType::DONTKNOW )
2677     {
2678         switch ( rKeyEvent.GetKeyCode().GetCode() )
2679         {
2680             case KEY_DELETE:
2681             case KEY_BACKSPACE: bDoesChange = true;
2682             break;
2683             case KEY_RETURN:
2684             case KEY_TAB:
2685             {
2686                 if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
2687                     bDoesChange = true;
2688             }
2689             break;
2690             default:
2691             {
2692                 bDoesChange = IsSimpleCharInput( rKeyEvent );
2693             }
2694         }
2695     }
2696     return bDoesChange;
2697 }
2698 
2699 bool EditEngine::IsSimpleCharInput( const KeyEvent& rKeyEvent )
2700 {
2701     return EditEngine::IsPrintable( rKeyEvent.GetCharCode() ) &&
2702         ( KEY_MOD2 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT ) ) &&
2703         ( KEY_MOD1 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT ) );
2704 }
2705 
2706 bool EditEngine::HasValidData( const css::uno::Reference< css::datatransfer::XTransferable >& rTransferable )
2707 {
2708     bool bValidData = false;
2709 
2710     if ( rTransferable.is() )
2711     {
2712         // Every application that copies rtf or any other text format also copies plain text into the clipboard....
2713         datatransfer::DataFlavor aFlavor;
2714         SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
2715         bValidData = rTransferable->isDataFlavorSupported( aFlavor );
2716     }
2717 
2718     return bValidData;
2719 }
2720 
2721 /** sets a link that is called at the beginning of a drag operation at an edit view */
2722 void EditEngine::SetBeginDropHdl( const Link<EditView*,void>& rLink )
2723 {
2724     pImpEditEngine->SetBeginDropHdl( rLink );
2725 }
2726 
2727 Link<EditView*,void> const & EditEngine::GetBeginDropHdl() const
2728 {
2729     return pImpEditEngine->GetBeginDropHdl();
2730 }
2731 
2732 /** sets a link that is called at the end of a drag operation at an edit view */
2733 void EditEngine::SetEndDropHdl( const Link<EditView*,void>& rLink )
2734 {
2735     pImpEditEngine->SetEndDropHdl( rLink );
2736 }
2737 
2738 Link<EditView*,void> const & EditEngine::GetEndDropHdl() const
2739 {
2740     return pImpEditEngine->GetEndDropHdl();
2741 }
2742 
2743 void EditEngine::SetFirstWordCapitalization( bool bCapitalize )
2744 {
2745     pImpEditEngine->SetFirstWordCapitalization( bCapitalize );
2746 }
2747 
2748 void EditEngine::SetReplaceLeadingSingleQuotationMark( bool bReplace )
2749 {
2750     pImpEditEngine->SetReplaceLeadingSingleQuotationMark( bReplace );
2751 }
2752 
2753 bool EditEngine::IsHtmlImportHandlerSet() const
2754 {
2755     return pImpEditEngine->aHtmlImportHdl.IsSet();
2756 }
2757 
2758 bool EditEngine::IsRtfImportHandlerSet() const
2759 {
2760     return pImpEditEngine->aRtfImportHdl.IsSet();
2761 }
2762 
2763 bool EditEngine::IsImportRTFStyleSheetsSet() const
2764 {
2765     return pImpEditEngine->GetStatus().DoImportRTFStyleSheets();
2766 }
2767 
2768 void EditEngine::CallHtmlImportHandler(HtmlImportInfo& rInfo)
2769 {
2770     pImpEditEngine->aHtmlImportHdl.Call(rInfo);
2771 }
2772 
2773 void EditEngine::CallRtfImportHandler(RtfImportInfo& rInfo)
2774 {
2775     pImpEditEngine->aRtfImportHdl.Call(rInfo);
2776 }
2777 
2778 EditPaM EditEngine::InsertParaBreak(const EditSelection& rEditSelection)
2779 {
2780     return pImpEditEngine->ImpInsertParaBreak(rEditSelection);
2781 }
2782 
2783 EditPaM EditEngine::InsertLineBreak(const EditSelection& rEditSelection)
2784 {
2785     return pImpEditEngine->InsertLineBreak(rEditSelection);
2786 }
2787 
2788 sal_Int32 EditEngine::GetOverflowingParaNum() const {
2789     return pImpEditEngine->GetOverflowingParaNum();
2790 }
2791 
2792 sal_Int32 EditEngine::GetOverflowingLineNum() const {
2793     return pImpEditEngine->GetOverflowingLineNum();
2794 }
2795 
2796 void EditEngine::ClearOverflowingParaNum() {
2797     pImpEditEngine->ClearOverflowingParaNum();
2798 }
2799 
2800 bool EditEngine::IsPageOverflow() {
2801     pImpEditEngine->CheckPageOverflow();
2802     return pImpEditEngine->IsPageOverflow();
2803 }
2804 
2805 EFieldInfo::EFieldInfo()
2806 {
2807 }
2808 
2809 
2810 EFieldInfo::EFieldInfo( const SvxFieldItem& rFieldItem, sal_Int32 nPara, sal_Int32 nPos ) :
2811     pFieldItem( new SvxFieldItem( rFieldItem ) ),
2812     aPosition( nPara, nPos )
2813 {
2814 }
2815 
2816 EFieldInfo::~EFieldInfo()
2817 {
2818 }
2819 
2820 EFieldInfo::EFieldInfo( const EFieldInfo& rFldInfo )
2821 {
2822     *this = rFldInfo;
2823 }
2824 
2825 EFieldInfo& EFieldInfo::operator= ( const EFieldInfo& rFldInfo )
2826 {
2827     if( this == &rFldInfo )
2828         return *this;
2829 
2830     pFieldItem.reset( rFldInfo.pFieldItem ? new SvxFieldItem( *rFldInfo.pFieldItem ) : nullptr );
2831     aCurrentText = rFldInfo.aCurrentText;
2832     aPosition = rFldInfo.aPosition;
2833 
2834     return *this;
2835 }
2836 
2837 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2838