diff options
Diffstat (limited to 'editeng/source/editeng/editdoc.cxx')
-rw-r--r-- | editeng/source/editeng/editdoc.cxx | 1895 |
1 files changed, 176 insertions, 1719 deletions
diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx index e1a9c91e3ee5..e482eea38652 100644 --- a/editeng/source/editeng/editdoc.cxx +++ b/editeng/source/editeng/editdoc.cxx @@ -50,19 +50,23 @@ #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; @@ -153,456 +157,230 @@ bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType ) return bValid; } -const SfxItemInfo aItemInfos[EDITITEMCOUNT] = { - { SID_ATTR_FRAMEDIRECTION, true }, // EE_PARA_WRITINGDIR - { 0, true }, // EE_PARA_XMLATTRIBS - { SID_ATTR_PARA_HANGPUNCTUATION, true }, // EE_PARA_HANGINGPUNCTUATION - { SID_ATTR_PARA_FORBIDDEN_RULES, true }, // EE_PARA_FORBIDDENRULES - { SID_ATTR_PARA_SCRIPTSPACE, true }, // EE_PARA_ASIANCJKSPACING - { SID_ATTR_NUMBERING_RULE, true }, // EE_PARA_NUMBULL - { 0, true }, // EE_PARA_HYPHENATE - { 0, true }, // EE_PARA_HYPHENATE_NO_CAPS - { 0, true }, // EE_PARA_BULLETSTATE - { 0, true }, // EE_PARA_OUTLLRSPACE - { SID_ATTR_PARA_OUTLLEVEL, true }, // EE_PARA_OUTLLEVEL - { SID_ATTR_PARA_BULLET, true }, // EE_PARA_BULLET - { SID_ATTR_LRSPACE, true }, // EE_PARA_LRSPACE - { SID_ATTR_ULSPACE, true }, // EE_PARA_ULSPACE - { SID_ATTR_PARA_LINESPACE, true }, // EE_PARA_SBL - { SID_ATTR_PARA_ADJUST, true }, // EE_PARA_JUST - { SID_ATTR_TABSTOP, true }, // EE_PARA_TABS - { SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, true }, // EE_PARA_JUST_METHOD - { SID_ATTR_ALIGN_VER_JUSTIFY, true }, // EE_PARA_VER_JUST - { SID_ATTR_CHAR_COLOR, true }, // EE_CHAR_COLOR - { SID_ATTR_CHAR_FONT, true }, // EE_CHAR_FONTINFO - { SID_ATTR_CHAR_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT - { SID_ATTR_CHAR_SCALEWIDTH, true }, // EE_CHAR_FONTWIDTH - { SID_ATTR_CHAR_WEIGHT, true }, // EE_CHAR_WEIGHT - { SID_ATTR_CHAR_UNDERLINE, true }, // EE_CHAR_UNDERLINE - { SID_ATTR_CHAR_STRIKEOUT, true }, // EE_CHAR_STRIKEOUT - { SID_ATTR_CHAR_POSTURE, true }, // EE_CHAR_ITALIC - { SID_ATTR_CHAR_CONTOUR, true }, // EE_CHAR_OUTLINE - { SID_ATTR_CHAR_SHADOWED, true }, // EE_CHAR_SHADOW - { SID_ATTR_CHAR_ESCAPEMENT, true }, // EE_CHAR_ESCAPEMENT - { SID_ATTR_CHAR_AUTOKERN, true }, // EE_CHAR_PAIRKERNING - { SID_ATTR_CHAR_KERNING, true }, // EE_CHAR_KERNING - { SID_ATTR_CHAR_WORDLINEMODE, true }, // EE_CHAR_WLM - { SID_ATTR_CHAR_LANGUAGE, true }, // EE_CHAR_LANGUAGE - { SID_ATTR_CHAR_CJK_LANGUAGE, true }, // EE_CHAR_LANGUAGE_CJK - { SID_ATTR_CHAR_CTL_LANGUAGE, true }, // EE_CHAR_LANGUAGE_CTL - { SID_ATTR_CHAR_CJK_FONT, true }, // EE_CHAR_FONTINFO_CJK - { SID_ATTR_CHAR_CTL_FONT, true }, // EE_CHAR_FONTINFO_CTL - { SID_ATTR_CHAR_CJK_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT_CJK - { SID_ATTR_CHAR_CTL_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT_CTL - { SID_ATTR_CHAR_CJK_WEIGHT, true }, // EE_CHAR_WEIGHT_CJK - { SID_ATTR_CHAR_CTL_WEIGHT, true }, // EE_CHAR_WEIGHT_CTL - { SID_ATTR_CHAR_CJK_POSTURE, true }, // EE_CHAR_ITALIC_CJK - { SID_ATTR_CHAR_CTL_POSTURE, true }, // EE_CHAR_ITALIC_CTL - { SID_ATTR_CHAR_EMPHASISMARK, true }, // EE_CHAR_EMPHASISMARK - { SID_ATTR_CHAR_RELIEF, true }, // EE_CHAR_RELIEF - { 0, true }, // EE_CHAR_RUBI_DUMMY - { 0, true }, // EE_CHAR_XMLATTRIBS - { SID_ATTR_CHAR_OVERLINE, true }, // EE_CHAR_OVERLINE - { SID_ATTR_CHAR_CASEMAP, true }, // EE_CHAR_CASEMAP - { SID_ATTR_CHAR_GRABBAG, true }, // EE_CHAR_GRABBAG - { SID_ATTR_CHAR_BACK_COLOR, true }, // EE_CHAR_BKGCOLOR - { 0, true }, // EE_FEATURE_TAB - { 0, true }, // EE_FEATURE_LINEBR - { SID_ATTR_CHAR_CHARSETCOLOR, true }, // EE_FEATURE_NOTCONV - { SID_FIELD, false }, // EE_FEATURE_FIELD -}; - EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE ) { // Create a new attribute in the pool - const SfxPoolItem& rNew = rPool.Put( rAttr ); - - EditCharAttrib* pNew = nullptr; - switch( rNew.Which() ) + switch( rAttr.Which() ) { case EE_CHAR_LANGUAGE: case EE_CHAR_LANGUAGE_CJK: case EE_CHAR_LANGUAGE_CTL: { - pNew = new EditCharAttribLanguage( static_cast<const SvxLanguageItem&>(rNew), nS, nE ); + return new EditCharAttribLanguage(rPool, rAttr, nS, nE); } break; case EE_CHAR_COLOR: { - pNew = new EditCharAttribColor( static_cast<const SvxColorItem&>(rNew), nS, nE ); + return new EditCharAttribColor(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTINFO: case EE_CHAR_FONTINFO_CJK: case EE_CHAR_FONTINFO_CTL: { - pNew = new EditCharAttribFont( static_cast<const SvxFontItem&>(rNew), nS, nE ); + return new EditCharAttribFont(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTHEIGHT: case EE_CHAR_FONTHEIGHT_CJK: case EE_CHAR_FONTHEIGHT_CTL: { - pNew = new EditCharAttribFontHeight( static_cast<const SvxFontHeightItem&>(rNew), nS, nE ); + return new EditCharAttribFontHeight(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTWIDTH: { - pNew = new EditCharAttribFontWidth( static_cast<const SvxCharScaleWidthItem&>(rNew), nS, nE ); + return new EditCharAttribFontWidth(rPool, rAttr, nS, nE ); } break; case EE_CHAR_WEIGHT: case EE_CHAR_WEIGHT_CJK: case EE_CHAR_WEIGHT_CTL: { - pNew = new EditCharAttribWeight( static_cast<const SvxWeightItem&>(rNew), nS, nE ); + return new EditCharAttribWeight(rPool, rAttr, nS, nE ); } break; case EE_CHAR_UNDERLINE: { - pNew = new EditCharAttribUnderline( static_cast<const SvxUnderlineItem&>(rNew), nS, nE ); + return new EditCharAttribUnderline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_OVERLINE: { - pNew = new EditCharAttribOverline( static_cast<const SvxOverlineItem&>(rNew), nS, nE ); + return new EditCharAttribOverline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_EMPHASISMARK: { - pNew = new EditCharAttribEmphasisMark( static_cast<const SvxEmphasisMarkItem&>(rNew), nS, nE ); + return new EditCharAttribEmphasisMark(rPool, rAttr, nS, nE ); } break; case EE_CHAR_RELIEF: { - pNew = new EditCharAttribRelief( static_cast<const SvxCharReliefItem&>(rNew), nS, nE ); + return new EditCharAttribRelief(rPool, rAttr, nS, nE ); } break; case EE_CHAR_STRIKEOUT: { - pNew = new EditCharAttribStrikeout( static_cast<const SvxCrossedOutItem&>(rNew), nS, nE ); + return new EditCharAttribStrikeout(rPool, rAttr, nS, nE ); } break; case EE_CHAR_ITALIC: case EE_CHAR_ITALIC_CJK: case EE_CHAR_ITALIC_CTL: { - pNew = new EditCharAttribItalic( static_cast<const SvxPostureItem&>(rNew), nS, nE ); + return new EditCharAttribItalic(rPool, rAttr, nS, nE ); } break; case EE_CHAR_OUTLINE: { - pNew = new EditCharAttribOutline( static_cast<const SvxContourItem&>(rNew), nS, nE ); + return new EditCharAttribOutline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_SHADOW: { - pNew = new EditCharAttribShadow( static_cast<const SvxShadowedItem&>(rNew), nS, nE ); + return new EditCharAttribShadow(rPool, rAttr, nS, nE ); } break; case EE_CHAR_ESCAPEMENT: { - pNew = new EditCharAttribEscapement( static_cast<const SvxEscapementItem&>(rNew), nS, nE ); + return new EditCharAttribEscapement(rPool, rAttr, nS, nE ); } break; case EE_CHAR_PAIRKERNING: { - pNew = new EditCharAttribPairKerning( static_cast<const SvxAutoKernItem&>(rNew), nS, nE ); + return new EditCharAttribPairKerning(rPool, rAttr, nS, nE ); } break; case EE_CHAR_KERNING: { - pNew = new EditCharAttribKerning( static_cast<const SvxKerningItem&>(rNew), nS, nE ); + return new EditCharAttribKerning(rPool, rAttr, nS, nE ); } break; case EE_CHAR_WLM: { - pNew = new EditCharAttribWordLineMode( static_cast<const SvxWordLineModeItem&>(rNew), nS, nE ); + return new EditCharAttribWordLineMode(rPool, rAttr, nS, nE ); } break; case EE_CHAR_XMLATTRIBS: { - pNew = new EditCharAttrib( rNew, nS, nE ); // Attribute is only for holding XML information... + return new EditCharAttrib(rPool, rAttr, nS, nE); // Attribute is only for holding XML information... } break; case EE_CHAR_CASEMAP: { - pNew = new EditCharAttribCaseMap( static_cast<const SvxCaseMapItem&>(rNew), nS, nE ); + return new EditCharAttribCaseMap(rPool, rAttr, nS, nE ); } break; case EE_CHAR_GRABBAG: { - pNew = new EditCharAttribGrabBag( static_cast<const SfxGrabBagItem&>(rNew), nS, nE ); + return new EditCharAttribGrabBag(rPool, rAttr, nS, nE ); } break; case EE_FEATURE_TAB: { - pNew = new EditCharAttribTab( static_cast<const SfxVoidItem&>(rNew), nS ); + return new EditCharAttribTab(rPool, rAttr, nS ); } break; case EE_FEATURE_LINEBR: { - pNew = new EditCharAttribLineBreak( static_cast<const SfxVoidItem&>(rNew), nS ); + return new EditCharAttribLineBreak(rPool, rAttr, nS ); } break; case EE_FEATURE_FIELD: { - pNew = new EditCharAttribField( static_cast<const SvxFieldItem&>(rNew), nS ); + return new EditCharAttribField(rPool, rAttr, nS ); } break; case EE_CHAR_BKGCOLOR: { - pNew = new EditCharAttribBackgroundColor( static_cast<const SvxBackgroundColorItem&>(rNew), nS, nE ); + return new EditCharAttribBackgroundColor(rPool, rAttr, nS, nE ); } break; default: - { - OSL_FAIL( "Invalid Attribute!" ); - } - } - return pNew; -} - -TextPortionList::TextPortionList() -{ -} - -TextPortionList::~TextPortionList() -{ - Reset(); -} - -void TextPortionList::Reset() -{ - maPortions.clear(); -} - -void TextPortionList::DeleteFromPortion(sal_Int32 nDelFrom) -{ - assert((nDelFrom < static_cast<sal_Int32>(maPortions.size())) || ((nDelFrom == 0) && maPortions.empty())); - PortionsType::iterator it = maPortions.begin(); - std::advance(it, nDelFrom); - maPortions.erase(it, maPortions.end()); -} - -sal_Int32 TextPortionList::Count() const -{ - return static_cast<sal_Int32>(maPortions.size()); -} - -const TextPortion& TextPortionList::operator[](sal_Int32 nPos) const -{ - return *maPortions[nPos]; -} - -TextPortion& TextPortionList::operator[](sal_Int32 nPos) -{ - return *maPortions[nPos]; -} - -void TextPortionList::Append(TextPortion* p) -{ - maPortions.push_back(std::unique_ptr<TextPortion>(p)); -} - -void TextPortionList::Insert(sal_Int32 nPos, TextPortion* p) -{ - maPortions.insert(maPortions.begin()+nPos, std::unique_ptr<TextPortion>(p)); -} - -void TextPortionList::Remove(sal_Int32 nPos) -{ - maPortions.erase(maPortions.begin()+nPos); -} - -namespace { - -class FindTextPortionByAddress -{ - const TextPortion* mp; -public: - explicit FindTextPortionByAddress(const TextPortion* p) : mp(p) {} - bool operator() (const std::unique_ptr<TextPortion>& v) const - { - return v.get() == mp; - } -}; - -} - -sal_Int32 TextPortionList::GetPos(const TextPortion* p) const -{ - PortionsType::const_iterator it = - std::find_if(maPortions.begin(), maPortions.end(), FindTextPortionByAddress(p)); - - if (it == maPortions.end()) - return std::numeric_limits<sal_Int32>::max(); // not found. - - return std::distance(maPortions.begin(), it); -} - -sal_Int32 TextPortionList::FindPortion( - sal_Int32 nCharPos, sal_Int32& nPortionStart, bool bPreferStartingPortion) const -{ - // When nCharPos at portion limit, the left portion is found - sal_Int32 nTmpPos = 0; - sal_Int32 n = maPortions.size(); - for (sal_Int32 i = 0; i < n; ++i) - { - const TextPortion& rPortion = *maPortions[i]; - nTmpPos = nTmpPos + rPortion.GetLen(); - if ( nTmpPos >= nCharPos ) - { - // take this one if we don't prefer the starting portion, or if it's the last one - if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( i == n-1 ) ) - { - nPortionStart = nTmpPos - rPortion.GetLen(); - return i; - } - } - } - OSL_FAIL( "FindPortion: Not found!" ); - return n - 1; -} - -sal_Int32 TextPortionList::GetStartPos(sal_Int32 nPortion) -{ - sal_Int32 nPos = 0; - for (sal_Int32 i = 0; i < nPortion; ++i) - { - const TextPortion& rPortion = *maPortions[i]; - nPos = nPos + rPortion.GetLen(); - } - return nPos; -} - -ExtraPortionInfo::ExtraPortionInfo() -: nOrgWidth(0) -, nWidthFullCompression(0) -, nPortionOffsetX(0) -, nMaxCompression100thPercent(0) -, nAsianCompressionTypes(AsianCompressionFlags::Normal) -, bFirstCharIsRightPunktuation(false) -, bCompressed(false) -, lineBreaksList() -{ -} - -ExtraPortionInfo::~ExtraPortionInfo() -{ -} - -void ExtraPortionInfo::SaveOrgDXArray( const tools::Long* pDXArray, sal_Int32 nLen ) -{ - if (pDXArray) - { - pOrgDXArray.reset(new tools::Long[nLen]); - memcpy( pOrgDXArray.get(), pDXArray, nLen * sizeof(tools::Long) ); + break; } - else - pOrgDXArray.reset(); -} - -ParaPortion::ParaPortion( ContentNode* pN ) : - pNode(pN), - nHeight(0), - nInvalidPosStart(0), - nFirstLineOffset(0), - nBulletX(0), - nInvalidDiff(0), - bInvalid(true), - bSimple(false), - bVisible(true), - bForceRepaint(false) -{ -} -ParaPortion::~ParaPortion() -{ + OSL_FAIL( "Invalid Attribute!" ); + return nullptr; } -void ParaPortion::MarkInvalid( sal_Int32 nStart, sal_Int32 nDiff ) +void ParaPortion::MarkInvalid(sal_Int32 nStart, sal_Int32 nDiff) { - if ( !bInvalid ) + if (!mbInvalid) { -// nInvalidPosEnd = nStart; // ??? => CreateLines - nInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff ); - nInvalidDiff = nDiff; +// mnInvalidPosEnd = nStart; // ??? => CreateLines + mnInvalidPosStart = nDiff >= 0 ? nStart : nStart + nDiff; + mnInvalidDiff = nDiff; } else { // Simple tap in succession - if ( ( nDiff > 0 ) && ( nInvalidDiff > 0 ) && - ( ( nInvalidPosStart+nInvalidDiff ) == nStart ) ) + if (nDiff > 0 && mnInvalidDiff > 0 && (mnInvalidPosStart + mnInvalidDiff) == nStart) { - nInvalidDiff = nInvalidDiff + nDiff; + mnInvalidDiff = mnInvalidDiff + nDiff; } // Simple delete in succession - else if ( ( nDiff < 0 ) && ( nInvalidDiff < 0 ) && ( nInvalidPosStart == nStart ) ) + else if (nDiff < 0 && mnInvalidDiff < 0 && mnInvalidPosStart == nStart) { - nInvalidPosStart = nInvalidPosStart + nDiff; - nInvalidDiff = nInvalidDiff + nDiff; + mnInvalidPosStart = mnInvalidPosStart + nDiff; + mnInvalidDiff = mnInvalidDiff + nDiff; } else { -// nInvalidPosEnd = pNode->Len(); - DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" ); - nInvalidPosStart = std::min( nInvalidPosStart, ( nDiff < 0 ? nStart+nDiff : nDiff ) ); - nInvalidDiff = 0; - bSimple = false; +// 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; } } - bInvalid = true; - aScriptInfos.clear(); - aWritingDirectionInfos.clear(); + mbInvalid = true; + maScriptInfos.clear(); + maWritingDirectionInfos.clear(); } -void ParaPortion::MarkSelectionInvalid( sal_Int32 nStart ) +void ParaPortion::MarkSelectionInvalid(sal_Int32 nStart) { - if ( !bInvalid ) + if ( !mbInvalid ) { - nInvalidPosStart = nStart; + mnInvalidPosStart = nStart; } else { - nInvalidPosStart = std::min( nInvalidPosStart, nStart ); + mnInvalidPosStart = std::min(mnInvalidPosStart, nStart); } - nInvalidDiff = 0; - bInvalid = true; - bSimple = false; - aScriptInfos.clear(); - aWritingDirectionInfos.clear(); + mnInvalidDiff = 0; + mbInvalid = true; + mbSimple = false; + maScriptInfos.clear(); + maWritingDirectionInfos.clear(); } sal_Int32 ParaPortion::GetLineNumber( sal_Int32 nIndex ) const { - SAL_WARN_IF( !aLineList.Count(), "editeng", "Empty ParaPortion in GetLine!" ); - DBG_ASSERT( bVisible, "Why GetLine() on an invisible paragraph?" ); + SAL_WARN_IF(!maLineList.Count(), "editeng", "Empty ParaPortion in GetLine!"); + DBG_ASSERT(mbVisible, "Why GetLine() on an invisible paragraph?"); - for ( sal_Int32 nLine = 0; nLine < aLineList.Count(); nLine++ ) + for ( sal_Int32 nLine = 0; nLine < maLineList.Count(); nLine++ ) { - if ( aLineList[nLine].IsIn( nIndex ) ) + if (maLineList[nLine].IsIn(nIndex)) return nLine; } // Then it should be at the end of the last line! - DBG_ASSERT( nIndex == aLineList[ aLineList.Count() - 1 ].GetEnd(), "Index dead wrong!" ); - return (aLineList.Count()-1); -} - -void ParaPortion::SetVisible( bool bMakeVisible ) -{ - bVisible = bMakeVisible; + DBG_ASSERT(nIndex == maLineList[maLineList.Count() - 1].GetEnd(), "Index dead wrong!"); + return (maLineList.Count() - 1); } void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormattedLine ) { - sal_Int32 nLines = aLineList.Count(); + sal_Int32 nLines = maLineList.Count(); DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Empty Portion?" ); if ( nLastFormattedLine < ( nLines - 1 ) ) { - const EditLine& rLastFormatted = aLineList[ nLastFormattedLine ]; - const EditLine& rUnformatted = aLineList[ nLastFormattedLine+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! @@ -617,7 +395,7 @@ void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormatted { for ( sal_Int32 nL = nLastFormattedLine+1; nL < nLines; nL++ ) { - EditLine& rLine = aLineList[ nL ]; + EditLine& rLine = maLineList[ nL ]; rLine.GetStartPortion() = rLine.GetStartPortion() + nPDiff; rLine.GetEndPortion() = rLine.GetEndPortion() + nPDiff; @@ -629,7 +407,7 @@ void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormatted } } } - DBG_ASSERT( aLineList[ aLineList.Count()-1 ].GetEnd() == pNode->Len(), "CorrectLines: The end is not right!" ); + DBG_ASSERT(maLineList[maLineList.Count() - 1].GetEnd() == mpNode->Len(), "CorrectLines: The end is not right!"); } // Shared reverse lookup acceleration pieces ... @@ -675,32 +453,14 @@ sal_Int32 FastGetPos(const Array& rArray, const Val* p, sal_Int32& rLastPos) } -ParaPortionList::ParaPortionList() : nLastCache( 0 ) -{ -} - -ParaPortionList::~ParaPortionList() -{ -} - sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const { return FastGetPos(maPortions, p, nLastCache); } -ParaPortion* ParaPortionList::operator [](sal_Int32 nPos) -{ - return 0 <= nPos && nPos < static_cast<sal_Int32>(maPortions.size()) ? maPortions[nPos].get() : nullptr; -} - -const ParaPortion* ParaPortionList::operator [](sal_Int32 nPos) const -{ - return 0 <= nPos && nPos < static_cast<sal_Int32>(maPortions.size()) ? maPortions[nPos].get() : nullptr; -} - std::unique_ptr<ParaPortion> ParaPortionList::Release(sal_Int32 nPos) { - if (nPos < 0 || static_cast<sal_Int32>(maPortions.size()) <= nPos) + if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos)) { SAL_WARN( "editeng", "ParaPortionList::Release - out of bounds pos " << nPos); return nullptr; @@ -712,7 +472,7 @@ std::unique_ptr<ParaPortion> ParaPortionList::Release(sal_Int32 nPos) void ParaPortionList::Remove(sal_Int32 nPos) { - if (nPos < 0 || static_cast<sal_Int32>(maPortions.size()) <= nPos) + if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos)) { SAL_WARN( "editeng", "ParaPortionList::Remove - out of bounds pos " << nPos); return; @@ -722,7 +482,7 @@ void ParaPortionList::Remove(sal_Int32 nPos) void ParaPortionList::Insert(sal_Int32 nPos, std::unique_ptr<ParaPortion> p) { - if (nPos < 0 || static_cast<sal_Int32>(maPortions.size()) < nPos) + if (nPos < 0 || maPortions.size() < o3tl::make_unsigned(nPos)) { SAL_WARN( "editeng", "ParaPortionList::Insert - out of bounds pos " << nPos); return; @@ -777,16 +537,6 @@ sal_Int32 ParaPortionList::FindParagraph(tools::Long nYOffset) const return EE_PARA_NOT_FOUND; } -const ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) const -{ - return 0 <= nPos && nPos < static_cast<sal_Int32>(maPortions.size()) ? maPortions[nPos].get() : nullptr; -} - -ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) -{ - return 0 <= nPos && nPos < static_cast<sal_Int32>(maPortions.size()) ? maPortions[nPos].get() : nullptr; -} - #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG void ParaPortionList::DbgCheck(ParaPortionList const& rParas, EditDoc const& rDoc) @@ -801,15 +551,9 @@ ParaPortionList::DbgCheck(ParaPortionList const& rParas, EditDoc const& rDoc) } #endif -ContentAttribsInfo::ContentAttribsInfo( const SfxItemSet& rParaAttribs ) : - aPrevParaAttribs( rParaAttribs) -{ -} - -void ContentAttribsInfo::RemoveAllCharAttribsFromPool(SfxItemPool& rPool) const +ContentAttribsInfo::ContentAttribsInfo( SfxItemSet aParaAttribs ) : + aPrevParaAttribs(std::move( aParaAttribs)) { - for (const std::unique_ptr<EditCharAttrib>& rAttrib : aPrevCharAttribs) - rPool.Remove(*rAttrib->GetItem()); } void ContentAttribsInfo::AppendCharAttrib(EditCharAttrib* pNew) @@ -854,6 +598,13 @@ void ConvertItem( std::unique_ptr<SfxPoolItem>& rPoolItem, MapUnit eSourceUnit, 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]; @@ -888,7 +639,7 @@ void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const Map sal_uInt16 nSlot = pDestPool->GetTrueSlotId( nWhich ); if ( nSlot ) { - sal_uInt16 nW = pSourcePool->GetTrueWhich( nSlot ); + sal_uInt16 nW = pSourcePool->GetTrueWhichIDFromSlotID( nSlot ); if ( nW ) nSourceWhich = nW; } @@ -912,208 +663,6 @@ void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const Map } } -EditLine::EditLine() : - nTxtWidth(0), - nStartPosX(0), - nStart(0), - nEnd(0), - nStartPortion(0), // to be able to tell the difference between a line - // without Portions from one with the Portion number 0 - nEndPortion(0), - nHeight(0), - nTxtHeight(0), - nMaxAscent(0), - bHangingPunctuation(false), - bInvalid(true) -{ -} - -EditLine::EditLine( const EditLine& r ) : - nTxtWidth(0), - nStartPosX(0), - nStart(r.nStart), - nEnd(r.nEnd), - nStartPortion(r.nStartPortion), - nEndPortion(r.nEndPortion), - nHeight(0), - nTxtHeight(0), - nMaxAscent(0), - bHangingPunctuation(r.bHangingPunctuation), - bInvalid(true) -{ -} - -EditLine::~EditLine() -{ -} - - -EditLine* EditLine::Clone() const -{ - EditLine* pL = new EditLine; - pL->aPositions = aPositions; - pL->nStartPosX = nStartPosX; - pL->nStart = nStart; - pL->nEnd = nEnd; - pL->nStartPortion = nStartPortion; - pL->nEndPortion = nEndPortion; - pL->nHeight = nHeight; - pL->nTxtWidth = nTxtWidth; - pL->nTxtHeight = nTxtHeight; - pL->nMaxAscent = nMaxAscent; - - return pL; -} - -bool operator == ( const EditLine& r1, const EditLine& r2 ) -{ - if ( r1.nStart != r2.nStart ) - return false; - - if ( r1.nEnd != r2.nEnd ) - return false; - - if ( r1.nStartPortion != r2.nStartPortion ) - return false; - - if ( r1.nEndPortion != r2.nEndPortion ) - return false; - - return true; -} - -EditLine& EditLine::operator = ( const EditLine& r ) -{ - nEnd = r.nEnd; - nStart = r.nStart; - nEndPortion = r.nEndPortion; - nStartPortion = r.nStartPortion; - return *this; -} - - -void EditLine::SetHeight( sal_uInt16 nH, sal_uInt16 nTxtH ) -{ - nHeight = nH; - nTxtHeight = ( nTxtH ? nTxtH : nH ); -} - -void EditLine::SetStartPosX( tools::Long start ) -{ - if (start > 0) - nStartPosX = start; - else - nStartPosX = 0; -} - -Size EditLine::CalcTextSize( ParaPortion& rParaPortion ) -{ - Size aSz; - Size aTmpSz; - - DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize before CreatePortions !" ); - - for ( sal_Int32 n = nStartPortion; n <= nEndPortion; n++ ) - { - TextPortion& rPortion = rParaPortion.GetTextPortions()[n]; - switch ( rPortion.GetKind() ) - { - case PortionKind::TEXT: - case PortionKind::FIELD: - case PortionKind::HYPHENATOR: - { - aTmpSz = rPortion.GetSize(); - aSz.AdjustWidth(aTmpSz.Width() ); - if ( aSz.Height() < aTmpSz.Height() ) - aSz.setHeight( aTmpSz.Height() ); - } - break; - case PortionKind::TAB: - { - aSz.AdjustWidth(rPortion.GetSize().Width() ); - } - break; - case PortionKind::LINEBREAK: break; - } - } - - SetHeight( static_cast<sal_uInt16>(aSz.Height()) ); - return aSz; -} - -EditLineList::EditLineList() -{ -} - -EditLineList::~EditLineList() -{ - Reset(); -} - -void EditLineList::Reset() -{ - maLines.clear(); -} - -void EditLineList::DeleteFromLine(sal_Int32 nDelFrom) -{ - assert(nDelFrom <= (static_cast<sal_Int32>(maLines.size()) - 1)); - LinesType::iterator it = maLines.begin(); - std::advance(it, nDelFrom); - maLines.erase(it, maLines.end()); -} - -sal_Int32 EditLineList::FindLine(sal_Int32 nChar, bool bInclEnd) -{ - sal_Int32 n = maLines.size(); - for (sal_Int32 i = 0; i < n; ++i) - { - const EditLine& rLine = *maLines[i]; - if ( (bInclEnd && (rLine.GetEnd() >= nChar)) || - (rLine.GetEnd() > nChar) ) - { - return i; - } - } - - DBG_ASSERT( !bInclEnd, "Line not found: FindLine" ); - return n - 1; -} - -sal_Int32 EditLineList::Count() const -{ - return maLines.size(); -} - -const EditLine& EditLineList::operator[](sal_Int32 nPos) const -{ - return *maLines[nPos]; -} - -EditLine& EditLineList::operator[](sal_Int32 nPos) -{ - return *maLines[nPos]; -} - -void EditLineList::Append(EditLine* p) -{ - maLines.push_back(std::unique_ptr<EditLine>(p)); -} - -void EditLineList::Insert(sal_Int32 nPos, EditLine* p) -{ - maLines.insert(maLines.begin()+nPos, std::unique_ptr<EditLine>(p)); -} - -EditPaM::EditPaM() : pNode(nullptr), nIndex(0) {} -EditPaM::EditPaM(ContentNode* p, sal_Int32 n) : pNode(p), nIndex(n) {} - - -void EditPaM::SetNode(ContentNode* p) -{ - pNode = p; -} - bool EditPaM::DbgIsBuggy( EditDoc const & rDoc ) const { return !pNode || @@ -1126,29 +675,6 @@ bool EditSelection::DbgIsBuggy( EditDoc const & rDoc ) const return aStartPaM.DbgIsBuggy( rDoc ) || aEndPaM.DbgIsBuggy( rDoc ); } -EditSelection::EditSelection() -{ -} - -EditSelection::EditSelection( const EditPaM& rStartAndAnd ) : - aStartPaM(rStartAndAnd), - aEndPaM(rStartAndAnd) -{ -} - -EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd ) : - aStartPaM(rStart), - aEndPaM(rEnd) -{ -} - -EditSelection& EditSelection::operator = ( const EditPaM& rPaM ) -{ - aStartPaM = rPaM; - aEndPaM = rPaM; - return *this; -} - void EditSelection::Adjust( const EditDoc& rNodes ) { DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in Adjust(1)" ); @@ -1175,793 +701,28 @@ void EditSelection::Adjust( const EditDoc& rNodes ) } } -bool operator == ( const EditPaM& r1, const EditPaM& r2 ) -{ - return ( r1.GetNode() == r2.GetNode() ) && - ( r1.GetIndex() == r2.GetIndex() ); -} - -bool operator != ( const EditPaM& r1, const EditPaM& r2 ) -{ - return !( r1 == r2 ); -} - -ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool ) -{ -} - -ContentNode::ContentNode( const OUString& rStr, const ContentAttribs& rContentAttribs ) : - maString(rStr), aContentAttribs(rContentAttribs) -{ -} - -ContentNode::~ContentNode() -{ -} - -void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew, SfxItemPool& rItemPool ) -{ - if ( !nNew ) - return; - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif - - // Since features are treated differently than normal character attributes, - // but can also affect the order of the start list. // In every if ..., in the next (n) opportunities due to bFeature or - // an existing special case, must (n-1) opportunities be provided with - // bResort. The most likely possibility receives no bResort, so that is - // not sorted anew when all attributes are the same. - bool bResort = false; - bool bExpandedEmptyAtIndexNull = false; - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); - while ( pAttrib ) - { - if ( pAttrib->GetEnd() >= nIndex ) - { - // Move all attributes behind the insertion point... - if ( pAttrib->GetStart() > nIndex ) - { - pAttrib->MoveForward( nNew ); - } - // 0: Expand empty attribute, if at insertion point - else if ( pAttrib->IsEmpty() ) - { - // Do not check Index, an empty one could only be there - // When later checking it anyhow: - // Special case: Start == 0; AbsLen == 1, nNew = 1 - // => Expand, because of paragraph break! - // Start <= nIndex, End >= nIndex => Start=End=nIndex! -// if ( pAttrib->GetStart() == nIndex ) - pAttrib->Expand( nNew ); - bResort = true; - if ( pAttrib->GetStart() == 0 ) - bExpandedEmptyAtIndexNull = true; - } - // 1: Attribute starts before, goes to index ... - else if ( pAttrib->GetEnd() == nIndex ) // Start must be before - { - // Only expand when there is no feature - // and if not in exclude list! - // Otherwise, a UL will go on until a new ULDB, expanding both -// if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) ) - if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) - { - if ( !pAttrib->IsEdge() ) - pAttrib->Expand( nNew ); - } - else - bResort = true; - } - // 2: Attribute starts before, goes past the Index... - else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) - { - DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" ); - pAttrib->Expand( nNew ); - } - // 3: Attribute starts on index... - else if ( pAttrib->GetStart() == nIndex ) - { - if ( pAttrib->IsFeature() ) - { - pAttrib->MoveForward( nNew ); - bResort = true; - } - else - { - bool bExpand = false; - if ( nIndex == 0 ) - { - bExpand = true; - if( bExpandedEmptyAtIndexNull ) - { - // Check if this kind of attribute was empty and expanded here... - sal_uInt16 nW = pAttrib->GetItem()->Which(); - for ( sal_Int32 nA = 0; nA < nAttr; nA++ ) - { - const EditCharAttrib& r = *aCharAttribList.GetAttribs()[nA]; - if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) ) - { - bExpand = false; - break; - } - } - - } - } - if ( bExpand ) - { - pAttrib->Expand( nNew ); - bResort = true; - } - else - { - pAttrib->MoveForward( nNew ); - } - } - } - } - - if ( pAttrib->IsEdge() ) - pAttrib->SetEdge(false); - - DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); - - DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribute distorted!" ); - DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attribute larger than paragraph!" ); - if ( pAttrib->IsEmpty() ) - { - OSL_FAIL( "Empty Attribute after ExpandAttribs?" ); - bResort = true; - rItemPool.Remove( *pAttrib->GetItem() ); - rAttribs.erase(rAttribs.begin()+nAttr); - --nAttr; - } - ++nAttr; - pAttrib = GetAttrib(rAttribs, nAttr); - } - - if ( bResort ) - aCharAttribList.ResortAttribs(); - - if (mpWrongList) - { - bool bSep = ( maString[ nIndex ] == ' ' ) || IsFeature( nIndex ); - mpWrongList->TextInserted( nIndex, nNew, bSep ); - } - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif -} - -void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted, SfxItemPool& rItemPool ) -{ - if ( !nDeleted ) - return; - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif - - // Since features are treated differently than normal character attributes, - // but can also affect the order of the start list - bool bResort = false; - sal_Int32 nEndChanges = nIndex+nDeleted; - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); - while ( pAttrib ) - { - bool bDelAttr = false; - if ( pAttrib->GetEnd() >= nIndex ) - { - // Move all Attribute behind the insert point... - if ( pAttrib->GetStart() >= nEndChanges ) - { - pAttrib->MoveBackward( nDeleted ); - } - // 1. Delete Internal attributes... - else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) - { - // Special case: Attribute covers the area exactly - // => keep as empty Attribute. - if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) - { - pAttrib->GetEnd() = nIndex; // empty - bResort = true; - } - else - bDelAttr = true; - } - // 2. Attribute starts earlier, ends inside or behind it ... - else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) - { - DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" ); - if ( pAttrib->GetEnd() <= nEndChanges ) // ends inside - pAttrib->GetEnd() = nIndex; - else - pAttrib->Collaps( nDeleted ); // ends behind - } - // 3. Attribute starts inside, ending behind ... - else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) - { - // Features not allowed to expand! - if ( pAttrib->IsFeature() ) - { - pAttrib->MoveBackward( nDeleted ); - bResort = true; - } - else - { - pAttrib->GetStart() = nEndChanges; - pAttrib->MoveBackward( nDeleted ); - } - } - } - DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); - - DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collapse: Attribute distorted!" ); - DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collapse: Attribute larger than paragraph!" ); - if ( bDelAttr ) - { - bResort = true; - rItemPool.Remove( *pAttrib->GetItem() ); - rAttribs.erase(rAttribs.begin()+nAttr); - nAttr--; - } - else if ( pAttrib->IsEmpty() ) - aCharAttribList.SetHasEmptyAttribs(true); - - nAttr++; - pAttrib = GetAttrib(rAttribs, nAttr); - } - - if ( bResort ) - aCharAttribList.ResortAttribs(); - - if (mpWrongList) - mpWrongList->TextDeleted(nIndex, nDeleted); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif -} - -void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, bool bKeepEndingAttribs ) -{ - assert(pPrevNode); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pPrevNode->aCharAttribList); -#endif - - sal_Int32 nCut = pPrevNode->Len(); - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rPrevAttribs = pPrevNode->GetCharAttribs().GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rPrevAttribs, nAttr); - while ( pAttrib ) - { - if ( pAttrib->GetEnd() < nCut ) - { - // remain unchanged... - ; - } - else if ( pAttrib->GetEnd() == nCut ) - { - // must be copied as an empty attributes. - if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) - { - EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); - assert(pNewAttrib); - aCharAttribList.InsertAttrib( pNewAttrib ); - } - } - else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) ) - { - // If cut is done right at the front then the attribute must be - // kept! Has to be copied and changed. - EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut ); - assert(pNewAttrib); - aCharAttribList.InsertAttrib( pNewAttrib ); - pAttrib->GetEnd() = nCut; - } - else - { - // Move all attributes in the current node (this) - CharAttribList::AttribsType::iterator it = rPrevAttribs.begin() + nAttr; - aCharAttribList.InsertAttrib(it->release()); - rPrevAttribs.erase(it); - pAttrib->MoveBackward( nCut ); - nAttr--; - } - nAttr++; - pAttrib = GetAttrib(rPrevAttribs, nAttr); - } - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pPrevNode->aCharAttribList); -#endif -} - -void ContentNode::AppendAttribs( ContentNode* pNextNode ) -{ - assert(pNextNode); - - sal_Int32 nNewStart = maString.getLength(); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pNextNode->aCharAttribList); -#endif - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rNextAttribs = pNextNode->GetCharAttribs().GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rNextAttribs, nAttr); - while ( pAttrib ) - { - // Move all attributes in the current node (this) - bool bMelted = false; - if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) ) - { - // Attributes can possibly be summarized as: - sal_Int32 nTmpAttr = 0; - EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); - while ( !bMelted && pTmpAttrib ) - { - if ( pTmpAttrib->GetEnd() == nNewStart ) - { - if (pTmpAttrib->Which() == pAttrib->Which()) - { - // prevent adding 2 0-length attributes at same position - if ((*(pTmpAttrib->GetItem()) == *(pAttrib->GetItem())) - || (0 == pAttrib->GetLen())) - { - pTmpAttrib->GetEnd() = - pTmpAttrib->GetEnd() + pAttrib->GetLen(); - rNextAttribs.erase(rNextAttribs.begin()+nAttr); - // Unsubscribe from the pool?! - bMelted = true; - } - else if (0 == pTmpAttrib->GetLen()) - { - aCharAttribList.Remove(nTmpAttr); - --nTmpAttr; // to cancel later increment... - } - } - } - ++nTmpAttr; - pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); - } - } - - if ( !bMelted ) - { - pAttrib->GetStart() = pAttrib->GetStart() + nNewStart; - pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart; - CharAttribList::AttribsType::iterator it = rNextAttribs.begin() + nAttr; - aCharAttribList.InsertAttrib(it->release()); - rNextAttribs.erase(it); - } - pAttrib = GetAttrib(rNextAttribs, nAttr); - } - // For the Attributes that just moved over: - rNextAttribs.clear(); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pNextNode->aCharAttribList); -#endif -} - -void ContentNode::CreateDefFont() -{ - // First use the information from the style ... - SfxStyleSheet* pS = aContentAttribs.GetStyleSheet(); - if ( pS ) - CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() ); - - // ... then iron out the hard paragraph formatting... - CreateFont( GetCharAttribs().GetDefFont(), - GetContentAttribs().GetItems(), pS == nullptr ); -} - -void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ) -{ - aContentAttribs.SetStyleSheet( pS ); - - - // First use the information from the style ... - GetCharAttribs().GetDefFont() = rFontFromStyle; - // ... then iron out the hard paragraph formatting... - CreateFont( GetCharAttribs().GetDefFont(), - GetContentAttribs().GetItems(), pS == nullptr ); -} - -void ContentNode::SetStyleSheet( SfxStyleSheet* pS, bool bRecalcFont ) -{ - aContentAttribs.SetStyleSheet( pS ); - if ( bRecalcFont ) - CreateDefFont(); -} - -bool ContentNode::IsFeature( sal_Int32 nPos ) const -{ - return maString[nPos] == CH_FEATURE; -} - -sal_Int32 ContentNode::Len() const -{ - return maString.getLength(); -} - -sal_uLong ContentNode::GetExpandedLen() const -{ - sal_uLong nLen = maString.getLength(); - - // Fields can be longer than the placeholder in the Node - const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); - for (sal_Int32 nAttr = rAttrs.size(); nAttr; ) - { - const EditCharAttrib& rAttr = *rAttrs[--nAttr]; - if (rAttr.Which() == EE_FEATURE_FIELD) - { - nLen += static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); - --nLen; // Standalone, to avoid corner cases when previous getLength() returns 0 - } - } - - return nLen; -} - -OUString ContentNode::GetExpandedText(sal_Int32 nStartPos, sal_Int32 nEndPos) const -{ - if ( nEndPos < 0 || nEndPos > Len() ) - nEndPos = Len(); - - DBG_ASSERT( nStartPos <= nEndPos, "Start and End reversed?" ); - - sal_Int32 nIndex = nStartPos; - OUStringBuffer aStr(256); - const EditCharAttrib* pNextFeature = GetCharAttribs().FindFeature( nIndex ); - while ( nIndex < nEndPos ) - { - sal_Int32 nEnd = nEndPos; - if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) ) - nEnd = pNextFeature->GetStart(); - else - pNextFeature = nullptr; // Feature does not interest the below - - DBG_ASSERT( nEnd >= nIndex, "End in front of the index?" ); - //!! beware of sub string length of -1 - if (nEnd > nIndex) - aStr.append( std::u16string_view(GetString()).substr(nIndex, nEnd - nIndex) ); - - if ( pNextFeature ) - { - switch ( pNextFeature->GetItem()->Which() ) - { - case EE_FEATURE_TAB: aStr.append( "\t" ); - break; - case EE_FEATURE_LINEBR: aStr.append( "\x0A" ); - break; - case EE_FEATURE_FIELD: - aStr.append( static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue() ); - break; - default: OSL_FAIL( "What feature?" ); - } - pNextFeature = GetCharAttribs().FindFeature( ++nEnd ); - } - nIndex = nEnd; - } - return aStr.makeStringAndClear(); -} - -void ContentNode::UnExpandPosition( sal_Int32 &rPos, bool bBiasStart ) -{ - sal_Int32 nOffset = 0; - - const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); - for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr ) - { - const EditCharAttrib& rAttr = *rAttrs[nAttr]; - assert (!(nAttr < rAttrs.size() - 1) || - rAttrs[nAttr]->GetStart() <= rAttrs[nAttr + 1]->GetStart()); - - nOffset = rAttr.GetStart(); - - if (nOffset >= rPos) // happens after the position - return; - - if (rAttr.Which() == EE_FEATURE_FIELD) - { - sal_Int32 nChunk = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); - nChunk--; // Character representing the field in the string - - if (nOffset + nChunk >= rPos) // we're inside the field - { - if (bBiasStart) - rPos = rAttr.GetStart(); - else - rPos = rAttr.GetEnd(); - return; - } - // Adjust for the position - rPos -= nChunk; - } - } - assert (rPos <= Len()); -} - -/* - * Fields are represented by a single character in the underlying string - * and/or selection, however, they can be expanded to the full value of - * the field. When we're dealing with selection / offsets however we need - * to deal in character positions inside the real (unexpanded) string. - * This method maps us back to character offsets. - */ -void ContentNode::UnExpandPositions( sal_Int32 &rStartPos, sal_Int32 &rEndPos ) -{ - UnExpandPosition( rStartPos, true ); - UnExpandPosition( rEndPos, false ); -} - -void ContentNode::SetChar(sal_Int32 nPos, sal_Unicode c) -{ - maString = maString.replaceAt(nPos, 1, OUString(c)); -} - -void ContentNode::Insert(const OUString& rStr, sal_Int32 nPos) -{ - maString = maString.replaceAt(nPos, 0, rStr); -} - -void ContentNode::Append(std::u16string_view rStr) -{ - maString += rStr; -} - -void ContentNode::Erase(sal_Int32 nPos) -{ - maString = maString.copy(0, nPos); -} - -void ContentNode::Erase(sal_Int32 nPos, sal_Int32 nCount) -{ - maString = maString.replaceAt(nPos, nCount, ""); -} - -OUString ContentNode::Copy(sal_Int32 nPos) const -{ - return maString.copy(nPos); -} - -OUString ContentNode::Copy(sal_Int32 nPos, sal_Int32 nCount) const -{ - return maString.copy(nPos, nCount); -} - -sal_Unicode ContentNode::GetChar(sal_Int32 nPos) const -{ - return maString[nPos]; -} - -void ContentNode::EnsureWrongList() -{ - if (!mpWrongList) - CreateWrongList(); -} - -WrongList* ContentNode::GetWrongList() -{ - return mpWrongList.get(); -} - -const WrongList* ContentNode::GetWrongList() const -{ - return mpWrongList.get(); -} - -void ContentNode::SetWrongList( WrongList* p ) -{ - mpWrongList.reset(p); -} - -void ContentNode::CreateWrongList() -{ - SAL_WARN_IF( mpWrongList && !mpWrongList->empty(), "editeng", "WrongList already exist!"); - if (!mpWrongList || !mpWrongList->empty()) - mpWrongList.reset(new WrongList); -} - -void ContentNode::DestroyWrongList() -{ - mpWrongList.reset(); -} - -void ContentNode::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - xmlTextWriterStartElement(pWriter, BAD_CAST("ContentNode")); - xmlTextWriterWriteAttribute(pWriter, BAD_CAST("maString"), BAD_CAST(maString.toUtf8().getStr())); - aContentAttribs.dumpAsXml(pWriter); - aCharAttribList.dumpAsXml(pWriter); - xmlTextWriterEndElement(pWriter); -} - - -ContentAttribs::ContentAttribs( SfxItemPool& rPool ) -: pStyle(nullptr) -, aAttribSet( rPool, svl::Items<EE_PARA_START, EE_CHAR_END>{} ) -{ -} - - -SvxTabStop ContentAttribs::FindTabStop( sal_Int32 nCurPos, sal_uInt16 nDefTab ) -{ - const SvxTabStopItem& rTabs = GetItem( EE_PARA_TABS ); - for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) - { - const SvxTabStop& rTab = rTabs[i]; - if ( rTab.GetTabPos() > nCurPos ) - return rTab; - } - - // Determine DefTab ... - SvxTabStop aTabStop; - const sal_Int32 x = nCurPos / nDefTab + 1; - aTabStop.GetTabPos() = nDefTab * x; - return aTabStop; -} - -void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS ) -{ - bool bStyleChanged = ( pStyle != pS ); - pStyle = pS; - // Only when other style sheet, not when current style sheet modified - if ( !(pStyle && bStyleChanged) ) - return; - - // Selectively remove the attributes from the paragraph formatting - // which are specified in the style, so that the attributes of the - // style can have an affect. - const SfxItemSet& rStyleAttribs = pStyle->GetItemSet(); - for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) - { - // Don't change bullet on/off - if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SfxItemState::SET ) ) - aAttribSet.ClearItem( nWhich ); - } -} - -const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) const -{ - // Hard paragraph attributes take precedence! - const SfxItemSet* pTakeFrom = &aAttribSet; - if ( pStyle && ( aAttribSet.GetItemState( nWhich, false ) != SfxItemState::SET ) ) - pTakeFrom = &pStyle->GetItemSet(); - - return pTakeFrom->Get( nWhich ); -} - -bool ContentAttribs::HasItem( sal_uInt16 nWhich ) const -{ - bool bHasItem = false; - if ( aAttribSet.GetItemState( nWhich, false ) == SfxItemState::SET ) - bHasItem = true; - else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SfxItemState::SET ) - bHasItem = true; - - return bHasItem; -} - -void ContentAttribs::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - xmlTextWriterStartElement(pWriter, BAD_CAST("ContentAttribs")); - xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("style"), "%s", pStyle->GetName().toUtf8().getStr()); - aAttribSet.dumpAsXml(pWriter); - xmlTextWriterEndElement(pWriter); -} - - -ItemList::ItemList() : CurrentItem( 0 ) -{ -} - -const SfxPoolItem* ItemList::First() -{ - CurrentItem = 0; - return aItemPool.empty() ? nullptr : aItemPool[ 0 ]; -} - -const SfxPoolItem* ItemList::Next() -{ - if ( CurrentItem + 1 < static_cast<sal_Int32>(aItemPool.size()) ) - { - ++CurrentItem; - return aItemPool[ CurrentItem ]; - } - return nullptr; -} - -void ItemList::Insert( const SfxPoolItem* pItem ) -{ - aItemPool.push_back( pItem ); - CurrentItem = aItemPool.size() - 1; -} - - EditDoc::EditDoc( SfxItemPool* pPool ) : - nLastCache(0), - pItemPool(pPool ? pPool : new EditEngineItemPool()), - nDefTab(DEFTAB), - bIsVertical(false), + mnLastCache(0), + mpItemPool(pPool ? pPool : new EditEngineItemPool()), + mnDefTab(DEFTAB), + mbIsVertical(false), mnRotation(TextRotation::NONE), - bIsFixedCellHeight(false), - bOwnerOfPool(pPool == nullptr), - bModified(false), - bDisableAttributeExpanding(false) + mbIsFixedCellHeight(false), + mbModified(false), + mbDisableAttributeExpanding(false) { // Don't create an empty node, Clear() will be called in EditEngine-CTOR }; EditDoc::~EditDoc() { - ImplDestroyContents(); - if ( bOwnerOfPool ) - SfxItemPool::Free(pItemPool); -} - -namespace { - -class RemoveEachItemFromPool -{ - EditDoc& mrDoc; -public: - explicit RemoveEachItemFromPool(EditDoc& rDoc) : mrDoc(rDoc) {} - void operator() (const std::unique_ptr<ContentNode>& rNode) - { - mrDoc.RemoveItemsFromPool(*rNode); - } -}; - -struct ClearSpellErrorsHandler -{ - void operator() (std::unique_ptr<ContentNode> const & rNode) - { - rNode->DestroyWrongList(); - } -}; - -} - -void EditDoc::ImplDestroyContents() -{ - std::for_each(maContents.begin(), maContents.end(), RemoveEachItemFromPool(*this)); maContents.clear(); } -void EditDoc::RemoveItemsFromPool(const ContentNode& rNode) -{ - for (sal_Int32 nAttr = 0; nAttr < rNode.GetCharAttribs().Count(); ++nAttr) - { - const EditCharAttrib& rAttr = *rNode.GetCharAttribs().GetAttribs()[nAttr]; - GetItemPool().Remove(*rAttr.GetItem()); - } -} - void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, SvtScriptType nScriptType ) { vcl::Font aPrevFont( rFont ); rFont.SetAlignment( ALIGN_BASELINE ); - rFont.SetTransparent( true ); sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ); sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ); @@ -1982,7 +743,11 @@ void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, S if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SfxItemState::SET ) ) rFont.SetColor( rSet.Get( EE_CHAR_COLOR ).GetValue() ); if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_BKGCOLOR ) == SfxItemState::SET ) ) - rFont.SetFillColor( rSet.Get( EE_CHAR_BKGCOLOR ).GetValue() ); + { + auto& aColor = rSet.Get( EE_CHAR_BKGCOLOR ).GetValue(); + rFont.SetTransparent(aColor.IsTransparent()); + rFont.SetFillColor(aColor); + } if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SfxItemState::SET ) ) rFont.SetFontSize( Size( rFont.GetFontSize().Width(), static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich_FontHeight ) ).GetHeight() ) ); if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SfxItemState::SET ) ) @@ -2034,75 +799,64 @@ void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, S void EditDoc::CreateDefFont( bool bUseStyles ) { - SfxItemSet aTmpSet( GetItemPool(), svl::Items<EE_PARA_START, EE_CHAR_END>{} ); - CreateFont( aDefFont, aTmpSet ); - aDefFont.SetVertical( IsVertical() ); - aDefFont.SetOrientation( Degree10(IsVertical() ? (IsTopToBottom() ? 2700 : 900) : 0) ); + SfxItemSetFixed<EE_PARA_START, EE_CHAR_END> aTmpSet( GetItemPool() ); + CreateFont(maDefFont, aTmpSet); + maDefFont.SetVertical( IsEffectivelyVertical() ); + maDefFont.SetOrientation( Degree10(IsEffectivelyVertical() ? (IsTopToBottom() ? 2700 : 900) : 0) ); - for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ ) + for (std::unique_ptr<ContentNode>& pNode : maContents) { - ContentNode* pNode = GetObject( nNode ); - pNode->GetCharAttribs().GetDefFont() = aDefFont; - if ( bUseStyles ) + pNode->GetCharAttribs().GetDefFont() = maDefFont; + if (bUseStyles) pNode->CreateDefFont(); } } -bool EditDoc::IsVertical() const +bool EditDoc::IsEffectivelyVertical() const { - return (bIsVertical && mnRotation == TextRotation::NONE) || - (!bIsVertical && mnRotation != TextRotation::NONE); + return (mbIsVertical && mnRotation == TextRotation::NONE) || + (!mbIsVertical && mnRotation != TextRotation::NONE); } bool EditDoc::IsTopToBottom() const { - return (bIsVertical && mnRotation == TextRotation::NONE) || - (!bIsVertical && mnRotation == TextRotation::TOPTOBOTTOM); + return (mbIsVertical && mnRotation == TextRotation::NONE) || + (!mbIsVertical && mnRotation == TextRotation::TOPTOBOTTOM); } -bool EditDoc::GetDirectVertical() const +bool EditDoc::GetVertical() const { - return bIsVertical; + return mbIsVertical; } -sal_Int32 EditDoc::GetPos(const ContentNode* p) const +sal_Int32 EditDoc::GetPos(const ContentNode* pContentNode) const { - return FastGetPos(maContents, p, nLastCache); + return FastGetPos(maContents, pContentNode, mnLastCache); } const ContentNode* EditDoc::GetObject(sal_Int32 nPos) const { - return 0 <= nPos && nPos < static_cast<sal_Int32>(maContents.size()) ? maContents[nPos].get() : nullptr; + return 0 <= nPos && o3tl::make_unsigned(nPos) < maContents.size() ? maContents[nPos].get() : nullptr; } ContentNode* EditDoc::GetObject(sal_Int32 nPos) { - return 0 <= nPos && nPos < static_cast<sal_Int32>(maContents.size()) ? maContents[nPos].get() : nullptr; -} - -const ContentNode* EditDoc::operator[](sal_Int32 nPos) const -{ - return GetObject(nPos); -} - -ContentNode* EditDoc::operator[](sal_Int32 nPos) -{ - return GetObject(nPos); + return 0 <= nPos && o3tl::make_unsigned(nPos) < maContents.size() ? maContents[nPos].get() : nullptr; } -void EditDoc::Insert(sal_Int32 nPos, ContentNode* p) +void EditDoc::Insert(sal_Int32 nPos, std::unique_ptr<ContentNode> pNode) { if (nPos < 0 || nPos == SAL_MAX_INT32) { SAL_WARN( "editeng", "EditDoc::Insert - overflow pos " << nPos); return; } - maContents.insert(maContents.begin()+nPos, std::unique_ptr<ContentNode>(p)); + maContents.insert(maContents.begin()+nPos, std::move(pNode)); } void EditDoc::Remove(sal_Int32 nPos) { - if (nPos < 0 || nPos >= static_cast<sal_Int32>(maContents.size())) + if (nPos < 0 || o3tl::make_unsigned(nPos) >= maContents.size()) { SAL_WARN( "editeng", "EditDoc::Remove - out of bounds pos " << nPos); return; @@ -2110,15 +864,17 @@ void EditDoc::Remove(sal_Int32 nPos) maContents.erase(maContents.begin() + nPos); } -void EditDoc::Release(sal_Int32 nPos) +std::unique_ptr<ContentNode> EditDoc::Release(sal_Int32 nPos) { - if (nPos < 0 || nPos >= static_cast<sal_Int32>(maContents.size())) + if (nPos < 0 || o3tl::make_unsigned(nPos) >= maContents.size()) { SAL_WARN( "editeng", "EditDoc::Release - out of bounds pos " << nPos); - return; + return nullptr; } - (void)maContents[nPos].release(); + + std::unique_ptr<ContentNode> pNode = std::move(maContents[nPos]); maContents.erase(maContents.begin() + nPos); + return pNode; } sal_Int32 EditDoc::Count() const @@ -2149,7 +905,7 @@ OUString EditDoc::GetText( LineEnd eEnd ) const const OUString aSep = EditDoc::GetSepStr( eEnd ); const sal_Int32 nSepSize = aSep.getLength(); - const sal_uInt32 nLen = GetTextLen() + (nNodes - 1)*nSepSize; + const sal_Int32 nLen = GetTextLen() + (nNodes - 1)*nSepSize; OUStringBuffer aBuffer(nLen + 16); // leave some slack @@ -2188,23 +944,22 @@ EditPaM EditDoc::GetEndPaM() const return EditPaM( pLastNode, pLastNode->Len() ); } -sal_uLong EditDoc::GetTextLen() const +sal_Int32 EditDoc::GetTextLen() const { - sal_uLong nLen = 0; - for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ ) + sal_Int32 nLength = 0; + for (auto const& pContent : maContents) { - const ContentNode* pNode = GetObject( nNode ); - nLen += pNode->GetExpandedLen(); + nLength += pContent->GetExpandedLen(); } - return nLen; + return nLength; } EditPaM EditDoc::Clear() { - ImplDestroyContents(); + maContents.clear(); - ContentNode* pNode = new ContentNode( GetItemPool() ); - Insert(0, pNode); + ContentNode* pNode = new ContentNode(GetItemPool()); + Insert(0, std::unique_ptr<ContentNode>(pNode)); CreateDefFont(false); @@ -2213,6 +968,17 @@ EditPaM EditDoc::Clear() return EditPaM( pNode, 0 ); } +namespace +{ +struct ClearSpellErrorsHandler +{ + void operator() (std::unique_ptr<ContentNode> const & rNode) + { + rNode->DestroyWrongList(); + } +}; +} + void EditDoc::ClearSpellErrors() { std::for_each(maContents.begin(), maContents.end(), ClearSpellErrorsHandler()); @@ -2220,11 +986,9 @@ void EditDoc::ClearSpellErrors() void EditDoc::SetModified( bool b ) { - bModified = b; - if ( bModified ) - { - aModifyHdl.Call( nullptr ); - } + mbModified = b; + if (mbModified) + maModifyHdl.Call(nullptr); } EditPaM EditDoc::RemoveText() @@ -2235,10 +999,10 @@ EditPaM EditDoc::RemoveText() SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() ); vcl::Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() ); - ImplDestroyContents(); + maContents.clear(); - ContentNode* pNode = new ContentNode( GetItemPool() ); - Insert(0, pNode); + ContentNode* pNode = new ContentNode(GetItemPool()); + Insert(0, std::unique_ptr<ContentNode>(pNode)); pNode->SetStyleSheet(pPrevStyle, false); pNode->GetContentAttribs().GetItems().Set( aPrevSet ); @@ -2246,19 +1010,19 @@ EditPaM EditDoc::RemoveText() SetModified(true); - return EditPaM( pNode, 0 ); + return EditPaM(pNode, 0); } -EditPaM EditDoc::InsertText( EditPaM aPaM, const OUString& rStr ) +EditPaM EditDoc::InsertText( EditPaM aPaM, std::u16string_view rStr ) { - DBG_ASSERT( rStr.indexOf( 0x0A ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); - DBG_ASSERT( rStr.indexOf( 0x0D ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); - DBG_ASSERT( rStr.indexOf( '\t' ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( 0x0A ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( 0x0D ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( '\t' ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); assert(aPaM.GetNode()); aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() ); - aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.getLength(), GetItemPool() ); - aPaM.SetIndex( aPaM.GetIndex() + rStr.getLength() ); + aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.size() ); + aPaM.SetIndex( aPaM.GetIndex() + rStr.size() ); SetModified( true ); @@ -2280,7 +1044,7 @@ EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs ) aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, true) ); // ContentNode constructor copies also the paragraph attributes - ContentNode* pNode = new ContentNode( aStr, aContentAttribs ); + ContentNode* pNode = new ContentNode(aStr, std::move(aContentAttribs)); // Copy the Default Font pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont(); @@ -2298,7 +1062,7 @@ EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs ) // Character attributes may need to be copied or trimmed: pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs ); - Insert(nPos+1, pNode); + Insert(nPos+1, std::unique_ptr<ContentNode>(pNode)); SetModified(true); @@ -2311,8 +1075,8 @@ EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem ) { assert(aPaM.GetNode()); - aPaM.GetNode()->Insert( OUString(CH_FEATURE), aPaM.GetIndex() ); - aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() ); + aPaM.GetNode()->Insert( rtl::OUStringChar(CH_FEATURE), aPaM.GetIndex() ); + aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1 ); // Create a feature-attribute for the feature... EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 ); @@ -2335,7 +1099,6 @@ EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight ) pLeft->Append(pRight->GetString()); // the one to the right disappears. - RemoveItemsFromPool(*pRight); sal_Int32 nRight = GetPos( pRight ); Remove( nRight ); @@ -2348,7 +1111,7 @@ void EditDoc::RemoveChars( EditPaM aPaM, sal_Int32 nChars ) { // Maybe remove Features! aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars ); - aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars, GetItemPool() ); + aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars ); SetModified( true ); } @@ -2371,7 +1134,7 @@ void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal // tdf#132288 By default inserting an attribute beside another that is of // the same type expands the original instead of inserting another. But the // spell check dialog doesn't want that behaviour - if (bDisableAttributeExpanding) + if (mbDisableAttributeExpanding) { pStartingAttrib = nullptr; pEndingAttrib = nullptr; @@ -2383,7 +1146,6 @@ void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal { // Will become a large Attribute. pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd(); - GetItemPool().Remove( *(pStartingAttrib->GetItem()) ); pNode->GetCharAttribs().Remove(pStartingAttrib); } else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) ) @@ -2427,7 +1189,7 @@ bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEn #endif // iterate over the attributes ... - sal_Int32 nAttr = 0; + std::size_t nAttr = 0; CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs(); EditCharAttrib* pAttr = GetAttrib(rAttribs, nAttr); while ( pAttr ) @@ -2505,11 +1267,12 @@ bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEn { DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Delete and retain the same attribute?" ); DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" ); - GetItemPool().Remove( *pAttr->GetItem() ); rAttribs.erase(rAttribs.begin()+nAttr); - nAttr--; } - nAttr++; + else + { + nAttr++; + } pAttr = GetAttrib(rAttribs, nAttr); } @@ -2587,7 +1350,7 @@ void EditDoc::FindAttribs( ContentNode* pNode, sal_Int32 nStartPos, sal_Int32 nE assert(pNode); DBG_ASSERT( nStartPos <= nEndPos, "Invalid region!" ); - sal_uInt16 nAttr = 0; + std::size_t nAttr = 0; EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); // No Selection... if ( nStartPos == nEndPos ) @@ -2695,340 +1458,34 @@ void EditDoc::dumpAsXml(xmlTextWriterPtr pWriter) const { pWriter = xmlNewTextWriterFilename("editdoc.xml", 0); xmlTextWriterSetIndent(pWriter,1); - xmlTextWriterSetIndentString(pWriter, BAD_CAST(" ")); - xmlTextWriterStartDocument(pWriter, nullptr, nullptr, nullptr); + (void)xmlTextWriterSetIndentString(pWriter, BAD_CAST(" ")); + (void)xmlTextWriterStartDocument(pWriter, nullptr, nullptr, nullptr); bOwns = true; } - xmlTextWriterStartElement(pWriter, BAD_CAST("EditDoc")); + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("EditDoc")); for (auto const & i : maContents) { i->dumpAsXml(pWriter); } - xmlTextWriterEndElement(pWriter); + (void)xmlTextWriterEndElement(pWriter); if (bOwns) { - xmlTextWriterEndDocument(pWriter); + (void)xmlTextWriterEndDocument(pWriter); xmlFreeTextWriter(pWriter); } } - -namespace { - -struct LessByStart -{ - bool operator() (const std::unique_ptr<EditCharAttrib>& left, const std::unique_ptr<EditCharAttrib>& right) const - { - return left->GetStart() < right->GetStart(); - } -}; - -} - -CharAttribList::CharAttribList() -: aAttribs() -, aDefFont() -, bHasEmptyAttribs(false) -{ -} - -CharAttribList::~CharAttribList() -{ -} - -void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib ) -{ -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// optimize: binary search? ! -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - // Maybe just simply iterate backwards: - // The most common and critical case: Attributes are already sorted - // (InsertBinTextObject!) binary search would not be optimal here. - // => Would bring something! - - const sal_Int32 nStart = pAttrib->GetStart(); // may be better for Comp.Opt. - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif - - if ( pAttrib->IsEmpty() ) - bHasEmptyAttribs = true; - - bool bInsert(true); - for (sal_Int32 i = 0, n = aAttribs.size(); i < n; ++i) - { - const EditCharAttrib& rCurAttrib = *aAttribs[i]; - if (rCurAttrib.GetStart() > nStart) - { - aAttribs.insert(aAttribs.begin()+i, std::unique_ptr<EditCharAttrib>(pAttrib)); - bInsert = false; - break; - } - } - - if (bInsert) aAttribs.push_back(std::unique_ptr<EditCharAttrib>(pAttrib)); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -void CharAttribList::ResortAttribs() -{ - std::sort(aAttribs.begin(), aAttribs.end(), LessByStart()); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool ) -{ -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif - for (sal_Int32 i = 0; i < static_cast<sal_Int32>(aAttribs.size()); ++i) - { - EditCharAttrib& rAttr = *aAttribs[i]; - for (sal_Int32 nNext = i+1; nNext < static_cast<sal_Int32>(aAttribs.size()); ++nNext) - { - EditCharAttrib& rNext = *aAttribs[nNext]; - if (!rAttr.IsFeature() && rNext.GetStart() == rAttr.GetEnd() && rNext.Which() == rAttr.Which()) - { - if (*rNext.GetItem() == *rAttr.GetItem()) - { - rAttr.GetEnd() = rNext.GetEnd(); - rItemPool.Remove(*rNext.GetItem()); - aAttribs.erase(aAttribs.begin()+nNext); - } - break; // only 1 attr with same which can start here. - } - else if (rNext.GetStart() > rAttr.GetEnd()) - { - break; - } - } - } -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -sal_Int32 CharAttribList::Count() const -{ - return aAttribs.size(); -} - -const EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::const_reverse_iterator it = std::find_if(aAttribs.rbegin(), aAttribs.rend(), - [&nWhich, &nPos](const AttribsType::value_type& rxAttr) { - return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); - if (it != aAttribs.rend()) - { - const EditCharAttrib& rAttr = **it; - return &rAttr; - } - return nullptr; -} - -EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::reverse_iterator it = std::find_if(aAttribs.rbegin(), aAttribs.rend(), - [&nWhich, &nPos](AttribsType::value_type& rxAttr) { - return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); - if (it != aAttribs.rend()) - { - EditCharAttrib& rAttr = **it; - return &rAttr; - } - return nullptr; -} - -const EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_Int32 nFromPos ) const -{ - assert(nWhich); - for (auto const& attrib : aAttribs) - { - const EditCharAttrib& rAttr = *attrib; - if (rAttr.GetStart() >= nFromPos && rAttr.Which() == nWhich) - return &rAttr; - } - return nullptr; -} - -bool CharAttribList::HasAttrib( sal_Int32 nStartPos, sal_Int32 nEndPos ) const -{ - return std::any_of(aAttribs.rbegin(), aAttribs.rend(), - [&nStartPos, &nEndPos](const AttribsType::value_type& rxAttr) { - return rxAttr->GetStart() < nEndPos && rxAttr->GetEnd() > nStartPos; }); -} - - -namespace { - -class FindByAddress -{ - const EditCharAttrib* mpAttr; -public: - explicit FindByAddress(const EditCharAttrib* p) : mpAttr(p) {} - bool operator() (const std::unique_ptr<EditCharAttrib>& r) const - { - return r.get() == mpAttr; - } -}; - -} - -void CharAttribList::Remove(const EditCharAttrib* p) -{ - AttribsType::iterator it = std::find_if(aAttribs.begin(), aAttribs.end(), FindByAddress(p)); - if (it != aAttribs.end()) - aAttribs.erase(it); -} - -void CharAttribList::Remove(sal_Int32 nPos) -{ - if (nPos >= static_cast<sal_Int32>(aAttribs.size())) - return; - - aAttribs.erase(aAttribs.begin()+nPos); -} - -void CharAttribList::SetHasEmptyAttribs(bool b) -{ - bHasEmptyAttribs = b; -} - -bool CharAttribList::HasBoundingAttrib( sal_Int32 nBound ) const -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend(); - for (; it != itEnd; ++it) - { - const EditCharAttrib& rAttr = **it; - if (rAttr.GetEnd() < nBound) - return false; - - if (rAttr.GetStart() == nBound || rAttr.GetEnd() == nBound) - return true; - } - return false; -} - -EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) -{ - if ( !bHasEmptyAttribs ) - return nullptr; - - for (const std::unique_ptr<EditCharAttrib>& rAttr : aAttribs) - { - if (rAttr->GetStart() == nPos && rAttr->GetEnd() == nPos && rAttr->Which() == nWhich) - return rAttr.get(); - } - return nullptr; -} - -namespace { - -class FindByStartPos -{ - sal_Int32 mnPos; -public: - explicit FindByStartPos(sal_Int32 nPos) : mnPos(nPos) {} - bool operator() (const std::unique_ptr<EditCharAttrib>& r) const - { - return r->GetStart() >= mnPos; - } -}; - -} - -const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const -{ - // First, find the first attribute that starts at or after specified position. - AttribsType::const_iterator it = - std::find_if(aAttribs.begin(), aAttribs.end(), FindByStartPos(nPos)); - - if (it == aAttribs.end()) - // All attributes are before the specified position. - return nullptr; - - // And find the first attribute with feature. - it = std::find_if(it, aAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsFeature(); } ); - return it == aAttribs.end() ? nullptr : it->get(); -} - -namespace { - -class RemoveEmptyAttrItem -{ - SfxItemPool& mrItemPool; -public: - explicit RemoveEmptyAttrItem(SfxItemPool& rPool) : mrItemPool(rPool) {} - void operator() (const std::unique_ptr<EditCharAttrib>& r) - { - if (r->IsEmpty()) - mrItemPool.Remove(*r->GetItem()); - } -}; - -} - -void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool ) -{ - std::for_each(aAttribs.begin(), aAttribs.end(), RemoveEmptyAttrItem(rItemPool)); - aAttribs.erase( std::remove_if(aAttribs.begin(), aAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsEmpty(); } ), aAttribs.end() ); - bHasEmptyAttribs = false; -} - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG -void CharAttribList::DbgCheckAttribs(CharAttribList const& rAttribs) -{ - std::set<std::pair<sal_Int32, sal_uInt16>> zero_set; - for (const std::unique_ptr<EditCharAttrib>& rAttr : rAttribs.aAttribs) - { - assert(rAttr->GetStart() <= rAttr->GetEnd()); - assert(!rAttr->IsFeature() || rAttr->GetLen() == 1); - if (0 == rAttr->GetLen()) - { - // not sure if 0-length attributes allowed at all in non-empty para? - assert(zero_set.insert(std::make_pair(rAttr->GetStart(), rAttr->Which())).second && "duplicate 0-length attribute detected"); - } - } - CheckOrderedList(rAttribs.GetAttribs()); -} -#endif - -void CharAttribList::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - xmlTextWriterStartElement(pWriter, BAD_CAST("CharAttribList")); - for (auto const & i : aAttribs) { - i->dumpAsXml(pWriter); - } - xmlTextWriterEndElement(pWriter); -} - EditEngineItemPool::EditEngineItemPool() - : SfxItemPool( "EditEngineItemPool", EE_ITEMS_START, EE_ITEMS_END, - aItemInfos, nullptr ) +: SfxItemPool("EditEngineItemPool") { - m_xDefItems = EditDLL::Get().GetGlobalData()->GetDefItems(); - SetDefaults(m_xDefItems->getDefaults()); + registerItemInfoPackage(getItemInfoPackageEditEngine()); } EditEngineItemPool::~EditEngineItemPool() { - ClearDefaults(); + SetSecondaryPool(nullptr); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |