/* * (c) Copyright Ascensio System SIA 2010-2023 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation. In accordance with * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect * that Ascensio System SIA expressly excludes the warranty of non-infringement * of any third-party rights. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish * street, Riga, Latvia, EU, LV-1050. * * The interactive user interfaces in modified source and object code versions * of the Program must display Appropriate Legal Notices, as required under * Section 5 of the GNU AGPL version 3. * * Pursuant to Section 7(b) of the License you must retain the original Product * logo when distributing the program. Pursuant to Section 7(e) we decline to * grant you any rights under trademark law for use of our trademarks. * * All the Product's GUI elements, including illustrations and icon sets, as * well as technical writing content are licensed under the terms of the * Creative Commons Attribution-ShareAlike 4.0 International. See the License * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode * */ #include "Run.h" #include "../DocxFlat.h" #include "../Docx.h" #include "../Document.h" #include "../Endnote.h" #include "../Footnote.h" #include "../Comments.h" #include "../Settings/Settings.h" #include "../Drawing/Drawing.h" #include "../Comments.h" #include "Table.h" #include "Paragraph.h" #include "AlternateContent.h" #include "RunProperty.h" #include "RunContent.h" #include "FldChar.h" #include "FldSimple.h" #include "Pict.h" #include "Annotations.h" #include "../../Common/SimpleTypes_Word.h" #include "../../../DesktopEditor/common/StringExt.h" namespace OOX { namespace Logic { CRun::CRun(OOX::Document *pMain, WritingElement *parent) : WritingElementWithChilds<>(pMain) { m_oRunProperty = NULL; m_oParent = parent; } CRun::~CRun() { ClearItems(); } const CRun& CRun::operator =(const XmlUtils::CXmlNode& oNode) { ClearItems(); fromXML( (XmlUtils::CXmlNode&)oNode ); return *this; } const CRun& CRun::operator =(const XmlUtils::CXmlLiteReader& oReader) { ClearItems(); fromXML( (XmlUtils::CXmlLiteReader&)oReader ); return *this; } void CRun::ClearItems() { m_oRsidDel.reset(); m_oRsidR.reset(); m_oRsidRPr.reset(); m_oRunProperty = NULL; WritingElementWithChilds<>::ClearItems(); } void CRun::fromXML(XmlUtils::CXmlNode& oNode) { m_oRunProperty = NULL; XmlMacroReadAttributeBase( oNode, L"w:rsidDel", m_oRsidDel ); XmlMacroReadAttributeBase( oNode, L"w:rsidR", m_oRsidR ); XmlMacroReadAttributeBase( oNode, L"w:rsidRPr", m_oRsidRPr ); std::vector oChilds; if ( oNode.GetNodes( L"*", oChilds ) ) { for ( size_t nIndex = 0; nIndex < oChilds.size(); nIndex++ ) { XmlUtils::CXmlNode& oItem = oChilds[nIndex]; if (oItem.IsValid()) { std::wstring sName = oItem.GetName(); WritingElement *pItem = NULL; if ( L"w:annotationRef" == sName ) AssignPtrXmlContent(pItem, CAnnotationRef, oItem) else if ( L"w:br" == sName ) AssignPtrXmlContent(pItem, CBr, oItem) else if ( L"w:commentReference" == sName ) AssignPtrXmlContent(pItem, CCommentReference, oItem) else if ( L"w:contentPart" == sName ) AssignPtrXmlContent(pItem, CContentPart, oItem) else if ( L"w:continuationSeparator" == sName ) AssignPtrXmlContent(pItem, CContinuationSeparator, oItem) else if ( L"w:cr" == sName ) AssignPtrXmlContent(pItem, CCr, oItem) else if ( L"w:dayLong" == sName ) AssignPtrXmlContent(pItem, CDayLong, oItem) else if ( L"w:dayShort" == sName ) AssignPtrXmlContent(pItem, CDayShort, oItem) else if ( L"w:delInstrText" == sName ) AssignPtrXmlContent(pItem, CDelInstrText, oItem) else if ( L"w:delText" == sName ) AssignPtrXmlContent(pItem, CDelText, oItem) else if ( L"w:drawing" == sName ) AssignPtrXmlContent(pItem, CDrawing, oItem) else if ( L"w:endnoteRef" == sName ) AssignPtrXmlContent(pItem, CEndnoteRef, oItem) else if ( L"w:endnoteReference" == sName ) AssignPtrXmlContent(pItem, CEndnoteReference, oItem) else if ( L"w:fldChar" == sName ) AssignPtrXmlContent(pItem, CFldChar, oItem) else if ( L"w:footnoteRef" == sName ) AssignPtrXmlContent(pItem, CFootnoteRef, oItem) else if ( L"w:footnoteReference" == sName ) AssignPtrXmlContent(pItem, CFootnoteReference, oItem) else if ( L"w:instrText" == sName ) AssignPtrXmlContent(pItem, CInstrText, oItem) else if ( L"w:lastRenderedPageBreak" == sName ) AssignPtrXmlContent(pItem, CLastRenderedPageBreak, oItem) else if ( L"w:monthLong" == sName ) AssignPtrXmlContent(pItem, CMonthLong, oItem) else if ( L"w:monthShort" == sName ) AssignPtrXmlContent(pItem, CMonthShort, oItem) else if ( L"w:noBreakHyphen" == sName ) AssignPtrXmlContent(pItem, CNoBreakHyphen, oItem) else if ( L"w:object" == sName ) AssignPtrXmlContent(pItem, CObject, oItem) else if ( L"w:pgNum" == sName ) AssignPtrXmlContent(pItem, CPgNum, oItem) else if ( L"w:pict" == sName ) AssignPtrXmlContent(pItem, CPicture, oItem) else if ( L"w:ptab" == sName ) AssignPtrXmlContent(pItem, CPTab, oItem) else if ( L"w:rPr" == sName ) { if (m_oRunProperty) { CRunProperty prop2(oItem); CRunProperty newProp = CRunProperty::Merge(*m_oRunProperty, prop2); pItem = m_oRunProperty = new CRunProperty(newProp); } else { pItem = m_oRunProperty = new CRunProperty( oItem ); } } else if ( L"w:ruby" == sName ) AssignPtrXmlContent(pItem, CRuby, oItem) else if ( L"w:separator" == sName ) AssignPtrXmlContent(pItem, CSeparator, oItem) else if ( L"w:softHyphen" == sName ) AssignPtrXmlContent(pItem, CSoftHyphen, oItem) else if ( L"w:sym" == sName ) AssignPtrXmlContent(pItem, CSym, oItem) else if ( L"w:t" == sName ) AssignPtrXmlContent(pItem, CText, oItem) else if ( L"w:tab" == sName ) AssignPtrXmlContent(pItem, CTab, oItem) else if ( L"w:yearLong" == sName ) AssignPtrXmlContent(pItem, CYearLong, oItem) else if ( L"w:yearShort" == sName ) AssignPtrXmlContent(pItem, CYearShort, oItem) if ( pItem ) m_arrItems.push_back( pItem ); } } } if ((m_oRunProperty) && (m_oRunProperty->m_pText)) { m_arrItems.push_back( m_oRunProperty->m_pText); m_oRunProperty->m_pText = NULL; } } void CRun::fromXML(XmlUtils::CXmlLiteReader& oReader) { m_oRunProperty = NULL; ReadAttributes( oReader ); if ( oReader.IsEmptyNode() ) return; fromXMLElems(oReader); } void CRun::fromXMLElems(XmlUtils::CXmlLiteReader& oReader) { if ( oReader.IsEmptyNode() ) return; WritingElement *pItem = NULL; int nParentDepth = oReader.GetDepth(); while( oReader.ReadNextSiblingNode( nParentDepth ) ) { pItem = fromXMLElem(oReader); if ( pItem ) { m_arrItems.push_back( pItem ); } } } WritingElement* CRun::fromXMLElem(XmlUtils::CXmlLiteReader& oReader) { std::wstring sName = XmlUtils::GetNameNoNS(oReader.GetName()); WritingElement *pItem = NULL; OOX::Document* document = WritingElement::m_pMainDocument; if ( L"AlternateContent" == sName ) pItem = new CAlternateContent( document ); else if ( L"annotationRef" == sName ) pItem = new CAnnotationRef( document ); else if ( L"br" == sName ) pItem = new CBr( document ); else if ( L"commentReference" == sName ) pItem = new CCommentReference( document ); else if ( L"contentPart" == sName ) pItem = new CContentPart( document ); else if ( L"continuationSeparator" == sName ) pItem = new CContinuationSeparator( document ); else if ( L"cr" == sName ) pItem = new CCr( document ); else if ( L"dayLong" == sName ) pItem = new CDayLong( document ); else if ( L"dayShort" == sName ) pItem = new CDayShort( document ); else if ( L"delInstrText" == sName ) pItem = new CDelInstrText( document ); else if ( L"delText" == sName ) pItem = new CDelText( document ); else if ( L"drawing" == sName ) pItem = new CDrawing( document ); else if ( L"endnote" == sName ) { CEndnoteReference *pEndRef = new CEndnoteReference(document); CFtnEdn *pEndnote = new CFtnEdn( document ); pEndnote->fromXML(oReader); CDocxFlat* docx_flat = dynamic_cast(document); if (docx_flat) { pEndnote->m_oId.Init(); pEndnote->m_oId->SetValue((int)(docx_flat->m_pEndnotes->m_arrEndnote.size() + 1)); pEndRef->m_oId = pEndnote->m_oId; docx_flat->m_pEndnotes->m_arrEndnote.push_back(pEndnote); docx_flat->m_pEndnotes->m_mapEndnote.insert(std::make_pair(pEndnote->m_oId->GetValue(), pEndnote)); if (!docx_flat->m_pSettings->m_oEndnotePr.Init()) docx_flat->m_pSettings->m_oEndnotePr.Init(); } pItem = pEndRef; } else if (L"r" == sName) { fromXMLElems(oReader); } else if (L"tbl" == sName) {//ERP CParagraph *paragraph = dynamic_cast(m_oParent); WritingElementWithChilds *parent = paragraph ? dynamic_cast(paragraph->m_oParent) : NULL; if (!parent) parent = dynamic_cast(m_oParent); if (parent) { WritingElement *pItemUpper = new CTbl(document); if (pItemUpper) { pItemUpper->fromXML(oReader); parent->m_arrItems.push_back(pItemUpper); } } } else if ( L"endnoteRef" == sName ) pItem = new CEndnoteRef( document ); else if ( L"endnoteReference" == sName ) pItem = new CEndnoteReference( document ); else if ( L"fldChar" == sName ) pItem = new CFldChar( document ); else if ( L"footnote" == sName ) { CFootnoteReference *pFootRef = new CFootnoteReference(document); CFtnEdn *pFootnote = new CFtnEdn( document ); pFootnote->m_eType = OOX::et_w_footnote; pFootnote->fromXML(oReader); CDocxFlat* docx_flat = dynamic_cast(document); if (docx_flat) { pFootnote->m_oId.Init(); pFootnote->m_oId->SetValue((int)(docx_flat->m_pFootnotes->m_arrFootnote.size() + 1)); pFootRef->m_oId = pFootnote->m_oId; docx_flat->m_pFootnotes->m_arrFootnote.push_back(pFootnote); docx_flat->m_pFootnotes->m_mapFootnote.insert(std::make_pair(pFootnote->m_oId->GetValue(), pFootnote)); } pItem = pFootRef; } else if ( L"footnoteRef" == sName ) pItem = new CFootnoteRef( document ); else if ( L"footnoteReference" == sName ) pItem = new CFootnoteReference( document ); else if ( L"instrText" == sName ) pItem = new CInstrText( document ); else if ( L"lastRenderedPageBreak" == sName ) pItem = new CLastRenderedPageBreak( document ); else if ( L"monthLong" == sName ) pItem = new CMonthLong( document ); else if ( L"monthShort" == sName ) pItem = new CMonthShort( document ); else if ( L"noBreakHyphen" == sName ) pItem = new CNoBreakHyphen( document ); else if ( L"object" == sName ) pItem = new CObject( document ); else if ( L"pgNum" == sName ) pItem = new CPgNum( document ); else if ( L"pict" == sName ) pItem = new CPicture( document ); else if ( L"ptab" == sName ) pItem = new CPTab( document ); else if ( L"rPr" == sName ) { if (m_oRunProperty) { CRunProperty prop2; prop2.fromXML(oReader, this); CRunProperty newProp = CRunProperty::Merge(*m_oRunProperty, prop2); pItem = m_oRunProperty = new CRunProperty(newProp); } else { pItem = m_oRunProperty = new CRunProperty(); m_oRunProperty->fromXML(oReader, this); } return pItem; } else if ( L"ruby" == sName ) pItem = new CRuby( document ); else if ( L"separator" == sName ) pItem = new CSeparator( document ); else if ( L"softHyphen" == sName ) pItem = new CSoftHyphen( document ); else if ( L"sym" == sName ) pItem = new CSym( document ); else if ( L"t" == sName ) { fromXMLText(oReader); } else if ( L"tab" == sName ) pItem = new CTab( document ); else if ( L"yearLong" == sName ) pItem = new CYearLong( document ); else if ( L"annotation" == sName) //Bookmark { nullable_string sType; WritingElement_ReadAttributes_ReadSingle2(oReader, L"w:type", sType); if (sType.IsInit() && std::wstring::npos != sType->find(L"Bookmark.Start")) AssignPtrXmlContent(pItem, CBookmarkStart, oReader) else if (sType.IsInit() && std::wstring::npos != sType->find(L"Bookmark.End")) AssignPtrXmlContent(pItem, CBookmarkEnd, oReader) else if (sType.IsInit() && std::wstring::npos != sType->find(L"Comment.Start")) AssignPtrXmlContent(pItem, CCommentRangeStart, oReader) else if (sType.IsInit() && std::wstring::npos != sType->find(L"Comment.End")) AssignPtrXmlContent(pItem, CCommentRangeEnd, oReader) else if (sType.IsInit() && std::wstring::npos != sType->find(L"Comment")) { //pItem = new CComment( oReader ); AssignPtrXmlContent(pItem, CComment, oReader) CDocxFlat* docx_flat = dynamic_cast(document); if (docx_flat) { CComment* pComment = dynamic_cast(pItem); if ((pComment) && (pComment->m_oId.IsInit())) { docx_flat->m_pComments->m_mapComments.insert( std::make_pair( pComment->m_oId->GetValue(), docx_flat->m_pComments->m_arrComments.size())); } docx_flat->m_pComments->m_arrComments.push_back( pComment ); pItem = NULL; } } } if (pItem) { pItem->fromXML(oReader); } return pItem; } void CRun::fromXMLText(XmlUtils::CXmlLiteReader& oReader) { CDocx* docx = dynamic_cast(WritingElement::m_pMainDocument); CDocxFlat* docx_flat = dynamic_cast(WritingElement::m_pMainDocument); //for 66 nullable oSpace; CText::ReadAttributes(oReader, oSpace); if ((docx) && (docx->m_oMain.document)) { if (false == oSpace.IsInit() && docx->m_oMain.document->m_oSpace.IsInit()) { oSpace = docx->m_oMain.document->m_oSpace; } } else if (docx_flat) { if (false == oSpace.IsInit() && docx_flat->m_oSpace.IsInit()) { oSpace = docx_flat->m_oSpace; } } if ( oReader.IsEmptyNode() ) return; bool bTrimLeft, bTrimRight; bTrimLeft = bTrimRight = !(oSpace.IsInit() && SimpleTypes::xmlspacePreserve == oSpace->GetValue()); CText* pTextLast = NULL; int nDepth = oReader.GetDepth(); XmlUtils::XmlNodeType eNodeType = XmlUtils::XmlNodeType_EndElement; while (oReader.Read(eNodeType) && oReader.GetDepth() >= nDepth && XmlUtils::XmlNodeType_EndElement != eNodeType) { if ( eNodeType == XmlUtils::XmlNodeType_Text || eNodeType == XmlUtils::XmlNodeType_Whitespace || eNodeType == XmlUtils::XmlNodeType_SIGNIFICANT_WHITESPACE || eNodeType == XmlUtils::XmlNodeType_CDATA) { const char* pValue = oReader.GetTextChar(); if(bTrimLeft) { bTrimLeft = false; pValue += NSStringExt::FindFirstNotOfA(pValue, " \n\r\t"); } if('\0' != pValue[0]) { pTextLast = new CText(); NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)pValue, (LONG)strlen(pValue), pTextLast->m_sText); m_arrItems.push_back( pTextLast ); } } else if (eNodeType == XmlUtils::XmlNodeType_Element) { WritingElement *pItem = fromXMLElem(oReader); if ( pItem ) m_arrItems.push_back( pItem ); bTrimLeft = false; pTextLast = NULL; } } if(bTrimRight && pTextLast) { NSStringExt::RTrim(pTextLast->m_sText, L" \n\r\t"); } } std::wstring CRun::toXML() const { std::wstring sResult = L""; if (m_oRunProperty) sResult += m_oRunProperty->toXML(); for ( size_t i = 0; i < m_arrItems.size(); ++i) { if ( m_arrItems[i] ) { if (m_arrItems[i]->getType() == OOX::et_w_rPr) continue; sResult += m_arrItems[i]->toXML(); } } sResult += L""; return sResult; } EElementType CRun::getType() const { return et_w_r; } void CRun::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { if ( oReader.GetAttributesCount() <= 0 ) return; if ( !oReader.MoveToFirstAttribute() ) return; std::wstring wsName = XmlUtils::GetNameNoNS(oReader.GetName()); while( !wsName.empty() ) { if ( L"rsidDel" == wsName ) m_oRsidDel = oReader.GetText(); else if ( L"rsidR" == wsName ) m_oRsidR = oReader.GetText(); else if ( L"rsidRPr" == wsName ) m_oRsidRPr = oReader.GetText(); if ( !oReader.MoveToNextAttribute() ) break; wsName = XmlUtils::GetNameNoNS(oReader.GetName()); } oReader.MoveToElement(); } } // namespace Logic } // namespace OOX