nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / edit / editsh.cxx
blob85c065d60fed907a69e788593811632d1a7bc50c
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 <hintids.hxx>
21 #include <vcl/commandevent.hxx>
22 #include <unotools/charclass.hxx>
23 #include <comphelper/processfactory.hxx>
24 #include <comphelper/string.hxx>
25 #include <unotools/transliterationwrapper.hxx>
26 #include <fmtsrnd.hxx>
27 #include <fmtinfmt.hxx>
28 #include <txtinet.hxx>
29 #include <frmfmt.hxx>
30 #include <charfmt.hxx>
31 #include <doc.hxx>
32 #include <IDocumentUndoRedo.hxx>
33 #include <IDocumentSettingAccess.hxx>
34 #include <IDocumentLinksAdministration.hxx>
35 #include <IDocumentFieldsAccess.hxx>
36 #include <IDocumentStatistics.hxx>
37 #include <IDocumentState.hxx>
38 #include <docary.hxx>
39 #include <editsh.hxx>
40 #include <frame.hxx>
41 #include <cntfrm.hxx>
42 #include <pam.hxx>
43 #include <ndtxt.hxx>
44 #include <flyfrm.hxx>
45 #include <swundo.hxx>
46 #include <calc.hxx>
47 #include <ndgrf.hxx>
48 #include <ndole.hxx>
49 #include <txtfrm.hxx>
50 #include <rootfrm.hxx>
51 #include <extinput.hxx>
52 #include <scriptinfo.hxx>
53 #include <unocrsrhelper.hxx>
54 #include <section.hxx>
55 #include <numrule.hxx>
56 #include <SwNodeNum.hxx>
57 #include <unocrsr.hxx>
58 #include <calbck.hxx>
60 using namespace com::sun::star;
62 void SwEditShell::Insert( sal_Unicode c, bool bOnlyCurrCursor )
64 StartAllAction();
65 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
67 const bool bSuccess = GetDoc()->getIDocumentContentOperations().InsertString(rPaM, OUString(c));
68 OSL_ENSURE( bSuccess, "Doc->Insert() failed." );
70 SaveTableBoxContent( rPaM.GetPoint() );
71 if( bOnlyCurrCursor )
72 break;
76 EndAllAction();
79 void SwEditShell::Insert2(const OUString &rStr, const bool bForceExpandHints )
81 StartAllAction();
83 const SwInsertFlags nInsertFlags =
84 bForceExpandHints
85 ? (SwInsertFlags::FORCEHINTEXPAND | SwInsertFlags::EMPTYEXPAND)
86 : SwInsertFlags::EMPTYEXPAND;
88 for(SwPaM& rCurrentCursor : getShellCursor( true )->GetRingContainer())
90 //OPT: GetSystemCharSet
91 const bool bSuccess =
92 GetDoc()->getIDocumentContentOperations().InsertString(rCurrentCursor, rStr, nInsertFlags);
93 OSL_ENSURE( bSuccess, "Doc->Insert() failed." );
95 if (bSuccess)
97 GetDoc()->UpdateRsid( rCurrentCursor, rStr.getLength() );
99 // Set paragraph rsid if beginning of paragraph
100 SwTextNode *const pTextNode =
101 rCurrentCursor.GetPoint()->nNode.GetNode().GetTextNode();
102 if( pTextNode && pTextNode->Len() == 1)
103 GetDoc()->UpdateParRsid( pTextNode );
106 SaveTableBoxContent( rCurrentCursor.GetPoint() );
111 // calculate cursor bidi level
112 SwCursor* pTmpCursor = GetCursor_();
113 const bool bDoNotSetBidiLevel = ! pTmpCursor ||
114 ( dynamic_cast<SwUnoCursor*>(pTmpCursor) != nullptr );
116 if ( ! bDoNotSetBidiLevel )
118 SwNode& rNode = pTmpCursor->GetPoint()->nNode.GetNode();
119 if ( rNode.IsTextNode() )
121 SwIndex& rIdx = pTmpCursor->GetPoint()->nContent;
122 sal_Int32 nPrevPos = rIdx.GetIndex();
123 if ( nPrevPos )
124 --nPrevPos;
126 SwTextFrame const* pFrame;
127 SwScriptInfo *const pSI = SwScriptInfo::GetScriptInfo(
128 static_cast<SwTextNode&>(rNode), &pFrame, true);
130 sal_uInt8 nLevel = 0;
131 if ( ! pSI )
133 // seems to be an empty paragraph.
134 Point aPt;
135 std::pair<Point, bool> const tmp(aPt, false);
136 pFrame = static_cast<SwTextFrame*>(
137 static_cast<SwTextNode&>(rNode).getLayoutFrame(
138 GetLayout(), pTmpCursor->GetPoint(), &tmp));
140 SwScriptInfo aScriptInfo;
141 aScriptInfo.InitScriptInfo(static_cast<SwTextNode&>(rNode),
142 pFrame->GetMergedPara(), pFrame->IsRightToLeft());
143 TextFrameIndex const iPrevPos(pFrame->MapModelToView(
144 &static_cast<SwTextNode&>(rNode), nPrevPos));
145 nLevel = aScriptInfo.DirType( iPrevPos );
147 else
149 if (TextFrameIndex(COMPLETE_STRING) != pSI->GetInvalidityA())
151 // mystery why this doesn't use the other overload?
152 pSI->InitScriptInfo(static_cast<SwTextNode&>(rNode), pFrame->GetMergedPara());
154 TextFrameIndex const iPrevPos(pFrame->MapModelToView(
155 &static_cast<SwTextNode&>(rNode), nPrevPos));
156 nLevel = pSI->DirType(iPrevPos);
159 pTmpCursor->SetCursorBidiLevel( nLevel );
163 SetInFrontOfLabel( false ); // #i27615#
165 EndAllAction();
168 void SwEditShell::Overwrite(const OUString &rStr)
170 StartAllAction();
171 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
173 if( !GetDoc()->getIDocumentContentOperations().Overwrite(rPaM, rStr ) )
175 OSL_FAIL( "Doc->getIDocumentContentOperations().Overwrite(Str) failed." );
177 SaveTableBoxContent( rPaM.GetPoint() );
179 EndAllAction();
182 void SwEditShell::SplitNode( bool bAutoFormat, bool bCheckTableStart )
184 StartAllAction();
185 GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
187 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
189 // Here, a table cell becomes a normal text cell.
190 GetDoc()->ClearBoxNumAttrs( rPaM.GetPoint()->nNode );
191 GetDoc()->getIDocumentContentOperations().SplitNode( *rPaM.GetPoint(), bCheckTableStart );
194 GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
196 if( bAutoFormat )
197 AutoFormatBySplitNode();
199 ClearTableBoxContent();
201 EndAllAction();
204 bool SwEditShell::AppendTextNode()
206 bool bRet = false;
207 StartAllAction();
208 GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
210 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
212 GetDoc()->ClearBoxNumAttrs( rPaM.GetPoint()->nNode );
213 bRet = GetDoc()->getIDocumentContentOperations().AppendTextNode( *rPaM.GetPoint()) || bRet;
216 GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
218 ClearTableBoxContent();
220 EndAllAction();
221 return bRet;
224 // the returned SwGrfNode pointer is used in GetGraphic() and GetGraphicSize()
225 SwGrfNode * SwEditShell::GetGrfNode_() const
227 SwGrfNode *pGrfNode = nullptr;
228 SwPaM* pCursor = GetCursor();
229 if( !pCursor->HasMark() ||
230 pCursor->GetPoint()->nNode == pCursor->GetMark()->nNode )
231 pGrfNode = pCursor->GetPoint()->nNode.GetNode().GetGrfNode();
233 return pGrfNode;
236 // returns a Graphic pointer if CurrentCursor->GetPoint() points to a SwGrfNode and
237 // GetMark is not set or points to the same Graphic
238 const Graphic* SwEditShell::GetGraphic( bool bWait ) const
240 SwGrfNode* pGrfNode = GetGrfNode_();
241 const Graphic* pGrf( nullptr );
242 if ( pGrfNode )
244 pGrf = &(pGrfNode->GetGrf(bWait && GraphicType::Default == pGrfNode->GetGrf().GetType()));
246 return pGrf;
249 bool SwEditShell::IsLinkedGrfSwapOut() const
251 SwGrfNode *pGrfNode = GetGrfNode_();
252 return pGrfNode &&
253 pGrfNode->IsLinkedFile() &&
254 GraphicType::Default == pGrfNode->GetGrfObj().GetType();
257 const GraphicObject* SwEditShell::GetGraphicObj() const
259 SwGrfNode* pGrfNode = GetGrfNode_();
260 return pGrfNode ? &(pGrfNode->GetGrfObj()) : nullptr;
263 const GraphicAttr* SwEditShell::GetGraphicAttr( GraphicAttr& rGA ) const
265 SwGrfNode* pGrfNode = GetGrfNode_();
266 const SwFrame* pFrame = GetCurrFrame(false);
267 return pGrfNode ? &(pGrfNode->GetGraphicAttr( rGA, pFrame )) : nullptr;
270 GraphicType SwEditShell::GetGraphicType() const
272 SwGrfNode *pGrfNode = GetGrfNode_();
273 return pGrfNode ? pGrfNode->GetGrfObj().GetType() : GraphicType::NONE;
276 // returns the size of a graphic in <rSz> if CurrentCursor->GetPoint() points to a SwGrfNode and
277 // GetMark is not set or points to the same graphic
278 bool SwEditShell::GetGrfSize(Size& rSz) const
280 SwNoTextNode* pNoTextNd;
281 SwPaM* pCurrentCursor = GetCursor();
282 if( ( !pCurrentCursor->HasMark()
283 || pCurrentCursor->GetPoint()->nNode == pCurrentCursor->GetMark()->nNode )
284 && nullptr != ( pNoTextNd = pCurrentCursor->GetNode().GetNoTextNode() ) )
286 rSz = pNoTextNd->GetTwipSize();
287 return true;
289 return false;
293 /// Read again if graphic is not OK and replace old one
294 void SwEditShell::ReRead( const OUString& rGrfName, const OUString& rFltName,
295 const Graphic* pGraphic )
297 StartAllAction();
298 mxDoc->getIDocumentContentOperations().ReRead( *GetCursor(), rGrfName, rFltName, pGraphic );
299 EndAllAction();
302 /// Returns the name and the filter name of a graphic if the pointer is on a graphic.
303 /// If a String-pointer is != 0 then return corresponding name.
304 void SwEditShell::GetGrfNms( OUString* pGrfName, OUString* pFltName,
305 const SwFlyFrameFormat* pFormat ) const
307 OSL_ENSURE( pGrfName || pFltName, "No parameters" );
308 if( pFormat )
309 SwDoc::GetGrfNms( *pFormat, pGrfName, pFltName );
310 else
312 SwGrfNode *pGrfNode = GetGrfNode_();
313 if( pGrfNode && pGrfNode->IsLinkedFile() )
314 pGrfNode->GetFileFilterNms( pGrfName, pFltName );
318 const tools::PolyPolygon *SwEditShell::GetGraphicPolygon() const
320 SwNoTextNode *pNd = GetCursor()->GetNode().GetNoTextNode();
321 return pNd->HasContour();
324 void SwEditShell::SetGraphicPolygon( const tools::PolyPolygon *pPoly )
326 SwNoTextNode *pNd = GetCursor()->GetNode().GetNoTextNode();
327 StartAllAction();
328 pNd->SetContour( pPoly );
329 SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pNd->getLayoutFrame(GetLayout())->GetUpper());
330 const SwFormatSurround &rSur = pFly->GetFormat()->GetSurround();
331 pFly->GetFormat()->NotifyClients( &rSur, &rSur );
332 GetDoc()->getIDocumentState().SetModified();
333 EndAllAction();
336 void SwEditShell::ClearAutomaticContour()
338 SwNoTextNode *pNd = GetCursor()->GetNode().GetNoTextNode();
339 OSL_ENSURE( pNd, "is no NoTextNode!" );
340 if( pNd->HasAutomaticContour() )
342 StartAllAction();
343 pNd->SetContour( nullptr );
344 SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pNd->getLayoutFrame(GetLayout())->GetUpper());
345 const SwFormatSurround &rSur = pFly->GetFormat()->GetSurround();
346 pFly->GetFormat()->NotifyClients( &rSur, &rSur );
347 GetDoc()->getIDocumentState().SetModified();
348 EndAllAction();
352 /** Get OLE object at pointer.
354 * Returns a pointer to a SvInPlaceObjectRef if CurrentCursor->GetPoint() points to a SwOLENode and
355 * GetMark is not set or points to the same object reference. Gets this pointer from the Doc
356 * if the object should be searched by name.
358 svt::EmbeddedObjectRef& SwEditShell::GetOLEObject() const
360 OSL_ENSURE( CNT_OLE == GetCntType(), "GetOLEObj: no OLENode." );
361 OSL_ENSURE( !GetCursor()->HasMark() ||
362 (GetCursor()->HasMark() &&
363 GetCursor()->GetPoint()->nNode == GetCursor()->GetMark()->nNode),
364 "GetOLEObj: no OLENode." );
366 SwOLENode *pOLENode = GetCursor()->GetNode().GetOLENode();
367 OSL_ENSURE( pOLENode, "GetOLEObj: no OLENode." );
368 SwOLEObj& rOObj = pOLENode->GetOLEObj();
369 return rOObj.GetObject();
372 bool SwEditShell::HasOLEObj( const OUString &rName ) const
374 SwStartNode *pStNd;
375 SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
376 while ( nullptr != (pStNd = aIdx.GetNode().GetStartNode()) )
378 ++aIdx;
379 SwNode& rNd = aIdx.GetNode();
380 if( rNd.IsOLENode() &&
381 rName == static_cast<SwOLENode&>(rNd).GetChartTableName() &&
382 static_cast<SwOLENode&>(rNd).getLayoutFrame( GetLayout() ) )
383 return true;
385 aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
387 return false;
390 void SwEditShell::SetChartName( const OUString &rName )
392 SwOLENode *pONd = GetCursor()->GetNode().GetOLENode();
393 OSL_ENSURE( pONd, "ChartNode not found" );
394 pONd->SetChartTableName( rName );
397 void SwEditShell::UpdateCharts( const OUString &rName )
399 GetDoc()->UpdateCharts( rName );
402 /// change table name
403 void SwEditShell::SetTableName( SwFrameFormat& rTableFormat, const OUString &rNewName )
405 GetDoc()->SetTableName( rTableFormat, rNewName );
408 /// request current word
409 OUString SwEditShell::GetCurWord() const
411 const SwPaM& rPaM = *GetCursor();
412 const SwTextNode* pNd = rPaM.GetNode().GetTextNode();
413 if (!pNd)
415 return OUString();
417 SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(pNd->getLayoutFrame(GetLayout())));
418 if (pFrame)
420 return pFrame->GetCurWord(*rPaM.GetPoint());
422 return OUString();
425 void SwEditShell::UpdateDocStat( )
427 StartAllAction();
428 GetDoc()->getIDocumentStatistics().UpdateDocStat( false, true );
429 EndAllAction();
432 const SwDocStat& SwEditShell::GetUpdatedDocStat()
434 StartAllAction();
435 const SwDocStat &rRet = GetDoc()->getIDocumentStatistics().GetUpdatedDocStat( false, true );
436 EndAllAction();
437 return rRet;
440 /// get the reference of a given name in the Doc
441 const SwFormatRefMark* SwEditShell::GetRefMark( const OUString& rName ) const
443 return GetDoc()->GetRefMark( rName );
446 /// get the names of all references in a Doc
447 sal_uInt16 SwEditShell::GetRefMarks( std::vector<OUString>* pStrings ) const
449 return GetDoc()->GetRefMarks( pStrings );
452 OUString SwEditShell::GetDropText( const sal_Int32 nChars ) const
455 * pb: made changes for #i74939#
457 * always return a string even though there is a selection
460 OUString aText;
461 SwPaM* pCursor = GetCursor();
462 if ( IsMultiSelection() )
464 // if a multi selection exists, search for the first line
465 // -> it is the cursor with the lowest index
466 sal_uLong nIndex = pCursor->GetMark()->nNode.GetIndex();
467 bool bPrev = true;
468 SwPaM* pLast = pCursor;
469 SwPaM* pTemp = pCursor;
470 while ( bPrev )
472 SwPaM* pPrev2 = pTemp->GetPrev();
473 bPrev = ( pPrev2 && pPrev2 != pLast );
474 if ( bPrev )
476 pTemp = pPrev2;
477 sal_uLong nTemp = pPrev2->GetMark()->nNode.GetIndex();
478 if ( nTemp < nIndex )
480 nIndex = nTemp;
481 pCursor = pPrev2;
487 SwTextNode const*const pTextNd = pCursor->GetNode(false).GetTextNode();
488 if( pTextNd )
490 SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(
491 pTextNd->getLayoutFrame(GetLayout())));
492 SAL_WARN_IF(!pTextFrame, "sw.core", "GetDropText cursor has no frame?");
493 if (pTextFrame)
495 TextFrameIndex const nDropLen(pTextFrame->GetDropLen(TextFrameIndex(nChars)));
496 aText = pTextFrame->GetText().copy(0, sal_Int32(nDropLen));
500 return aText;
503 void SwEditShell::ReplaceDropText( const OUString &rStr, SwPaM* pPaM )
505 SwPaM* pCursor = pPaM ? pPaM : GetCursor();
506 if( !(pCursor->GetPoint()->nNode == pCursor->GetMark()->nNode &&
507 pCursor->GetNode().GetTextNode()->IsTextNode()) )
508 return;
510 StartAllAction();
512 const SwNodeIndex& rNd = pCursor->GetPoint()->nNode;
513 SwPaM aPam( rNd, rStr.getLength(), rNd, 0 );
514 SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(
515 rNd.GetNode().GetTextNode()->getLayoutFrame(GetLayout())));
516 if (pTextFrame)
518 *aPam.GetPoint() = pTextFrame->MapViewToModelPos(TextFrameIndex(0));
519 *aPam.GetMark() = pTextFrame->MapViewToModelPos(TextFrameIndex(
520 std::min(rStr.getLength(), pTextFrame->GetText().getLength())));
522 if( !GetDoc()->getIDocumentContentOperations().Overwrite( aPam, rStr ) )
524 OSL_FAIL( "Doc->getIDocumentContentOperations().Overwrite(Str) failed." );
527 EndAllAction();
530 OUString SwEditShell::Calculate()
532 OUStringBuffer aFormel; // the final formula
533 SwCalc aCalc( *GetDoc() );
534 const CharClass& rCC = GetAppCharClass();
536 for(SwPaM& rCurrentPaM : GetCursor()->GetNext()->GetRingContainer())
538 SwTextNode* pTextNd = rCurrentPaM.GetNode().GetTextNode();
539 if(pTextNd)
541 const SwPosition *pStart = rCurrentPaM.Start(), *pEnd = rCurrentPaM.End();
542 const sal_Int32 nStt = pStart->nContent.GetIndex();
543 OUString aStr = pTextNd->GetExpandText(GetLayout(),
544 nStt, pEnd->nContent.GetIndex() - nStt);
546 aStr = rCC.lowercase( aStr );
548 bool bValidFields = false;
549 sal_Int32 nPos = 0;
551 while( nPos < aStr.getLength() )
553 sal_Unicode ch = aStr[ nPos++ ];
554 if( rCC.isLetter( aStr, nPos-1 ) || ch == '_' )
556 sal_Int32 nTmpStt = nPos-1;
557 while( nPos < aStr.getLength() &&
558 0 != ( ch = aStr[ nPos++ ]) &&
559 (rCC.isLetterNumeric( aStr, nPos - 1 ) ||
560 ch == '_'|| ch == '.' ))
563 if( nPos < aStr.getLength() )
564 --nPos;
566 OUString sVar = aStr.copy( nTmpStt, nPos - nTmpStt );
567 if( !::FindOperator( sVar ) &&
568 (aCalc.GetVarTable().Find(sVar) ||
569 aCalc.VarLook( sVar )) )
571 if( !bValidFields )
573 GetDoc()->getIDocumentFieldsAccess().FieldsToCalc( aCalc,
574 pStart->nNode.GetIndex(),
575 pStart->nContent.GetIndex() );
576 bValidFields = true;
578 aFormel.append("(").append(aCalc.GetStrResult( aCalc.VarLook( sVar )->nValue )).append(")");
580 else
581 aFormel.append(sVar);
583 else
584 aFormel.append(ch);
589 return aCalc.GetStrResult( aCalc.Calculate(aFormel.makeStringAndClear()) );
592 sfx2::LinkManager& SwEditShell::GetLinkManager()
594 return mxDoc->getIDocumentLinksAdministration().GetLinkManager();
597 void *SwEditShell::GetIMapInventor() const
599 // The node on which the cursor points should be sufficient as a unique identifier
600 return static_cast<void*>(&(GetCursor()->GetNode()));
603 // #i73788#
604 Graphic SwEditShell::GetIMapGraphic() const
606 // returns always a graphic if the cursor is in a Fly
607 CurrShell aCurr( const_cast<SwEditShell*>(this) );
608 Graphic aRet;
609 SwPaM* pCursor = GetCursor();
610 if ( !pCursor->HasMark() )
612 SwNode& rNd =pCursor->GetNode();
613 if( rNd.IsGrfNode() )
615 SwGrfNode & rGrfNode(static_cast<SwGrfNode&>(rNd));
616 aRet = rGrfNode.GetGrf(GraphicType::Default == rGrfNode.GetGrf().GetType());
618 else if ( rNd.IsOLENode() )
620 if (const Graphic* pGraphic = static_cast<SwOLENode&>(rNd).GetGraphic())
621 aRet = *pGraphic;
623 else
625 SwFlyFrame* pFlyFrame = rNd.GetContentNode()->getLayoutFrame( GetLayout() )->FindFlyFrame();
626 if(pFlyFrame)
627 aRet = pFlyFrame->GetFormat()->MakeGraphic();
630 return aRet;
633 bool SwEditShell::InsertURL( const SwFormatINetFormat& rFormat, const OUString& rStr, bool bKeepSelection )
635 // URL and hint text (directly or via selection) necessary
636 if( rFormat.GetValue().isEmpty() || ( rStr.isEmpty() && !HasSelection() ) )
637 return false;
638 StartAllAction();
639 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::UI_INSERT_URLTXT, nullptr);
640 bool bInsText = true;
642 if( !rStr.isEmpty() )
644 SwPaM* pCursor = GetCursor();
645 if( pCursor->HasMark() && *pCursor->GetPoint() != *pCursor->GetMark() )
647 // Selection existent, multi selection?
648 bool bDelText = true;
649 if( !pCursor->IsMultiSelection() )
651 // simple selection -> check the text
652 const OUString sText(comphelper::string::stripEnd(GetSelText(), ' '));
653 if( sText == rStr )
654 bDelText = bInsText = false;
656 else if( rFormat.GetValue() == rStr ) // Are Name and URL equal?
657 bDelText = bInsText = false;
659 if( bDelText )
660 Delete();
662 else if( pCursor->IsMultiSelection() && rFormat.GetValue() == rStr )
663 bInsText = false;
665 if( bInsText )
667 Insert2( rStr );
668 SetMark();
669 ExtendSelection( false, rStr.getLength() );
672 else
673 bInsText = false;
675 SetAttrItem( rFormat );
676 if (bInsText && !IsCursorPtAtEnd())
677 SwapPam();
678 if(!bKeepSelection)
679 ClearMark();
680 if( bInsText )
681 DontExpandFormat();
682 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::UI_INSERT_URLTXT, nullptr );
683 EndAllAction();
684 return true;
687 void SwEditShell::GetINetAttrs( SwGetINetAttrs& rArr )
689 rArr.clear();
691 const SwCharFormats* pFormats = GetDoc()->GetCharFormats();
692 for( auto n = pFormats->size(); 1 < n; )
694 SwIterator<SwTextINetFormat,SwCharFormat> aIter(*(*pFormats)[--n]);
695 for( SwTextINetFormat* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
697 SwTextNode const*const pTextNd(pFnd->GetpTextNode());
698 SwTextFrame const*const pFrame(pTextNd
699 ? static_cast<SwTextFrame const*>(pTextNd->getLayoutFrame(GetLayout()))
700 : nullptr);
701 if (nullptr != pTextNd && nullptr != pFrame
702 && pTextNd->GetNodes().IsDocNodes()
703 // check it's not fully deleted
704 && pFrame->MapModelToView(pTextNd, pFnd->GetStart())
705 != pFrame->MapModelToView(pTextNd, *pFnd->GetEnd()))
707 SwTextINetFormat& rAttr = *pFnd;
708 OUString sText( pTextNd->GetExpandText(GetLayout(),
709 rAttr.GetStart(), *rAttr.GetEnd() - rAttr.GetStart()) );
711 sText = sText.replaceAll("\x0a", "");
712 sText = comphelper::string::strip(sText, ' ');
714 if( !sText.isEmpty() )
716 rArr.emplace_back(sText, rAttr);
723 /// If the cursor is in an INetAttribute then it will be deleted completely (incl. hint text, the
724 /// latter is needed for drag & drop)
725 void SwEditShell::DelINetAttrWithText()
727 bool bRet = SelectTextAttr( RES_TXTATR_INETFMT, false );
728 if( bRet )
729 DeleteSel( *GetCursor() );
732 /// Set the DontExpand flag at the text character attributes
733 bool SwEditShell::DontExpandFormat()
735 bool bRet = false;
736 if( !IsTableMode() && GetDoc()->DontExpandFormat( *GetCursor()->GetPoint() ))
738 bRet = true;
739 CallChgLnk();
741 return bRet;
744 SvNumberFormatter* SwEditShell::GetNumberFormatter()
746 return GetDoc()->GetNumberFormatter();
749 bool SwEditShell::ConvertFieldsToText()
751 StartAllAction();
752 bool bRet = GetDoc()->ConvertFieldsToText(*GetLayout());
753 EndAllAction();
754 return bRet;
757 void SwEditShell::SetNumberingRestart()
759 StartAllAction();
760 Push();
761 // iterate over all text contents - body, frames, header, footer, footnote text
762 SwPaM* pCursor = GetCursor();
763 for(int i = 0; i < 2; i++)
765 if(!i)
766 MakeFindRange(SwDocPositions::Start, SwDocPositions::End, pCursor); // body content
767 else
768 MakeFindRange(SwDocPositions::OtherStart, SwDocPositions::OtherEnd, pCursor); // extra content
769 SwPosition* pSttPos = pCursor->Start(), *pEndPos = pCursor->End();
770 sal_uLong nCurrNd = pSttPos->nNode.GetIndex();
771 sal_uLong nEndNd = pEndPos->nNode.GetIndex();
772 if( nCurrNd <= nEndNd )
774 SwContentFrame* pContentFrame;
775 bool bGoOn = true;
776 // iterate over all paragraphs
777 while( bGoOn )
779 SwNode* pNd = GetDoc()->GetNodes()[ nCurrNd ];
780 switch( pNd->GetNodeType() )
782 case SwNodeType::Text:
783 pContentFrame = static_cast<SwTextNode*>(pNd)->getLayoutFrame( GetLayout() );
784 if( nullptr != pContentFrame )
786 // skip hidden frames - ignore protection!
787 if( !static_cast<SwTextFrame*>(pContentFrame)->IsHiddenNow() )
789 // if the node is numbered and the starting value of the numbering equals the
790 // start value of the numbering rule then set this value as hard starting value
792 // get the node num
793 // OD 2005-11-09
794 SwTextNode* pTextNd( pNd->GetTextNode() );
795 SwNumRule* pNumRule( pTextNd->GetNumRule() );
797 // sw_redlinehide: not sure what this should do, only called from mail-merge
798 bool bIsNodeNum =
799 ( pNumRule && pTextNd->GetNum() &&
800 ( pTextNd->HasNumber() || pTextNd->HasBullet() ) &&
801 pTextNd->IsCountedInList() &&
802 !pTextNd->IsListRestart() );
803 if (bIsNodeNum)
805 int nListLevel = pTextNd->GetActualListLevel();
807 if (nListLevel < 0)
808 nListLevel = 0;
810 if (nListLevel >= MAXLEVEL)
811 nListLevel = MAXLEVEL - 1;
813 bIsNodeNum = pTextNd->GetNum()->GetNumber() ==
814 pNumRule->Get( static_cast<sal_uInt16>(nListLevel) ).GetStart();
816 if (bIsNodeNum)
818 // now set the start value as attribute
819 SwPosition aCurrentNode(*pNd);
820 GetDoc()->SetNumRuleStart( aCurrentNode );
824 break;
825 case SwNodeType::Section:
826 // skip hidden sections - ignore protection!
827 if(static_cast<SwSectionNode*>(pNd)->GetSection().IsHidden() )
828 nCurrNd = pNd->EndOfSectionIndex();
829 break;
830 default: break;
833 bGoOn = nCurrNd < nEndNd;
834 ++nCurrNd;
839 Pop(PopMode::DeleteCurrent);
840 EndAllAction();
843 sal_uInt16 SwEditShell::GetLineCount()
845 sal_uInt16 nRet = 0;
846 CalcLayout();
847 SwPaM* pPam = GetCursor();
848 SwNodeIndex& rPtIdx = pPam->GetPoint()->nNode;
849 SwNodeIndex aStart( rPtIdx );
850 SwContentNode* pCNd;
851 SwContentFrame *pContentFrame = nullptr;
853 aStart = 0;
855 while( nullptr != ( pCNd = GetDoc()->GetNodes().GoNextSection(
856 &aStart, true, false )) )
858 if( nullptr != ( pContentFrame = pCNd->getLayoutFrame( GetLayout() ) ) && pContentFrame->IsTextFrame() )
860 SwTextFrame *const pFrame(static_cast<SwTextFrame*>(pContentFrame));
861 nRet = nRet + pFrame->GetLineCount(TextFrameIndex(COMPLETE_STRING));
862 if (GetLayout()->HasMergedParas())
864 if (auto const*const pMerged = pFrame->GetMergedPara())
866 aStart = *pMerged->pLastNode;
871 return nRet;
874 tools::Long SwEditShell::CompareDoc( const SwDoc& rDoc )
876 StartAllAction();
877 tools::Long nRet = GetDoc()->CompareDoc( rDoc );
878 EndAllAction();
879 return nRet;
882 tools::Long SwEditShell::MergeDoc( const SwDoc& rDoc )
884 StartAllAction();
885 tools::Long nRet = GetDoc()->MergeDoc( rDoc );
886 EndAllAction();
887 return nRet;
890 const SwFootnoteInfo& SwEditShell::GetFootnoteInfo() const
892 return GetDoc()->GetFootnoteInfo();
895 void SwEditShell::SetFootnoteInfo(const SwFootnoteInfo& rInfo)
897 StartAllAction();
898 CurrShell aCurr( this );
899 GetDoc()->SetFootnoteInfo(rInfo);
900 CallChgLnk();
901 EndAllAction();
904 const SwEndNoteInfo& SwEditShell::GetEndNoteInfo() const
906 return GetDoc()->GetEndNoteInfo();
909 void SwEditShell::SetEndNoteInfo(const SwEndNoteInfo& rInfo)
911 StartAllAction();
912 CurrShell aCurr( this );
913 GetDoc()->SetEndNoteInfo(rInfo);
914 EndAllAction();
917 const SwLineNumberInfo& SwEditShell::GetLineNumberInfo() const
919 return GetDoc()->GetLineNumberInfo();
922 void SwEditShell::SetLineNumberInfo(const SwLineNumberInfo& rInfo)
924 StartAllAction();
925 CurrShell aCurr( this );
926 GetDoc()->SetLineNumberInfo(rInfo);
927 AddPaintRect( GetLayout()->getFrameArea() );
928 EndAllAction();
931 sal_uInt16 SwEditShell::GetLinkUpdMode() const
933 return getIDocumentSettingAccess().getLinkUpdateMode( false );
936 void SwEditShell::SetLinkUpdMode( sal_uInt16 nMode )
938 getIDocumentSettingAccess().setLinkUpdateMode( nMode );
941 // Interface for TextInputData - (for text input of japanese/chinese characters)
942 void SwEditShell::CreateExtTextInput(LanguageType eInputLanguage)
944 SwExtTextInput* pRet = GetDoc()->CreateExtTextInput( *GetCursor() );
945 pRet->SetLanguage(eInputLanguage);
946 pRet->SetOverwriteCursor( SwCursorShell::IsOverwriteCursor() );
949 OUString SwEditShell::DeleteExtTextInput( bool bInsText )
951 const SwPosition& rPos = *GetCursor()->GetPoint();
952 SwExtTextInput* pDel = GetDoc()->GetExtTextInput( rPos.nNode.GetNode(),
953 rPos.nContent.GetIndex() );
954 if( !pDel )
956 //JP 25.10.2001: under UNIX the cursor is moved before the Input-
957 // Engine event comes in. So take any - normally there
958 // exist only one at the time. -- Task 92016
959 pDel = GetDoc()->GetExtTextInput();
961 OUString sRet;
962 if( pDel )
964 OUString sTmp;
965 SwUnoCursorHelper::GetTextFromPam(*pDel, sTmp);
966 sRet = sTmp;
967 CurrShell aCurr( this );
968 StartAllAction();
969 pDel->SetInsText( bInsText );
970 SetOverwriteCursor( pDel->IsOverwriteCursor() );
971 const SwPosition aPos( *pDel->GetPoint() );
972 GetDoc()->DeleteExtTextInput( pDel );
974 // In this case, the "replace" function did not set the cursor
975 // to the original position. Therefore we have to do this manually.
976 if ( ! bInsText && IsOverwriteCursor() )
977 *GetCursor()->GetPoint() = aPos;
979 EndAllAction();
981 return sRet;
984 void SwEditShell::SetExtTextInputData( const CommandExtTextInputData& rData )
986 SwPaM* pCurrentCursor = GetCursor();
987 const SwPosition& rPos = *pCurrentCursor->GetPoint();
988 SwExtTextInput* pInput = GetDoc()->GetExtTextInput( rPos.nNode.GetNode() );
989 if( !pInput )
990 return;
992 StartAllAction();
993 CurrShell aCurr( this );
995 if( !rData.IsOnlyCursorChanged() )
996 pInput->SetInputData( rData );
997 // position cursor
998 const SwPosition& rStt = *pInput->Start();
999 const sal_Int32 nNewCursorPos = rStt.nContent.GetIndex() + rData.GetCursorPos();
1001 // ugly but works
1002 ShowCursor();
1003 const sal_Int32 nDiff = nNewCursorPos - rPos.nContent.GetIndex();
1004 if( nDiff != 0)
1006 bool bLeft = nDiff < 0;
1007 sal_Int32 nMaxGuard = std::abs(nDiff);
1008 while (true)
1010 auto nOldPos = pCurrentCursor->GetPoint()->nContent.GetIndex();
1011 if (bLeft)
1012 Left(1, CRSR_SKIP_CHARS);
1013 else
1014 Right(1, CRSR_SKIP_CHARS);
1015 auto nNewPos = pCurrentCursor->GetPoint()->nContent.GetIndex();
1017 // expected success
1018 if (nNewPos == nNewCursorPos)
1019 break;
1021 if (nNewPos == nOldPos)
1023 // if there was no movement, we have failed for some reason
1024 SAL_WARN("sw.core", "IM cursor move failed");
1025 break;
1028 if (--nMaxGuard == 0)
1030 // if it takes more cursor moves than there are utf-16 chars to move past
1031 // something has probably gone wrong
1032 SAL_WARN("sw.core", "IM abandoning cursor positioning");
1033 break;
1038 SetOverwriteCursor( rData.IsCursorOverwrite() );
1040 EndAllAction();
1042 if( !rData.IsCursorVisible() ) // must be called after the EndAction
1043 HideCursor();
1047 void SwEditShell::TransliterateText( TransliterationFlags nType )
1049 utl::TransliterationWrapper aTrans( ::comphelper::getProcessComponentContext(), nType );
1050 StartAllAction();
1051 CurrShell aCurr( this );
1053 SwPaM* pCursor = GetCursor();
1054 if( pCursor->GetNext() != pCursor )
1056 GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
1057 for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
1059 if( rPaM.HasMark() )
1060 GetDoc()->getIDocumentContentOperations().TransliterateText( rPaM, aTrans );
1062 GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
1064 else
1065 GetDoc()->getIDocumentContentOperations().TransliterateText( *pCursor, aTrans );
1067 EndAllAction();
1070 void SwEditShell::CountWords( SwDocStat& rStat ) const
1072 for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
1074 if( rPaM.HasMark() )
1075 SwDoc::CountWords( rPaM, rStat );
1080 void SwEditShell::ApplyViewOptions( const SwViewOption &rOpt )
1082 SwCursorShell::StartAction();
1083 SwViewShell::ApplyViewOptions( rOpt );
1084 SwEditShell::EndAction();
1087 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */