summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/docxattributeoutput.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/docxattributeoutput.cxx')
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx379
1 files changed, 272 insertions, 107 deletions
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index e74ea397c40a..2d6ed05c3247 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -137,6 +137,7 @@
#include <frmatr.hxx>
#include <txtatr.hxx>
#include <frameformats.hxx>
+#include <textcontentcontrol.hxx>
#include <o3tl/string_view.hxx>
#include <o3tl/unit_conversion.hxx>
@@ -363,16 +364,6 @@ void DocxAttributeOutput::WriteFloatingTable(ww8::Frame const* pParentFrame)
m_rExport.SetFloatingTableFrame(nullptr);
}
-void DocxAttributeOutput::StartContentControl(const SwFormatContentControl& rFormatContentControl)
-{
- m_pContentControl = rFormatContentControl.GetContentControl();
-}
-
-void DocxAttributeOutput::EndContentControl()
-{
- ++m_nCloseContentControlInThisRun;
-}
-
static void checkAndWriteFloatingTables(DocxAttributeOutput& rDocxAttributeOutput)
{
const auto& rExport = rDocxAttributeOutput.GetExport();
@@ -624,16 +615,24 @@ void SdtBlockHelper::DeleteAndResetTheLists()
m_pTextAttrs.clear();
if (!m_aAlias.isEmpty())
m_aAlias.clear();
+ if (!m_aTag.isEmpty())
+ m_aTag.clear();
+ if (!m_aLock.isEmpty())
+ m_aLock.clear();
if (!m_aPlaceHolderDocPart.isEmpty())
m_aPlaceHolderDocPart.clear();
if (!m_aColor.isEmpty())
m_aColor.clear();
- m_bHasId = false;
+ if (!m_aAppearance.isEmpty())
+ m_aAppearance.clear();
+ m_bShowingPlaceHolder = false;
+ m_nId = 0;
+ m_nTabIndex = 0;
}
void SdtBlockHelper::WriteSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer, bool bRunTextIsOn, bool bParagraphHasDrawing)
{
- if (m_nSdtPrToken <= 0 && !m_pDataBindingAttrs.is() && !m_bHasId)
+ if (m_nSdtPrToken <= 0 && !m_pDataBindingAttrs.is() && !m_nId)
return;
// sdt start mark
@@ -688,19 +687,15 @@ void SdtBlockHelper::WriteSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer, b
// clear sdt status
m_nSdtPrToken = 0;
- m_pTokenChildren.clear();
- m_pDataBindingAttrs.clear();
- m_pTextAttrs.clear();
- m_aAlias.clear();
- m_bHasId = false;
+ DeleteAndResetTheLists();
}
void SdtBlockHelper::WriteExtraParams(::sax_fastparser::FSHelperPtr& pSerializer)
{
- if (m_nSdtPrToken == FSNS(XML_w, XML_id) || m_bHasId)
- //Word won't open a document with an empty id tag, we fill it with a random number
- pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val),
- OString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max())));
+ if (m_nId)
+ {
+ pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val), OString::number(m_nId));
+ }
if (m_pDataBindingAttrs.is())
{
@@ -720,13 +715,32 @@ void SdtBlockHelper::WriteExtraParams(::sax_fastparser::FSHelperPtr& pSerializer
pSerializer->singleElementNS(XML_w, XML_docPart, FSNS(XML_w, XML_val), m_aPlaceHolderDocPart);
pSerializer->endElementNS(XML_w, XML_placeholder);
}
+
+ if (m_bShowingPlaceHolder)
+ pSerializer->singleElementNS(XML_w, XML_showingPlcHdr);
+
if (!m_aColor.isEmpty())
{
pSerializer->singleElementNS(XML_w15, XML_color, FSNS(XML_w, XML_val), m_aColor);
}
+ if (!m_aAppearance.isEmpty())
+ {
+ pSerializer->singleElementNS(XML_w15, XML_appearance, FSNS(XML_w15, XML_val), m_aAppearance);
+ }
+
if (!m_aAlias.isEmpty())
pSerializer->singleElementNS(XML_w, XML_alias, FSNS(XML_w, XML_val), m_aAlias);
+
+ if (!m_aTag.isEmpty())
+ pSerializer->singleElementNS(XML_w, XML_tag, FSNS(XML_w, XML_val), m_aTag);
+
+ if (m_nTabIndex)
+ pSerializer->singleElementNS(XML_w, XML_tabIndex, FSNS(XML_w, XML_val),
+ OString::number(m_nTabIndex));
+
+ if (!m_aLock.isEmpty())
+ pSerializer->singleElementNS(XML_w, XML_lock, FSNS(XML_w, XML_val), m_aLock);
}
void SdtBlockHelper::EndSdtBlock(::sax_fastparser::FSHelperPtr& pSerializer)
@@ -826,13 +840,41 @@ void SdtBlockHelper::GetSdtParamsFromGrabBag(const uno::Sequence<beans::Property
m_aColor = sValue;
}
}
+ else if (aPropertyValue.Name == "ooxml:CT_SdtPr_appearance")
+ {
+ if (!(aPropertyValue.Value >>= m_aAppearance))
+ SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt appearance value");
+ }
+ else if (aPropertyValue.Name == "ooxml:CT_SdtPr_showingPlcHdr")
+ {
+ if (!(aPropertyValue.Value >>= m_bShowingPlaceHolder))
+ SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt ShowingPlcHdr");
+ }
else if (aPropertyValue.Name == "ooxml:CT_SdtPr_alias" && m_aAlias.isEmpty())
{
if (!(aPropertyValue.Value >>= m_aAlias))
SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt alias value");
}
+ else if (aPropertyValue.Name == "ooxml:CT_SdtPr_tag" && m_aTag.isEmpty())
+ {
+ if (!(aPropertyValue.Value >>= m_aTag))
+ SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt tag value");
+ }
else if (aPropertyValue.Name == "ooxml:CT_SdtPr_id")
- m_bHasId = true;
+ {
+ if (!(aPropertyValue.Value >>= m_nId))
+ SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt id value");
+ }
+ else if (aPropertyValue.Name == "ooxml:CT_SdtPr_tabIndex" && !m_nTabIndex)
+ {
+ if (!(aPropertyValue.Value >>= m_nTabIndex))
+ SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt tabIndex value");
+ }
+ else if (aPropertyValue.Name == "ooxml:CT_SdtPr_lock" && m_aLock.isEmpty())
+ {
+ if (!(aPropertyValue.Value >>= m_aLock))
+ SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt lock value");
+ }
else if (aPropertyValue.Name == "ooxml:CT_SdtPr_citation")
m_nSdtPrToken = FSNS(XML_w, XML_citation);
else if (aPropertyValue.Name == "ooxml:CT_SdtPr_docPartObj" ||
@@ -1094,7 +1136,6 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT
//These should be written out to the actual Node and not to the anchor.
//Clear them as they will be repopulated when the node is processed.
m_aParagraphSdt.m_nSdtPrToken = 0;
- m_aParagraphSdt.m_bHasId = false;
m_aParagraphSdt.DeleteAndResetTheLists();
}
@@ -1466,13 +1507,13 @@ void DocxAttributeOutput::EndParagraphProperties(const SfxItemSet& rParagraphMar
if ( pRedlineParagraphMarkerDeleted )
{
- StartRedline( pRedlineParagraphMarkerDeleted );
- EndRedline( pRedlineParagraphMarkerDeleted );
+ StartRedline( pRedlineParagraphMarkerDeleted, /*bLastRun=*/true );
+ EndRedline( pRedlineParagraphMarkerDeleted, /*bLastRun=*/true );
}
if ( pRedlineParagraphMarkerInserted )
{
- StartRedline( pRedlineParagraphMarkerInserted );
- EndRedline( pRedlineParagraphMarkerInserted );
+ StartRedline( pRedlineParagraphMarkerInserted, /*bLastRun=*/true );
+ EndRedline( pRedlineParagraphMarkerInserted, /*bLastRun=*/true );
}
// mergeTopMarks() after paragraph mark properties child elements.
@@ -1510,7 +1551,8 @@ void DocxAttributeOutput::EndParagraphProperties(const SfxItemSet& rParagraphMar
m_pSerializer->endElementNS(XML_w, XML_smartTag);
}
- if ( m_nColBreakStatus == COLBRK_WRITE || m_nColBreakStatus == COLBRK_WRITEANDPOSTPONE )
+ if ((m_nColBreakStatus == COLBRK_WRITE || m_nColBreakStatus == COLBRK_WRITEANDPOSTPONE)
+ && !m_rExport.SdrExporter().IsDMLAndVMLDrawingOpen())
{
m_pSerializer->startElementNS(XML_w, XML_r);
m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "column");
@@ -1522,7 +1564,8 @@ void DocxAttributeOutput::EndParagraphProperties(const SfxItemSet& rParagraphMar
m_nColBreakStatus = COLBRK_NONE;
}
- if ( m_bPostponedPageBreak && !m_bWritingHeaderFooter )
+ if (m_bPostponedPageBreak && !m_bWritingHeaderFooter
+ && !m_rExport.SdrExporter().IsDMLAndVMLDrawingOpen())
{
m_pSerializer->startElementNS(XML_w, XML_r);
m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "page");
@@ -1575,7 +1618,7 @@ void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData, sal_Int32
m_pSerializer->mark(Tag_StartRun_3); // let's call it "postponed text"
}
-void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /*bLastRun*/)
+void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, sal_Int32 nLen, bool bLastRun)
{
int nFieldsInPrevHyperlink = m_nFieldsInHyperlink;
// Reset m_nFieldsInHyperlink if a new hyperlink is about to start
@@ -1632,12 +1675,6 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
m_bEndCharSdt = false;
}
- for (; m_nCloseContentControlInPreviousRun > 0; --m_nCloseContentControlInPreviousRun)
- {
- // Not the last run of this paragraph.
- WriteContentControlEnd();
- }
-
if ( m_closeHyperlinkInPreviousRun )
{
if ( m_startedHyperlink )
@@ -1665,9 +1702,9 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
// InputField with extra grabbag params - it is sdt field
(pIt->eType == ww::eFILLIN && static_cast<const SwInputField*>(pIt->pField.get())->getGrabBagParams().hasElements())))
{
- StartRedline( m_pRedlineData );
+ StartRedline( m_pRedlineData, bLastRun );
StartField_Impl( pNode, nPos, *pIt, true );
- EndRedline( m_pRedlineData );
+ EndRedline( m_pRedlineData, bLastRun );
if (m_startedHyperlink)
++m_nFieldsInHyperlink;
@@ -1735,10 +1772,8 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
m_nHyperLinkCount++;
}
- WriteContentControlStart();
-
// if there is some redlining in the document, output it
- StartRedline( m_pRedlineData );
+ StartRedline( m_pRedlineData, bLastRun );
// XML_r node should be surrounded with bookmark-begin and bookmark-end nodes if it has bookmarks.
// The same is applied for permission ranges.
@@ -1782,6 +1817,17 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
DoWriteBookmarkStartIfExist(nPos);
+ if (nLen != -1)
+ {
+ SwTextAttr* pAttr = pNode->GetTextAttrAt(nPos, RES_TXTATR_CONTENTCONTROL, SwTextNode::DEFAULT);
+ if (pAttr && pAttr->GetStart() == nPos)
+ {
+ auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
+ m_pContentControl = pTextContentControl->GetContentControl().GetContentControl();
+ WriteContentControlStart();
+ }
+ }
+
m_pSerializer->startElementNS(XML_w, XML_r);
if(GetExport().m_bTabInTOC && m_pHyperlinkAttrList.is())
{
@@ -1800,9 +1846,19 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
// append the actual run end
m_pSerializer->endElementNS( XML_w, XML_r );
+ if (nLen != -1)
+ {
+ sal_Int32 nEnd = nPos + nLen;
+ SwTextAttr* pAttr = pNode->GetTextAttrAt(nPos, RES_TXTATR_CONTENTCONTROL, SwTextNode::DEFAULT);
+ if (pAttr && *pAttr->GetEnd() == nEnd)
+ {
+ WriteContentControlEnd();
+ }
+ }
+
// if there is some redlining in the document, output it
// (except in the case of fields with multiple runs)
- EndRedline( m_pRedlineData );
+ EndRedline( m_pRedlineData, bLastRun );
// enclose in a sdt block, if necessary: if one is already started, then don't do it for now
// (so on export sdt blocks are never nested ATM)
@@ -1847,12 +1903,6 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
m_pRedlineData = nullptr;
}
- for (; m_nCloseContentControlInThisRun > 0; --m_nCloseContentControlInThisRun)
- {
- // Last run of this paragraph.
- WriteContentControlEnd();
- }
-
if ( m_closeHyperlinkInThisRun )
{
if ( m_startedHyperlink )
@@ -1912,7 +1962,7 @@ void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /
if ( m_pRedlineData )
{
- EndRedline( m_pRedlineData );
+ EndRedline( m_pRedlineData, bLastRun );
m_pRedlineData = nullptr;
}
@@ -2218,11 +2268,9 @@ void DocxAttributeOutput::WriteFFData( const FieldInfos& rInfos )
}
else if ( rInfos.eType == ww::eFORMCHECKBOX )
{
- OUString sName;
+ const OUString sName = params.getName();
bool bChecked = false;
- params.extractParam( ODF_FORMCHECKBOX_NAME, sName );
-
const sw::mark::ICheckboxFieldmark* pCheckboxFm = dynamic_cast<const sw::mark::ICheckboxFieldmark*>(&rFieldmark);
if ( pCheckboxFm && pCheckboxFm->IsChecked() )
bChecked = true;
@@ -2336,6 +2384,11 @@ void DocxAttributeOutput::WriteContentControlStart()
return;
}
+ if (m_bAnchorLinkedToNode)
+ {
+ return;
+ }
+
m_pSerializer->startElementNS(XML_w, XML_sdt);
m_pSerializer->startElementNS(XML_w, XML_sdtPr);
if (!m_pContentControl->GetPlaceholderDocPart().isEmpty())
@@ -2360,6 +2413,44 @@ void DocxAttributeOutput::WriteContentControlStart()
m_pContentControl->GetColor());
}
+ if (!m_pContentControl->GetAppearance().isEmpty())
+ {
+ m_pSerializer->singleElementNS(XML_w15, XML_appearance, FSNS(XML_w15, XML_val),
+ m_pContentControl->GetAppearance());
+ }
+
+ if (!m_pContentControl->GetAlias().isEmpty())
+ {
+ m_pSerializer->singleElementNS(XML_w, XML_alias, FSNS(XML_w, XML_val),
+ m_pContentControl->GetAlias());
+ }
+
+ if (!m_pContentControl->GetTag().isEmpty())
+ {
+ m_pSerializer->singleElementNS(XML_w, XML_tag, FSNS(XML_w, XML_val),
+ m_pContentControl->GetTag());
+ }
+
+ if (m_pContentControl->GetId())
+ {
+ m_pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val),
+ OString::number(m_pContentControl->GetId()));
+ }
+
+ if (m_pContentControl->GetTabIndex())
+ {
+ // write the unsigned value as as if it were signed since that is all we can import
+ const sal_Int32 nTabIndex = static_cast<sal_Int32>(m_pContentControl->GetTabIndex());
+ m_pSerializer->singleElementNS(XML_w, XML_tabIndex, FSNS(XML_w, XML_val),
+ OString::number(nTabIndex));
+ }
+
+ if (!m_pContentControl->GetLock().isEmpty())
+ {
+ m_pSerializer->singleElementNS(XML_w, XML_lock, FSNS(XML_w, XML_val),
+ m_pContentControl->GetLock());
+ }
+
if (m_pContentControl->GetShowingPlaceHolder())
{
m_pSerializer->singleElementNS(XML_w, XML_showingPlcHdr);
@@ -2390,16 +2481,35 @@ void DocxAttributeOutput::WriteContentControlStart()
m_pSerializer->endElementNS(XML_w14, XML_checkbox);
}
- if (m_pContentControl->HasListItems())
+ if (m_pContentControl->GetComboBox() || m_pContentControl->GetDropDown())
{
- m_pSerializer->startElementNS(XML_w, XML_dropDownList);
+ if (m_pContentControl->GetComboBox())
+ {
+ m_pSerializer->startElementNS(XML_w, XML_comboBox);
+ }
+ else
+ {
+ m_pSerializer->startElementNS(XML_w, XML_dropDownList);
+ }
for (const auto& rItem : m_pContentControl->GetListItems())
{
- m_pSerializer->singleElementNS(XML_w, XML_listItem,
- FSNS(XML_w, XML_displayText), rItem.m_aDisplayText,
- FSNS(XML_w, XML_value), rItem.m_aValue);
+ rtl::Reference<FastAttributeList> xAttributes = FastSerializerHelper::createAttrList();
+ if (!rItem.m_aDisplayText.isEmpty())
+ {
+ // If there is no display text, need to omit the attribute, not write an empty one.
+ xAttributes->add(FSNS(XML_w, XML_displayText), rItem.m_aDisplayText);
+ }
+ xAttributes->add(FSNS(XML_w, XML_value), rItem.m_aValue);
+ m_pSerializer->singleElementNS(XML_w, XML_listItem, xAttributes);
+ }
+ if (m_pContentControl->GetComboBox())
+ {
+ m_pSerializer->endElementNS(XML_w, XML_comboBox);
+ }
+ else
+ {
+ m_pSerializer->endElementNS(XML_w, XML_dropDownList);
}
- m_pSerializer->endElementNS(XML_w, XML_dropDownList);
}
if (m_pContentControl->GetDate())
@@ -2428,8 +2538,33 @@ void DocxAttributeOutput::WriteContentControlStart()
m_pSerializer->endElementNS(XML_w, XML_date);
}
+ if (m_pContentControl->GetPlainText())
+ {
+ m_pSerializer->singleElementNS(XML_w, XML_text);
+ }
+
m_pSerializer->endElementNS(XML_w, XML_sdtPr);
m_pSerializer->startElementNS(XML_w, XML_sdtContent);
+
+ const OUString& rPrefixMapping = m_pContentControl->GetDataBindingPrefixMappings();
+ const OUString& rXpath = m_pContentControl->GetDataBindingXpath();
+ if (!rXpath.isEmpty())
+ {
+ // This content control has a data binding, update the data source.
+ SwTextContentControl* pTextAttr = m_pContentControl->GetTextAttr();
+ SwTextNode* pTextNode = m_pContentControl->GetTextNode();
+ SwPosition aPoint(*pTextNode, pTextAttr->GetStart());
+ SwPosition aMark(*pTextNode, *pTextAttr->GetEnd());
+ SwPaM aPam(aMark, aPoint);
+ OUString aSnippet = aPam.GetText();
+ static sal_Unicode const aForbidden[] = {
+ CH_TXTATR_BREAKWORD,
+ 0
+ };
+ aSnippet = comphelper::string::removeAny(aSnippet, aForbidden);
+ m_rExport.AddSdtData(rPrefixMapping, rXpath, aSnippet);
+ }
+
m_pContentControl = nullptr;
}
@@ -3337,7 +3472,8 @@ bool DocxAttributeOutput::FootnoteEndnoteRefTag()
the switch in DocxAttributeOutput::RunText() nicer ;-)
*/
static bool impl_WriteRunText( FSHelperPtr const & pSerializer, sal_Int32 nTextToken,
- const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true )
+ const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true,
+ const OUString& rSymbolFont = OUString() )
{
const sal_Unicode *pBegin = rBegin;
@@ -3348,32 +3484,39 @@ static bool impl_WriteRunText( FSHelperPtr const & pSerializer, sal_Int32 nTextT
if ( pBegin >= pEnd )
return false; // we want to write at least one character
- // we have to add 'preserve' when starting/ending with space
- if ( *pBegin == ' ' || *( pEnd - 1 ) == ' ' )
+ bool bIsSymbol = !rSymbolFont.isEmpty();
+
+ std::u16string_view aView( pBegin, pEnd - pBegin );
+ if (bIsSymbol)
{
- pSerializer->startElementNS(XML_w, nTextToken, FSNS(XML_xml, XML_space), "preserve");
+ for (char16_t aChar : aView)
+ {
+ pSerializer->singleElementNS(XML_w, XML_sym,
+ FSNS(XML_w, XML_font), rSymbolFont,
+ FSNS(XML_w, XML_char), OString::number(aChar, 16));
+ }
}
else
- pSerializer->startElementNS(XML_w, nTextToken);
-
- pSerializer->writeEscaped( std::u16string_view( pBegin, pEnd - pBegin ) );
+ {
+ // we have to add 'preserve' when starting/ending with space
+ if ( *pBegin == ' ' || *( pEnd - 1 ) == ' ' )
+ pSerializer->startElementNS(XML_w, nTextToken, FSNS(XML_xml, XML_space), "preserve");
+ else
+ pSerializer->startElementNS(XML_w, nTextToken);
- pSerializer->endElementNS( XML_w, nTextToken );
+ pSerializer->writeEscaped( aView );
+ pSerializer->endElementNS( XML_w, nTextToken );
+ }
return true;
}
-void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding /*eCharSet*/ )
+void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding /*eCharSet*/, const OUString& rSymbolFont )
{
if( m_closeHyperlinkInThisRun )
{
m_closeHyperlinkInPreviousRun = true;
}
- if (m_nCloseContentControlInThisRun > 0)
- {
- ++m_nCloseContentControlInPreviousRun;
- --m_nCloseContentControlInThisRun;
- }
m_bRunTextIsOn = true;
// one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
const sal_Unicode *pBegin = rText.getStr();
@@ -3428,7 +3571,7 @@ void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding /*eCh
}
}
- impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false );
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false, rSymbolFont );
}
void DocxAttributeOutput::RawText(const OUString& rText, rtl_TextEncoding /*eCharSet*/)
@@ -3440,7 +3583,7 @@ void DocxAttributeOutput::StartRuby( const SwTextNode& rNode, sal_Int32 nPos, co
{
WW8Ruby aWW8Ruby( rNode, rRuby, GetExport() );
SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::StartRuby( const SwTextNode& rNode, const SwFormatRuby& rRuby )" );
- EndRun( &rNode, nPos ); // end run before starting ruby to avoid nested runs, and overlap
+ EndRun( &rNode, nPos, -1 ); // end run before starting ruby to avoid nested runs, and overlap
assert(!m_closeHyperlinkInThisRun); // check that no hyperlink overlaps ruby
assert(!m_closeHyperlinkInPreviousRun);
m_pSerializer->startElementNS(XML_w, XML_r);
@@ -3484,7 +3627,7 @@ void DocxAttributeOutput::StartRuby( const SwTextNode& rNode, sal_Int32 nPos, co
EndRunProperties( nullptr );
RunText( rRuby.GetText( ) );
- EndRun( &rNode, nPos );
+ EndRun( &rNode, nPos, -1 );
m_pSerializer->endElementNS( XML_w, XML_rt );
m_pSerializer->startElementNS(XML_w, XML_rubyBase);
@@ -3494,7 +3637,7 @@ void DocxAttributeOutput::StartRuby( const SwTextNode& rNode, sal_Int32 nPos, co
void DocxAttributeOutput::EndRuby(const SwTextNode& rNode, sal_Int32 nPos)
{
SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::EndRuby()" );
- EndRun( &rNode, nPos );
+ EndRun( &rNode, nPos, -1 );
m_pSerializer->endElementNS( XML_w, XML_rubyBase );
m_pSerializer->endElementNS( XML_w, XML_ruby );
m_pSerializer->endElementNS( XML_w, XML_r );
@@ -3725,7 +3868,12 @@ void DocxAttributeOutput::Redline( const SwRedlineData* pRedlineData)
m_pSerializer->startElementNS(XML_w, XML_pPr);
- OString sStyleName = MSWordStyles::CreateStyleId( sParaStyleName );
+ OString sStyleName;
+ if (auto format = m_rExport.m_rDoc.FindTextFormatCollByName(sParaStyleName))
+ if (auto slot = m_rExport.m_pStyles->GetSlot(format); slot != 0xfff)
+ sStyleName = m_rExport.m_pStyles->GetStyleId(slot);
+ if (sStyleName.isEmpty())
+ sStyleName = MSWordStyles::CreateStyleId(sParaStyleName);
if ( !sStyleName.isEmpty() )
m_pSerializer->singleElementNS(XML_w, XML_pStyle, FSNS(XML_w, XML_val), sStyleName);
@@ -3768,13 +3916,14 @@ void DocxAttributeOutput::Redline( const SwRedlineData* pRedlineData)
// The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
// 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
// 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
-void DocxAttributeOutput::StartRedline( const SwRedlineData * pRedlineData )
+void DocxAttributeOutput::StartRedline( const SwRedlineData * pRedlineData, bool bLastRun )
{
if ( !pRedlineData )
return;
// write out stack of this redline recursively (first the oldest)
- StartRedline( pRedlineData->Next() );
+ if ( !bLastRun )
+ StartRedline( pRedlineData->Next(), false );
OString aId( OString::number( m_nRedlineId++ ) );
@@ -3817,7 +3966,7 @@ void DocxAttributeOutput::StartRedline( const SwRedlineData * pRedlineData )
}
}
-void DocxAttributeOutput::EndRedline( const SwRedlineData * pRedlineData )
+void DocxAttributeOutput::EndRedline( const SwRedlineData * pRedlineData, bool bLastRun )
{
if ( !pRedlineData || m_bWritingField )
return;
@@ -3841,7 +3990,8 @@ void DocxAttributeOutput::EndRedline( const SwRedlineData * pRedlineData )
}
// write out stack of this redline recursively (first the newest)
- EndRedline( pRedlineData->Next() );
+ if ( !bLastRun )
+ EndRedline( pRedlineData->Next(), false );
}
void DocxAttributeOutput::FormatDrop( const SwTextNode& /*rNode*/, const SwFormatDrop& /*rSwFormatDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t )
@@ -6879,6 +7029,11 @@ void DocxAttributeOutput::pushToTableExportContext(DocxTableExportContext& rCont
rContext.m_bStartedParaSdt = m_aParagraphSdt.m_bStartedSdt;
m_aParagraphSdt.m_bStartedSdt = false;
+ rContext.m_bStartedRunSdt = m_aRunSdt.m_bStartedSdt;
+ m_aRunSdt.m_bStartedSdt = false;
+
+ rContext.m_nHyperLinkCount = m_nHyperLinkCount;
+ m_nHyperLinkCount = 0;
}
void DocxAttributeOutput::popFromTableExportContext(DocxTableExportContext const & rContext)
@@ -6887,6 +7042,8 @@ void DocxAttributeOutput::popFromTableExportContext(DocxTableExportContext const
m_tableReference->m_bTableCellOpen = rContext.m_bTableCellOpen;
m_tableReference->m_nTableDepth = rContext.m_nTableDepth;
m_aParagraphSdt.m_bStartedSdt = rContext.m_bStartedParaSdt;
+ m_aRunSdt.m_bStartedSdt = rContext.m_bStartedRunSdt;
+ m_nHyperLinkCount = rContext.m_nHyperLinkCount;
}
void DocxAttributeOutput::WriteTextBox(uno::Reference<drawing::XShape> xShape)
@@ -7021,7 +7178,7 @@ static bool lcl_guessQFormat(const OUString& rName, sal_uInt16 nWwId)
}
void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType,
- sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nLink, sal_uInt16 nWwId, sal_uInt16 nId, bool bAutoUpdate )
+ sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nLink, sal_uInt16 nWwId, sal_uInt16 nSlot, bool bAutoUpdate )
{
bool bQFormat = false, bUnhideWhenUsed = false, bSemiHidden = false, bLocked = false, bDefault = false, bCustomStyle = false;
OUString aRsid, aUiPriority;
@@ -7029,12 +7186,12 @@ void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType,
uno::Any aAny;
if (eType == STYLE_TYPE_PARA || eType == STYLE_TYPE_CHAR)
{
- const SwFormat* pFormat = m_rExport.m_pStyles->GetSwFormat(nId);
+ const SwFormat* pFormat = m_rExport.m_pStyles->GetSwFormat(nSlot);
pFormat->GetGrabBagItem(aAny);
}
else
{
- const SwNumRule* pRule = m_rExport.m_pStyles->GetSwNumRule(nId);
+ const SwNumRule* pRule = m_rExport.m_pStyles->GetSwNumRule(nSlot);
pRule->GetGrabBagItem(aAny);
}
const uno::Sequence<beans::PropertyValue>& rGrabBag = aAny.get< uno::Sequence<beans::PropertyValue> >();
@@ -7061,28 +7218,25 @@ void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType,
SAL_WARN("sw.ww8", "Unhandled style property: " << rProp.Name);
}
- // MSO exports English names and writerfilter only recognize them.
- const char *pEnglishName = nullptr;
const char* pType = nullptr;
switch (eType)
{
case STYLE_TYPE_PARA:
pType = "paragraph";
- if ( nWwId < ww::stiMax)
- pEnglishName = ww::GetEnglishNameFromSti( static_cast<ww::sti>(nWwId ) );
break;
- case STYLE_TYPE_CHAR: pType = "character"; break;
+ case STYLE_TYPE_CHAR:
+ pType = "character";
+ break;
case STYLE_TYPE_LIST: pType = "numbering"; break;
}
pStyleAttributeList->add(FSNS( XML_w, XML_type ), pType);
- pStyleAttributeList->add(FSNS(XML_w, XML_styleId), m_rExport.m_pStyles->GetStyleId(nId));
+ pStyleAttributeList->add(FSNS(XML_w, XML_styleId), m_rExport.m_pStyles->GetStyleId(nSlot));
if (bDefault)
pStyleAttributeList->add(FSNS(XML_w, XML_default), "1");
if (bCustomStyle)
pStyleAttributeList->add(FSNS(XML_w, XML_customStyle), "1");
m_pSerializer->startElementNS( XML_w, XML_style, pStyleAttributeList);
- m_pSerializer->singleElementNS( XML_w, XML_name,
- FSNS( XML_w, XML_val ), pEnglishName ? pEnglishName : rName.toUtf8() );
+ m_pSerializer->singleElementNS(XML_w, XML_name, FSNS(XML_w, XML_val), rName);
if ( nBase != 0x0FFF && eType != STYLE_TYPE_LIST)
{
@@ -7090,7 +7244,7 @@ void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType,
FSNS( XML_w, XML_val ), m_rExport.m_pStyles->GetStyleId(nBase) );
}
- if ( nNext != nId && eType != STYLE_TYPE_LIST)
+ if ( nNext != nSlot && eType != STYLE_TYPE_LIST)
{
m_pSerializer->singleElementNS( XML_w, XML_next,
FSNS( XML_w, XML_val ), m_rExport.m_pStyles->GetStyleId(nNext) );
@@ -7703,10 +7857,16 @@ void DocxAttributeOutput::EmbedFont( std::u16string_view name, FontFamily family
{
if( !m_rExport.m_rDoc.getIDocumentSettingAccess().get( DocumentSettingId::EMBED_FONTS ))
return; // no font embedding with this document
- EmbedFontStyle( name, XML_embedRegular, family, ITALIC_NONE, WEIGHT_NORMAL, pitch );
- EmbedFontStyle( name, XML_embedBold, family, ITALIC_NONE, WEIGHT_BOLD, pitch );
- EmbedFontStyle( name, XML_embedItalic, family, ITALIC_NORMAL, WEIGHT_NORMAL, pitch );
- EmbedFontStyle( name, XML_embedBoldItalic, family, ITALIC_NORMAL, WEIGHT_BOLD, pitch );
+ bool foundFont
+ = EmbedFontStyle(name, XML_embedRegular, family, ITALIC_NONE, WEIGHT_NORMAL, pitch);
+ foundFont
+ = EmbedFontStyle(name, XML_embedBold, family, ITALIC_NONE, WEIGHT_BOLD, pitch) || foundFont;
+ foundFont = EmbedFontStyle(name, XML_embedItalic, family, ITALIC_NORMAL, WEIGHT_NORMAL, pitch)
+ || foundFont;
+ foundFont = EmbedFontStyle(name, XML_embedBoldItalic, family, ITALIC_NORMAL, WEIGHT_BOLD, pitch)
+ || foundFont;
+ if (!foundFont)
+ EmbedFontStyle(name, XML_embedRegular, family, ITALIC_NONE, WEIGHT_DONTKNOW, pitch);
}
static char toHexChar( int value )
@@ -7714,21 +7874,21 @@ static char toHexChar( int value )
return value >= 10 ? value + 'A' - 10 : value + '0';
}
-void DocxAttributeOutput::EmbedFontStyle( std::u16string_view name, int tag, FontFamily family, FontItalic italic,
- FontWeight weight, FontPitch pitch )
+bool DocxAttributeOutput::EmbedFontStyle(std::u16string_view name, int tag, FontFamily family,
+ FontItalic italic, FontWeight weight, FontPitch pitch)
{
// Embed font if at least viewing is allowed (in which case the opening app must check
// the font license rights too and open either read-only or not use the font for editing).
OUString fontUrl = EmbeddedFontsHelper::fontFileUrl( name, family, italic, weight, pitch,
EmbeddedFontsHelper::FontRights::ViewingAllowed );
if( fontUrl.isEmpty())
- return;
+ return false;
// TODO IDocumentSettingAccess::EMBED_SYSTEM_FONTS
if( !fontFilesMap.count( fontUrl ))
{
osl::File file( fontUrl );
if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None )
- return;
+ return false;
uno::Reference< css::io::XOutputStream > xOutStream = m_rExport.GetFilter().openFragmentStream(
"word/fonts/font" + OUString::number(m_nextFontId) + ".odttf",
"application/vnd.openxmlformats-officedocument.obfuscatedFont" );
@@ -7747,7 +7907,7 @@ void DocxAttributeOutput::EmbedFontStyle( std::u16string_view name, int tag, Fon
{
SAL_WARN( "sw.ww8", "Font file size too small (" << fontUrl << ")" );
xOutStream->closeOutput();
- return;
+ return false;
}
for( int i = 0;
i < 16;
@@ -7764,7 +7924,7 @@ void DocxAttributeOutput::EmbedFontStyle( std::u16string_view name, int tag, Fon
{
SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl );
xOutStream->closeOutput();
- return;
+ return false;
}
if( eof )
break;
@@ -7772,7 +7932,7 @@ void DocxAttributeOutput::EmbedFontStyle( std::u16string_view name, int tag, Fon
{
SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl );
xOutStream->closeOutput();
- return;
+ return false;
}
if( readSize == 0 )
break;
@@ -7792,6 +7952,7 @@ void DocxAttributeOutput::EmbedFontStyle( std::u16string_view name, int tag, Fon
m_pSerializer->singleElementNS( XML_w, tag,
FSNS( XML_r, XML_id ), fontFilesMap[ fontUrl ].relId,
FSNS( XML_w, XML_fontKey ), fontFilesMap[ fontUrl ].fontKey );
+ return true;
}
OString DocxAttributeOutput::TransHighlightColor( sal_uInt8 nIco )
@@ -8589,9 +8750,13 @@ void DocxAttributeOutput::CharHighlight( const SvxBrushItem& rHighlight )
void DocxAttributeOutput::TextINetFormat( const SwFormatINetFormat& rLink )
{
- OString aStyleId = MSWordStyles::CreateStyleId(rLink.GetINetFormat());
- if (!aStyleId.isEmpty() && !aStyleId.equalsIgnoreAsciiCase("DefaultStyle"))
- m_pSerializer->singleElementNS(XML_w, XML_rStyle, FSNS(XML_w, XML_val), aStyleId);
+ const SwCharFormat* pFormat = m_rExport.m_rDoc.FindCharFormatByName(rLink.GetINetFormat());
+ if (pFormat)
+ {
+ OString aStyleId(m_rExport.m_pStyles->GetStyleId(m_rExport.GetId(pFormat)));
+ if (!aStyleId.equalsIgnoreAsciiCase("DefaultStyle"))
+ m_pSerializer->singleElementNS(XML_w, XML_rStyle, FSNS(XML_w, XML_val), aStyleId);
+ }
}
void DocxAttributeOutput::TextCharFormat( const SwFormatCharFormat& rCharFormat )