// check these before Range to prevent misinterpretation of text frames // and cells also implement XTextRange
SwXFrame *const pFrame = dynamic_cast<SwXFrame*>(xIfc.get()); if (pFrame)
{ const SwFrameFormat *const pFrameFormat(pFrame->GetFrameFormat()); if (pFrameFormat && &pFrameFormat->GetDoc() == &rTargetDoc)
{
o_rFrame = std::make_pair(pFrameFormat->GetName(), pFrame->GetFlyCntType());
} return;
}
SwXCell *const pCell = dynamic_cast<SwXCell*>(xIfc.get()); if (pCell)
{
SwFrameFormat *const pFrameFormat(pCell->GetFrameFormat()); if (pFrameFormat && &pFrameFormat->GetDoc() == &rTargetDoc)
{
SwTableBox * pBox = pCell->GetTableBox();
SwTable *const pTable = SwTable::FindTable(pFrameFormat); // ??? what's the benefit of setting pBox in this convoluted way?
pBox = pCell->FindBox(pTable, pBox); if (pBox)
{
SwPaM aPam(*pBox->GetSttNd());
aPam.Move(fnMoveForward, GoInNode);
lcl_createPamCopy(o_rpPaM, aPam);
}
} return;
}
uno::Reference<text::XTextRange> const xTextRange(xIfc, UNO_QUERY); if (xTextRange.is())
{
SwUnoInternalPaM aPam(rTargetDoc); if (::sw::XTextRangeToSwPaM(aPam, xTextRange))
{
lcl_createPamCopy(o_rpPaM, aPam);
} return;
}
SwXCellRange *const pCellRange = dynamic_cast<SwXCellRange*>(xIfc.get()); if (pCellRange)
{
SwUnoCursor const*const pUnoCursor(pCellRange->GetTableCursor()); if (pUnoCursor && &pUnoCursor->GetDoc() == &rTargetDoc)
{ // probably can't copy it to o_rpPaM for this since it's // a SwTableCursor
o_rpTableCursor = dynamic_cast<SwUnoTableCursor const*>(pUnoCursor);
} return;
}
SwTextNode *const pTextNode = rPam.GetPointNode().GetTextNode(); if (&rPam.GetPointNode() == &rPam.GetMarkNode()
&& pTextNode && pTextNode->GetpSwpHints())
{
sal_Int32 nPaMStart = rPam.Start()->GetContentIndex();
sal_Int32 nPaMEnd = rPam.End()->GetContentIndex();
Sequence< OUString> aCharStyles;
SwpHints* pHints = pTextNode->GetpSwpHints(); for( size_t nAttr = 0; nAttr < pHints->Count(); ++nAttr )
{
SwTextAttr* pAttr = pHints->Get( nAttr ); if(pAttr->Which() != RES_TXTATR_CHARFMT) continue; const sal_Int32 nAttrStart = pAttr->GetStart(); const sal_Int32 nAttrEnd = *pAttr->GetEnd(); //check if the attribute touches the selection if( ( nAttrEnd > nPaMStart && nAttrStart < nPaMEnd ) ||
( !nAttrStart && !nAttrEnd && !nPaMStart && !nPaMEnd ) )
{ //check for overlapping if(nAttrStart > nPaMStart ||
nAttrEnd < nPaMEnd)
{
aCharStyles.realloc(0); break;
} else
{ //now the attribute should start before or at the selection //and it should end at the end of the selection or behind
OSL_ENSURE(nAttrStart <= nPaMStart && nAttrEnd >=nPaMEnd, "attribute overlaps or is outside"); //now the name of the style has to be added to the sequence
aCharStyles.realloc(aCharStyles.getLength() + 1);
OSL_ENSURE(pAttr->GetCharFormat().GetCharFormat(), "no character format set");
aCharStyles.getArray()[aCharStyles.getLength() - 1] =
SwStyleNameMapper::GetProgName(
pAttr->GetCharFormat().GetCharFormat()->GetName(), SwGetPoolIdFromName::ChrFmt).toString();
}
}
sal_Int16 IsNodeNumStart(SwPaM const & rPam, PropertyState& eState)
{ const SwTextNode* pTextNd = rPam.GetPointNode().GetTextNode(); // correction: check, if restart value is set at the text node and use // new method <SwTextNode::GetAttrListRestartValue()> to retrieve the value if ( pTextNd && pTextNd->GetNumRule() && pTextNd->IsListRestart() &&
pTextNd->HasAttrListRestartValue() )
{
eState = PropertyState_DIRECT_VALUE;
sal_Int16 nTmp = sal::static_int_cast< sal_Int16 >(pTextNd->GetAttrListRestartValue()); return nTmp;
}
eState = PropertyState_DEFAULT_VALUE; return -1;
}
void setNumberingProperty(const Any& rValue, SwPaM& rPam)
{
uno::Reference<XIndexReplace> xIndexReplace; if(rValue >>= xIndexReplace)
{ auto pSwNum = dynamic_cast<SwXNumberingRules*>(xIndexReplace.get()); if(pSwNum)
{
SwDoc& rDoc = rPam.GetDoc(); if(pSwNum->GetNumRule())
{
SwNumRule aRule(*pSwNum->GetNumRule()); const UIName* pNewCharStyles = pSwNum->GetNewCharStyleNames(); const UIName* pBulletFontNames = pSwNum->GetBulletFontNames(); for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
{
SwNumFormat aFormat(aRule.Get( i )); if (!pNewCharStyles[i].isEmpty() &&
!SwXNumberingRules::isInvalidStyle(pNewCharStyles[i]) &&
(!aFormat.GetCharFormat() || pNewCharStyles[i] != aFormat.GetCharFormat()->GetName()))
{ if (pNewCharStyles[i].isEmpty())
{ // FIXME // Is something missing/wrong here? // if condition is always false due to outer check!
aFormat.SetCharFormat(nullptr);
} else
{
// get CharStyle and set the rule const size_t nChCount = rDoc.GetCharFormats()->size();
SwCharFormat* pCharFormat = nullptr; for(size_t nCharFormat = 0; nCharFormat < nChCount; ++nCharFormat)
{
SwCharFormat& rChFormat = *((*(rDoc.GetCharFormats()))[nCharFormat]); if(rChFormat.GetName() == pNewCharStyles[i])
{
pCharFormat = &rChFormat; break;
}
}
if( rPam.GetNext() != &rPam ) // Multiple selection?
{
rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
SwPamRanges aRangeArr( rPam );
SwPaM aPam( *rPam.GetPoint() ); for ( size_t n = 0; n < aRangeArr.Count(); ++n )
{ // no start of a new list
rDoc.SetNumRule(aRangeArr.SetPam( n, aPam ), aRule, SwDoc::SetNumRuleMode::Default);
}
rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
} else
{ // no start of a new list
rDoc.SetNumRule(rPam, aRule, SwDoc::SetNumRuleMode::Default);
}
void GetCurPageStyle(SwPaM const & rPaM, ProgName &rString)
{ if (!rPaM.GetPointContentNode()) return; // TODO: is there an easy way to get it for tables/sections?
SwRootFrame* pLayout = rPaM.GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(); // Consider the position inside the content node, since the node may span over multiple pages // with different page styles.
SwContentFrame* pFrame = rPaM.GetPointContentNode()->getLayoutFrame(pLayout, rPaM.GetPoint()); if(pFrame)
{ const SwPageFrame* pPage = pFrame->FindPageFrame(); if(pPage)
{
SwStyleNameMapper::FillProgName(pPage->GetPageDesc()->GetName(),
rString, SwGetPoolIdFromName::PageDesc);
}
}
}
// reset special properties of the cursor void resetCursorPropertyValue(const SfxItemPropertyMapEntry& rEntry, SwPaM& rPam)
{
SwDoc& rDoc = rPam.GetDoc(); switch(rEntry.nWID)
{ case FN_UNO_PARA_STYLE : break; case FN_UNO_PAGE_STYLE : break; case FN_UNO_NUM_START_VALUE :
{
UnoActionContext aAction(&rDoc);
break; case FN_UNO_NUM_LEVEL : break; case FN_UNO_NUM_RULES: break; case FN_UNO_CHARFMT_SEQUENCE:
{
rDoc.ResetAttrs(rPam, true, { RES_TXTATR_CHARFMT });
} break;
}
}
void InsertFile(SwUnoCursor* pUnoCursor, const OUString& rURL, const uno::Sequence< beans::PropertyValue >& rOptions)
{ if (SwTextNode const*const pTextNode = pUnoCursor->GetPoint()->GetNode().GetTextNode())
{ // TODO: check meta field here too in case it ever grows a 2nd char if (pTextNode->GetTextAttrAt(pUnoCursor->GetPoint()->GetContentIndex(),
RES_TXTATR_INPUTFIELD, ::sw::GetTextAttrMode::Parent))
{ throw uno::RuntimeException(u"cannot insert file inside input field"_ustr);
}
// insert text and scan for CR characters in order to insert // paragraph breaks at those positions by calling SplitNode bool DocInsertStringSplitCR(
SwDoc &rDoc, const SwPaM &rNewCursor,
std::u16string_view rText, constbool bForceExpandHints )
{ bool bOK = true;
for (size_t i = 0; i < rText.size(); ++i)
{
sal_Unicode const ch(rText[i]); if (linguistic::IsControlChar(ch)
&& ch != '\r' && ch != '\n' && ch != '\t')
{
SAL_WARN("sw.uno", "DocInsertStringSplitCR: refusing to insert control character " << int(ch)); returnfalse;
}
}
// grouping done in InsertString is intended for typing, not API calls
::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
SwTextNode* const pTextNd =
rNewCursor.GetPoint()->GetNode().GetTextNode(); if (!pTextNd)
{
SAL_INFO("sw.uno", "DocInsertStringSplitCR: need a text node"); returnfalse;
}
OUString aText;
sal_Int32 nStartIdx = 0; const sal_Int32 nMaxLength = COMPLETE_STRING - pTextNd->GetText().getLength();
// Read the 'Redline Revert Properties' from the parameters // Check if the value exists if ( bFoundRevertProperties )
{ int nMap = 0; // Make sure that paragraph format gets its own map, otherwise e.g. fill attributes are not preserved. if (eType == RedlineType::ParagraphFormat)
{
nMap = PROPERTY_MAP_PARAGRAPH; if (!aRevertProperties.hasElements())
{ // to reject the paragraph style change, use standard style
xRedlineExtraData.reset(new SwRedlineExtraData_FormatColl( UIName(u""_ustr), RES_POOLCOLL_STANDARD, nullptr ));
}
} else
nMap = PROPERTY_MAP_TEXTPORTION_EXTENSIONS;
SfxItemPropertySet const& rPropSet = *aSwMapProvider.GetPropertySet(nMap);
// Check if there are any properties if (aRevertProperties.hasElements())
{
SwDoc& rDoc = rPaM.GetDoc();
// Build set of attributes we want to fetch
WhichRangesContainer aWhichPairs;
std::vector<SfxItemPropertyMapEntry const*> aEntries;
std::vector<uno::Any> aValues;
aEntries.reserve(aRevertProperties.getLength());
sal_uInt16 nStyleId = USHRT_MAX;
sal_uInt16 nCharStyleId = USHRT_MAX;
sal_uInt16 nNumId = USHRT_MAX; for (constauto& rRevertProperty : aRevertProperties)
{ const OUString &rPropertyName = rRevertProperty.Name;
SfxItemPropertyMapEntry const* pEntry = rPropSet.getPropertyMap().getByName(rPropertyName);
SwRangeRedline* pRedline = new SwRangeRedline( aRedlineData, rPaM );
// set IsMoved bit of the redline to show and handle moved text if ( nMovedID > 0 )
{
pRedline->SetMoved( nMovedID );
rRedlineAccess.GetRedlineTable().setMovedIDIfNeeded(nMovedID);
}
RedlineFlags nPrevMode = rRedlineAccess.GetRedlineFlags( ); // xRedlineExtraData is copied here
pRedline->SetExtraData( xRedlineExtraData.get() );
// set table row property "HasTextChangesOnly" to false // to handle tracked deletion or insertion of the table row on the UI const SvxPrintItem *pHasTextChangesOnlyProp =
rTableLine.GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT); if ( !pHasTextChangesOnlyProp || pHasTextChangesOnlyProp->GetValue() )
{
SvxPrintItem aSetTracking(RES_PRINT, false);
SwNodeIndex aInsPos( *(rTableLine.GetTabBoxes()[0]->GetSttNd()), 1 ); // as a workaround for the rows without text content, // add a redline with invisible text CH_TXT_TRACKED_DUMMY_CHAR if ( rTableLine.IsEmpty() )
{
SwPaM aPaM(aInsPos);
rDoc.getIDocumentContentOperations().InsertString( aPaM,
OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
aPaM.SetMark();
aPaM.GetMark()->SetContent(0);
makeRedline(aPaM, RedlineType::TableRowInsert == eType
? u"Insert"
: u"Delete", rRedlineProperties);
}
SwCursor aCursor( SwPosition(aInsPos), nullptr );
rDoc.SetRowNotTracked( aCursor, aSetTracking );
}
// set table row property "HasTextChangesOnly" to false // to handle tracked deletion or insertion of the table row on the UI const SvxPrintItem *pHasTextChangesOnlyProp =
rTableBox.GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT); if ( !pHasTextChangesOnlyProp || pHasTextChangesOnlyProp->GetValue() )
{
SvxPrintItem aSetTracking(RES_PRINT, false);
SwNodeIndex aInsPos( *rTableBox.GetSttNd(), 1 ); // as a workaround for the cells without text content, // add a redline with invisible text CH_TXT_TRACKED_DUMMY_CHAR if ( rTableBox.IsEmpty() )
{
SwPaM aPaM(aInsPos);
rDoc.getIDocumentContentOperations().InsertString( aPaM,
OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
aPaM.SetMark();
aPaM.GetMark()->SetContent(0);
makeRedline(aPaM, RedlineType::TableCellInsert == eType
? u"Insert"
: u"Delete", rRedlineProperties);
}
SwCursor aCursor( SwPosition(aInsPos), nullptr );
rDoc.SetBoxAttr( aCursor, aSetTracking );
}
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.