android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / uibase / wrtsh / wrtsh1.cxx
blobaf96916885d5e00af038abc1f9e795270a363593
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/beans/XPropertySet.hpp>
21 #include <com/sun/star/container/XChild.hpp>
22 #include <com/sun/star/embed/EmbedMisc.hpp>
23 #include <com/sun/star/embed/EmbedStates.hpp>
24 #include <com/sun/star/embed/EmbedVerbs.hpp>
25 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
26 #include <com/sun/star/chart2/XChartDocument.hpp>
27 #include <com/sun/star/util/XModifiable.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
30 #include <hintids.hxx>
31 #include <sot/exchange.hxx>
32 #include <svx/xfillit0.hxx>
33 #include <svx/hdft.hxx>
34 #include <svx/svdview.hxx>
35 #include <svl/itemiter.hxx>
36 #include <tools/bigint.hxx>
37 #include <svtools/insdlg.hxx>
38 #include <sfx2/ipclient.hxx>
39 #include <editeng/formatbreakitem.hxx>
40 #include <editeng/svxacorr.hxx>
41 #include <editeng/ulspitem.hxx>
42 #include <vcl/graph.hxx>
43 #include <unotools/charclass.hxx>
44 #include <comphelper/storagehelper.hxx>
45 #include <svx/svxdlg.hxx>
46 #include <svx/extrusionbar.hxx>
47 #include <svx/fontworkbar.hxx>
48 #include <dialoghelp.hxx>
49 #include <frmfmt.hxx>
50 #include <fmtftn.hxx>
51 #include <fmthdft.hxx>
52 #include <fmtpdsc.hxx>
53 #include <txtfrm.hxx>
54 #include <wdocsh.hxx>
55 #include <swmodule.hxx>
56 #include <wrtsh.hxx>
57 #include <view.hxx>
58 #include <cmdid.h>
59 #include <pagedesc.hxx>
60 #include <frmmgr.hxx>
61 #include <swundo.hxx>
62 #include <swcli.hxx>
63 #include <poolfmt.hxx>
64 #include <edtwin.hxx>
65 #include <fmtcol.hxx>
66 #include <swtable.hxx>
67 #include <viscrs.hxx>
68 #include <swdtflvr.hxx>
69 #include <doc.hxx>
70 #include <IDocumentSettingAccess.hxx>
71 #include <SwCapObjType.hxx>
72 #include <SwStyleNameMapper.hxx>
73 #include <sfx2/request.hxx>
74 #include <paratr.hxx>
75 #include <ndtxt.hxx>
76 #include <editeng/acorrcfg.hxx>
77 #include <IMark.hxx>
78 #include <sfx2/bindings.hxx>
79 #include <flyfrm.hxx>
81 // -> #111827#
82 #include <SwRewriter.hxx>
83 #include <strings.hrc>
84 // <- #111827#
86 #include <toolkit/helper/vclunohelper.hxx>
87 #include <sfx2/viewfrm.hxx>
88 #include <vcl/uitest/logger.hxx>
89 #include <vcl/uitest/eventdescription.hxx>
90 #include <osl/diagnose.h>
91 #include <o3tl/unit_conversion.hxx>
93 #include <PostItMgr.hxx>
94 #include <FrameControlsManager.hxx>
95 #include <fldmgr.hxx>
96 #include <docufld.hxx>
97 #include <IDocumentFieldsAccess.hxx>
98 #include <fmtfld.hxx>
100 #include <sfx2/msgpool.hxx>
101 #include <sfx2/msg.hxx>
102 #include <svtools/embedhlp.hxx>
103 #include <svx/postattr.hxx>
104 #include <comphelper/lok.hxx>
105 #include <comphelper/propertyvalue.hxx>
106 #include <svtools/optionsdrawinglayer.hxx>
107 #include <svl/numformat.hxx>
108 #include <svl/zformat.hxx>
109 #include <memory>
111 #include "../../core/crsr/callnk.hxx"
112 #include <frmtool.hxx>
113 #include <viewopt.hxx>
115 #include <IDocumentUndoRedo.hxx>
116 #include <UndoInsert.hxx>
117 #include <UndoCore.hxx>
118 #include <formatlinebreak.hxx>
119 #include <formatcontentcontrol.hxx>
120 #include <textcontentcontrol.hxx>
122 using namespace sw::mark;
123 using namespace com::sun::star;
124 namespace {
126 void collectUIInformation(const OUString& rAction, const OUString& aParameters)
128 EventDescription aDescription;
129 aDescription.aAction = rAction;
130 aDescription.aParameters = {{"parameters", aParameters}};
131 aDescription.aID = "writer_edit";
132 aDescription.aKeyWord = "SwEditWinUIObject";
133 aDescription.aParent = "MainWindow";
134 UITestLogger::getInstance().logEvent(aDescription);
139 sal_uInt32 MakeAllOutlineContentTemporarilyVisible::nLock = 0;
141 static bool lcl_IsAllowed(const SwWrtShell* rSh)
143 if (rSh->GetViewOptions()->IsShowOutlineContentVisibilityButton() && rSh->IsEndPara())
145 SwTextNode* pTextNode = rSh->GetCursor()->GetPointNode().GetTextNode();
146 if (pTextNode && pTextNode->IsOutline())
148 // disallow if this is an outline node having folded content
149 bool bVisible = true;
150 pTextNode->GetAttrOutlineContentVisible(bVisible);
151 if (!bVisible)
152 return false;
155 return true;
158 #define BITFLD_INI_LIST \
159 m_bClearMark = \
160 m_bIns = true;\
161 m_bAddMode = \
162 m_bBlockMode = \
163 m_bExtMode = \
164 m_bInSelect = \
165 m_bLayoutMode = \
166 m_bSelWrd = \
167 m_bSelLn = \
168 m_bRetainSelection = false; \
169 m_bIsInClickToEdit = false;
171 static SvxAutoCorrect* lcl_IsAutoCorr()
173 SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
174 if( pACorr && !pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
175 ACFlags::AddNonBrkSpace | ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
176 ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | ACFlags::Autocorrect |
177 ACFlags::SetDOIAttr ))
178 pACorr = nullptr;
179 return pACorr;
182 void SwWrtShell::NoEdit(bool bHideCursor)
184 if(bHideCursor)
185 HideCursor();
188 void SwWrtShell::Edit()
190 if (CanInsert())
192 ShowCursor();
196 bool SwWrtShell::IsEndWrd()
198 SwMvContext aMvContext(this);
199 if(IsEndPara() && !IsSttPara())
200 return true;
202 return IsEndWord();
205 // Insert string
206 void SwWrtShell::InsertByWord( const OUString & rStr)
208 if( rStr.isEmpty() )
209 return;
211 bool bDelim = GetAppCharClass().isLetterNumeric( rStr, 0 );
212 sal_Int32 nPos = 0, nStt = 0;
213 for( ; nPos < rStr.getLength(); nPos++ )
215 bool bTmpDelim = GetAppCharClass().isLetterNumeric( rStr, nPos );
216 if( bTmpDelim != bDelim )
218 Insert( rStr.copy( nStt, nPos - nStt ));
219 nStt = nPos;
222 if( nStt != nPos )
223 Insert( rStr.copy( nStt, nPos - nStt ));
226 void SwWrtShell::Insert( const OUString &rStr )
228 ResetCursorStack();
229 if( !CanInsert() )
230 return;
232 bool bStarted = false;
233 bool bHasSel = HasSelection(),
234 bCallIns = m_bIns /*|| bHasSel*/;
235 bool bDeleted = false;
237 if( bHasSel || ( !m_bIns && IsInHiddenRange(/*bSelect=*/true) ) )
239 // Only here parenthesizing, because the normal
240 // insert is already in parentheses at Editshell.
241 StartAllAction();
243 SwRewriter aRewriter;
245 aRewriter.AddRule(UndoArg1, GetCursorDescr());
246 aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
248 OUString aTmpStr = SwResId(STR_START_QUOTE) +
249 rStr + SwResId(STR_END_QUOTE);
251 aRewriter.AddRule(UndoArg3, aTmpStr);
254 StartUndo(SwUndoId::REPLACE, &aRewriter);
255 bStarted = true;
256 Push();
257 // let's interpret a selection within the same node as "replace"
258 bDeleted = DelRight(GetCursor()->GetPoint()->GetNode() == GetCursor()->GetMark()->GetNode());
259 Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore selection (if tracking changes)
260 NormalizePam(false); // tdf#127635 put point at the end of deletion
261 ClearMark();
264 bCallIns ?
265 SwEditShell::Insert2( rStr, bDeleted ) : SwEditShell::Overwrite( rStr );
267 // Check whether node is content control
268 SwTextContentControl* pTextContentControl = CursorInsideContentControl();
269 if (pTextContentControl)
271 std::shared_ptr<SwContentControl> pContentControl =
272 pTextContentControl->GetContentControl().GetContentControl();
273 if (pContentControl)
275 // Set showingPlcHdr to false as node has been edited
276 pContentControl->SetShowingPlaceHolder(false);
280 if( bStarted )
282 EndUndo();
283 EndAllAction();
287 // Maximum height limit not possible, because the maximum height
288 // of the current frame can not be obtained.
290 void SwWrtShell::InsertGraphic( const OUString &rPath, const OUString &rFilter,
291 const Graphic &rGrf, SwFlyFrameAttrMgr *pFrameMgr,
292 RndStdIds nAnchorType )
294 ResetCursorStack();
295 if ( !CanInsert() )
296 return;
298 StartAllAction();
300 SwRewriter aRewriter;
301 aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC));
303 StartUndo(SwUndoId::INSERT, &aRewriter);
305 if ( HasSelection() )
306 DelRight();
307 // Inserted graphics in its own paragraph,
308 // if at the end of a non-empty paragraph.
309 //For i120928,avoid to split node
311 EnterSelFrameMode();
313 bool bSetGrfSize = true;
314 bool bOwnMgr = false;
316 if ( !pFrameMgr )
318 bOwnMgr = true;
319 pFrameMgr = new SwFlyFrameAttrMgr( true, this, Frmmgr_Type::GRF, nullptr );
321 // CAUTION
322 // GetAttrSet makes an adjustment
323 // While pasting is a SwFrameSize present
324 // because of the DEF-Framesize
325 // These must be removed explicitly for the optimal size.
326 pFrameMgr->DelAttr(RES_FRM_SIZE);
328 if (nAnchorType != RndStdIds::FLY_AT_PARA)
329 // Something other than at-para was requested.
330 pFrameMgr->SetAnchor(nAnchorType);
332 else
334 Size aSz( pFrameMgr->GetSize() );
335 if ( !aSz.Width() || !aSz.Height() )
337 aSz.setWidth(o3tl::toTwips(1, o3tl::Length::cm));
338 aSz.setHeight(o3tl::toTwips(1, o3tl::Length::cm));
339 pFrameMgr->SetSize( aSz );
341 else if ( aSz.Width() != DFLT_WIDTH && aSz.Height() != DFLT_HEIGHT )
342 bSetGrfSize = false;
344 pFrameMgr->SetHeightSizeType(SwFrameSize::Fixed);
347 // during change tracking, insert the image anchored as character
348 // (to create an SwRangeRedline on its anchor point)
349 if ( IsRedlineOn() && nAnchorType != RndStdIds::FLY_AS_CHAR )
350 pFrameMgr->SetAnchor( RndStdIds::FLY_AS_CHAR );
352 // Insert the graphic
353 SwFEShell::Insert(rPath, rFilter, &rGrf, &pFrameMgr->GetAttrSet());
354 if ( bOwnMgr )
355 pFrameMgr->UpdateAttrMgr();
357 if( bSetGrfSize )
359 Size aSizePixel = rGrf.GetSizePixel();
360 Size aBound = GetGraphicDefaultSize();
362 sal_Int32 nPreferredDPI = mxDoc->getIDocumentSettingAccess().getImagePreferredDPI();
363 Size aGrfSize;
365 if (nPreferredDPI > 0)
367 auto nWidth = o3tl::toTwips(aSizePixel.Width() / double(nPreferredDPI), o3tl::Length::in);
368 auto nHeight = o3tl::toTwips(aSizePixel.Height() / double(nPreferredDPI), o3tl::Length::in);
369 aGrfSize = Size(nWidth, nHeight);
371 else
373 GetGrfSize(aGrfSize);
376 // Add the margin attributes to GrfSize,
377 // because these counts at the margin additionally
378 aGrfSize.AdjustWidth(pFrameMgr->CalcWidthBorder() );
379 aGrfSize.AdjustHeight(pFrameMgr->CalcHeightBorder() );
381 const BigInt aTempWidth( aGrfSize.Width() );
382 const BigInt aTempHeight( aGrfSize.Height());
384 // Fit width if necessary, scale down the height proportional thereafter.
385 if( aGrfSize.Width() > aBound.Width() )
387 aGrfSize.setWidth( aBound.Width() );
388 aGrfSize.setHeight( BigInt(aBound.Width()) * aTempHeight / aTempWidth );
390 // Fit height if necessary, scale down the width proportional thereafter.
391 if( aGrfSize.Height() > aBound.Height() )
393 aGrfSize.setHeight( aBound.Height() );
394 aGrfSize.setWidth( BigInt(aBound.Height()) * aTempWidth / aTempHeight );
396 pFrameMgr->SetSize( aGrfSize );
397 pFrameMgr->UpdateFlyFrame();
399 if ( bOwnMgr )
400 delete pFrameMgr;
402 EndUndo();
403 EndAllAction();
406 // Insert an OLE-Object into the CORE.
407 // if no object is transferred, then one will be created.
409 void SwWrtShell::InsertObject( const svt::EmbeddedObjectRef& xRef, SvGlobalName const *pName,
410 sal_uInt16 nSlotId )
412 ResetCursorStack();
413 if( !CanInsert() )
414 return;
416 if( !xRef.is() )
418 // temporary storage
419 svt::EmbeddedObjectRef xObj;
420 uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetTemporaryStorage();
421 bool bDoVerb = true;
422 if ( pName )
424 comphelper::EmbeddedObjectContainer aCnt( xStor );
425 OUString aName;
426 // TODO/LATER: get aspect?
427 xObj.Assign( aCnt.CreateEmbeddedObject( pName->GetByteSequence(), aName ), embed::Aspects::MSOLE_CONTENT );
429 else
431 SvObjectServerList aServerList;
432 switch (nSlotId)
434 case SID_INSERT_OBJECT:
436 aServerList.FillInsertObjects();
437 aServerList.Remove( SwDocShell::Factory().GetClassId() );
438 [[fallthrough]];
441 // TODO/LATER: recording! Convert properties to items
442 case SID_INSERT_FLOATINGFRAME:
444 SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
445 const SfxSlot* pSlot = pSlotPool->GetSlot(nSlotId);
446 OUString aCmd = pSlot->GetCommand();
447 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
448 ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg(pFact->CreateInsertObjectDialog(GetFrameWeld(mxDoc->GetDocShell()),
449 aCmd, xStor, &aServerList));
450 if (pDlg)
452 pDlg->Execute();
453 bDoVerb = pDlg->IsCreateNew();
454 OUString aIconMediaType;
455 uno::Reference< io::XInputStream > xIconMetaFile = pDlg->GetIconIfIconified( &aIconMediaType );
456 xObj.Assign( pDlg->GetObject(),
457 xIconMetaFile.is() ? embed::Aspects::MSOLE_ICON : embed::Aspects::MSOLE_CONTENT );
458 if ( xIconMetaFile.is() )
459 xObj.SetGraphicStream( xIconMetaFile, aIconMediaType );
462 break;
465 default:
466 break;
470 if ( xObj.is() )
472 if( InsertOleObject( xObj ) && bDoVerb )
474 SfxInPlaceClient* pClient = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
475 if ( !pClient )
477 pClient = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
478 SetCheckForOLEInCaption( true );
481 if ( xObj.GetViewAspect() == embed::Aspects::MSOLE_ICON )
483 SwRect aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
484 aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
485 MapMode aMapMode( MapUnit::MapTwip );
486 Size aSize = xObj.GetSize( &aMapMode );
487 aArea.Width( aSize.Width() );
488 aArea.Height( aSize.Height() );
489 RequestObjectResize( aArea, xObj.GetObject() );
491 else
492 CalcAndSetScale( xObj );
494 //#50270# We don't need to handle error, this is handled by the
495 //DoVerb in the SfxViewShell
496 pClient->DoVerb(embed::EmbedVerbs::MS_OLEVERB_SHOW);
498 // TODO/LATER: set document name - should be done in Client
502 else
504 if( HasSelection() )
505 DelRight();
506 InsertOleObject( xRef );
510 // Insert object into the Core.
511 // From ClipBoard or Insert
513 bool SwWrtShell::InsertOleObject( const svt::EmbeddedObjectRef& xRef, SwFlyFrameFormat **pFlyFrameFormat )
515 //tdf#125100 Ensure that ole object is initially shown as pictogram
516 comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mxDoc->GetDocShell()->getEmbeddedObjectContainer();
517 bool bSaveUserAllowsLinkUpdate = rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
518 rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true);
520 ResetCursorStack();
521 StartAllAction();
523 StartUndo(SwUndoId::INSERT);
525 //Some differences between StarMath and any other objects:
526 //1. Selections should be deleted. For StarMath the Text should be
527 // passed to the Object
528 //2. If the cursor is at the end of a non empty paragraph a paragraph
529 // break should be inserted. StarMath objects are character bound and
530 // no break should be inserted.
531 //3. If an selection is passed to a StarMath object, this object should
532 // not be activated. false should be returned then.
533 bool bStarMath = true;
534 bool bActivate = true;
536 // set parent to get correct VisArea(in case of object needing parent printer)
537 uno::Reference < container::XChild > xChild( xRef.GetObject(), uno::UNO_QUERY );
538 if ( xChild.is() )
539 xChild->setParent( mxDoc->GetDocShell()->GetModel() );
541 SvGlobalName aCLSID( xRef->getClassID() );
542 bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
543 if( IsSelection() )
545 if( bStarMath )
547 OUString aMathData;
548 GetSelectedText( aMathData, ParaBreakType::ToOnlyCR );
550 if( !aMathData.isEmpty() && svt::EmbeddedObjectRef::TryRunningState( xRef.GetObject() ) )
552 uno::Reference < beans::XPropertySet > xSet( xRef->getComponent(), uno::UNO_QUERY );
553 if ( xSet.is() )
557 xSet->setPropertyValue("Formula", uno::Any( aMathData ) );
558 bActivate = false;
560 catch (const uno::Exception&)
566 DelRight();
569 if ( !bStarMath )
570 SwFEShell::SplitNode( false, false );
572 EnterSelFrameMode();
574 const SvGlobalName* pName = nullptr;
575 SvGlobalName aObjClsId;
576 if (xRef.is())
578 aObjClsId = SvGlobalName(xRef.GetObject()->getClassID());
579 pName = &aObjClsId;
581 SwFlyFrameAttrMgr aFrameMgr( true, this, Frmmgr_Type::OLE, pName );
582 aFrameMgr.SetHeightSizeType(SwFrameSize::Fixed);
584 SwRect aBound;
585 CalcBoundRect( aBound, aFrameMgr.GetAnchor() );
587 //The Size should be suggested by the OLE server
588 MapMode aMapMode( MapUnit::MapTwip );
589 Size aSz = xRef.GetSize( &aMapMode );
591 //Object size can be limited
592 if ( aSz.Width() > aBound.Width() )
594 //Always limit proportional.
595 aSz.setHeight( aSz.Height() * aBound.Width() / aSz.Width() );
596 aSz.setWidth( aBound.Width() );
598 aFrameMgr.SetSize( aSz );
599 SwFlyFrameFormat *pFormat = SwFEShell::InsertObject( xRef, &aFrameMgr.GetAttrSet() );
601 // --> #i972#
602 if ( bStarMath && mxDoc->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ) )
603 AlignFormulaToBaseline( xRef.GetObject() );
605 if (pFlyFrameFormat)
606 *pFlyFrameFormat = pFormat;
608 if ( SotExchange::IsChart( aCLSID ) )
610 uno::Reference< embed::XEmbeddedObject > xEmbeddedObj = xRef.GetObject();
611 if ( xEmbeddedObj.is() )
613 bool bDisableDataTableDialog = false;
614 svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj );
615 uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
616 if ( xProps.is() &&
617 ( xProps->getPropertyValue("DisableDataTableDialog") >>= bDisableDataTableDialog ) &&
618 bDisableDataTableDialog )
620 xProps->setPropertyValue("DisableDataTableDialog",
621 uno::Any( false ) );
622 xProps->setPropertyValue("DisableComplexChartTypes",
623 uno::Any( false ) );
624 uno::Reference< util::XModifiable > xModifiable( xProps, uno::UNO_QUERY );
625 if ( xModifiable.is() )
627 xModifiable->setModified( true );
633 EndAllAction();
634 GetView().AutoCaption(OLE_CAP, &aCLSID);
636 SwRewriter aRewriter;
638 if ( bStarMath )
639 aRewriter.AddRule(UndoArg1, SwResId(STR_MATH_FORMULA));
640 else if ( SotExchange::IsChart( aCLSID ) )
641 aRewriter.AddRule(UndoArg1, SwResId(STR_CHART));
642 else
643 aRewriter.AddRule(UndoArg1, SwResId(STR_OLE));
645 EndUndo(SwUndoId::INSERT, &aRewriter);
647 rEmbeddedObjectContainer.setUserAllowsLinkUpdate(bSaveUserAllowsLinkUpdate);
649 return bActivate;
652 // The current selected OLE object will be loaded with the
653 // verb into the server.
654 void SwWrtShell::LaunchOLEObj(sal_Int32 nVerb)
656 if ( GetCntType() != CNT_OLE ||
657 GetView().GetViewFrame().GetFrame().IsInPlace() )
658 return;
660 svt::EmbeddedObjectRef& xRef = GetOLEObject();
661 OSL_ENSURE( xRef.is(), "OLE not found" );
663 // LOK: we don't want to handle any other embedded objects than
664 // charts, there are too many problems with eg. embedded spreadsheets
665 // (like it creates a separate view for the calc sheet)
666 if (comphelper::LibreOfficeKit::isActive())
668 const auto classId = xRef->getClassID();
669 if (!SotExchange::IsChart(classId) && !SotExchange::IsMath(classId))
670 return;
673 SfxInPlaceClient* pCli = GetView().FindIPClient( xRef.GetObject(), &GetView().GetEditWin() );
674 if ( !pCli )
675 pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xRef );
677 uno::Reference<lang::XInitialization> xOLEInit(xRef.GetObject(), uno::UNO_QUERY);
678 if (xOLEInit.is())
680 uno::Sequence<beans::PropertyValue> aArguments
681 = { comphelper::makePropertyValue("ReadOnly", pCli->IsProtected()) };
682 xOLEInit->initialize({ uno::Any(aArguments) });
685 static_cast<SwOleClient*>(pCli)->SetInDoVerb( true );
687 CalcAndSetScale( xRef );
688 pCli->DoVerb( nVerb );
690 static_cast<SwOleClient*>(pCli)->SetInDoVerb( false );
691 CalcAndSetScale( xRef );
694 void SwWrtShell::MoveObjectIfActive( svt::EmbeddedObjectRef& xObj, const Point& rOffset )
698 sal_Int32 nState = xObj->getCurrentState();
699 if ( nState == css::embed::EmbedStates::INPLACE_ACTIVE
700 || nState == css::embed::EmbedStates::UI_ACTIVE )
702 SfxInPlaceClient* pCli =
703 GetView().FindIPClient( xObj.GetObject(), &(GetView().GetEditWin()) );
704 if ( pCli )
706 tools::Rectangle aArea = pCli->GetObjArea();
707 aArea += rOffset;
708 pCli->SetObjArea( aArea );
712 catch (const uno::Exception&)
717 void SwWrtShell::CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
718 const SwRect *pFlyPrtRect,
719 const SwRect *pFlyFrameRect,
720 const bool bNoTextFramePrtAreaChanged )
722 // Setting the scale of the client. This arises from the difference
723 // between the VisArea of the object and the ObjArea.
724 OSL_ENSURE( xObj.is(), "ObjectRef not valid" );
726 sal_Int64 nAspect = xObj.GetViewAspect();
727 if ( nAspect == embed::Aspects::MSOLE_ICON )
728 return; // the replacement image is completely controlled by container in this case
730 sal_Int64 nMisc = 0;
731 bool bLinkingChart = false;
735 nMisc = xObj->getStatus( nAspect );
737 // This can surely only be a non-active object, if desired they
738 // get the new size set as VisArea (StarChart).
739 if( embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE & nMisc )
741 // TODO/MBA: testing
742 SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
743 : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
744 if( !aRect.IsEmpty() )
746 // TODO/LEAN: getMapUnit can switch object to running state
747 // xObj.TryRunningState();
749 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
751 // TODO/LATER: needs complete VisArea?!
752 Size aSize( OutputDevice::LogicToLogic(aRect.SVRect(), MapMode(MapUnit::MapTwip), MapMode(aUnit)).GetSize() );
753 awt::Size aSz;
754 aSz.Width = aSize.Width();
755 aSz.Height = aSize.Height();
757 // Action 'setVisualAreaSize' doesn't have to turn on the
758 // modified state of the document, either.
759 bool bModified = false;
760 uno::Reference<util::XModifiable> xModifiable(xObj->getComponent(), uno::UNO_QUERY);
761 if (xModifiable.is())
762 bModified = xModifiable->isModified();
763 xObj->setVisualAreaSize( nAspect, aSz );
764 xModifiable.set(xObj->getComponent(), uno::UNO_QUERY);
765 if (xModifiable.is() && xModifiable->isModified() && !bModified)
766 xModifiable->setModified(bModified);
768 // #i48419# - action 'UpdateReplacement' doesn't
769 // have to change the modified state of the document.
770 // This is only a workaround for the defect, that this action
771 // modifies a document after load, because unnecessarily the
772 // replacement graphic is updated, in spite of the fact that
773 // nothing has been changed.
774 // If the replacement graphic changes by this action, the document
775 // will be already modified via other mechanisms.
777 bool bResetEnableSetModified(false);
778 if ( GetDoc()->GetDocShell()->IsEnableSetModified() )
780 GetDoc()->GetDocShell()->EnableSetModified( false );
781 bResetEnableSetModified = true;
784 //#i79576# don't destroy chart replacement images on load
785 //#i79578# don't request a new replacement image for charts to often
786 //a chart sends a modified call to the framework if it was changed
787 //thus the replacement update is already handled elsewhere
788 if ( !SotExchange::IsChart( xObj->getClassID() ) )
789 xObj.UpdateReplacement();
791 if ( bResetEnableSetModified )
793 GetDoc()->GetDocShell()->EnableSetModified();
798 // TODO/LATER: this is only a workaround,
799 uno::Reference< chart2::XChartDocument > xChartDocument( xObj->getComponent(), uno::UNO_QUERY );
800 bLinkingChart = ( xChartDocument.is() && !xChartDocument->hasInternalDataProvider() );
803 catch (const uno::Exception&)
805 // TODO/LATER: handle the error
806 return;
809 SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
810 if ( !pCli )
812 if ( (embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY & nMisc)
813 || bLinkingChart
814 // --> OD #i117189# - refine condition for non-resizable objects
815 // non-resizable objects need to be set the size back by this method
816 || ( bNoTextFramePrtAreaChanged && nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE ) )
818 pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
820 else
821 return;
824 // TODO/LEAN: getMapUnit can switch object to running state
825 // xObj.TryRunningState();
827 awt::Size aSize;
830 aSize = xObj->getVisualAreaSize( nAspect );
832 catch (const embed::NoVisualAreaSizeException&)
834 OSL_FAIL("Can't get visual area size!" );
835 // the scaling will not be done
837 catch (const uno::Exception&)
839 // TODO/LATER: handle the error
840 OSL_FAIL("Can't get visual area size!" );
841 return;
844 Size _aVisArea( aSize.Width, aSize.Height );
846 Fraction aScaleWidth( 1, 1 );
847 Fraction aScaleHeight( 1, 1 );
849 bool bUseObjectSize = false;
851 // As long as there comes no reasonable size from the object,
852 // nothing can be scaled.
853 if( _aVisArea.Width() && _aVisArea.Height() )
855 const MapMode aTmp( MapUnit::MapTwip );
856 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
857 _aVisArea = OutputDevice::LogicToLogic(_aVisArea, MapMode(aUnit), aTmp);
858 Size aObjArea;
859 if ( pFlyPrtRect )
860 aObjArea = pFlyPrtRect->SSize();
861 else
862 aObjArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ).SSize();
864 // differ the aObjArea and _aVisArea by 1 Pixel then set new VisArea
865 tools::Long nX, nY;
866 SwSelPaintRects::Get1PixelInLogic( *this, &nX, &nY );
867 if( !( _aVisArea.Width() - nX <= aObjArea.Width() &&
868 _aVisArea.Width() + nX >= aObjArea.Width() &&
869 _aVisArea.Height()- nY <= aObjArea.Height()&&
870 _aVisArea.Height()+ nY >= aObjArea.Height() ))
872 if ( nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE )
874 // the object must not be scaled,
875 // the size stored in object must be used for restoring
876 bUseObjectSize = true;
878 else
880 aScaleWidth = Fraction( aObjArea.Width(), _aVisArea.Width() );
881 aScaleHeight = Fraction( aObjArea.Height(), _aVisArea.Height());
886 // Now is the favorable time to set the ObjArea.
887 // The Scaling must be considered.
888 SwRect aArea;
889 if ( pFlyPrtRect )
891 aArea = *pFlyPrtRect;
892 aArea += pFlyFrameRect->Pos();
894 else
896 aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
897 aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
900 if ( bUseObjectSize )
902 // --> this moves non-resizable object so that when adding borders the baseline remains the same
903 const SwFlyFrameFormat *pFlyFrameFormat = dynamic_cast< const SwFlyFrameFormat * >( GetFlyFrameFormat() );
904 OSL_ENSURE( pFlyFrameFormat, "Could not find fly frame." );
905 if ( pFlyFrameFormat )
907 const Point &rPoint = pFlyFrameFormat->GetLastFlyFramePrtRectPos();
908 SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
909 : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
910 aArea += rPoint - aRect.Pos(); // adjust area by diff of printing area position in order to keep baseline alignment correct.
912 aArea.Width ( _aVisArea.Width() );
913 aArea.Height( _aVisArea.Height() );
914 RequestObjectResize( aArea, xObj.GetObject() );
916 else
918 double nWidth(pCli->GetScaleWidth());
919 double nHeight(pCli->GetScaleHeight());
920 if (nWidth && nHeight)
922 aArea.Width ( aArea.Width() / nWidth );
923 aArea.Height( aArea.Height() / nHeight );
927 pCli->SetObjAreaAndScale( aArea.SVRect(), aScaleWidth, aScaleHeight );
930 void SwWrtShell::ConnectObj( svt::EmbeddedObjectRef& xObj, const SwRect &rPrt,
931 const SwRect &rFrame )
933 SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin());
934 if ( !pCli )
935 new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
936 CalcAndSetScale( xObj, &rPrt, &rFrame );
939 // Insert hard page break;
940 // Selections will be overwritten
941 void SwWrtShell::InsertPageBreak(const OUString *pPageDesc, const ::std::optional<sal_uInt16>& oPgNum )
943 if (!lcl_IsAllowed(this))
944 return;
946 ResetCursorStack();
947 if( CanInsert() )
949 SwActContext aActContext(this);
950 StartUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
952 if ( !IsCursorInTable() )
954 if(HasSelection())
955 DelRight();
956 SwFEShell::SplitNode();
957 // delete the numbered attribute of the last line if the last line is empty
958 GetDoc()->ClearLineNumAttrs( *GetCursor()->GetPoint() );
961 const SwPageDesc *pDesc = pPageDesc
962 ? FindPageDescByName( *pPageDesc, true ) : nullptr;
963 if( pDesc )
965 SwFormatPageDesc aDesc( pDesc );
966 aDesc.SetNumOffset( oPgNum );
967 SetAttrItem( aDesc );
969 else
970 SetAttrItem( SvxFormatBreakItem(SvxBreak::PageBefore, RES_BREAK) );
971 EndUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
973 collectUIInformation("BREAK_PAGE", "parameter");
976 // Insert hard page break;
977 // Selections will be overwritten
979 void SwWrtShell::InsertLineBreak(std::optional<SwLineBreakClear> oClear)
981 if (!lcl_IsAllowed(this))
982 return;
984 ResetCursorStack();
985 if( CanInsert() )
987 if(HasSelection())
988 DelRight();
990 const sal_Unicode cIns = 0x0A;
991 SwLineBreakClear eClear = SwLineBreakClear::NONE;
992 if (oClear.has_value())
994 eClear = *oClear;
996 SvxAutoCorrect* pACorr = lcl_IsAutoCorr();
997 if (pACorr && eClear == SwLineBreakClear::NONE)
998 AutoCorrect( *pACorr, cIns );
999 else
1001 if (eClear == SwLineBreakClear::NONE)
1003 SwWrtShell::Insert(OUString(cIns));
1005 else
1007 SwFormatLineBreak aLineBreak(eClear);
1008 SetAttrItem(aLineBreak);
1014 // Insert hard column break;
1015 // Selections will be overwritten
1017 void SwWrtShell::InsertColumnBreak()
1019 if (!lcl_IsAllowed(this))
1020 return;
1022 SwActContext aActContext(this);
1023 ResetCursorStack();
1024 if( !CanInsert() )
1025 return;
1027 StartUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
1029 if ( !IsCursorInTable() )
1031 if(HasSelection())
1032 DelRight();
1033 SwFEShell::SplitNode( false, false );
1035 SetAttrItem(SvxFormatBreakItem(SvxBreak::ColumnBefore, RES_BREAK));
1037 EndUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
1040 void SwWrtShell::InsertContentControl(SwContentControlType eType)
1042 if (!lcl_IsAllowed(this))
1044 return;
1047 ResetCursorStack();
1048 if (!CanInsert())
1050 return;
1053 auto pContentControl = std::make_shared<SwContentControl>(nullptr);
1054 OUString aPlaceholder;
1055 switch (eType)
1057 case SwContentControlType::RICH_TEXT:
1058 case SwContentControlType::PLAIN_TEXT:
1060 pContentControl->SetShowingPlaceHolder(true);
1061 if (eType == SwContentControlType::PLAIN_TEXT)
1063 pContentControl->SetPlainText(true);
1065 if (!HasSelection())
1067 aPlaceholder = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER);
1069 break;
1071 case SwContentControlType::CHECKBOX:
1073 pContentControl->SetCheckbox(true);
1074 // Ballot Box with X
1075 pContentControl->SetCheckedState(u"\u2612");
1076 // Ballot Box
1077 pContentControl->SetUncheckedState(OUString(u"\u2610"));
1078 aPlaceholder = u"\u2610";
1079 break;
1081 case SwContentControlType::COMBO_BOX:
1082 case SwContentControlType::DROP_DOWN_LIST:
1084 if (eType == SwContentControlType::COMBO_BOX)
1086 pContentControl->SetComboBox(true);
1088 else if (eType == SwContentControlType::DROP_DOWN_LIST)
1090 pContentControl->SetDropDown(true);
1093 pContentControl->SetShowingPlaceHolder(true);
1094 if (!HasSelection())
1096 aPlaceholder = SwResId(STR_DROPDOWN_CONTENT_CONTROL_PLACEHOLDER);
1098 SwContentControlListItem aListItem;
1099 aListItem.m_aValue = aPlaceholder;
1100 pContentControl->SetListItems({ aListItem });
1101 break;
1103 case SwContentControlType::PICTURE:
1105 // Set up the picture content control.
1106 pContentControl->SetShowingPlaceHolder(true);
1107 pContentControl->SetPicture(true);
1109 // Create the placeholder bitmap.
1110 BitmapEx aBitmap(Size(1, 1), vcl::PixelFormat::N24_BPP);
1111 Color aColor = SvtOptionsDrawinglayer::getHilightColor();
1112 aColor.IncreaseLuminance(255 * 0.75);
1113 aBitmap.Erase(aColor);
1114 SwRewriter aRewriter;
1115 aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC_DEFNAME));
1116 StartUndo(SwUndoId::INSERT, &aRewriter);
1117 LockPaint(LockPaintReason::InsertGraphic);
1118 StartAction();
1119 InsertGraphic(OUString(), OUString(), aBitmap, nullptr, RndStdIds::FLY_AS_CHAR);
1121 // Set properties on the bitmap.
1122 SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE> aSet(GetDoc()->GetAttrPool());
1123 GetFlyFrameAttr(aSet);
1124 SwFormatFrameSize aSize(SwFrameSize::Fixed, 3000, 3000);
1125 aSet.Put(aSize);
1126 SetFlyFrameAttr(aSet);
1127 SwFrameFormat* pFrameFormat = GetFlyFrameFormat();
1128 EndAction();
1129 UnlockPaint();
1130 EndUndo();
1132 // Go after the anchor position.
1133 UnSelectFrame();
1134 LeaveSelFrameMode();
1136 SwCursor* pCursor = getShellCursor(true);
1137 pCursor->DeleteMark();
1138 const SwFormatAnchor& rFormatAnchor = pFrameFormat->GetAnchor();
1139 pCursor->GetPoint()->Assign( *rFormatAnchor.GetAnchorContentNode(), rFormatAnchor.GetAnchorContentOffset() + 1);
1142 // Select before the anchor position.
1143 Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
1144 break;
1146 case SwContentControlType::DATE:
1148 pContentControl->SetShowingPlaceHolder(true);
1149 pContentControl->SetDate(true);
1150 SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
1151 sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE);
1152 const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat);
1153 pContentControl->SetDateFormat(pFormat->GetFormatstring());
1154 pContentControl->SetDateLanguage(LanguageTag(pFormat->GetLanguage()).getBcp47());
1155 if (!HasSelection())
1157 aPlaceholder = SwResId(STR_DATE_CONTENT_CONTROL_PLACEHOLDER);
1159 break;
1162 if (aPlaceholder.getLength())
1164 Insert(aPlaceholder);
1165 Left(SwCursorSkipMode::Chars, /*bSelect=*/true, aPlaceholder.getLength(),
1166 /*bBasicCall=*/false);
1168 SwFormatContentControl aContentControl(pContentControl, RES_TXTATR_CONTENTCONTROL);
1169 SetAttrItem(aContentControl);
1172 // Insert footnote
1173 // rStr - optional footnote mark
1175 void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit )
1177 ResetCursorStack();
1178 if( !CanInsert() )
1179 return;
1181 if(HasSelection())
1183 //collapse cursor to the end
1184 if(!IsCursorPtAtEnd())
1185 SwapPam();
1186 ClearMark();
1188 SwPosition aPos = *GetCursor()->GetPoint();
1189 SwFormatFootnote aFootNote( bEndNote );
1190 if(!rStr.isEmpty())
1191 aFootNote.SetNumStr( rStr );
1193 SetAttrItem(aFootNote);
1195 if( bEdit )
1197 // For editing the footnote text.
1198 Left(SwCursorSkipMode::Chars, false, 1, false );
1199 GotoFootnoteText();
1201 m_aNavigationMgr.addEntry(aPos);
1204 // tdf#141634
1205 static bool lcl_FoldedOutlineNodeEndOfParaSplit(SwWrtShell *pThis)
1207 SwTextNode* pTextNode = pThis->GetCursor()->GetPointNode().GetTextNode();
1208 if (pTextNode && pTextNode->IsOutline())
1210 bool bVisible = true;
1211 pTextNode->GetAttrOutlineContentVisible(bVisible);
1212 if (!bVisible)
1214 const SwNodes& rNodes = pThis->GetNodes();
1215 const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
1216 SwOutlineNodes::size_type nPos;
1217 (void) rOutlineNodes.Seek_Entry(pTextNode, &nPos);
1219 SwNode* pSttNd = rOutlineNodes[nPos];
1221 // determine end node of folded outline content
1222 SwNode* pEndNd = &rNodes.GetEndOfContent();
1223 if (rOutlineNodes.size() > nPos + 1)
1224 pEndNd = rOutlineNodes[nPos + 1];
1226 if (pThis->GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
1228 // get the next outline node after the folded outline content (iPos)
1229 // it is the next outline node with the same level or less
1230 int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel();
1231 SwOutlineNodes::size_type iPos = nPos;
1232 while (++iPos < rOutlineNodes.size() &&
1233 rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel);
1235 // get the correct end node
1236 // the outline node may be in frames, headers, footers special section of doc model
1237 SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode();
1238 while (pStartOfSectionNodeSttNd->StartOfSectionNode()
1239 != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode())
1241 pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode();
1243 pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode();
1245 if (iPos < rOutlineNodes.size())
1247 SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode();
1248 while (pStartOfSectionNode->StartOfSectionNode()
1249 != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode())
1251 pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode();
1253 if (pStartOfSectionNodeSttNd == pStartOfSectionNode)
1254 pEndNd = rOutlineNodes[iPos];
1258 // table, text box, header, footer
1259 if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
1261 // insert before section end node
1262 if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex())
1264 SwNodeIndex aIdx(*pSttNd->EndOfSectionNode());
1265 while (aIdx.GetNode().IsEndNode())
1266 --aIdx;
1267 ++aIdx;
1268 pEndNd = &aIdx.GetNode();
1271 // if pSttNd isn't in table but pEndNd is then insert after table
1272 else if (pEndNd->GetTableBox())
1274 pEndNd = pEndNd->FindTableNode();
1275 SwNodeIndex aIdx(*pEndNd, -1);
1276 // account for nested tables
1277 while (aIdx.GetNode().GetTableBox())
1279 pEndNd = aIdx.GetNode().FindTableNode();
1280 aIdx.Assign(*pEndNd, -1);
1282 aIdx.Assign(*pEndNd->EndOfSectionNode(), +1);
1283 pEndNd = &aIdx.GetNode();
1285 // end node determined
1287 // now insert the new outline node
1288 SwDoc* pDoc = pThis->GetDoc();
1290 // insert at end of tablebox doesn't work correct without
1291 MakeAllOutlineContentTemporarilyVisible a(pDoc);
1293 SwTextNode* pNd = pDoc->GetNodes().MakeTextNode(*pEndNd, pTextNode->GetTextColl(), true);
1295 (void) rOutlineNodes.Seek_Entry(pNd, &nPos);
1296 pThis->GotoOutline(nPos);
1298 if (pDoc->GetIDocumentUndoRedo().DoesUndo())
1300 pDoc->GetIDocumentUndoRedo().ClearRedo();
1301 pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsert>(*pNd));
1302 pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoFormatColl>
1303 (SwPaM(*pNd), pNd->GetTextColl(), true, true));
1306 pThis->SetModified();
1307 return true;
1310 return false;
1313 // SplitNode; also, because
1314 // - of deleting selected content;
1315 // - of reset of the Cursorstack if necessary.
1317 void SwWrtShell::SplitNode( bool bAutoFormat )
1319 ResetCursorStack();
1320 if( !CanInsert() )
1321 return;
1323 SwActContext aActContext(this);
1325 m_rView.GetEditWin().FlushInBuffer();
1326 StartUndo(SwUndoId::SPLITNODE);
1328 bool bHasSel = HasSelection();
1329 if (bHasSel)
1330 DelRight();
1332 bool bHandled = false;
1333 if (GetViewOptions()->IsShowOutlineContentVisibilityButton() && IsEndPara())
1334 bHandled = lcl_FoldedOutlineNodeEndOfParaSplit(this);
1336 if (!bHandled)
1337 SwFEShell::SplitNode( bAutoFormat );
1339 EndUndo(SwUndoId::SPLITNODE);
1342 // Turn on numbering
1343 // Parameter: Optional specification of a name for the named list;
1344 // this indicates a position if it is possible to convert them
1345 // into a number and less than nMaxRules.
1347 // To test the CharFormats at the numbering
1348 // external void SetNumChrFormat( SwWrtShell*, SwNumRules& );
1350 // -> #i40041#
1351 // Preconditions (as far as OD has figured out):
1352 // - <SwEditShell::HasNumber()> is false, if <bNum> is true
1353 // - <SwEditShell::HasBullet()> is false, if <bNum> is false
1354 // Behavior of method is determined by the current situation at the current
1355 // cursor position in the document.
1356 void SwWrtShell::NumOrBulletOn(bool bNum)
1358 StartUndo(SwUndoId::NUMORNONUM);
1360 const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
1362 // - activate outline rule respectively turning on outline rule for
1363 // current text node. But, only for turning on a numbering (<bNum> == true).
1364 // - overwrite found numbering rule at current cursor position, if
1365 // no numbering rule can be retrieved from the paragraph style.
1366 bool bContinueFoundNumRule( false );
1367 bool bActivateOutlineRule( false );
1368 int nActivateOutlineLvl( MAXLEVEL ); // only relevant, if <bActivateOutlineRule> == true
1369 SwTextFormatColl * pColl = GetCurTextFormatColl();
1370 if ( pColl )
1372 // retrieve numbering rule at paragraph
1373 // style, which is found at current cursor position in the document.
1374 SwNumRule* pCollRule = mxDoc->FindNumRulePtr(pColl->GetNumRule().GetValue());
1375 // #125993# - The outline numbering rule isn't allowed
1376 // to be derived from a parent paragraph style to a derived one.
1377 // Thus check, if the found outline numbering rule is directly
1378 // set at the paragraph style <pColl>. If not, set <pCollRule> to NULL
1379 if ( pCollRule && pCollRule == GetDoc()->GetOutlineNumRule() )
1381 const SwNumRule* pDirectCollRule =
1382 mxDoc->FindNumRulePtr(pColl->GetNumRule( false ).GetValue());
1383 if ( !pDirectCollRule )
1385 pCollRule = nullptr;
1389 if ( !pCollRule )
1391 pNumRule = pCollRule;
1393 // no activation or continuation of outline numbering in Writer/Web document
1394 else if ( bNum &&
1395 !dynamic_cast<SwWebDocShell*>(GetDoc()->GetDocShell()) &&
1396 pCollRule == GetDoc()->GetOutlineNumRule() )
1398 if ( pNumRule == pCollRule )
1400 // check, if text node at current cursor positioned is counted.
1401 // If not, let it been counted. Then it has to be checked,
1402 // of the outline numbering has to be activated or continued.
1403 SwTextNode const*const pTextNode = sw::GetParaPropsNode(
1404 *GetLayout(), GetCursor()->GetPoint()->GetNode());
1405 if ( pTextNode && !pTextNode->IsCountedInList() )
1407 // check, if numbering of the outline level of the paragraph
1408 // style is active. If not, activate this outline level.
1409 nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1410 OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
1411 "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
1412 if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
1413 pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1414 == SVX_NUM_NUMBER_NONE )
1416 // activate outline numbering
1417 bActivateOutlineRule = true;
1419 else
1421 // turning on outline numbering at current cursor position
1422 bContinueFoundNumRule = true;
1425 else
1427 // #i101234#
1428 // activate outline numbering, because from the precondition
1429 // it's known, that <SwEdit::HasNumber()> == false
1430 bActivateOutlineRule = true;
1431 nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1434 else if ( !pNumRule )
1436 // #i101234#
1437 // Check, if corresponding list level of the outline numbering
1438 // has already a numbering format set.
1439 nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1440 if ( pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1441 == SVX_NUM_NUMBER_NONE )
1443 // activate outline numbering, because from the precondition
1444 // it's known, that <SwEdit::HasNumber()> == false
1445 bActivateOutlineRule = true;
1447 else
1449 // turning on outline numbering at current cursor position
1450 bContinueFoundNumRule = true;
1453 else
1455 // check, if numbering of the outline level of the paragraph
1456 // style is active. If not, activate this outline level.
1457 nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1458 OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
1459 "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
1460 if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
1461 pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1462 == SVX_NUM_NUMBER_NONE )
1464 // activate outline numbering
1465 bActivateOutlineRule = true;
1467 else
1469 // turning on outline numbering at current cursor position
1470 bContinueFoundNumRule = true;
1473 pNumRule = pCollRule;
1477 // Only automatic numbering/bullet rules should be changed.
1478 // Note: The outline numbering rule is also an automatic one. It's only
1479 // changed, if it has to be activated.
1480 if ( pNumRule )
1482 if ( !pNumRule->IsAutoRule() )
1484 pNumRule = nullptr;
1486 else if ( pNumRule == GetDoc()->GetOutlineNumRule() &&
1487 !bActivateOutlineRule && !bContinueFoundNumRule )
1489 pNumRule = nullptr;
1493 // Search for a previous numbering/bullet rule to continue it.
1494 OUString sContinuedListId;
1495 if ( !pNumRule )
1497 pNumRule = GetDoc()->SearchNumRule( *GetCursor()->GetPoint(),
1498 false, bNum, false, 0,
1499 sContinuedListId, GetLayout() );
1500 bContinueFoundNumRule = pNumRule != nullptr;
1503 if (pNumRule)
1505 SwNumRule aNumRule(*pNumRule);
1507 // do not change found numbering/bullet rule, if it should only be continued.
1508 if ( !bContinueFoundNumRule )
1510 SwTextNode const*const pTextNode = sw::GetParaPropsNode(
1511 *GetLayout(), GetCursor()->GetPoint()->GetNode());
1513 if (pTextNode)
1515 // use above retrieve outline level, if outline numbering has to be activated.
1516 int nLevel = bActivateOutlineRule
1517 ? nActivateOutlineLvl
1518 : pTextNode->GetActualListLevel();
1520 if (nLevel < 0)
1521 nLevel = 0;
1523 if (nLevel >= MAXLEVEL)
1524 nLevel = MAXLEVEL - 1;
1526 SwNumFormat aFormat(aNumRule.Get(o3tl::narrowing<sal_uInt16>(nLevel)));
1528 if (bNum)
1529 aFormat.SetNumberingType(SVX_NUM_ARABIC);
1530 else
1532 // #i63395# Only apply user defined default bullet font
1533 if ( numfunc::IsDefBulletFontUserDefined() )
1535 const vcl::Font* pFnt = &numfunc::GetDefBulletFont();
1536 aFormat.SetBulletFont( pFnt );
1538 aFormat.SetBulletChar( numfunc::GetBulletChar(static_cast<sal_uInt8>(nLevel)));
1539 aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1540 // #i93908# clear suffix for bullet lists
1541 aFormat.SetListFormat("", "", nLevel);
1543 aNumRule.Set(o3tl::narrowing<sal_uInt16>(nLevel), aFormat);
1547 // reset indent attribute on applying list style
1548 SetCurNumRule( aNumRule, false, sContinuedListId, true );
1550 else
1552 // #i95907#
1553 const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
1554 numfunc::GetDefaultPositionAndSpaceMode() );
1555 SwNumRule aNumRule( GetUniqueNumRuleName(), ePosAndSpaceMode );
1556 // Append the character template at the numbering.
1557 SwCharFormat* pChrFormat;
1558 SwDocShell* pDocSh = GetView().GetDocShell();
1559 // #i63395#
1560 // Only apply user defined default bullet font
1561 const vcl::Font* pFnt = numfunc::IsDefBulletFontUserDefined()
1562 ? &numfunc::GetDefBulletFont()
1563 : nullptr;
1565 if (bNum)
1567 pChrFormat = GetCharFormatFromPool( RES_POOLCHR_NUM_LEVEL );
1569 else
1571 pChrFormat = GetCharFormatFromPool( RES_POOLCHR_BULLET_LEVEL );
1574 const SwTextNode *const pTextNode = sw::GetParaPropsNode(*GetLayout(),
1575 GetCursor()->GetPoint()->GetNode());
1576 const SwTwips nWidthOfTabs = pTextNode
1577 ? pTextNode->GetWidthOfLeadingTabs()
1578 : 0;
1579 GetDoc()->getIDocumentContentOperations().RemoveLeadingWhiteSpace(*GetCursor());
1581 const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh ) != nullptr;
1582 const bool bRightToLeft = IsInRightToLeftText();
1583 for( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
1585 SwNumFormat aFormat( aNumRule.Get( nLvl ) );
1586 aFormat.SetCharFormat( pChrFormat );
1588 if (! bNum)
1590 // #i63395#
1591 // Only apply user defined default bullet font
1592 if ( pFnt )
1594 aFormat.SetBulletFont( pFnt );
1596 aFormat.SetBulletChar( numfunc::GetBulletChar(nLvl) );
1597 aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1598 // #i93908# clear suffix for bullet lists
1599 aFormat.SetListFormat("", "", nLvl);
1602 // #i95907#
1603 if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1605 if(bHtml && nLvl)
1607 // 1/2" for HTML
1608 aFormat.SetAbsLSpace(nLvl * 720);
1610 else if ( nWidthOfTabs > 0 )
1612 aFormat.SetAbsLSpace(nWidthOfTabs + nLvl * 720);
1616 // #i38904# Default alignment for
1617 // numbering/bullet should be rtl in rtl paragraph:
1618 if ( bRightToLeft )
1620 aFormat.SetNumAdjust( SvxAdjust::Right );
1623 aNumRule.Set( nLvl, aFormat );
1626 // #i95907#
1627 if ( pTextNode &&
1628 ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1631 const SwTwips nTextNodeIndent = pTextNode->GetAdditionalIndentForStartingNewList();
1632 if ( ( nTextNodeIndent + nWidthOfTabs ) != 0 )
1634 // #i111172#/fdo#85666
1635 // If text node is already inside a list, assure that the indents
1636 // are the same. Thus, adjust the indent change value by subtracting
1637 // indents of to be applied list style.
1638 SwTwips nIndentChange = nTextNodeIndent + nWidthOfTabs;
1639 if ( pTextNode->GetNumRule() )
1641 int nLevel = pTextNode->GetActualListLevel();
1643 if (nLevel < 0)
1644 nLevel = 0;
1646 if (nLevel >= MAXLEVEL)
1647 nLevel = MAXLEVEL - 1;
1649 const SwNumFormat& aFormat( aNumRule.Get( nLevel ) );
1650 if ( aFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1652 nIndentChange -= aFormat.GetIndentAt() + aFormat.GetFirstLineIndent();
1655 aNumRule.ChangeIndent( nIndentChange );
1658 // reset indent attribute on applying list style
1659 // start new list
1660 SetCurNumRule( aNumRule, true, OUString(), true );
1663 EndUndo(SwUndoId::NUMORNONUM);
1665 // <- #i40041#
1667 void SwWrtShell::NumOn()
1669 NumOrBulletOn(true);
1672 void SwWrtShell::NumOrBulletOff()
1674 const SwNumRule * pCurNumRule = GetNumRuleAtCurrCursorPos();
1676 if (!pCurNumRule)
1677 return;
1679 if (pCurNumRule->IsOutlineRule())
1681 SwNumRule aNumRule(*pCurNumRule);
1683 SwTextNode * pTextNode =
1684 sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->GetNode());
1686 if (pTextNode)
1688 int nLevel = pTextNode->GetActualListLevel();
1690 if (nLevel < 0)
1691 nLevel = 0;
1693 if (nLevel >= MAXLEVEL)
1694 nLevel = MAXLEVEL - 1;
1696 SwNumFormat aFormat(aNumRule.Get(o3tl::narrowing<sal_uInt16>(nLevel)));
1698 aFormat.SetNumberingType(SVX_NUM_NUMBER_NONE);
1699 aNumRule.Set(nLevel, aFormat);
1701 // no start or continuation of a list - the outline style is only changed.
1702 SetCurNumRule( aNumRule, false );
1705 else
1707 DelNumRules();
1710 // #126346# - Cursor can not be anymore in front of
1711 // a label, because numbering/bullet is switched off.
1712 SetInFrontOfLabel( false );
1714 // <- #i29560#
1716 // Request Default-Bulletlist
1718 void SwWrtShell::BulletOn()
1720 NumOrBulletOn(false);
1723 SelectionType SwWrtShell::GetSelectionType() const
1725 // ContentType cannot be determined within a Start-/EndAction.
1726 // Because there is no invalid value TEXT will be returned.
1727 // The value does not matter, it may be updated in EndAction anyway.
1729 if (ActionPend())
1730 return IsSelFrameMode() ? SelectionType::Frame : SelectionType::Text;
1732 SwView &_rView = const_cast<SwView&>(GetView());
1733 if (_rView.GetPostItMgr() && _rView.GetPostItMgr()->HasActiveSidebarWin() )
1734 return SelectionType::PostIt;
1736 // Inserting a frame is not a DrawMode
1737 SelectionType nCnt;
1738 if ( !_rView.GetEditWin().IsFrameAction() &&
1739 (IsObjSelected() || (_rView.IsDrawMode() && !IsFrameSelected()) ))
1741 if (GetDrawView()->IsTextEdit())
1742 nCnt = SelectionType::DrawObjectEditMode;
1743 else
1745 if (GetView().IsFormMode()) // Only Form selected
1746 nCnt = SelectionType::DbForm;
1747 else
1748 nCnt = SelectionType::DrawObject; // Any draw object
1750 if (_rView.IsBezierEditMode())
1751 nCnt |= SelectionType::Ornament;
1752 else if( GetDrawView()->GetContext() == SdrViewContext::Media )
1753 nCnt |= SelectionType::Media;
1755 if (svx::checkForSelectedCustomShapes( GetDrawView(), true /* bOnlyExtruded */ ))
1757 nCnt |= SelectionType::ExtrudedCustomShape;
1760 if (svx::checkForSelectedFontWork( GetDrawView() ))
1762 nCnt |= SelectionType::FontWork;
1766 return nCnt;
1769 nCnt = static_cast<SelectionType>(GetCntType());
1771 if ( IsFrameSelected() )
1773 if (_rView.IsDrawMode())
1774 _rView.LeaveDrawCreate(); // clean up (Bug #45639)
1775 if ( !(nCnt & (SelectionType::Graphic | SelectionType::Ole)) )
1776 return SelectionType::Frame;
1779 if ( IsCursorInTable() )
1780 nCnt |= SelectionType::Table;
1782 if ( IsTableMode() )
1784 nCnt |= SelectionType::Table | SelectionType::TableCell;
1785 SwTable::SearchType eTableSel = GetEnhancedTableSelection();
1786 if ( eTableSel == SwTable::SEARCH_ROW )
1787 nCnt |= SelectionType::TableRow;
1788 else if ( eTableSel == SwTable::SEARCH_COL )
1789 nCnt |= SelectionType::TableCol;
1792 // Do not pop up numbering toolbar, if the text node has a numbering of type SVX_NUM_NUMBER_NONE.
1793 const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
1794 if ( pNumRule )
1796 const SwTextNode* pTextNd =
1797 sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->GetNode());
1799 if ( pTextNd && pTextNd->IsInList() )
1801 int nLevel = pTextNd->GetActualListLevel();
1803 if (nLevel < 0)
1804 nLevel = 0;
1806 if (nLevel >= MAXLEVEL)
1807 nLevel = MAXLEVEL - 1;
1809 const SwNumFormat& rFormat = pNumRule->Get(nLevel);
1810 if ( SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() )
1811 nCnt |= SelectionType::NumberList;
1815 return nCnt;
1818 // Find the text collection with the name rCollname
1819 // Returns: Pointer at the collection or 0, if no
1820 // text collection with this name exists, or
1821 // this is a default template.
1823 SwTextFormatColl *SwWrtShell::GetParaStyle(const OUString &rCollName, GetStyle eCreate )
1825 SwTextFormatColl* pColl = FindTextFormatCollByName( rCollName );
1826 if( !pColl && GETSTYLE_NOCREATE != eCreate )
1828 sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCollName, SwGetPoolIdFromName::TxtColl );
1829 if( USHRT_MAX != nId || GETSTYLE_CREATEANY == eCreate )
1830 pColl = GetTextCollFromPool( nId );
1832 return pColl;
1835 // Find the text collection with the name rCollname
1836 // Returns: Pointer at the collection or 0, if no
1837 // character template with this name exists, or
1838 // this is a default template or template is automatic.
1840 SwCharFormat *SwWrtShell::GetCharStyle(const OUString &rFormatName, GetStyle eCreate )
1842 SwCharFormat* pFormat = FindCharFormatByName( rFormatName );
1843 if( !pFormat && GETSTYLE_NOCREATE != eCreate )
1845 sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rFormatName, SwGetPoolIdFromName::ChrFmt );
1846 if( USHRT_MAX != nId || GETSTYLE_CREATEANY == eCreate )
1847 pFormat = static_cast<SwCharFormat*>(GetFormatFromPool( nId ));
1849 return pFormat;
1852 // Find the table format with the name rFormatname
1853 // Returns: Pointer at the collection or 0, if no
1854 // frame format with this name exists or
1855 // this is a default format or the format is automatic.
1857 SwFrameFormat *SwWrtShell::GetTableStyle(std::u16string_view rFormatName)
1859 for( size_t i = GetTableFrameFormatCount(); i; )
1861 SwFrameFormat *pFormat = &GetTableFrameFormat( --i );
1862 if( !pFormat->IsDefault() &&
1863 pFormat->GetName() == rFormatName && IsUsed( *pFormat ) )
1864 return pFormat;
1866 return nullptr;
1869 void SwWrtShell::addCurrentPosition() {
1870 SwPaM* pPaM = GetCursor();
1871 m_aNavigationMgr.addEntry(*pPaM->GetPoint());
1874 // Applying templates
1876 void SwWrtShell::SetPageStyle(const OUString &rCollName)
1878 if( !SwCursorShell::HasSelection() && !IsSelFrameMode() && !IsObjSelected() )
1880 SwPageDesc* pDesc = FindPageDescByName( rCollName, true );
1881 if( pDesc )
1882 ChgCurPageDesc( *pDesc );
1886 // Access templates
1888 OUString const & SwWrtShell::GetCurPageStyle() const
1890 return GetPageDesc(GetCurPageDesc( false/*bCalcFrame*/ )).GetName();
1893 // Change the current template referring to the existing change.
1895 void SwWrtShell::QuickUpdateStyle()
1897 SwTextFormatColl *pColl = GetCurTextFormatColl();
1899 // Default cannot be changed
1900 if(pColl && !pColl->IsDefault())
1902 FillByEx(pColl);
1903 // Also apply the template to remove hard attribute assignment.
1904 SetTextFormatColl(pColl);
1908 void SwWrtShell::AutoUpdatePara(SwTextFormatColl* pColl, const SfxItemSet& rStyleSet, SwPaM* pPaM )
1910 SwPaM* pCursor = pPaM ? pPaM : GetCursor( );
1911 SfxItemSetFixed<
1912 RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1913 RES_PARATR_BEGIN, RES_PARATR_END - 1,
1914 RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
1915 SID_ATTR_TABSTOP_DEFAULTS,SID_ATTR_TABSTOP_OFFSET,
1916 SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
1917 SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
1918 SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM> aCoreSet( GetAttrPool() );
1919 GetPaMAttr( pCursor, aCoreSet );
1920 bool bReset = false;
1921 SfxItemIter aParaIter( aCoreSet );
1922 for (auto pParaItem = aParaIter.GetCurItem(); pParaItem; pParaItem = aParaIter.NextItem())
1924 if(!IsInvalidItem(pParaItem))
1926 sal_uInt16 nWhich = pParaItem->Which();
1927 if(SfxItemState::SET == aParaIter.GetItemState() &&
1928 SfxItemState::SET == rStyleSet.GetItemState(nWhich))
1930 aParaIter.ClearItem();
1931 bReset = true;
1935 StartAction();
1936 if(bReset)
1938 ResetAttr({}, pCursor);
1939 SetAttrSet(aCoreSet, SetAttrMode::DEFAULT, pCursor);
1941 mxDoc->ChgFormat(*pColl, rStyleSet );
1942 EndAction();
1945 void SwWrtShell::AutoUpdateFrame( SwFrameFormat* pFormat, const SfxItemSet& rStyleSet )
1947 StartAction();
1949 ResetFlyFrameAttr( &rStyleSet );
1950 pFormat->SetFormatAttr( rStyleSet );
1952 EndAction();
1955 void SwWrtShell::AutoCorrect( SvxAutoCorrect& rACorr, sal_Unicode cChar )
1957 ResetCursorStack();
1958 if(!CanInsert())
1959 return;
1961 bool bStarted = false;
1962 SwRewriter aRewriter;
1964 if(HasSelection())
1966 // Only parentheses here, because the regular insert
1967 // is already clipped to the editshell
1968 StartAllAction();
1970 OUString aTmpStr1 = SwResId(STR_START_QUOTE) +
1971 GetSelText() +
1972 SwResId(STR_END_QUOTE);
1973 OUString aTmpStr3 = SwResId(STR_START_QUOTE) +
1974 OUStringChar(cChar) +
1975 SwResId(STR_END_QUOTE);
1976 aRewriter.AddRule( UndoArg1, aTmpStr1 );
1977 aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDS) );
1978 aRewriter.AddRule( UndoArg3, aTmpStr3 );
1980 StartUndo( SwUndoId::REPLACE, &aRewriter );
1981 bStarted = true;
1982 DelRight(true);
1984 SwEditShell::AutoCorrect( rACorr, IsInsMode(), cChar );
1986 if(bStarted)
1988 EndAllAction();
1989 EndUndo( SwUndoId::REPLACE, &aRewriter );
1993 // Some kind of controlled copy ctor
1995 SwWrtShell::SwWrtShell( SwWrtShell& rSh, vcl::Window *_pWin, SwView &rShell )
1996 : SwFEShell(rSh, _pWin)
1997 , m_rView(rShell)
1998 , m_aNavigationMgr(*this)
2000 BITFLD_INI_LIST
2001 CurrShell aCurr( this );
2003 SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
2004 SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
2006 // place the cursor on the first field...
2007 IFieldmark *pBM = nullptr;
2008 if (IsFormProtected() && (pBM = GetFieldmarkAfter(/*bLoop=*/true)) !=nullptr) {
2009 GotoFieldmark(pBM);
2013 SwWrtShell::SwWrtShell( SwDoc& rDoc, vcl::Window *_pWin, SwView &rShell,
2014 const SwViewOption *pViewOpt )
2015 : SwFEShell(rDoc, _pWin, pViewOpt)
2016 , m_rView(rShell)
2017 , m_aNavigationMgr(*this)
2019 BITFLD_INI_LIST
2020 CurrShell aCurr( this );
2021 SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
2022 SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
2024 // place the cursor on the first field...
2025 IFieldmark *pBM = nullptr;
2026 if (IsFormProtected() && (pBM = GetFieldmarkAfter(/*bLoop=*/true)) !=nullptr) {
2027 GotoFieldmark(pBM);
2031 SwWrtShell::~SwWrtShell()
2033 CurrShell aCurr( this );
2034 while(IsModePushed())
2035 PopMode();
2036 while(PopCursor(false))
2038 SwTransferable::ClearSelection( *this );
2041 bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete)
2043 ::std::optional<SwCallLink> aLink(std::in_place, *this);
2044 return Pop(eDelete, aLink);
2047 bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete, ::std::optional<SwCallLink>& roLink)
2049 bool bRet = SwCursorShell::Pop(eDelete, roLink);
2050 if( bRet && IsSelection() )
2052 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
2053 m_fnKillSel = &SwWrtShell::ResetSelect;
2055 return bRet;
2058 bool SwWrtShell::CanInsert()
2060 if(IsSelFrameMode())
2062 return false;
2065 if(IsObjSelected())
2067 return false;
2070 if(GetView().GetDrawFuncPtr())
2072 return false;
2075 if(GetView().GetPostItMgr()->GetActiveSidebarWin())
2077 return false;
2080 return true;
2083 void SwWrtShell::ChgDBData(const SwDBData& aDBData)
2085 SwEditShell::ChgDBData(aDBData);
2086 //notify the db-beamer if available
2087 GetView().NotifyDBChanged();
2090 OUString SwWrtShell::GetSelDescr() const
2092 OUString aResult;
2094 SelectionType nSelType = GetSelectionType();
2095 switch (nSelType)
2097 case SelectionType::Graphic:
2098 aResult = SwResId(STR_GRAPHIC);
2100 break;
2101 case SelectionType::Frame:
2103 const SwFrameFormat * pFrameFormat = GetSelectedFrameFormat();
2105 if (pFrameFormat)
2106 aResult = pFrameFormat->GetDescription();
2108 break;
2109 case SelectionType::DrawObject:
2111 aResult = SwResId(STR_DRAWING_OBJECTS);
2113 break;
2114 default:
2115 if (mxDoc)
2116 aResult = GetCursorDescr();
2119 return aResult;
2122 void SwWrtShell::ApplyViewOptions( const SwViewOption &rOpt )
2124 SwFEShell::ApplyViewOptions( rOpt );
2125 //#i115062# invalidate meta character slot
2126 GetView().GetViewFrame().GetBindings().Invalidate( FN_VIEW_META_CHARS );
2129 void SwWrtShell::SetReadonlyOption(bool bSet)
2131 GetView().GetEditWin().GetFrameControlsManager().SetReadonlyControls( bSet );
2132 SwViewShell::SetReadonlyOption( bSet );
2135 // Switch on/off header or footer of a page style - if an empty name is
2136 // given all styles are changed
2138 void SwWrtShell::ChangeHeaderOrFooter(
2139 std::u16string_view rStyleName, bool bHeader, bool bOn, bool bShowWarning)
2141 SdrView *const pSdrView = GetDrawView();
2142 if (pSdrView && pSdrView->IsTextEdit())
2143 { // tdf#107474 deleting header may delete active drawing object
2144 pSdrView->SdrEndTextEdit(true);
2146 addCurrentPosition();
2147 StartAllAction();
2148 StartUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
2149 bool bExecute = true;
2150 bool bCursorSet = false;
2151 for( size_t nFrom = 0, nTo = GetPageDescCnt();
2152 nFrom < nTo; ++nFrom )
2154 SwPageDesc aDesc( GetPageDesc( nFrom ));
2155 OUString sTmp(aDesc.GetName());
2156 if( rStyleName.empty() || rStyleName == sTmp )
2158 bool bChgd = false;
2160 if( bShowWarning && !bOn && GetActiveView() && GetActiveView() == &GetView() &&
2161 ( (bHeader && aDesc.GetMaster().GetHeader().IsActive()) ||
2162 (!bHeader && aDesc.GetMaster().GetFooter().IsActive()) ) )
2164 bShowWarning = false;
2165 //Actions have to be closed while the dialog is showing
2166 EndAllAction();
2168 weld::Window* pParent = GetView().GetFrameWeld();
2169 short nResult;
2170 if (bHeader) {
2171 nResult = DeleteHeaderDialog(pParent).run();
2172 } else {
2173 nResult = DeleteFooterDialog(pParent).run();
2176 bExecute = nResult == RET_YES;
2177 StartAllAction();
2178 if (nResult == RET_YES)
2179 ToggleHeaderFooterEdit();
2181 if( bExecute )
2183 bChgd = true;
2184 SwFrameFormat &rMaster = aDesc.GetMaster();
2185 if(bHeader)
2186 rMaster.SetFormatAttr( SwFormatHeader( bOn ));
2187 else
2188 rMaster.SetFormatAttr( SwFormatFooter( bOn ));
2189 if( bOn )
2191 // keep in sync with FN_PGNUMBER_WIZARD
2192 constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm);
2193 SvxULSpaceItem aUL(bHeader ? 0 : constTwips_5mm, bHeader ? constTwips_5mm : 0, RES_UL_SPACE );
2194 SwFrameFormat* pFormat = bHeader ?
2195 const_cast<SwFrameFormat*>(rMaster.GetHeader().GetHeaderFormat()) :
2196 const_cast<SwFrameFormat*>(rMaster.GetFooter().GetFooterFormat());
2197 pFormat->SetFormatAttr( aUL );
2198 XFillStyleItem aFill(drawing::FillStyle_NONE);
2199 pFormat->SetFormatAttr(aFill);
2202 if( bChgd )
2204 ChgPageDesc( nFrom, aDesc );
2206 if( !bCursorSet && bOn )
2208 if ( !IsHeaderFooterEdit() )
2209 ToggleHeaderFooterEdit();
2210 bCursorSet = SetCursorInHdFt(
2211 rStyleName.empty() ? SIZE_MAX : nFrom,
2212 bHeader );
2217 EndUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
2218 EndAllAction();
2221 void SwWrtShell::SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow )
2223 SwViewShell::SetShowHeaderFooterSeparator( eControl, bShow );
2224 if ( !bShow )
2225 GetView().GetEditWin().GetFrameControlsManager().HideControls( eControl );
2228 void SwWrtShell::InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq)
2230 SwPostItField* pPostIt = dynamic_cast<SwPostItField*>(rFieldMgr.GetCurField());
2231 bool bNew = !(pPostIt && pPostIt->GetTyp()->Which() == SwFieldIds::Postit);
2232 if (bNew || GetView().GetPostItMgr()->IsAnswer())
2234 const SvxPostItAuthorItem* pAuthorItem = rReq.GetArg<SvxPostItAuthorItem>(SID_ATTR_POSTIT_AUTHOR);
2235 OUString sAuthor;
2236 if ( pAuthorItem )
2237 sAuthor = pAuthorItem->GetValue();
2238 else
2240 std::size_t nAuthor = SW_MOD()->GetRedlineAuthor();
2241 sAuthor = SW_MOD()->GetRedlineAuthor(nAuthor);
2244 const SvxPostItTextItem* pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT);
2245 OUString sText;
2246 if ( pTextItem )
2247 sText = pTextItem->GetValue();
2249 // If we have a text already registered for answer, use that
2250 if (GetView().GetPostItMgr()->IsAnswer() && !GetView().GetPostItMgr()->GetAnswerText().isEmpty())
2252 sText = GetView().GetPostItMgr()->GetAnswerText();
2253 GetView().GetPostItMgr()->RegisterAnswerText(OUString());
2256 if ( HasSelection() && !IsTableMode() )
2258 KillPams();
2261 // #i120513# Inserting a comment into an autocompletion crashes
2262 // --> suggestion has to be removed before
2263 GetView().GetEditWin().StopQuickHelp();
2265 SwInsertField_Data aData(SwFieldTypesEnum::Postit, 0, sAuthor, sText, 0);
2267 if (IsSelFrameMode())
2269 SwFlyFrame* pFly = GetSelectedFlyFrame();
2271 // Remember the anchor of the selected object before deletion.
2272 std::optional<SwPosition> oAnchor;
2273 if (pFly)
2275 SwFrameFormat* pFormat = pFly->GetFormat();
2276 if (pFormat)
2278 RndStdIds eAnchorId = pFormat->GetAnchor().GetAnchorId();
2279 if ((eAnchorId == RndStdIds::FLY_AS_CHAR || eAnchorId == RndStdIds::FLY_AT_CHAR) && pFormat->GetAnchor().GetAnchorNode())
2281 oAnchor.emplace(*pFormat->GetAnchor().GetContentAnchor());
2286 // A frame is selected, end frame selection.
2287 EnterStdMode();
2288 GetView().AttrChangedNotify(nullptr);
2290 // Set up text selection, so the anchor of the frame will be the anchor of the
2291 // comment.
2292 if (pFly)
2294 if (oAnchor)
2295 *GetCurrentShellCursor().GetPoint() = *oAnchor;
2296 SwFrameFormat* pFormat = pFly->GetFormat();
2297 if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
2299 Right(SwCursorSkipMode::Cells, /*bSelect=*/true, 1, /*bBasicCall=*/false, /*bVisual=*/true);
2301 else if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR)
2303 aData.m_oAnnotationRange.emplace(*GetCurrentShellCursor().Start(),
2304 *GetCurrentShellCursor().End());
2309 rFieldMgr.InsertField( aData );
2311 Push();
2312 SwCursorShell::Left(1, SwCursorSkipMode::Chars);
2313 pPostIt = static_cast<SwPostItField*>(rFieldMgr.GetCurField());
2314 Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore cursor position
2317 // Client has disabled annotations rendering, no need to
2318 // focus the postit field
2319 if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
2320 return;
2322 if (pPostIt)
2324 SwFieldType* pType = GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(), false);
2325 if(auto pFormat = pType->FindFormatForField(pPostIt))
2326 pFormat->Broadcast( SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::FOCUS, &GetView() ) );
2330 bool SwWrtShell::IsOutlineContentVisible(const size_t nPos)
2332 const SwOutlineNodes& rOutlineNodes = GetDoc()->GetNodes().GetOutLineNds();
2333 const SwNode* pOutlineNode = rOutlineNodes[nPos];
2335 // no layout frame means outline folding is set to include sub levels and the outline node has
2336 // a parent outline node with outline content visible attribute false (folded outline content)
2337 if (!pOutlineNode->GetTextNode()->getLayoutFrame(nullptr))
2338 return false;
2340 // try the next node to determine if this outline node has visible content
2341 SwNodeIndex aIdx(*pOutlineNode, +1);
2342 if (aIdx.GetNode() == aIdx.GetNodes().GetEndOfContent()) // end of regular content
2343 return false;
2345 if (aIdx.GetNode().IsTextNode() || aIdx.GetNode().IsTableNode() ||
2346 aIdx.GetNode().IsSectionNode())
2348 // * sublevels treated as outline content
2349 // If next node (aIdx) doesn't have a layout frame
2350 // then this outline node does not have visible outline content.
2351 // * sublevels NOT treated as outline content
2352 // If the next node (aIdx) is the next outline node
2353 // then return the outline content visible attribute value.
2354 if (!GetViewOptions()->IsTreatSubOutlineLevelsAsContent() &&
2355 nPos + 1 < rOutlineNodes.size() &&
2356 rOutlineNodes[nPos + 1] == &aIdx.GetNode())
2357 return GetAttrOutlineContentVisible(nPos);
2359 if (aIdx.GetNode().IsTextNode())
2360 return aIdx.GetNode().GetTextNode()->getLayoutFrame(nullptr);
2361 if (aIdx.GetNode().IsTableNode())
2363 SwTable& rTable = aIdx.GetNode().GetTableNode()->GetTable();
2364 return rTable.HasLayout();
2366 if (aIdx.GetNode().IsSectionNode())
2368 const auto pFormat = aIdx.GetNode().GetSectionNode()->GetSection().GetFormat();
2369 return pFormat && pFormat->IsVisible();
2373 return true;
2376 void SwWrtShell::MakeOutlineLevelsVisible(const int nLevel)
2378 MakeAllOutlineContentTemporarilyVisible a(GetDoc());
2380 m_rView.SetMaxOutlineLevelShown(nLevel);
2382 bool bDocChanged = false;
2384 const SwOutlineNodes& rOutlineNodes = GetNodes().GetOutLineNds();
2386 // Make all missing frames.
2387 for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNodes.size(); ++nPos)
2389 SwNode* pNode = rOutlineNodes[nPos];
2390 if (!pNode->GetTextNode()->getLayoutFrame(GetLayout()))
2392 SwNodeIndex aIdx(*pNode, +1);
2393 // Make the outline paragraph frame
2394 MakeFrames(GetDoc(), *pNode, aIdx.GetNode());
2395 // Make the outline content visible but don't set the outline visible attribute and
2396 // don't make outline content made visible not visible that have outline visible
2397 // attribute false. Visibility will be taken care of when
2398 // MakeAllOutlineContentTemporarilyVisible goes out of scope.
2399 MakeOutlineContentVisible(nPos, true, false);
2400 bDocChanged = true;
2403 // Remove outline paragraph frame and outline content frames above given level.
2404 for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNodes.size(); ++nPos)
2406 SwNode* pNode = rOutlineNodes[nPos];
2407 auto nOutlineLevel = pNode->GetTextNode()->GetAttrOutlineLevel();
2408 if (nOutlineLevel > nLevel)
2410 // Remove the outline content but don't set the outline visible attribute. Visibility
2411 // will be taken care of when MakeAllOutlineContentTemporarilyVisible goes out of scope.
2412 MakeOutlineContentVisible(nPos, false, false);
2413 // Remove the outline paragraph frame.
2414 pNode->GetTextNode()->DelFrames(GetLayout());
2415 bDocChanged = true;
2419 // Broadcast DocChanged if document layout has changed so the Navigator will be updated.
2420 if (bDocChanged)
2421 GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
2424 void SwWrtShell::MakeOutlineContentVisible(const size_t nPos, bool bMakeVisible, bool bSetAttrOutlineVisibility)
2426 const SwNodes& rNodes = GetNodes();
2427 const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
2429 SwNode* pSttNd = rOutlineNodes[nPos];
2431 // determine end node
2432 SwNode* pEndNd = &rNodes.GetEndOfContent();
2433 if (rOutlineNodes.size() > nPos + 1)
2434 pEndNd = rOutlineNodes[nPos + 1];
2436 if (GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
2438 // get the last outline node to include (iPos)
2439 int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel();
2440 int nMaxOutlineLevelShown = m_rView.GetMaxOutlineLevelShown();
2441 SwOutlineNodes::size_type iPos = nPos;
2442 while (++iPos < rOutlineNodes.size() &&
2443 rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel &&
2444 rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() <= nMaxOutlineLevelShown);
2446 // get the correct end node
2447 // the outline node may be in frames, headers, footers special section of doc model
2448 SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode();
2449 while (pStartOfSectionNodeSttNd->StartOfSectionNode()
2450 != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode())
2452 pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode();
2454 pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode();
2456 if (iPos < rOutlineNodes.size())
2458 SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode();
2459 while (pStartOfSectionNode->StartOfSectionNode()
2460 != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode())
2462 pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode();
2464 if (pStartOfSectionNodeSttNd == pStartOfSectionNode)
2465 pEndNd = rOutlineNodes[iPos];
2469 // table, text box, header, footer
2470 if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
2472 // limit to within section
2473 if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex())
2474 pEndNd = pSttNd->EndOfSectionNode();
2476 // if pSttNd isn't in table but pEndNd is, skip over all outline nodes in table
2477 else if (pEndNd->GetTableBox())
2479 pEndNd = &rNodes.GetEndOfContent();
2480 for (size_t nOutlinePos = nPos + 2; nOutlinePos < rOutlineNodes.size(); nOutlinePos++)
2482 if (!(rOutlineNodes[nOutlinePos]->GetTableBox()))
2484 pEndNd = rOutlineNodes[nOutlinePos];
2485 break;
2489 // end node determined
2491 // Remove content frames from the next node after the starting outline node to
2492 // the determined ending node. Always do this to prevent the chance of duplicate
2493 // frames being made. They will be remade below if needed.
2494 SwNodeIndex aIdx(*pSttNd, +1);
2495 while (aIdx != *pEndNd)
2497 SwNode* pNd = &aIdx.GetNode();
2498 if (pNd->IsContentNode())
2499 pNd->GetContentNode()->DelFrames(nullptr);
2500 else if (pNd->IsTableNode())
2501 pNd->GetTableNode()->DelFrames(nullptr);
2502 ++aIdx;
2505 if (bMakeVisible) // make outline nodes outline content visible
2507 // reset the index marker and make frames
2508 aIdx.Assign(*pSttNd, +1);
2509 MakeFrames(GetDoc(), aIdx.GetNode(), *pEndNd);
2511 if (bSetAttrOutlineVisibility)
2513 pSttNd->GetTextNode()->SetAttrOutlineContentVisible(true);
2515 // make outline content made visible that have outline visible attribute false not visible
2516 while (aIdx != *pEndNd)
2518 SwNode* pNd = &aIdx.GetNode();
2519 if (pNd->IsTextNode() && pNd->GetTextNode()->IsOutline())
2521 SwTextNode* pTextNd = pNd->GetTextNode();
2522 bool bOutlineContentVisibleAttr = true;
2523 pTextNd->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
2524 if (!bOutlineContentVisibleAttr)
2526 SwOutlineNodes::size_type iPos;
2527 if (rOutlineNodes.Seek_Entry(pTextNd, &iPos))
2529 if (pTextNd->getLayoutFrame(nullptr))
2530 MakeOutlineContentVisible(iPos, false);
2534 ++aIdx;
2538 else if (bSetAttrOutlineVisibility)
2539 pSttNd->GetTextNode()->SetAttrOutlineContentVisible(false);
2542 // make content visible or not visible only if needed
2543 void SwWrtShell::InvalidateOutlineContentVisibility()
2545 GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
2547 const SwOutlineNodes& rOutlineNds = GetNodes().GetOutLineNds();
2548 for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos)
2550 bool bIsOutlineContentVisible = IsOutlineContentVisible(nPos);
2551 bool bOutlineContentVisibleAttr = true;
2552 rOutlineNds[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
2553 if (!bIsOutlineContentVisible && bOutlineContentVisibleAttr)
2554 MakeOutlineContentVisible(nPos);
2555 else if (bIsOutlineContentVisible && !bOutlineContentVisibleAttr)
2556 MakeOutlineContentVisible(nPos, false);
2560 void SwWrtShell::MakeAllFoldedOutlineContentVisible(bool bMakeVisible)
2562 if (bMakeVisible)
2564 // make all content visible
2566 // When shortcut is assigned to the show outline content visibility button and used to
2567 // toggle the feature and the mouse pointer is on an outline frame the button will not
2568 // be removed. An easy way to make sure the button does not remain shown is to use the
2569 // HideControls function.
2570 GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
2572 // temporarily set outline content visible attribute true for folded outline nodes
2573 std::vector<SwNode*> aFoldedOutlineNodeArray;
2574 for (SwNode* pNd: GetNodes().GetOutLineNds())
2576 bool bOutlineContentVisibleAttr = true;
2577 pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
2578 if (!bOutlineContentVisibleAttr)
2580 aFoldedOutlineNodeArray.push_back(pNd);
2581 pNd->GetTextNode()->SetAttrOutlineContentVisible(true);
2585 StartAction();
2586 InvalidateOutlineContentVisibility();
2587 EndAction();
2589 // restore outline content visible attribute for folded outline nodes
2590 for (SwNode* pNd: aFoldedOutlineNodeArray)
2591 pNd->GetTextNode()->SetAttrOutlineContentVisible(false);
2593 else
2595 if (SdrView* pSdrView = GetDrawView(); pSdrView && pSdrView->IsTextEdit() )
2597 bool bLockView = IsViewLocked();
2598 LockView(true);
2599 EndTextEdit();
2600 LockView(bLockView);
2602 if (IsSelFrameMode() || IsObjSelected())
2604 UnSelectFrame();
2605 LeaveSelFrameMode();
2606 GetView().LeaveDrawCreate();
2607 EnterStdMode();
2610 // Get current frame in which the cursor is positioned for use in placing the cursor.
2611 const SwFrame* pCurrFrame = GetCurrFrame(false);
2613 SwOutlineNodes::size_type nPos = GetOutlinePos();
2615 StartAction();
2616 InvalidateOutlineContentVisibility();
2617 EndAction();
2619 // If needed, find visible outline node frame to place cursor.
2620 if (!pCurrFrame || !pCurrFrame->isFrameAreaDefinitionValid() || pCurrFrame->IsInDtor() ||
2621 (nPos != SwOutlineNodes::npos &&
2622 !GetNodes().GetOutLineNds()[nPos]->GetTextNode()->getLayoutFrame(nullptr)))
2624 while (nPos != SwOutlineNodes::npos &&
2625 !GetNodes().GetOutLineNds()[nPos]->GetTextNode()->getLayoutFrame(nullptr))
2626 --nPos;
2627 if (nPos != SwOutlineNodes::npos)
2629 EnterStdMode();
2630 GotoOutline(nPos);
2634 GetView().GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
2637 bool SwWrtShell::GetAttrOutlineContentVisible(const size_t nPos) const
2639 bool bVisibleAttr = true;
2640 GetNodes().GetOutLineNds()[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bVisibleAttr);
2641 return bVisibleAttr;
2644 bool SwWrtShell::HasFoldedOutlineContentSelected() const
2646 for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
2648 SwPaM aPaM(*rPaM.GetMark(), *rPaM.GetPoint());
2649 aPaM.Normalize();
2650 SwNodeIndex aPointIdx(aPaM.GetPoint()->GetNode());
2651 SwNodeIndex aMarkIdx(aPaM.GetMark()->GetNode());
2652 if (aPointIdx == aMarkIdx)
2653 continue;
2654 // Return true if any nodes in PaM are folded outline content nodes.
2655 SwOutlineNodes::size_type nPos;
2656 for (SwNodeIndex aIdx = aPointIdx; aIdx <= aMarkIdx; ++aIdx)
2658 if (GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(&(aIdx.GetNode()), &nPos) &&
2659 !GetAttrOutlineContentVisible(nPos))
2660 return true;
2663 return false;
2666 void SwWrtShell::InfoReadOnlyDialog(bool bAsync) const
2668 if (bAsync)
2670 auto xInfo = std::make_shared<weld::MessageDialogController>(
2671 GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog");
2672 if (GetViewOptions()->IsShowOutlineContentVisibilityButton() &&
2673 HasFoldedOutlineContentSelected())
2675 xInfo->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
2676 xInfo->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
2678 weld::DialogController::runAsync(xInfo, [](int) {});
2680 else
2682 std::unique_ptr<weld::Builder>
2683 xBuilder(Application::CreateBuilder(GetView().GetFrameWeld(),
2684 "modules/swriter/ui/inforeadonlydialog.ui"));
2685 std::unique_ptr<weld::MessageDialog>
2686 xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
2687 if (GetViewOptions()->IsShowOutlineContentVisibilityButton() &&
2688 HasFoldedOutlineContentSelected())
2690 xInfo->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
2691 xInfo->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
2693 xInfo->run();
2697 bool SwWrtShell::WarnHiddenSectionDialog() const
2699 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(
2700 GetView().GetFrameWeld(), "modules/swriter/ui/warnhiddensectiondialog.ui"));
2701 std::unique_ptr<weld::MessageDialog> xQuery(
2702 xBuilder->weld_message_dialog("WarnHiddenSectionDialog"));
2703 if (GetViewOptions()->IsShowOutlineContentVisibilityButton()
2704 && HasFoldedOutlineContentSelected())
2706 xQuery->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
2707 xQuery->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
2710 return (RET_YES == xQuery->run());
2713 bool SwWrtShell::WarnSwitchToDesignModeDialog() const
2715 std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(nullptr,
2716 VclMessageType::Question, VclButtonsType::YesNo, SwResId(STR_A11Y_DESIGN_MODE_PRIMARY)));
2717 xQuery->set_default_response(RET_YES);
2718 xQuery->set_title(SwResId(STR_A11Y_DESIGN_MODE_TITLE));
2719 xQuery->set_secondary_text(SwResId(STR_A11Y_DESIGN_MODE_SECONDARY));
2721 return (RET_YES == xQuery->run());
2724 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */