1
0
Fork 0
libreoffice/sw/source/core/txtnode/atrref.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

224 lines
7 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <fmtrfmrk.hxx>
#include <libxml/xmlwriter.h>
#include <hintids.hxx>
#include <hints.hxx>
#include <txtrfmrk.hxx>
#include <unorefmark.hxx>
#include <utility>
#include <sfx2/viewsh.hxx>
#include <tools/json_writer.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <comphelper/lok.hxx>
#include <doc.hxx>
#include <ndtxt.hxx>
#include <pam.hxx>
#include <translatehelper.hxx>
#include <wrtsh.hxx>
SwFormatRefMark::~SwFormatRefMark( )
{
}
SwFormatRefMark::SwFormatRefMark( OUString aName )
: SfxPoolItem(RES_TXTATR_REFMARK)
, m_pTextAttr(nullptr)
, m_aRefName(std::move(aName))
{
setNonShareable();
}
SwFormatRefMark::SwFormatRefMark( const SwFormatRefMark& rAttr )
: SfxPoolItem(RES_TXTATR_REFMARK)
, m_pTextAttr(nullptr)
, m_aRefName(rAttr.m_aRefName)
{
setNonShareable();
}
void SwFormatRefMark::SetXRefMark(rtl::Reference<SwXReferenceMark> const& xMark)
{ m_wXReferenceMark = xMark.get(); }
bool SwFormatRefMark::operator==( const SfxPoolItem& rAttr ) const
{
assert(SfxPoolItem::operator==(rAttr));
return m_aRefName == static_cast<const SwFormatRefMark&>(rAttr).m_aRefName;
}
SwFormatRefMark* SwFormatRefMark::Clone( SfxItemPool* ) const
{
return new SwFormatRefMark( *this );
}
void SwFormatRefMark::InvalidateRefMark()
{
if (auto xUnoRefMark = m_wXReferenceMark.get())
{
xUnoRefMark->OnFormatRefMarkDeleted();
m_wXReferenceMark.clear();
}
}
void SwFormatRefMark::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatRefMark"));
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("m_pTextAttr"), "%p", m_pTextAttr);
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("ref-name"),
BAD_CAST(m_aRefName.toUtf8().getStr()));
SfxPoolItem::dumpAsXml(pWriter);
(void)xmlTextWriterEndElement(pWriter);
}
// attribute for content references in the text
SwTextRefMark::SwTextRefMark(
const SfxPoolItemHolder& rAttr,
sal_Int32 const nStartPos,
sal_Int32 const*const pEnd)
: SwTextAttr(rAttr, nStartPos)
, SwTextAttrEnd( rAttr, nStartPos, nStartPos )
, m_pTextNode( nullptr )
, m_pEnd( nullptr )
{
SwFormatRefMark& rSwFormatRefMark(static_cast<SwFormatRefMark&>(GetAttr()));
rSwFormatRefMark.m_pTextAttr = this;
if ( pEnd )
{
m_nEnd = *pEnd;
m_pEnd = & m_nEnd;
}
else
{
SetHasDummyChar(true);
}
SetDontMoveAttr( true );
SetOverlapAllowedAttr( true );
/* FIXME: Setting the DontExpand flag would solve tdf#81720,
* but old behavior was restored due to regressions; see tdf#157287.
* After applying a proper fix, remember to restore testDontExpandRefmark!
*SetDontExpand( true ); // like hyperlinks, reference markers shouldn't expand
*SetLockExpandFlag( true ); // protect the flag
*/
}
SwTextRefMark::~SwTextRefMark()
{
if (!comphelper::LibreOfficeKit::isActive() || GetTextNode().GetDoc().IsClipBoard())
return;
SfxViewShell* pViewShell = SfxViewShell::Current();
if (!pViewShell)
return;
OUString fieldCommand = GetRefMark().GetRefName();
tools::JsonWriter aJson;
aJson.put("commandName", ".uno:DeleteField");
aJson.put("success", true);
{
auto result = aJson.startNode("result");
aJson.put("DeleteField", fieldCommand);
}
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString());
}
const sal_Int32* SwTextRefMark::GetEnd() const
{
return m_pEnd;
}
void SwTextRefMark::SetEnd(sal_Int32 n)
{
if (*m_pEnd != n)
{
sal_Int32 nOldEndPos = *m_pEnd;
*m_pEnd = n;
if (m_pHints)
m_pHints->EndPosChanged(Which(), GetStart(), nOldEndPos, *m_pEnd);
}
}
void SwTextRefMark::UpdateFieldContent(SwDoc* pDoc, SwWrtShell& rWrtSh, const OUString& aContent)
{
if (!this->End())
{
return;
}
// Insert markers to remember where the paste positions are.
const SwTextNode& rTextNode = this->GetTextNode();
SwPaM aMarkers(SwPosition(rTextNode, *this->End()));
IDocumentContentOperations& rIDCO = pDoc->getIDocumentContentOperations();
/* FIXME: see above re: expanding behavior
*this->SetLockExpandFlag(false);
*this->SetDontExpand(false);
*/
if (rIDCO.InsertString(aMarkers, u"XY"_ustr))
{
SwPaM aPasteEnd(SwPosition(rTextNode, *this->End()));
aPasteEnd.Move(fnMoveBackward, GoInContent);
// Paste HTML content.
SwPaM* pCursorPos = rWrtSh.GetCursor();
*pCursorPos = aPasteEnd;
SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aContent.toUtf8());
// Update the refmark to point to the new content.
sal_Int32 nOldStart = this->GetStart();
sal_Int32 nNewStart = *this->End();
// First grow it to include text till the end of the paste position.
this->SetEnd(aPasteEnd.GetPoint()->GetContentIndex());
// Then shrink it to only start at the paste start: we know that the refmark was
// truncated to the paste start, as the refmark has to stay inside a single text node
this->SetStart(nNewStart);
rTextNode.GetSwpHints().SortIfNeedBe();
SwPaM aEndMarker(*aPasteEnd.GetPoint());
aEndMarker.SetMark();
aEndMarker.GetMark()->AdjustContent(1);
SwPaM aStartMarker(SwPosition(rTextNode, nOldStart), SwPosition(rTextNode, nNewStart));
// Remove markers. The start marker includes the old content as well.
rIDCO.DeleteAndJoin(aStartMarker);
rIDCO.DeleteAndJoin(aEndMarker);
}
// Restore flags.
/* FIXME: see above re: expanding behavior
*this->SetDontExpand(true);
*this->SetLockExpandFlag(true);
*/
}
void SwTextRefMark::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTextRefMark"));
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
SwTextAttr::dumpAsXml(pWriter);
(void)xmlTextWriterEndElement(pWriter);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */