/* -*- 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 <editdoc.hxx>
#include <editeng/tstpitem.hxx>
#include <editeng/colritem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/crossedoutitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/flditem.hxx>
#include <editeng/postitem.hxx>
#include <editeng/kernitem.hxx>
#include <editeng/wrlmitem.hxx>
#include <editeng/wghtitem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/cmapitem.hxx>
#include <editeng/contouritem.hxx>
#include <editeng/escapementitem.hxx>
#include <editeng/shdditem.hxx>
#include <editeng/autokernitem.hxx>
#include <editeng/langitem.hxx>
#include <editeng/emphasismarkitem.hxx>
#include <editeng/charscaleitem.hxx>
#include <editeng/charreliefitem.hxx>
#include <editeng/editids.hrc>
#include <editeng/editdata.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/lspcitem.hxx>
#if ENABLE_YRS
#include <editeng/frmdiritem.hxx>
#include <editeng/hngpnctitem.hxx>
#include <editeng/forbiddenruleitem.hxx>
#include <editeng/scriptspaceitem.hxx>
#include <editeng/adjustitem.hxx>
#include <editeng/justifyitem.hxx>
#include <editeng/numdef.hxx>
#include <svl/itemiter.hxx>
#endif
#include <editeng/eerdll.hxx>
#include <eerdll2.hxx>
#include "impedit.hxx"
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <o3tl/safeint.hxx>
#include <osl/diagnose.h>
#include <svl/grabbagitem.hxx>
#include <svl/voiditem.hxx>
#include <tools/debug.hxx>
#include <com/sun/star/i18n/ScriptType.hpp>
#include <libxml/xmlwriter.h>
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <limits>
#include <memory>
#include <set>
#include <string_view>
#include <utility>
using namespace ::com::sun::star;
sal_uInt16 GetScriptItemId( sal_uInt16 nItemId, SvtScriptType nScriptType )
{
sal_uInt16 nId = nItemId;
if ( ( nScriptType == SvtScriptType::ASIAN ) ||
( nScriptType == SvtScriptType::COMPLEX ) )
{
switch ( nItemId )
{
case EE_CHAR_LANGUAGE:
nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CT
L;
break ;
case EE_CHAR_FONTINFO:
nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL;
break ;
case EE_CHAR_FONTHEIGHT:
nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL;
break ;
case EE_CHAR_WEIGHT:
nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL;
break ;
case EE_CHAR_ITALIC:
nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL;
break ;
}
}
return nId;
}
bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType )
{
bool bValid = true ;
switch ( nItemId )
{
case EE_CHAR_LANGUAGE:
bValid = nScriptType == i18n::ScriptType::LATIN;
break ;
case EE_CHAR_LANGUAGE_CJK:
bValid = nScriptType == i18n::ScriptType::ASIAN;
break ;
case EE_CHAR_LANGUAGE_CTL:
bValid = nScriptType == i18n::ScriptType::COMPLEX;
break ;
case EE_CHAR_FONTINFO:
bValid = nScriptType == i18n::ScriptType::LATIN;
break ;
case EE_CHAR_FONTINFO_CJK:
bValid = nScriptType == i18n::ScriptType::ASIAN;
break ;
case EE_CHAR_FONTINFO_CTL:
bValid = nScriptType == i18n::ScriptType::COMPLEX;
break ;
case EE_CHAR_FONTHEIGHT:
bValid = nScriptType == i18n::ScriptType::LATIN;
break ;
case EE_CHAR_FONTHEIGHT_CJK:
bValid = nScriptType == i18n::ScriptType::ASIAN;
break ;
case EE_CHAR_FONTHEIGHT_CTL:
bValid = nScriptType == i18n::ScriptType::COMPLEX;
break ;
case EE_CHAR_WEIGHT:
bValid = nScriptType == i18n::ScriptType::LATIN;
break ;
case EE_CHAR_WEIGHT_CJK:
bValid = nScriptType == i18n::ScriptType::ASIAN;
break ;
case EE_CHAR_WEIGHT_CTL:
bValid = nScriptType == i18n::ScriptType::COMPLEX;
break ;
case EE_CHAR_ITALIC:
bValid = nScriptType == i18n::ScriptType::LATIN;
break ;
case EE_CHAR_ITALIC_CJK:
bValid = nScriptType == i18n::ScriptType::ASIAN;
break ;
case EE_CHAR_ITALIC_CTL:
bValid = nScriptType == i18n::ScriptType::COMPLEX;
break ;
}
return bValid;
}
EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE )
{
// Create a new attribute in the pool
switch ( rAttr.Which() )
{
case EE_CHAR_LANGUAGE:
case EE_CHAR_LANGUAGE_CJK:
case EE_CHAR_LANGUAGE_CTL:
{
return new EditCharAttribLanguage(rPool, rAttr, nS, nE);
}
break ;
case EE_CHAR_COLOR:
{
return new EditCharAttribColor(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_FONTINFO:
case EE_CHAR_FONTINFO_CJK:
case EE_CHAR_FONTINFO_CTL:
{
return new EditCharAttribFont(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_FONTHEIGHT:
case EE_CHAR_FONTHEIGHT_CJK:
case EE_CHAR_FONTHEIGHT_CTL:
{
return new EditCharAttribFontHeight(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_FONTWIDTH:
{
return new EditCharAttribFontWidth(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_WEIGHT:
case EE_CHAR_WEIGHT_CJK:
case EE_CHAR_WEIGHT_CTL:
{
return new EditCharAttribWeight(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_UNDERLINE:
{
return new EditCharAttribUnderline(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_OVERLINE:
{
return new EditCharAttribOverline(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_EMPHASISMARK:
{
return new EditCharAttribEmphasisMark(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_RELIEF:
{
return new EditCharAttribRelief(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_STRIKEOUT:
{
return new EditCharAttribStrikeout(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_ITALIC:
case EE_CHAR_ITALIC_CJK:
case EE_CHAR_ITALIC_CTL:
{
return new EditCharAttribItalic(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_OUTLINE:
{
return new EditCharAttribOutline(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_SHADOW:
{
return new EditCharAttribShadow(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_ESCAPEMENT:
{
return new EditCharAttribEscapement(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_PAIRKERNING:
{
return new EditCharAttribPairKerning(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_KERNING:
{
return new EditCharAttribKerning(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_WLM:
{
return new EditCharAttribWordLineMode(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_XMLATTRIBS:
{
return new EditCharAttrib(rPool, rAttr, nS, nE); // Attribute is only for holding XML information...
}
break ;
case EE_CHAR_CASEMAP:
{
return new EditCharAttribCaseMap(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_GRABBAG:
{
return new EditCharAttribGrabBag(rPool, rAttr, nS, nE );
}
break ;
case EE_FEATURE_TAB:
{
return new EditCharAttribTab(rPool, rAttr, nS );
}
break ;
case EE_FEATURE_LINEBR:
{
return new EditCharAttribLineBreak(rPool, rAttr, nS );
}
break ;
case EE_FEATURE_FIELD:
{
return new EditCharAttribField(rPool, rAttr, nS );
}
break ;
case EE_CHAR_BKGCOLOR:
{
return new EditCharAttribBackgroundColor(rPool, rAttr, nS, nE );
}
break ;
case EE_CHAR_RUBY:
{
return new EditCharAttribRuby(rPool, rAttr, nS, nE);
}
break ;
case EE_CHAR_SCRIPT_HINT:
{
return new EditCharAttribScriptHint(rPool, rAttr, nS, nE);
}
break ;
default :
break ;
}
OSL_FAIL( "Invalid Attribute!" );
return nullptr;
}
void ParaPortion::MarkInvalid(sal_Int32 nStart, sal_Int32 nDiff)
{
if (!mbInvalid)
{
// mnInvalidPosEnd = nStart; // ??? => CreateLines
mnInvalidPosStart = nDiff >= 0 ? nStart : nStart + nDiff;
mnInvalidDiff = nDiff;
}
else
{
// Simple tap in succession
if (nDiff > 0 && mnInvalidDiff > 0 && (mnInvalidPosStart + mnInvalidDiff) == nStart)
{
mnInvalidDiff = mnInvalidDiff + nDiff;
}
// Simple delete in succession
else if (nDiff < 0 && mnInvalidDiff < 0 && mnInvalidPosStart == nStart)
{
mnInvalidPosStart = mnInvalidPosStart + nDiff;
mnInvalidDiff = mnInvalidDiff + nDiff;
}
else
{
// mnInvalidPosEnd = pNode->Len();
DBG_ASSERT(nDiff >= 0 || (nStart + nDiff) >= 0, "MarkInvalid: Diff out of Range" );
mnInvalidPosStart = std::min(mnInvalidPosStart, nDiff < 0 ? nStart + nDiff : nDiff);
mnInvalidDiff = 0;
mbSimple = false ;
}
}
mbInvalid = true ;
maScriptInfos.clear();
maWritingDirectionInfos.clear();
}
void ParaPortion::MarkSelectionInvalid(sal_Int32 nStart)
{
if ( !mbInvalid )
{
mnInvalidPosStart = nStart;
}
else
{
mnInvalidPosStart = std::min(mnInvalidPosStart, nStart);
}
mnInvalidDiff = 0;
mbInvalid = true ;
mbSimple = false ;
maScriptInfos.clear();
maWritingDirectionInfos.clear();
}
sal_Int32 ParaPortion::GetLineNumber( sal_Int32 nIndex ) const
{
const sal_Int32 nCount = maLineList.Count();
assert(nCount > 0 && "Empty ParaPortion in GetLine!" );
if (nCount == 0)
return 0;
DBG_ASSERT(mbVisible, "Why GetLine() on an invisible paragraph?" );
for ( sal_Int32 nLine = 0; nLine < nCount; nLine++ )
{
if (maLineList[nLine].IsIn(nIndex))
return nLine;
}
// Then it should be at the end of the last line!
DBG_ASSERT(nIndex == maLineList[nCount - 1].GetEnd(), "Index dead wrong!" );
return nCount - 1;
}
void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormattedLine )
{
sal_Int32 nLines = maLineList.Count();
DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Empty Portion?" );
if ( nLastFormattedLine < ( nLines - 1 ) )
{
const EditLine& rLastFormatted = maLineList[ nLastFormattedLine ];
const EditLine& rUnformatted = maLineList[ nLastFormattedLine+1 ];
sal_Int32 nPortionDiff = rUnformatted.GetStartPortion() - rLastFormatted.GetEndPortion();
sal_Int32 nTextDiff = rUnformatted.GetStart() - rLastFormatted.GetEnd();
nTextDiff++; // LastFormatted->GetEnd() was included => 1 deducted too much!
// The first unformatted must begin exactly one Portion behind the last
// of the formatted:
// If the modified line was split into one portion, can
// nLastEnd > nNextStart!
int nPDiff = -( nPortionDiff-1 );
int nTDiff = -( nTextDiff-1 );
if ( nPDiff || nTDiff )
{
for ( sal_Int32 nL = nLastFormattedLine+1; nL < nLines; nL++ )
{
EditLine& rLine = maLineList[ nL ];
rLine.GetStartPortion() = rLine.GetStartPortion() + nPDiff;
rLine.GetEndPortion() = rLine.GetEndPortion() + nPDiff;
rLine.GetStart() = rLine.GetStart() + nTDiff;
rLine.GetEnd() = rLine.GetEnd() + nTDiff;
rLine.SetValid();
}
}
}
DBG_ASSERT(maLineList[maLineList.Count() - 1].GetEnd() == mpNode->Len(), "CorrectLines: The end is not right!" );
}
// Shared reverse lookup acceleration pieces ...
namespace {
template <typename Array, typename Val>
sal_Int32 FastGetPos(const Array& rArray, const Val* p, sal_Int32& rLastPos)
{
sal_Int32 nArrayLen = rArray.size();
// Through certain filter code-paths we do a lot of appends, which in
// turn call GetPos - creating some N^2 nightmares. If we have a
// non-trivially large list, do a few checks from the end first.
if (rLastPos > 16 && nArrayLen > 16)
{
sal_Int32 nEnd;
if (rLastPos > nArrayLen - 2)
nEnd = nArrayLen;
else
nEnd = rLastPos + 2;
for (sal_Int32 nIdx = rLastPos - 2; nIdx < nEnd; ++nIdx)
{
if (rArray.at(nIdx).get() == p)
{
rLastPos = nIdx;
return nIdx;
}
}
}
// The world's lamest linear search from svarray...
for (sal_Int32 nIdx = 0; nIdx < nArrayLen; ++nIdx)
if (rArray.at(nIdx).get() == p)
{
rLastPos = nIdx;
return rLastPos;
}
// XXX "not found" condition for sal_Int32 indexes
return EE_PARA_MAX;
}
}
sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const
{
return FastGetPos(maPortions, p, nLastCache);
}
std::unique_ptr<ParaPortion> ParaPortionList::Release(sal_Int32 nPos)
{
if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos))
{
SAL_WARN( "editeng" , "ParaPortionList::Release - out of bounds pos " << nPos);
return nullptr;
}
std::unique_ptr<ParaPortion> p = std::move(maPortions[nPos]);
maPortions.erase(maPortions.begin()+nPos);
return p;
}
void ParaPortionList::Remove(sal_Int32 nPos)
{
if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos))
{
SAL_WARN( "editeng" , "ParaPortionList::Remove - out of bounds pos " << nPos);
return ;
}
maPortions.erase(maPortions.begin()+nPos);
}
void ParaPortionList::Insert(sal_Int32 nPos, std::unique_ptr<ParaPortion> p)
{
if (nPos < 0 || maPortions.size() < o3tl::make_unsigned(nPos))
{
SAL_WARN( "editeng" , "ParaPortionList::Insert - out of bounds pos " << nPos);
return ;
}
maPortions.insert(maPortions.begin()+nPos, std::move(p));
}
void ParaPortionList::Append(std::unique_ptr<ParaPortion> p)
{
maPortions.push_back(std::move(p));
}
sal_Int32 ParaPortionList::Count() const
{
size_t nSize = maPortions.size();
if (nSize > SAL_MAX_INT32)
{
SAL_WARN( "editeng" , "ParaPortionList::Count - overflow " << nSize);
return SAL_MAX_INT32;
}
return nSize;
}
void ParaPortionList::Reset()
{
maPortions.clear();
}
tools::Long ParaPortionList::GetYOffset(const ParaPortion* pPPortion) const
{
tools::Long nHeight = 0;
for (const auto & rPortion : maPortions)
{
const ParaPortion* pTmpPortion = rPortion.get();
if ( pTmpPortion == pPPortion )
return nHeight;
nHeight += pTmpPortion->GetHeight();
}
OSL_FAIL( "GetYOffset: Portion not found" );
return nHeight;
}
sal_Int32 ParaPortionList::FindParagraph(tools::Long nYOffset) const
{
tools::Long nY = 0;
for (size_t i = 0, n = maPortions.size(); i < n; ++i)
{
nY += maPortions[i]->GetHeight(); // should also be correct even in bVisible!
if ( nY > nYOffset )
return i <= SAL_MAX_INT32 ? static_cast <sal_Int32>(i) : SAL_MAX_INT32;
}
return EE_PARA_MAX;
}
#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
void
ParaPortionList::DbgCheck(ParaPortionList const & rParas, EditDoc const & rDoc)
{
assert(rParas.Count() == rDoc.Count());
for (sal_Int32 i = 0; i < rParas.Count(); ++i)
{
assert(rParas.SafeGetObject(i) != nullptr);
assert(rParas.SafeGetObject(i)->GetNode() != nullptr);
assert(rParas.SafeGetObject(i)->GetNode() == rDoc.GetObject(i));
}
}
#endif
ContentAttribsInfo::ContentAttribsInfo( SfxItemSet aParaAttribs ) :
aPrevParaAttribs(std::move( aParaAttribs))
{
}
void ContentAttribsInfo::AppendCharAttrib(EditCharAttrib* pNew)
{
aPrevCharAttribs.push_back(std::unique_ptr<EditCharAttrib>(pNew));
}
void ConvertItem( std::unique_ptr<SfxPoolItem>& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit )
{
DBG_ASSERT( eSourceUnit != eDestUnit, "ConvertItem - Why?!" );
switch ( rPoolItem->Which() )
{
case EE_PARA_LRSPACE:
{
assert(dynamic_cast <const SvxLRSpaceItem *>(rPoolItem.get()) != nullptr);
SvxLRSpaceItem& rItem = static_cast <SvxLRSpaceItem&>(*rPoolItem);
if (rItem.GetTextFirstLineOffset().m_nUnit == css::util::MeasureUnit::TWIP)
{
rItem.SetTextFirstLineOffset(
SvxIndentValue::twips(sal::static_int_cast<short >(OutputDevice::LogicToLogic(
rItem.ResolveTextFirstLineOffset({}), eSourceUnit, eDestUnit))));
}
rItem.SetTextLeft(SvxIndentValue::twips(
OutputDevice::LogicToLogic(rItem.ResolveTextLeft({}), eSourceUnit, eDestUnit)));
if (rItem.GetRight().m_nUnit == css::util::MeasureUnit::TWIP)
{
rItem.SetRight(SvxIndentValue::twips(
OutputDevice::LogicToLogic(rItem.ResolveRight({}), eSourceUnit, eDestUnit)));
}
}
break ;
case EE_PARA_ULSPACE:
{
assert(dynamic_cast <const SvxULSpaceItem *>(rPoolItem.get()) != nullptr);
SvxULSpaceItem& rItem = static_cast <SvxULSpaceItem&>(*rPoolItem);
rItem.SetUpper( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetUpper(), eSourceUnit, eDestUnit ) ) );
rItem.SetLower( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLower(), eSourceUnit, eDestUnit ) ) );
}
break ;
case EE_PARA_SBL:
{
assert(dynamic_cast <const SvxLineSpacingItem *>(rPoolItem.get()) != nullptr);
SvxLineSpacingItem& rItem = static_cast <SvxLineSpacingItem&>(*rPoolItem);
// SetLineHeight changes also eLineSpace!
if ( rItem.GetLineSpaceRule() == SvxLineSpaceRule::Min )
rItem.SetLineHeight( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLineHeight(), eSourceUnit, eDestUnit ) ) );
}
break ;
case EE_PARA_TABS:
{
assert(dynamic_cast <const SvxTabStopItem *>(rPoolItem.get()) != nullptr);
SvxTabStopItem& rItem = static_cast <SvxTabStopItem&>(*rPoolItem);
SvxTabStopItem* pNewItem(new SvxTabStopItem(EE_PARA_TABS));
if (sal_Int32 nDefTabDistance = rItem.GetDefaultDistance())
{
pNewItem->SetDefaultDistance(
OutputDevice::LogicToLogic(nDefTabDistance, eSourceUnit, eDestUnit));
}
for ( sal_uInt16 i = 0; i < rItem.Count(); i++ )
{
const SvxTabStop& rTab = rItem[i];
SvxTabStop aNewStop( OutputDevice::LogicToLogic( rTab.GetTabPos(), eSourceUnit, eDestUnit ), rTab.GetAdjustment(), rTab.GetDecimal(), rTab.GetFill() );
pNewItem->Insert( aNewStop );
}
rPoolItem.reset(pNewItem);
}
break ;
case EE_CHAR_FONTHEIGHT:
case EE_CHAR_FONTHEIGHT_CJK:
case EE_CHAR_FONTHEIGHT_CTL:
{
assert(dynamic_cast <const SvxFontHeightItem *>(rPoolItem.get()) != nullptr);
SvxFontHeightItem& rItem = static_cast <SvxFontHeightItem&>(*rPoolItem);
rItem.SetHeight( OutputDevice::LogicToLogic( rItem.GetHeight(), eSourceUnit, eDestUnit ) );
}
break ;
}
}
void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit, const MapUnit* pDestUnit )
{
const SfxItemPool* pSourcePool = rSource.GetPool();
const SfxItemPool* pDestPool = rDest.GetPool();
for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
{
// If possible go through SlotID ...
sal_uInt16 nSourceWhich = nWhich;
sal_uInt16 nSlot = pDestPool->GetTrueSlotId( nWhich );
if ( nSlot )
{
sal_uInt16 nW = pSourcePool->GetTrueWhichIDFromSlotID( nSlot );
if ( nW )
nSourceWhich = nW;
}
if ( rSource.GetItemState( nSourceWhich, false ) == SfxItemState::SET )
{
MapUnit eSourceUnit = pSourceUnit ? *pSourceUnit : pSourcePool->GetMetric( nSourceWhich );
MapUnit eDestUnit = pDestUnit ? *pDestUnit : pDestPool->GetMetric( nWhich );
if ( eSourceUnit != eDestUnit )
{
std::unique_ptr<SfxPoolItem> pItem(rSource.Get( nSourceWhich ).Clone());
ConvertItem( pItem, eSourceUnit, eDestUnit );
pItem->SetWhich(nWhich);
rDest.Put( std::move(pItem) );
}
else
{
rDest.Put( rSource.Get( nSourceWhich ).CloneSetWhich(nWhich) );
}
}
}
}
bool EditPaM::DbgIsBuggy( EditDoc const & rDoc ) const
{
return !pNode ||
rDoc.GetPos( pNode ) >= rDoc.Count() ||
nIndex > pNode->Len();
}
bool EditSelection::DbgIsBuggy( EditDoc const & rDoc ) const
{
return aStartPaM.DbgIsBuggy( rDoc ) || aEndPaM.DbgIsBuggy( rDoc );
}
void EditSelection::Adjust( const EditDoc& rNodes )
{
DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in Adjust(1)" );
DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index out of range in Adjust(2)" );
const ContentNode* pStartNode = aStartPaM.GetNode();
const ContentNode* pEndNode = aEndPaM.GetNode();
sal_Int32 nStartNode = rNodes.GetPos( pStartNode );
sal_Int32 nEndNode = rNodes.GetPos( pEndNode );
DBG_ASSERT( nStartNode != SAL_MAX_INT32, "Node out of range in Adjust(1)" );
DBG_ASSERT( nEndNode != SAL_MAX_INT32, "Node out of range in Adjust(2)" );
const bool bSwap = ( nStartNode > nEndNode ) ||
( ( nStartNode == nEndNode ) &&
( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) );
if ( bSwap )
{
EditPaM aTmpPaM( aStartPaM );
aStartPaM = aEndPaM;
aEndPaM = aTmpPaM;
}
}
#if ENABLE_YRS
#include <editeng/yrstransactionsupplier.hxx>
#include <editeng/yrs.hxx>
namespace {
struct YrsReplayGuard
{
IYrsTransactionSupplier *const m_pYrsSupplier;
IYrsTransactionSupplier::Mode m_Mode;
explicit YrsReplayGuard(IYrsTransactionSupplier *const pYrsSupplier)
: m_pYrsSupplier(pYrsSupplier)
{
if (m_pYrsSupplier)
{
m_Mode = m_pYrsSupplier->SetMode(IYrsTransactionSupplier::Mode::Replay);
}
}
~YrsReplayGuard()
{
if (m_pYrsSupplier)
{
m_pYrsSupplier->SetMode(m_Mode);
}
}
};
struct YrsWrite
{
YTransaction *const pTxn;
Branch *const pProps;
Branch *const pText;
};
constexpr char CH_PARA = 0x0d;
YrsWrite GetYrsWrite(IYrsTransactionSupplier *const pYrsSupplier,
OString const & rId, YTransaction *const pInTxn = nullptr)
{
if (!pYrsSupplier)
{
return { nullptr, nullptr, nullptr };
}
YDoc *const pDoc{pYrsSupplier->GetYDoc()};
YTransaction *const pTxn{pInTxn ? pInTxn : pYrsSupplier->GetWriteTransaction()};
// write is disabled when receiving edits from peers
if (!pTxn)
{
return { nullptr, nullptr, nullptr };
}
assert(pDoc);
Branch *const pComments{pYrsSupplier->GetCommentMap()};
::std::unique_ptr<YOutput, YOutputDeleter> const pComment{ymap_get(pComments, pTxn, rId.getStr())};
yvalidate(pComment->tag == Y_ARRAY);
yvalidate(pComment->len == 1);
Branch *const pCommentArray{pComment->value.y_type};
::std::unique_ptr<YOutput, YOutputDeleter> const pProps{yarray_get(pCommentArray, pTxn, 1)};
yvalidate(pProps->tag == Y_MAP);
yvalidate(pProps->len == 1);
::std::unique_ptr<YOutput, YOutputDeleter> const pText{yarray_get(pCommentArray, pTxn, 2)};
yvalidate(pText->tag == Y_TEXT);
yvalidate(pText->len == 1);
return { pTxn, pProps->value.y_type, pText->value.y_type };
}
void YrsSetVertical(IYrsTransactionSupplier *const pYrsSupplier,
OString const & rCommentId, bool const isVertical)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
YInput const input{yinput_bool(isVertical ? Y_TRUE : Y_FALSE)};
ymap_insert(yw.pProps, yw.pTxn, "is-vertical" , &input);
}
void YrsSetRotation(IYrsTransactionSupplier *const pYrsSupplier,
OString const & rCommentId, TextRotation const nRotation)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
YInput const input{yinput_long(static_cast <int64_t>(nRotation))};
ymap_insert(yw.pProps, yw.pTxn, "rotation" , &input);
}
void YrsSetDefTab(IYrsTransactionSupplier *const pYrsSupplier,
OString const & rCommentId, sal_uInt16 const nDefTab)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
YInput const input{yinput_long(static_cast <int64_t>(nDefTab))};
ymap_insert(yw.pProps, yw.pTxn, "def-tab" , &input);
}
void YrsInsertAttribImplImpl(YrsWrite const & yw, SfxPoolItem const & rItm,
uint32_t const nStart, uint32_t const nLen)
{
::std::vector<YInput> tabStops;
::std::vector<::std::vector<YInput>> tabStopValues;
::std::vector<OString> tempStrings;
::std::vector<YInput> itemArray;
::std::vector<char const *> itemNames;
YInput attr;
char const * attrName;
switch (rItm.Which())
{
case EE_CHAR_COLOR:
case EE_CHAR_BKGCOLOR:
{
sal_uInt32 const nColor{static_cast <SvxColorItem const &>(rItm).getColor()};
attr = yinput_long(nColor);
attrName = rItm.Which() == EE_CHAR_COLOR ? "EE_CHAR_COLOR" : "EE_CHAR_BKGCOLOR" ;
break ;
}
case EE_CHAR_FONTINFO:
case EE_CHAR_FONTINFO_CJK:
case EE_CHAR_FONTINFO_CTL:
{
SvxFontItem const & rItem{static_cast <SvxFontItem const &>(rItm)};
tempStrings.reserve(2); // prevent realloc
tempStrings.emplace_back(OUStringToOString(rItem.GetFamilyName(), RTL_TEXTENCODING_UTF8));
itemArray.emplace_back(yinput_string(tempStrings.back().getStr()));
itemNames.emplace_back("familyname" );
tempStrings.emplace_back(OUStringToOString(rItem.GetStyleName(), RTL_TEXTENCODING_UTF8));
itemArray.emplace_back(yinput_string(tempStrings.back().getStr()));
itemNames.emplace_back("style" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetFamily())));
itemNames.emplace_back("family" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetPitch())));
itemNames.emplace_back("pitch" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetCharSet())));
itemNames.emplace_back("charset" );
attr = yinput_json_map(const_cast <char **>(itemNames.data()), itemArray.data(), itemArray.size());
attrName = rItm.Which() == EE_CHAR_FONTINFO
? "EE_CHAR_FONTINFO"
: rItm.Which() == EE_CHAR_FONTINFO_CJK ? "EE_CHAR_FONTINFO_CJK" : "EE_CHAR_FONTINFO_CTL" ;
break ;
}
case EE_CHAR_FONTHEIGHT:
case EE_CHAR_FONTHEIGHT_CJK:
case EE_CHAR_FONTHEIGHT_CTL:
{
SvxFontHeightItem const & rItem{static_cast <SvxFontHeightItem const &>(rItm)};
itemNames.emplace_back("height" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetHeight())));
itemNames.emplace_back("prop" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetProp())));
itemNames.emplace_back("propunit" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetPropUnit())));
attr = yinput_json_map(const_cast <char **>(itemNames.data()), itemArray.data(), itemArray.size());
attrName = rItm.Which() == EE_CHAR_FONTHEIGHT
? "EE_CHAR_FONTHEIGHT"
: rItm.Which() == EE_CHAR_FONTHEIGHT_CJK ? "EE_CHAR_FONTHEIGHT_CJK" : "EE_CHAR_FONTHEIGHT_CTL" ;
break ;
}
case EE_CHAR_FONTWIDTH:
{
SvxCharScaleWidthItem const & rItem{static_cast <SvxCharScaleWidthItem const &>(rItm)};
attr = yinput_long(rItem.GetValue());
attrName = "EE_CHAR_FONTWIDTH" ;
break ;
}
case EE_CHAR_WEIGHT:
case EE_CHAR_WEIGHT_CJK:
case EE_CHAR_WEIGHT_CTL:
{
SvxWeightItem const & rItem{static_cast <SvxWeightItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetWeight()));
attrName = rItm.Which() == EE_CHAR_WEIGHT
? "EE_CHAR_WEIGHT"
: rItm.Which() == EE_CHAR_WEIGHT_CJK ? "EE_CHAR_WEIGHT_CJK" : "EE_CHAR_WEIGHT_CTL" ;
break ;
}
case EE_CHAR_UNDERLINE:
case EE_CHAR_OVERLINE:
{
SvxTextLineItem const & rItem{static_cast <SvxTextLineItem const &>(rItm)};
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetLineStyle())));
itemNames.emplace_back("style" );
itemArray.emplace_back(yinput_long(uint64_t(sal_uInt32(rItem.GetColor()))));
itemNames.emplace_back("color" );
attr = yinput_json_map(const_cast <char **>(itemNames.data()), itemArray.data(), itemArray.size());
attrName = rItm.Which() == EE_CHAR_UNDERLINE ? "EE_CHAR_UNDERLINE" : "EE_CHAR_OVERLINE" ;
break ;
}
case EE_CHAR_STRIKEOUT:
{
SvxCrossedOutItem const & rItem{static_cast <SvxCrossedOutItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetStrikeout()));
attrName = "EE_CHAR_STRIKEOUT" ;
break ;
}
case EE_CHAR_ITALIC:
case EE_CHAR_ITALIC_CJK:
case EE_CHAR_ITALIC_CTL:
{
SvxPostureItem const & rItem{static_cast <SvxPostureItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetPosture()));
attrName = rItm.Which() == EE_CHAR_ITALIC
? "EE_CHAR_ITALIC"
: rItm.Which() == EE_CHAR_ITALIC_CJK ? "EE_CHAR_ITALIC_CJK" : "EE_CHAR_ITALIC_CTL" ;
break ;
}
case EE_CHAR_OUTLINE:
{
SvxContourItem const & rItem{static_cast <SvxContourItem const &>(rItm)};
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = "EE_CHAR_OUTLINE" ;
break ;
}
case EE_CHAR_SHADOW:
{
SvxShadowedItem const & rItem{static_cast <SvxShadowedItem const &>(rItm)};
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = "EE_CHAR_SHADOW" ;
break ;
}
case EE_CHAR_ESCAPEMENT:
{
SvxEscapementItem const & rItem{static_cast <SvxEscapementItem const &>(rItm)};
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetEsc())));
itemNames.emplace_back("esc" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetProportionalHeight())));
itemNames.emplace_back("prop" );
attr = yinput_json_map(const_cast <char **>(itemNames.data()), itemArray.data(), itemArray.size());
attrName = "EE_CHAR_ESCAPEMENT" ;
break ;
}
case EE_CHAR_PAIRKERNING:
{
SvxAutoKernItem const & rItem{static_cast <SvxAutoKernItem const &>(rItm)};
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = "EE_CHAR_PAIRKERNING" ;
break ;
}
case EE_CHAR_KERNING:
{
SvxKerningItem const & rItem{static_cast <SvxKerningItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue()));
attrName = "EE_CHAR_KERNING" ;
break ;
}
case EE_CHAR_WLM:
{
SvxWordLineModeItem const & rItem{static_cast <SvxWordLineModeItem const &>(rItm)};
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = "EE_CHAR_WLM" ;
break ;
}
case EE_CHAR_LANGUAGE:
case EE_CHAR_LANGUAGE_CJK:
case EE_CHAR_LANGUAGE_CTL:
{
SvxLanguageItem const & rItem{static_cast <SvxLanguageItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue().get()));
attrName = rItm.Which() == EE_CHAR_LANGUAGE
? "EE_CHAR_LANGUAGE"
: rItm.Which() == EE_CHAR_LANGUAGE_CJK ? "EE_CHAR_LANGUAGE_CJK" : "EE_CHAR_LANGUAGE_CTL" ;
break ;
}
case EE_CHAR_EMPHASISMARK:
{
SvxEmphasisMarkItem const & rItem{static_cast <SvxEmphasisMarkItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue()));
attrName = "EE_CHAR_EMPHASISMARK" ;
break ;
}
case EE_CHAR_RELIEF:
{
SvxCharReliefItem const & rItem{static_cast <SvxCharReliefItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue()));
attrName = "EE_CHAR_RELIEF" ;
break ;
}
case EE_CHAR_CASEMAP:
{
SvxCaseMapItem const & rItem{static_cast <SvxCaseMapItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue()));
attrName = "EE_CHAR_CASEMAP" ;
break ;
}
case EE_PARA_WRITINGDIR:
{
SvxFrameDirectionItem const & rItem{static_cast <SvxFrameDirectionItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue()));
attrName = "EE_PARA_WRITINGDIR" ;
break ;
}
case EE_PARA_HANGINGPUNCTUATION:
{
SvxHangingPunctuationItem const & rItem{static_cast <SvxHangingPunctuationItem const &>(rItm)};
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = "EE_PARA_HANGINGPUNCTUATION" ;
break ;
}
case EE_PARA_FORBIDDENRULES:
{
SvxForbiddenRuleItem const & rItem{static_cast <SvxForbiddenRuleItem const &>(rItm)};
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = "EE_PARA_FORBIDDENRULES" ;
break ;
}
case EE_PARA_ASIANCJKSPACING:
{
SvxScriptSpaceItem const & rItem{static_cast <SvxScriptSpaceItem const &>(rItm)};
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = "EE_PARA_ASIANCJKSPACING" ;
break ;
}
//TODO complex, but apparently no way to set this in comment? inline constexpr TypedWhichId<SvxNumBulletItem> EE_PARA_NUMBULLET (EE_PARA_START+5);
case EE_PARA_HYPHENATE:
case EE_PARA_HYPHENATE_NO_CAPS:
case EE_PARA_HYPHENATE_NO_LAST_WORD:
case EE_PARA_BULLETSTATE:
{
SfxBoolItem const & rItem{static_cast <SfxBoolItem const &>(rItm)};
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = rItm.Which() == EE_PARA_HYPHENATE
? "EE_PARA_HYPHENATE"
: rItm.Which() == EE_PARA_HYPHENATE_NO_CAPS
? "EE_PARA_HYPHENATE_NO_CAPS"
: rItm.Which() == EE_PARA_HYPHENATE_NO_LAST_WORD
? "EE_PARA_HYPHENATE_NO_LAST_WORD"
: "EE_PARA_BULLETSTATE" ;
break ;
}
//TODO no way to set this in comment? inline constexpr TypedWhichId<SvxLRSpaceItem> EE_PARA_OUTLLRSPACE (EE_PARA_START+10);
case EE_PARA_OUTLLEVEL:
{
SfxInt16Item const & rItem{static_cast <SfxInt16Item const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue()));
attrName = "EE_PARA_OUTLLEVEL" ;
break ;
}
//TODO complex, but apparently no way to set this in comment? inline constexpr TypedWhichId<SvxBulletItem> EE_PARA_BULLET (EE_PARA_START+12);
case EE_PARA_LRSPACE:
{
SvxLRSpaceItem const & rItem{static_cast <SvxLRSpaceItem const &>(rItm)};
itemArray.emplace_back(yinput_float(rItem.GetTextFirstLineOffset().m_dValue));
itemNames.emplace_back("first-line-offset" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetTextFirstLineOffset().m_nUnit)));
itemNames.emplace_back("first-line-offset-unit" );
itemArray.emplace_back(yinput_float(rItem.GetLeft().m_dValue));
itemNames.emplace_back("left-margin" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetLeft().m_nUnit)));
itemNames.emplace_back("left-margin-unit" );
itemArray.emplace_back(yinput_float(rItem.GetRight().m_dValue));
itemNames.emplace_back("right-margin" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetRight().m_nUnit)));
itemNames.emplace_back("right-margin-unit" );
itemArray.emplace_back(yinput_bool(rItem.IsAutoFirst() ? Y_TRUE : Y_FALSE));
itemNames.emplace_back("auto-first" );
attr = yinput_json_map(const_cast <char **>(itemNames.data()), itemArray.data(), itemArray.size());
attrName = "EE_PARA_LRSPACE" ;
break ;
}
case EE_PARA_ULSPACE:
{
SvxULSpaceItem const & rItem{static_cast <SvxULSpaceItem const &>(rItm)};
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetUpper())));
itemNames.emplace_back("upper-margin" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetLower())));
itemNames.emplace_back("lower-margin" );
// TODO what does EE support here?
attr = yinput_json_map(const_cast <char **>(itemNames.data()), itemArray.data(), itemArray.size());
attrName = "EE_PARA_ULSPACE" ;
break ;
}
case EE_PARA_SBL:
{
SvxLineSpacingItem const & rItem{static_cast <SvxLineSpacingItem const &>(rItm)};
switch (rItem.GetLineSpaceRule())
{
case SvxLineSpaceRule::Auto :
break ;
case SvxLineSpaceRule::Fix:
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetLineHeight())));
itemNames.emplace_back("line-space-fix" );
break ;
case SvxLineSpaceRule::Min:
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetLineHeight())));
itemNames.emplace_back("line-space-min" );
break ;
}
switch (rItem.GetInterLineSpaceRule())
{
case SvxInterLineSpaceRule::Off:
break ;
case SvxInterLineSpaceRule::Prop:
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetPropLineSpace())));
itemNames.emplace_back("inter-line-space-prop" );
break ;
case SvxInterLineSpaceRule::Fix:
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetInterLineSpace())));
itemNames.emplace_back("inter-line-space-fix" );
break ;
}
attr = yinput_json_map(const_cast <char **>(itemNames.data()), itemArray.data(), itemArray.size());
attrName = "EE_PARA_SBL" ;
break ;
}
case EE_PARA_JUST:
{
SvxAdjustItem const & rItem{static_cast <SvxAdjustItem const &>(rItm)};
switch (rItem.GetAdjust())
{
case SvxAdjust::Left:
case SvxAdjust::Right:
case SvxAdjust::Center:
attr = yinput_long(uint64_t(rItem.GetAdjust()));
break ;
case SvxAdjust::Block:
switch (rItem.GetLastBlock())
{
case SvxAdjust::Left:
attr = yinput_long(uint64_t(SvxAdjust::Block));
break ;
case SvxAdjust::Center:
attr = yinput_long(uint64_t(5));
break ;
case SvxAdjust::Block:
attr = yinput_long(uint64_t(rItem.GetOneWord() == SvxAdjust::Block ? 7 : 6));
break ;
default :
assert(false );
}
break ;
default :
assert(false );
}
attrName = "EE_PARA_JUST" ;
break ;
}
case EE_PARA_TABS:
{
SvxTabStopItem const & rItem{static_cast <SvxTabStopItem const &>(rItm)};
itemNames.emplace_back("default-distance" );
itemArray.emplace_back(yinput_long(uint64_t(rItem.GetDefaultDistance())));
tabStopValues.reserve(rItem.Count()); // prevent realloc
for (decltype(rItem.Count()) i{0}; i < rItem.Count(); ++i)
{
SvxTabStop const & rTab{rItem.At(i)};
char const *const names[]{"pos" , "adjustment" , "decimal" , "fill" };
tabStopValues.emplace_back();
tabStopValues.back().emplace_back(yinput_long(uint64_t(rTab.GetTabPos())));
tabStopValues.back().emplace_back(yinput_long(uint64_t(rTab.GetAdjustment())));
tabStopValues.back().emplace_back(yinput_long(uint64_t(rTab.GetDecimal())));
tabStopValues.back().emplace_back(yinput_long(uint64_t(rTab.GetFill())));
tabStops.emplace_back(yinput_json_map(const_cast <char **>(names), tabStopValues.back().data(), 4));
}
itemNames.emplace_back("tab-stops" );
itemArray.emplace_back(yinput_json_array(tabStops.data(), tabStops.size()));
attr = yinput_json_map(const_cast <char **>(itemNames.data()), itemArray.data(), itemArray.size());
attrName = "EE_PARA_TABS" ;
break ;
}
case EE_PARA_JUST_METHOD:
{
SvxJustifyMethodItem const & rItem{static_cast <SvxJustifyMethodItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue()));
attrName = "EE_PARA_JUST_METHOD" ;
break ;
}
case EE_PARA_VER_JUST:
{
SvxVerJustifyItem const & rItem{static_cast <SvxVerJustifyItem const &>(rItm)};
attr = yinput_long(uint64_t(rItem.GetValue()));
attrName = "EE_PARA_VER_JUST" ;
break ;
}
// these aren't editable?
//constexpr TypedWhichId<SvXMLAttrContainerItem> EE_CHAR_XMLATTRIBS (EE_CHAR_START+27);
//constexpr TypedWhichId<SfxGrabBagItem> EE_CHAR_GRABBAG (EE_CHAR_START+30);
default :
assert(false );
}
assert(itemNames.size() == itemArray.size());
YInput const attrs{yinput_json_map(const_cast <char **>(&attrName), &attr, 1)};
ytext_format(yw.pText, yw.pTxn, nStart, nLen, &attrs);
}
void YrsInsertAttribImpl(YrsWrite const & yw, uint32_t const offset, EditCharAttrib const *const pAttr)
{
auto const start{offset + pAttr->GetStart()};
auto const len{pAttr->GetEnd() - pAttr->GetStart()};
YrsInsertAttribImplImpl(yw, *pAttr->GetItem(), start, len);
}
void YrsInsertFeature(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId,
EditDoc const & rDoc, uint32_t const index, EditCharAttrib const *const pAttr)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
i += pAttr->GetStart();
char const feature[]{ CH_FEATURE, '\0' };
switch (pAttr->Which())
{
case EE_FEATURE_TAB:
case EE_FEATURE_LINEBR:
{
YInput const type{yinput_string(pAttr->Which() == EE_FEATURE_TAB ? "tab" : "line" )};
YInput attrArray[]{ type };
char const *const attrNames[]{ "feature" };
YInput const attrs{yinput_json_map(const_cast <char **>(attrNames), attrArray, 1)};
ytext_insert(yw.pText, yw.pTxn, i, feature, &attrs);
break ;
}
case EE_FEATURE_FIELD:
{
SvxURLField const *const pURLField{dynamic_cast <SvxURLField const *>(dynamic_cast <SvxFieldItem const *>(pAttr->GetItem())->GetField())};
assert(pURLField);
YInput const type{yinput_string("url" )};
// ??? somehow this comes out as Y_JSON_NUM at the other end?
YInput const format{yinput_long(static_cast <int64_t>(pURLField->GetFormat()))};
OString const urlStr{OUStringToOString(pURLField->GetURL(), RTL_TEXTENCODING_UTF8)};
YInput const url{yinput_string(urlStr.getStr())};
OString const reprStr{OUStringToOString(pURLField->GetRepresentation(), RTL_TEXTENCODING_UTF8)};
YInput const representation{yinput_string(reprStr.getStr())};
OString const targetStr{OUStringToOString(pURLField->GetTargetFrame(), RTL_TEXTENCODING_UTF8)};
YInput const targetframe{yinput_string(targetStr.getStr())};
YInput attrArray[]{ type, format, url, representation, targetframe };
char const *const attrNames[]{ "feature" , "url-format" , "url-url" , "url-representation" , "url-targetframe" };
// don't use yinput_ymap for this!
YInput const attrs{yinput_json_map(const_cast <char **>(attrNames), attrArray, 5)};
ytext_insert(yw.pText, yw.pTxn, i, feature, &attrs);
break ;
}
default : // EE_FEATURE_NOTCONV appears unused?
assert(false );
}
}
void YrsAddPara(IYrsTransactionSupplier *const pYrsSupplier,
OString const & rCommentId, EditDoc const & rDoc, uint32_t const index)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
SAL_INFO("editeng.yrs" , "YRS YrsAddPara" );
// need to encode into 1 YText
char const para[]{ CH_PARA, '\0' };
uint32_t i{0};
// UTF-16 index should be equal to EditDoc one
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
ContentAttribs const & rParaAttribs{rDoc.GetObject(index)->GetContentAttribs()};
auto const pStyle{rParaAttribs.GetStyleSheet()};
if (pStyle)
{
OString const styleName{OUStringToOString(pStyle->GetName(), RTL_TEXTENCODING_UTF8)};
YInput const style{yinput_string(styleName.getStr())};
YInput attrArray[]{ style };
char const *const attrNames[]{ "para-style" };
YInput const attrs{yinput_json_map(const_cast <char **>(attrNames), attrArray, 1)};
ytext_insert(yw.pText, yw.pTxn, i, para, &attrs);
}
else
{
ytext_insert(yw.pText, yw.pTxn, i, para, nullptr);
}
for (SfxItemIter it{rParaAttribs.GetItems()}; !it.IsAtEnd(); it.NextItem())
{
YrsInsertAttribImplImpl(yw, *it.GetCurItem(), i, 1);
}
}
void YrsRemovePara(IYrsTransactionSupplier *const pYrsSupplier,
OString const & rCommentId, EditDoc const & rDoc, uint32_t const index)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
if (index != 0)
{
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
}
uint32_t const len(rDoc.GetObject(index)->Len() + 1);
ytext_remove_range(yw.pText, yw.pTxn, i, len);
}
void YrsClear(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
auto const len{ytext_len(yw.pText, yw.pTxn)};
ytext_remove_range(yw.pText, yw.pTxn, 0, len);
}
void YrsInsertParaBreak(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId,
EditDoc const & rDoc, uint32_t const index, uint32_t const content)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
// need to encode into 1 YText
char const para[]{ CH_PARA, '\0' };
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
i += content;
ContentAttribs const & rParaAttribs{rDoc.GetObject(index)->GetContentAttribs()};
OString const styleName{OUStringToOString(rParaAttribs.GetStyleSheet()->GetName(), RTL_TEXTENCODING_UTF8)};
YInput const style{yinput_string(styleName.getStr())};
YInput attrArray[]{ style };
char const *const attrNames[]{ "para-style" };
YInput const attrs{yinput_json_map(const_cast <char **>(attrNames), attrArray, 1)};
ytext_insert(yw.pText, yw.pTxn, i, para, &attrs);
for (SfxItemIter it{rParaAttribs.GetItems()}; !it.IsAtEnd(); it.NextItem())
{
YrsInsertAttribImplImpl(yw, *it.GetCurItem(), i, 1);
}
}
void YrsInsertText(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId,
EditDoc const & rDoc, uint32_t const index, uint32_t const content, ::std::u16string_view const rText)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
i += content;
OString const text{::rtl::OUStringToOString(rText, RTL_TEXTENCODING_UTF8)};
ytext_insert(yw.pText, yw.pTxn, i, text.getStr(), nullptr);
}
void YrsConnectPara(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId,
EditDoc const & rDoc, uint32_t const index, uint32_t const pos)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
i += pos;
ytext_remove_range(yw.pText, yw.pTxn, i, 1);
}
void YrsRemoveChars(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId,
EditDoc const & rDoc, uint32_t const index, uint32_t const content, uint32_t const length)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
i += content;
ytext_remove_range(yw.pText, yw.pTxn, i, length);
}
void YrsSetStyle(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId,
EditDoc const & rDoc, uint32_t const index, ::std::u16string_view const rStyle)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
i += rDoc.GetObject(index)->Len();
OString const styleName{OUStringToOString(rStyle, RTL_TEXTENCODING_UTF8)};
YInput const style{yinput_string(styleName.getStr())};
YInput attrArray[]{ style };
char const *const attrNames[]{ "para-style" };
YInput const attrs{yinput_json_map(const_cast <char **>(attrNames), attrArray, 1)};
ytext_format(yw.pText, yw.pTxn, i, 1, &attrs);
}
void YrsSetParaAttr(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId,
EditDoc const & rDoc, uint32_t const index, SfxPoolItem const & rItem)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
i += rDoc.GetObject(index)->Len();
YrsInsertAttribImplImpl(yw, rItem, i, 1);
}
char const * YrsWhichToAttrName(sal_Int16 const nWhich)
{
switch (nWhich)
{
case EE_CHAR_COLOR:
return "EE_CHAR_COLOR" ;
case EE_CHAR_BKGCOLOR:
return "EE_CHAR_BKGCOLOR" ;
case EE_CHAR_FONTINFO:
return "EE_CHAR_FONTINFO" ;
case EE_CHAR_FONTINFO_CJK:
return "EE_CHAR_FONTINFO_CJK" ;
case EE_CHAR_FONTINFO_CTL:
return "EE_CHAR_FONTINFO_CTL" ;
case EE_CHAR_FONTHEIGHT:
return "EE_CHAR_FONTHEIGHT" ;
case EE_CHAR_FONTHEIGHT_CJK:
return "EE_CHAR_FONTHEIGHT_CJK" ;
case EE_CHAR_FONTHEIGHT_CTL:
return "EE_CHAR_FONTHEIGHT_CTL" ;
case EE_CHAR_FONTWIDTH:
return "EE_CHAR_FONTWIDTH" ;
case EE_CHAR_WEIGHT:
return "EE_CHAR_WEIGHT" ;
case EE_CHAR_WEIGHT_CJK:
return "EE_CHAR_WEIGHT_CJK" ;
case EE_CHAR_WEIGHT_CTL:
return "EE_CHAR_WEIGHT_CTL" ;
case EE_CHAR_UNDERLINE:
return "EE_CHAR_UNDERLINE" ;
case EE_CHAR_OVERLINE:
return "EE_CHAR_OVERLINE" ;
case EE_CHAR_STRIKEOUT:
return "EE_CHAR_STRIKEOUT" ;
case EE_CHAR_ITALIC:
return "EE_CHAR_ITALIC" ;
case EE_CHAR_ITALIC_CJK:
return "EE_CHAR_ITALIC_CJK" ;
case EE_CHAR_ITALIC_CTL:
return "EE_CHAR_ITALIC_CTL" ;
case EE_CHAR_OUTLINE:
return "EE_CHAR_OUTLINE" ;
case EE_CHAR_SHADOW:
return "EE_CHAR_SHADOW" ;
case EE_CHAR_ESCAPEMENT:
return "EE_CHAR_ESCAPEMENT" ;
case EE_CHAR_PAIRKERNING:
return "EE_CHAR_PAIRKERNING" ;
case EE_CHAR_KERNING:
return "EE_CHAR_KERNING" ;
case EE_CHAR_WLM:
return "EE_CHAR_WLM" ;
case EE_CHAR_LANGUAGE:
return "EE_CHAR_LANGUAGE" ;
case EE_CHAR_LANGUAGE_CJK:
return "EE_CHAR_LANGUAGE_CJK" ;
case EE_CHAR_LANGUAGE_CTL:
return "EE_CHAR_LANGUAGE_CTL" ;
case EE_CHAR_EMPHASISMARK:
return "EE_CHAR_EMPHASISMARK" ;
case EE_CHAR_RELIEF:
return "EE_CHAR_RELIEF" ;
case EE_CHAR_CASEMAP:
return "EE_CHAR_CASEMAP" ;
case EE_PARA_WRITINGDIR:
return "EE_PARA_WRITINGDIR" ;
case EE_PARA_HANGINGPUNCTUATION:
return "EE_PARA_HANGINGPUNCTUATION" ;
case EE_PARA_FORBIDDENRULES:
return "EE_PARA_FORBIDDENRULES" ;
case EE_PARA_ASIANCJKSPACING:
return "EE_PARA_ASIANCJKSPACING" ;
//TODO complex, but apparently no way to set this in comment? inline constexpr TypedWhichId<SvxNumBulletItem> EE_PARA_NUMBULLET (EE_PARA_START+5);
case EE_PARA_HYPHENATE:
return "EE_PARA_HYPHENATE" ;
case EE_PARA_HYPHENATE_NO_CAPS:
return "EE_PARA_HYPHENATE_NO_CAPS" ;
case EE_PARA_HYPHENATE_NO_LAST_WORD:
return "EE_PARA_HYPHENATE_NO_LAST_WORD" ;
case EE_PARA_BULLETSTATE:
return "EE_PARA_BULLETSTATE" ;
//TODO no way to set this in comment? inline constexpr TypedWhichId<SvxLRSpaceItem> EE_PARA_OUTLLRSPACE (EE_PARA_START+10);
case EE_PARA_OUTLLEVEL:
return "EE_PARA_OUTLLEVEL" ;
//TODO complex, but apparently no way to set this in comment? inline constexpr TypedWhichId<SvxBulletItem> EE_PARA_BULLET (EE_PARA_START+12);
case EE_PARA_LRSPACE:
return "EE_PARA_LRSPACE" ;
case EE_PARA_ULSPACE:
return "EE_PARA_ULSPACE" ;
case EE_PARA_SBL:
return "EE_PARA_SBL" ;
case EE_PARA_JUST:
return "EE_PARA_JUST" ;
case EE_PARA_TABS:
return "EE_PARA_TABS" ;
case EE_PARA_JUST_METHOD:
return "EE_PARA_JUST_METHOD" ;
case EE_PARA_VER_JUST:
return "EE_PARA_VER_JUST" ;
default :
assert(false );
}
}
void YrsRemoveAttrib(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId,
EditDoc const & rDoc, uint32_t const index, sal_uInt16 const nWhich, sal_Int32 const nStart, sal_Int32 const nEnd)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
YInput const attr{yinput_null()};
char const *const attrName{YrsWhichToAttrName(nWhich)};
YInput const attrs{yinput_json_map(const_cast <char **>(&attrName), const_cast <YInput*>(&attr), 1)};
ytext_format(yw.pText, yw.pTxn, i + nStart, nEnd - nStart, &attrs);
}
void YrsInsertAttrib(IYrsTransactionSupplier *const pYrsSupplier, OString const & rCommentId, EditDoc const & rDoc, uint32_t const index, EditCharAttrib const *const pAttr)
{
YrsWrite const yw{GetYrsWrite(pYrsSupplier, rCommentId)};
if (yw.pTxn == nullptr)
{
return ;
}
uint32_t i{0};
for (auto paras{index}; paras != 0; --paras)
{
i += rDoc.GetObject(paras-1)->Len() + 1;
}
YrsInsertAttribImpl(yw, i, pAttr);
}
uint64_t YrsReadInt(YOutput const & rValue)
{
// with the v1 encoding, JSON is being sent apparently (like "family":2) , which has issues with integers being sometimes read as floats so workaround here
if (rValue.tag == Y_JSON_INT)
{
return rValue.value.integer;
}
else
{
yvalidate(rValue.tag == Y_JSON_NUM);
return ::std::lround(rValue.value.num);
}
}
void YrsImplInsertAttr(SfxItemSet & rSet, ::std::vector<sal_uInt16> *const pRemoved,
char const *const pKey, YOutput const & rValue)
{
sal_uInt16 nWhich{0};
if (strcmp(pKey, "EE_CHAR_COLOR" ) == 0)
{
nWhich = EE_CHAR_COLOR;
}
else if (strcmp(pKey, "EE_CHAR_BKGCOLOR" ) == 0)
{
nWhich = EE_CHAR_BKGCOLOR;
}
else if (strcmp(pKey, "EE_CHAR_FONTINFO" ) == 0)
{
nWhich = EE_CHAR_FONTINFO;
}
else if (strcmp(pKey, "EE_CHAR_FONTINFO_CJK" ) == 0)
{
nWhich = EE_CHAR_FONTINFO_CJK;
}
else if (strcmp(pKey, "EE_CHAR_FONTINFO_CTL" ) == 0)
{
nWhich = EE_CHAR_FONTINFO_CTL;
}
else if (strcmp(pKey, "EE_CHAR_FONTHEIGHT" ) == 0)
{
nWhich = EE_CHAR_FONTHEIGHT;
}
else if (strcmp(pKey, "EE_CHAR_FONTHEIGHT_CJK" ) == 0)
{
nWhich = EE_CHAR_FONTHEIGHT_CJK;
}
else if (strcmp(pKey, "EE_CHAR_FONTHEIGHT_CTL" ) == 0)
{
nWhich = EE_CHAR_FONTHEIGHT_CTL;
}
else if (strcmp(pKey, "EE_CHAR_FONTWIDTH" ) == 0)
{
nWhich = EE_CHAR_FONTWIDTH;
}
else if (strcmp(pKey, "EE_CHAR_WEIGHT" ) == 0)
{
nWhich = EE_CHAR_WEIGHT;
}
else if (strcmp(pKey, "EE_CHAR_WEIGHT_CJK" ) == 0)
{
nWhich = EE_CHAR_WEIGHT_CJK;
}
else if (strcmp(pKey, "EE_CHAR_WEIGHT_CTL" ) == 0)
{
nWhich = EE_CHAR_WEIGHT_CTL;
}
else if (strcmp(pKey, "EE_CHAR_UNDERLINE" ) == 0)
{
nWhich = EE_CHAR_UNDERLINE;
}
else if (strcmp(pKey, "EE_CHAR_OVERLINE" ) == 0)
{
nWhich = EE_CHAR_OVERLINE;
}
else if (strcmp(pKey, "EE_CHAR_STRIKEOUT" ) == 0)
{
nWhich = EE_CHAR_STRIKEOUT;
}
else if (strcmp(pKey, "EE_CHAR_ITALIC" ) == 0)
{
nWhich = EE_CHAR_ITALIC;
}
else if (strcmp(pKey, "EE_CHAR_ITALIC_CJK" ) == 0)
{
nWhich = EE_CHAR_ITALIC_CJK;
}
else if (strcmp(pKey, "EE_CHAR_ITALIC_CTL" ) == 0)
{
nWhich = EE_CHAR_ITALIC_CTL;
}
else if (strcmp(pKey, "EE_CHAR_OUTLINE" ) == 0)
{
nWhich = EE_CHAR_OUTLINE;
}
else if (strcmp(pKey, "EE_CHAR_SHADOW" ) == 0)
{
nWhich = EE_CHAR_SHADOW;
}
else if (strcmp(pKey, "EE_CHAR_ESCAPEMENT" ) == 0)
{
nWhich = EE_CHAR_ESCAPEMENT;
}
else if (strcmp(pKey, "EE_CHAR_PAIRKERNING" ) == 0)
{
nWhich = EE_CHAR_PAIRKERNING;
}
else if (strcmp(pKey, "EE_CHAR_KERNING" ) == 0)
{
nWhich = EE_CHAR_KERNING;
}
else if (strcmp(pKey, "EE_CHAR_WLM" ) == 0)
{
nWhich = EE_CHAR_WLM;
}
else if (strcmp(pKey, "EE_CHAR_LANGUAGE" ) == 0)
{
nWhich = EE_CHAR_LANGUAGE;
}
else if (strcmp(pKey, "EE_CHAR_LANGUAGE_CJK" ) == 0)
{
nWhich = EE_CHAR_LANGUAGE_CJK;
}
else if (strcmp(pKey, "EE_CHAR_LANGUAGE_CTL" ) == 0)
{
nWhich = EE_CHAR_LANGUAGE_CTL;
}
else if (strcmp(pKey, "EE_CHAR_EMPHASISMARK" ) == 0)
{
nWhich = EE_CHAR_EMPHASISMARK;
}
else if (strcmp(pKey, "EE_CHAR_RELIEF" ) == 0)
{
nWhich = EE_CHAR_RELIEF;
}
else if (strcmp(pKey, "EE_CHAR_CASEMAP" ) == 0)
{
nWhich = EE_CHAR_CASEMAP;
}
else if (strcmp(pKey, "EE_PARA_WRITINGDIR" ) == 0)
{
nWhich = EE_PARA_WRITINGDIR;
}
else if (strcmp(pKey, "EE_PARA_HANGINGPUNCTUATION" ) == 0)
{
nWhich = EE_PARA_HANGINGPUNCTUATION;
}
else if (strcmp(pKey, "EE_PARA_FORBIDDENRULES" ) == 0)
{
nWhich = EE_PARA_FORBIDDENRULES;
}
else if (strcmp(pKey, "EE_PARA_ASIANCJKSPACING" ) == 0)
{
nWhich = EE_PARA_ASIANCJKSPACING;
}
else if (strcmp(pKey, "EE_PARA_HYPHENATE" ) == 0)
{
nWhich = EE_PARA_HYPHENATE;
}
else if (strcmp(pKey, "EE_PARA_HYPHENATE_NO_CAPS" ) == 0)
{
nWhich = EE_PARA_HYPHENATE_NO_CAPS;
}
else if (strcmp(pKey, "EE_PARA_HYPHENATE_NO_LAST_WORD" ) == 0)
{
nWhich = EE_PARA_HYPHENATE_NO_LAST_WORD;
}
else if (strcmp(pKey, "EE_PARA_BULLETSTATE" ) == 0)
{
nWhich = EE_PARA_BULLETSTATE;
}
else if (strcmp(pKey, "EE_PARA_OUTLLEVEL" ) == 0)
{
nWhich = EE_PARA_OUTLLEVEL;
}
else if (strcmp(pKey, "EE_PARA_LRSPACE" ) == 0)
{
nWhich = EE_PARA_LRSPACE;
}
else if (strcmp(pKey, "EE_PARA_ULSPACE" ) == 0)
{
nWhich = EE_PARA_ULSPACE;
}
else if (strcmp(pKey, "EE_PARA_SBL" ) == 0)
{
nWhich = EE_PARA_SBL;
}
else if (strcmp(pKey, "EE_PARA_JUST" ) == 0)
{
nWhich = EE_PARA_JUST;
}
else if (strcmp(pKey, "EE_PARA_TABS" ) == 0)
{
nWhich = EE_PARA_TABS;
}
else if (strcmp(pKey, "EE_PARA_JUST_METHOD" ) == 0)
{
nWhich = EE_PARA_JUST_METHOD;
}
else if (strcmp(pKey, "EE_PARA_VER_JUST" ) == 0)
{
nWhich = EE_PARA_VER_JUST;
}
else if (pKey[0] == 'E' && pKey[1] == 'E' && pKey[2] == '_' )
{
abort();
}
else
{
return ;
}
if (rValue.tag == Y_JSON_NULL)
{
assert(pRemoved);
if (pRemoved)
{
pRemoved->emplace_back(nWhich);
}
return ;
}
else switch (nWhich)
{
case EE_CHAR_COLOR:
case EE_CHAR_BKGCOLOR:
{
Color const c(ColorTransparency, YrsReadInt(rValue));
SvxColorItem const item(c, nWhich);
rSet.Put(item);
break ;
}
case EE_CHAR_FONTINFO:
case EE_CHAR_FONTINFO_CJK:
case EE_CHAR_FONTINFO_CTL:
{
yvalidate(rValue.tag == Y_JSON_MAP);
::std::optional<OUString> oFamilyName;
::std::optional<OUString> oStyle;
::std::optional<FontFamily> oFamily;
::std::optional<FontPitch> oPitch;
::std::optional<rtl_TextEncoding> oCharset;
for (decltype(rValue.len) i = 0; i < rValue.len; ++i)
{
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=96 H=96 G=95
¤ Dauer der Verarbeitung: 0.33 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland