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