/* -*- 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 .
*/
// 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;
std::size_t nAttr = 0;
CharAttribList::AttribsType& rAttribs = maCharAttribList.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 elseif (pAttrib->IsEmpty() && pAttrib->IsExpandable())
{ // 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 ... elseif ( 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->IsExpandable()
&& !maCharAttribList.FindEmptyAttrib(pAttrib->Which(), nIndex))
{ if ( !pAttrib->IsEdge() )
pAttrib->Expand( nNew );
} else
bResort = true;
} // 2: Attribute starts before, goes past the Index... elseif ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
{
DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" );
pAttrib->Expand( nNew );
} // 3: Attribute starts on index... elseif ( pAttrib->GetStart() == nIndex )
{ if (!pAttrib->IsExpandable())
{
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 ( std::size_t nA = 0; nA < nAttr; nA++ )
{ const EditCharAttrib& r = *maCharAttribList.GetAttribs()[nA]; if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) )
{
bExpand = false; break;
}
}
// 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;
void ContentNode::CreateDefFont()
{ // First use the information from the style ...
SfxStyleSheet* pS = maContentAttribs.GetStyleSheet(); if ( pS )
CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() );
// ... then iron out the hard paragraph formatting...
CreateFont( GetCharAttribs().GetDefFont(),
GetContentAttribs().GetItems(), pS == nullptr );
}
// First use the information from the style ...
GetCharAttribs().GetDefFont() = rFontFromStyle; // ... then iron out the hard paragraph formatting...
CreateFont( GetCharAttribs().GetDefFont(),
GetContentAttribs().GetItems(), pS == nullptr );
}
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( GetString().subView(nIndex, nEnd - nIndex) );
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::checkAndDeleteEmptyAttribs() const
{ // Delete empty attributes, but only if paragraph is not empty! if (GetCharAttribs().HasEmptyAttribs() && Len())
{ const_cast<ContentNode*>(this)->GetCharAttribs().DeleteEmptyAttribs();
}
}
void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS )
{ bool bStyleChanged = ( mpStyle != pS );
mpStyle = pS; // Only when other style sheet, not when current style sheet modified if ( !(mpStyle && 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 = mpStyle->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 ) )
maAttribSet.ClearItem( nWhich );
}
}
// Maybe just simply iterate backwards: // The most common and critical case: Attributes are already sorted // (InsertTextObject!) binary search would not be optimal here. // => Would bring something!
const sal_Int32 nStart = pAttrib->GetStart(); // may be better for Comp.Opt.
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(maAttribs.rbegin(), maAttribs.rend(),
[&nWhich, &nPos](const AttribsType::value_type& rxAttr) { return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); if (it != maAttribs.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(maAttribs.rbegin(), maAttribs.rend(),
[&nWhich, &nPos](AttribsType::value_type& rxAttr) { return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); if (it != maAttribs.rend())
{
EditCharAttrib& rAttr = **it; return &rAttr;
} return nullptr;
}
void CharAttribList::SetHasEmptyAttribs(bool b)
{
mbHasEmptyAttribs = 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 = maAttribs.rbegin(), itEnd = maAttribs.rend(); for (; it != itEnd; ++it)
{ const EditCharAttrib& rAttr = **it; if (rAttr.GetEnd() < nBound) returnfalse;
const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const
{ // First, find the first attribute that starts at or after specified position.
AttribsType::const_iterator iterator =
std::find_if(maAttribs.begin(), maAttribs.end(), FindByStartPos(nPos));
if (iterator == maAttribs.end())
{ // All attributes are before the specified position. return nullptr;
}
// And find the first attribute with feature.
iterator = std::find_if(iterator, maAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsFeature();
});
if (iterator == maAttribs.end())
{ // Couldn't find the feature return nullptr;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.