// Extension for Sections: // these always have content position 0xffffffff! // There is never a field on this, only up to COMPLETE_STRING possible
SetGetExpField::SetGetExpField( const SwSectionNode& rSectNd, const SwPosition* pPos,
sal_uInt16 const nPageNumber)
: m_nPageNumber(nPageNumber)
{
m_eSetGetExpFieldType = SECTIONNODE;
m_CNTNT.pSection = &rSectNd.GetSection();
if( pFirstStt != pNextStt )
{ if( pFirst->IsTextNode() && pNext->IsTextNode() &&
( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() ))
{ // FIXME: in NewFieldPortion(), SwGetExpField are expanded via // DocumentFieldsManager::FieldsToExpand() calling // std::upper_bound binary search function - the sort order // depends on the fly positions in the layout, but the fly // positions depend on the expansion of the SwGetExpField! // This circular dep will cause trouble, it would be better to // use only model positions (anchor), but then how to compare // at-page anchored flys which don't have a model anchor? return ::IsFrameBehind( *pNext->GetTextNode(), m_nContent, *pFirst->GetTextNode(), m_nContent );
} return pFirstStt->GetIndex() < pNextStt->GetIndex();
}
}
// same Section: is the field in the same Node? if( pFirst != pNext ) return pFirst->GetIndex() < pNext->GetIndex();
// same Node in the Section, check Position in the Node return GetCntPosFromContent() < rField.GetCntPosFromContent();
}
const SwNode* SetGetExpField::GetNodeFromContent() const
{ const SwNode* pRet = nullptr; if( m_CNTNT.pTextField ) switch( m_eSetGetExpFieldType )
{ case TEXTFIELD:
pRet = &m_CNTNT.pTextField->GetTextNode(); break;
case TEXTINET:
pRet = &m_CNTNT.pTextINet->GetTextNode(); break;
case SECTIONNODE:
pRet = m_CNTNT.pSection->GetFormat()->GetSectionNode(); break;
case BOOKMARK:
pRet = &m_CNTNT.pBookmark->GetMarkStart().GetNode(); break;
case CRSRPOS:
pRet = &m_CNTNT.pPos->GetNode(); break;
case TEXTTOXMARK:
pRet = &m_CNTNT.pTextTOX->GetTextNode(); break;
case TABLEBOX: if( m_CNTNT.pTBox->GetSttNd() )
{
SwNodeIndex aIdx( *m_CNTNT.pTBox->GetSttNd() );
pRet = SwNodes::GoNext(&aIdx);
} break;
case FLYFRAME:
{
SwNodeIndex aIdx( *m_CNTNT.pFlyFormat->GetContent().GetContentIdx() );
pRet = SwNodes::GoNext(&aIdx);
} break;
} return pRet;
}
/// Look up the Name, if it is present, return its String, otherwise return an empty String
OUString LookString( std::unordered_map<OUString, OUString> const & rTable, const OUString& rName )
{ auto it = rTable.find( comphelper::string::strip(rName, ' ') ); if( it != rTable.end() ) return it->second;
return OUString();
}
SwDBData const & SwDoc::GetDBData()
{ #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS if(maDBData.sDataSource.isEmpty())
{ // Similar to: SwEditShell::IsAnyDatabaseFieldInDoc for (constauto& pFieldType : *getIDocumentFieldsAccess().GetFieldTypes())
{ if (IsUsed(*pFieldType))
{
SwFieldIds nWhich = pFieldType->Which(); switch(nWhich)
{ case SwFieldIds::Database: case SwFieldIds::DbNextSet: case SwFieldIds::DbNumSet: case SwFieldIds::DbSetNumber:
{
std::vector<SwFormatField*> vFields;
pFieldType->GatherFields(vFields); if(vFields.size())
{ if(SwFieldIds::Database == nWhich)
maDBData = static_cast<SwDBFieldType*>(vFields.front()->GetField()->GetTyp())->GetDBData(); else
maDBData = static_cast<SwDBNameInfField*> (vFields.front()->GetField())->GetRealDBData();
}
} break; default: break;
}
}
}
} if(maDBData.sDataSource.isEmpty())
maDBData = SwDBManager::GetAddressDBName(); #endif return maDBData;
}
void SwDoc::SetInitDBFields( bool b )
{ #if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
(void) b; #else
GetDBManager()->SetInitDBFields( b ); #endif
}
/// Get all databases that are used by fields static OUString lcl_DBDataToString(const SwDBData& rData)
{ return rData.sDataSource + OUStringChar(DB_DELIM)
+ rData.sCommand + OUStringChar(DB_DELIM)
+ OUString::number(rData.nCommandType);
}
case SwFieldIds::DbSetNumber: case SwFieldIds::DatabaseName:
AddUsedDBToList( rDBNameList,
lcl_DBDataToString(static_cast<const SwDBNameInfField*>(pField)->GetRealDBData() )); break;
case SwFieldIds::DbNumSet: case SwFieldIds::DbNextSet:
AddUsedDBToList( rDBNameList,
lcl_DBDataToString(static_cast<const SwDBNameInfField*>(pField)->GetRealDBData() ));
[[fallthrough]]; // JP: is that right like that?
case SwFieldIds::HiddenText: case SwFieldIds::HiddenPara:
AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
pField->GetPar1(), aUsedDBNames ));
aUsedDBNames.clear(); break;
case SwFieldIds::SetExp: case SwFieldIds::GetExp: case SwFieldIds::Table:
AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
pField->GetFormula(), aUsedDBNames ));
aUsedDBNames.clear(); break; default: break;
} returntrue;
});
} #endif
}
// SwFormatField is non-shareable, so const_cast is somewhat OK const_cast<SwFormatField&>(rFormatField).RegisterToFieldType( *pTyp );
pField->ChgTyp(pTyp);
case SwFieldIds::DbSetNumber: case SwFieldIds::DatabaseName: if (IsNameInArray(rOldNames,
lcl_DBDataToString(static_cast<SwDBNameInfField*>(pField)->GetRealDBData())))
{ static_cast<SwDBNameInfField*>(pField)->SetDBData(aNewDBData);
bExpand = true;
} break;
case SwFieldIds::DbNumSet: case SwFieldIds::DbNextSet: if (IsNameInArray(rOldNames,
lcl_DBDataToString(static_cast<SwDBNameInfField*>(pField)->GetRealDBData())))
{ static_cast<SwDBNameInfField*>(pField)->SetDBData(aNewDBData);
}
[[fallthrough]]; case SwFieldIds::HiddenText: case SwFieldIds::HiddenPara:
pField->SetPar1( ReplaceUsedDBs(rOldNames, rNewName, pField->GetPar1()) );
bExpand = true; break;
case SwFieldIds::SetExp: case SwFieldIds::GetExp: case SwFieldIds::Table:
pField->SetPar2( ReplaceUsedDBs(rOldNames, rNewName, pField->GetFormula()) );
bExpand = true; break; default: break;
}
void SwDocUpdateField::InsDelFieldInFieldLst( bool bIns, const SwTextField& rField )
{ const SwFieldIds nWhich = rField.GetFormatField().GetField()->GetTyp()->Which(); switch( nWhich )
{ case SwFieldIds::Database: case SwFieldIds::SetExp: case SwFieldIds::HiddenPara: case SwFieldIds::HiddenText: case SwFieldIds::DbNumSet: case SwFieldIds::DbNextSet: case SwFieldIds::DbSetNumber: case SwFieldIds::GetExp: break; // these have to be added/removed!
default: return;
}
SetFieldsDirty( true ); if (!m_pFieldSortList)
{ if( !bIns ) // if list is present and deleted return; // don't do a thing
m_pFieldSortList.reset(new SetGetExpFields);
}
if( bIns ) // insert anew:
GetBodyNode( rField, nWhich ); else
{ // look up via the pTextField pointer. It is a sorted list, but it's sorted by node // position. Until this is found, the search for the pointer is already done.
SetGetExpFields::size_type n = 0; while (n < m_pFieldSortList->size())
{ if (&rField == (*m_pFieldSortList)[n]->GetPointer())
{
m_pFieldSortList->erase_at(n); // one field can occur multiple times
} else
{
++n;
}
}
}
}
void SwDocUpdateField::MakeFieldList_( SwDoc& rDoc, int eGetMode )
{ // new version: walk all fields of the attribute pool
m_pFieldSortList.reset(new SetGetExpFields);
// consider and unhide sections // with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>) // notes by OD: // eGetMode == GETFLD_CALC in call from methods SwDoc::FieldsToCalc // eGetMode == GETFLD_EXPAND in call from method SwDoc::FieldsToExpand // eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFields // I figured out that hidden section only have to be shown, // if fields have updated (call by SwDoc::UpdateExpFields) and thus // the hide conditions of section have to be updated. // For correct updating the hide condition of a section, its position // have to be known in order to insert the hide condition as a new // expression field into the sorted field list (<m_pFieldSortList>). if ( eGetMode == GETFLD_ALL ) // Collect the sections first. Supply sections that are hidden by condition // with frames so that the contained fields are sorted properly.
{ // In order for the frames to be created the right way, they have to be expanded // from top to bottom
std::vector<SwNodeOffset> aTmpArr; for (constauto& rFormat : rDoc.GetSections())
{
SwSection* pSect = rFormat->GetSection(); if( !pSect || !pSect->IsHidden() || pSect->GetCondition().isEmpty() ) continue; if (SwSectionNode* pSectNd = pSect->GetFormat()->GetSectionNode())
{
SwNodeOffset nIdx = pSectNd->GetIndex();
aTmpArr.push_back( nIdx );
}
}
std::sort(aTmpArr.begin(), aTmpArr.end());
// add all to the list so that they are sorted for (constauto &nId : aTmpArr)
{
SwSectionNode const& rSectionNode(*rDoc.GetNodes()[ nId ]->GetSectionNode());
GetBodyNodeGeneric(rSectionNode, rSectionNode);
}
// bookmarks with hide conditions, handle similar to sections autoconst& rIDMA(*rDoc.getIDocumentMarkAccess()); for (auto it = rIDMA.getBookmarksBegin(); it != rIDMA.getBookmarksEnd(); ++it)
{
::sw::mark::Bookmark const* const pBookmark(*it);
assert(pBookmark); if (!pBookmark->GetHideCondition().isEmpty())
{
GetBodyNodeGeneric((*it)->GetMarkStart().GetNode(), *pBookmark);
}
}
}
// always the first! (in tab headline, header-/footer)
Point aPt;
std::pair<Point, bool> const tmp(aPt, false); // need pos to get the frame on the correct page
SwPosition const pos(rTextNd, rTField.GetStart()); const SwFrame* pFrame = rTextNd.getLayoutFrame(
rDoc.getIDocumentLayoutAccess().GetCurrentLayout(), &pos, &tmp);
// We don't want to update fields in redlines, or those // in frames whose anchor is in redline. However, we do want to update // fields in hidden sections. So: In order to be updated, a field 1) // must have a frame, or 2) it must be in the document body. if (pFrame == nullptr && bIsInBody)
{ // try harder to get a frame for the page number
pFrame = ::sw::FindNeighbourFrameForNode(rTextNd); // possibly there is no layout at all, happens in mail merge
} if( (pFrame != nullptr) || bIsInBody )
{
pNew.reset(new SetGetExpField(rTextNd, &rTField, std::nullopt,
pFrame ? pFrame->GetPhyPageNum() : 0));
}
} else
{ // create index to determine the TextNode
SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() ); boolconst bResult = GetBodyTextNode( rDoc, aPos, *pFrame );
OSL_ENSURE(bResult, "where is the Field");
pNew.reset(new SetGetExpField(aPos.GetNode(), &rTField, aPos.GetContentIndex(),
pFrame->GetPhyPageNum()));
}
if (rNode.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex())
{ do { // middle check loop
// we need to get the anchor first // create index to determine the TextNode
SwPosition aPos(rNode);
SwContentNode const*const pCNd = rNode.IsSectionNode()
? SwNodes::GoNext(&aPos.nNode) // to the next ContentNode
: rNode.GetContentNode();
if( !pCNd || !pCNd->IsTextNode() ) break;
// always the first! (in tab headline, header-/footer)
Point aPt;
std::pair<Point, bool> const tmp(aPt, false); const SwContentFrame* pFrame = pCNd->getLayoutFrame(
rDoc.getIDocumentLayoutAccess().GetCurrentLayout(),
nullptr, &tmp); if( !pFrame ) break;
boolconst bResult = GetBodyTextNode( rDoc, aPos, *pFrame );
OSL_ENSURE(bResult, "where is the Field");
pNew.reset(new SetGetExpField(rCond, &aPos, pFrame->GetPhyPageNum()));
} while( false );
}
if( !pNew )
{ // try harder to get a frame for the page number
SwFrame const*const pFrame = ::sw::FindNeighbourFrameForNode(rNode);
pNew.reset(new SetGetExpField(rCond, nullptr, pFrame ? pFrame->GetPhyPageNum() : 0));
}
m_pFieldSortList->insert( std::move(pNew) );
}
void SwDocUpdateField::InsertFieldType( const SwFieldType& rType )
{
OUString sFieldName; switch( rType.Which() )
{ case SwFieldIds::User :
sFieldName = static_cast<const SwUserFieldType&>(rType).GetName().toString(); break; case SwFieldIds::SetExp:
sFieldName = static_cast<const SwSetExpFieldType&>(rType).GetName().toString(); break; default:
OSL_ENSURE( false, "No valid field type" );
}
if( sFieldName.isEmpty() ) return;
SetFieldsDirty( true ); // look up and remove from the hash table
sFieldName = GetAppCharClass().lowercase( sFieldName );
auto it = m_FieldTypeTable.find( sFieldName ); if( it == m_FieldTypeTable.end() )
m_FieldTypeTable.insert( { sFieldName, &rType } );
}
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.