diff options
21 files changed, 1991 insertions, 760 deletions
diff --git a/writerfilter/Library_rtftok.mk b/writerfilter/Library_rtftok.mk index b4345454a163..9e3b592c20e1 100644 --- a/writerfilter/Library_rtftok.mk +++ b/writerfilter/Library_rtftok.mk @@ -62,6 +62,8 @@ $(eval $(call gb_Library_add_linked_libs,rtftok,\ $(eval $(call gb_Library_add_exception_objects,rtftok,\ writerfilter/source/rtftok/rtfdocumentfactory \ writerfilter/source/rtftok/rtfdocumentimpl \ + writerfilter/source/rtftok/rtfsdrimport \ + writerfilter/source/rtftok/rtftokenizer \ writerfilter/source/rtftok/rtfcontrolwords \ writerfilter/source/rtftok/rtfcharsets \ writerfilter/source/rtftok/rtfreferenceproperties \ diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 231b1aba3953..0a9e61ad3084 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -3161,7 +3161,8 @@ void DomainMapper::lcl_startParagraphGroup() static ::rtl::OUString sDefault(RTL_CONSTASCII_USTRINGPARAM("Standard") ); if (m_pImpl->GetTopContext()) { - m_pImpl->GetTopContext()->Insert( PROP_PARA_STYLE_NAME, true, uno::makeAny( sDefault ) ); + if (!m_pImpl->IsInShape()) + m_pImpl->GetTopContext()->Insert( PROP_PARA_STYLE_NAME, true, uno::makeAny( sDefault ) ); if (m_pImpl->isBreakDeferred(PAGE_BREAK)) m_pImpl->GetTopContext()->Insert( PROP_BREAK_TYPE, true, uno::makeAny( com::sun::star::style::BreakType_PAGE_BEFORE) ); else if (m_pImpl->isBreakDeferred(COLUMN_BREAK)) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 3b698970ed98..285670fd7fd2 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1335,6 +1335,7 @@ void DomainMapper_Impl::PushAnnotation() void DomainMapper_Impl::PopFootOrEndnote() { + RemoveLastParagraph(); m_aTextAppendStack.pop(); } @@ -1388,6 +1389,7 @@ void DomainMapper_Impl::PopShapeContext() { if ( m_bShapeContextAdded ) { + RemoveLastParagraph(); m_aTextAppendStack.pop(); m_bShapeContextAdded = false; } @@ -3184,16 +3186,28 @@ sal_Int32 DomainMapper_Impl::GetCurrentRedlineToken( ) void DomainMapper_Impl::SetCurrentRedlineAuthor( rtl::OUString sAuthor ) { - RedlineParamsPtr pCurrent( GetTopRedline( ) ); - if ( pCurrent.get( ) ) - pCurrent->m_sAuthor = sAuthor; + if (!m_xAnnotationField.is()) + { + RedlineParamsPtr pCurrent( GetTopRedline( ) ); + if ( pCurrent.get( ) ) + pCurrent->m_sAuthor = sAuthor; + } + else + m_xAnnotationField->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Author")), + uno::makeAny(sAuthor)); } void DomainMapper_Impl::SetCurrentRedlineDate( rtl::OUString sDate ) { - RedlineParamsPtr pCurrent( GetTopRedline( ) ); - if ( pCurrent.get( ) ) - pCurrent->m_sDate = sDate; + if (!m_xAnnotationField.is()) + { + RedlineParamsPtr pCurrent( GetTopRedline( ) ); + if ( pCurrent.get( ) ) + pCurrent->m_sDate = sDate; + } + else + m_xAnnotationField->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DateTimeValue")), + uno::makeAny(lcl_DateStringToDateTime(sDate))); } void DomainMapper_Impl::SetCurrentRedlineId( sal_Int32 sId ) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index d4147b1cb782..1b8b2be25036 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -474,6 +474,7 @@ public: bool IsStyleSheetImport()const { return m_bInStyleSheetImport;} void SetAnyTableImport( bool bSet ) { m_bInAnyTableImport = bSet;} bool IsAnyTableImport()const { return m_bInAnyTableImport;} + bool IsInShape()const { return m_bIsInShape;} void PushShapeContext( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape ); void PopShapeContext(); diff --git a/writerfilter/source/dmapper/NumberingManager.cxx b/writerfilter/source/dmapper/NumberingManager.cxx index 049f5b941af9..0cab937789a9 100644 --- a/writerfilter/source/dmapper/NumberingManager.cxx +++ b/writerfilter/source/dmapper/NumberingManager.cxx @@ -834,7 +834,8 @@ void ListsManager::lcl_sprm( Sprm& rSprm ) case NS_rtf::LN_FWORD6: #endif case NS_rtf::LN_IXCHFOLLOW: - m_pCurrentDefinition->GetCurrentLevel( )->SetValue( nSprmId, nIntValue ); + if (m_pCurrentDefinition->GetCurrentLevel().get()) + m_pCurrentDefinition->GetCurrentLevel( )->SetValue( nSprmId, nIntValue ); break; case NS_ooxml::LN_CT_Lvl_lvlText: case NS_ooxml::LN_CT_Lvl_rPr : //contains LN_EG_RPrBase_rFonts diff --git a/writerfilter/source/rtftok/rtfcharsets.cxx b/writerfilter/source/rtftok/rtfcharsets.cxx index 96f6feb9237e..360db9e501ea 100644 --- a/writerfilter/source/rtftok/rtfcharsets.cxx +++ b/writerfilter/source/rtftok/rtfcharsets.cxx @@ -25,7 +25,7 @@ * instead of those above. */ -#include <rtftypes.hxx> +#include <rtfcharsets.hxx> #include <sal/macros.h> namespace writerfilter { diff --git a/writerfilter/source/rtftok/rtftypes.hxx b/writerfilter/source/rtftok/rtfcharsets.hxx index 3f437f34b534..e4f824d93d49 100644 --- a/writerfilter/source/rtftok/rtftypes.hxx +++ b/writerfilter/source/rtftok/rtfcharsets.hxx @@ -25,23 +25,11 @@ * instead of those above. */ -#ifndef _RTFTYPES_HXX_ -#define _RTFTYPES_HXX_ - -#include <rtfcontrolwords.hxx> +#ifndef _RTFCHARSETS_HXX_ +#define _RTFCHARSETS_HXX_ namespace writerfilter { namespace rtftok { - /// Respresents an RTF Control Word - typedef struct - { - const char *sKeyword; - int nControlType; - RTFKeyword nIndex; - } RTFSymbol; - extern RTFSymbol aRTFControlWords[]; - extern int nRTFControlWords; - /// RTF legacy charsets typedef struct { @@ -53,6 +41,6 @@ namespace writerfilter { } // namespace rtftok } // namespace writerfilter -#endif // _RTFTYPES_HXX_ +#endif // _RTFCHARSETS_HXX_ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/rtftok/rtfcontrolwords.cxx b/writerfilter/source/rtftok/rtfcontrolwords.cxx index 9034f6f4caa3..0d7f0c049187 100644 --- a/writerfilter/source/rtftok/rtfcontrolwords.cxx +++ b/writerfilter/source/rtftok/rtfcontrolwords.cxx @@ -25,8 +25,6 @@ * instead of those above. */ -#include <rtfdocumentimpl.hxx> -#include <rtftypes.hxx> #include <rtfcontrolwords.hxx> #include <sal/macros.h> diff --git a/writerfilter/source/rtftok/rtfcontrolwords.hxx b/writerfilter/source/rtftok/rtfcontrolwords.hxx index a6c35312c19f..55e17e3e29ea 100644 --- a/writerfilter/source/rtftok/rtfcontrolwords.hxx +++ b/writerfilter/source/rtftok/rtfcontrolwords.hxx @@ -1846,6 +1846,26 @@ enum RTFKeyword RTF_ZWNJ }; +/// Types of an RTF Control Word +enum RTFControlTypes +{ + CONTROL_FLAG, // eg \sbknone takes no parameter + CONTROL_DESTINATION, // eg \fonttbl, if ignored, the whole group should be skipped + CONTROL_SYMBOL, // eg \tab + CONTROL_TOGGLE, // eg \b (between on and off) + CONTROL_VALUE // eg \fs (requires parameter) +}; + +/// Respresents an RTF Control Word +typedef struct +{ + const char *sKeyword; + int nControlType; + RTFKeyword nIndex; +} RTFSymbol; + +extern RTFSymbol aRTFControlWords[]; +extern int nRTFControlWords; } // namespace rtftok } // namespace writerfilter diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index 930059d431d0..cdefe9eaf546 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -25,24 +25,35 @@ * instead of those above. */ -#include <rtfdocumentimpl.hxx> -#include <rtftypes.hxx> -#include <rtfcontrolwords.hxx> -#include <rtfvalue.hxx> -#include <rtfsprm.hxx> -#include <rtfreferenceproperties.hxx> -#include <doctok/sprmids.hxx> // NS_sprm namespace -#include <doctok/resourceids.hxx> // NS_rtf namespace -#include <ooxml/resourceids.hxx> // NS_ooxml namespace -#include <ooxml/OOXMLFastTokens.hxx> // ooxml namespace -#include <unotools/ucbstreamhelper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <editeng/borderline.hxx> #include <rtl/strbuf.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/tencinfo.h> #include <svl/lngmisc.hxx> -#include <editeng/borderline.hxx> +#include <unotools/ucbstreamhelper.hxx> #include <unotools/streamwrap.hxx> -#include <com/sun/star/beans/XPropertySet.hpp> + +#include <doctok/sprmids.hxx> // NS_sprm namespace +#include <doctok/resourceids.hxx> // NS_rtf namespace +#include <ooxml/resourceids.hxx> // NS_ooxml namespace +#include <ooxml/OOXMLFastTokens.hxx> // ooxml namespace + +#include <rtfdocumentimpl.hxx> +#include <rtfsdrimport.hxx> +#include <rtftokenizer.hxx> +#include <rtfcharsets.hxx> +#include <rtfcontrolwords.hxx> +#include <rtfvalue.hxx> +#include <rtfsprm.hxx> +#include <rtfreferenceproperties.hxx> + +#define TWIP_TO_MM100(TWIP) ((TWIP) >= 0 ? (((TWIP)*127L+36L)/72L) : (((TWIP)*127L-36L)/72L)) using std::make_pair; using rtl::OString; @@ -54,17 +65,17 @@ using rtl::OUStringToOString; namespace writerfilter { namespace rtftok { -static RTFSprms_t& lcl_getNumPr(std::stack<RTFParserState>& aStates) +static RTFSprms& lcl_getNumPr(std::stack<RTFParserState>& aStates) { // insert the numpr sprm if necessary - RTFValue::Pointer_t p = RTFSprm::find(aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_numPr); + RTFValue::Pointer_t p = aStates.top().aParagraphSprms.find(NS_ooxml::LN_CT_PPrBase_numPr); if (!p.get()) { - RTFSprms_t aAttributes; - RTFSprms_t aSprms; + RTFSprms aAttributes; + RTFSprms aSprms; RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms)); - aStates.top().aParagraphSprms.push_back(make_pair(NS_ooxml::LN_CT_PPrBase_numPr, pValue)); - p = RTFSprm::find(aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_numPr); + aStates.top().aParagraphSprms->push_back(make_pair(NS_ooxml::LN_CT_PPrBase_numPr, pValue)); + p = aStates.top().aParagraphSprms.find(NS_ooxml::LN_CT_PPrBase_numPr); } return p->getSprms(); } @@ -79,42 +90,42 @@ static Id lcl_getParagraphBorder(sal_uInt32 nIndex) return aBorderIds[nIndex]; } -static void lcl_putNestedAttribute(RTFSprms_t& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue, +static void lcl_putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue, bool bOverwrite = false, bool bAttribute = true) { - RTFValue::Pointer_t pParent = RTFSprm::find(rSprms, nParent); + RTFValue::Pointer_t pParent = rSprms.find(nParent); if (!pParent.get()) { - RTFSprms_t aAttributes; + RTFSprms aAttributes; RTFValue::Pointer_t pParentValue(new RTFValue(aAttributes)); - rSprms.push_back(make_pair(nParent, pParentValue)); + rSprms->push_back(make_pair(nParent, pParentValue)); pParent = pParentValue; } - RTFSprms_t& rAttributes = (bAttribute ? pParent->getAttributes() : pParent->getSprms()); + RTFSprms& rAttributes = (bAttribute ? pParent->getAttributes() : pParent->getSprms()); if (bOverwrite) - for (RTFSprms_t::iterator i = rAttributes.begin(); i != rAttributes.end(); ++i) + for (RTFSprms::Iterator_t i = rAttributes->begin(); i != rAttributes->end(); ++i) if (i->first == nId) { i->second = pValue; return; } - rAttributes.push_back(make_pair(nId, pValue)); + rAttributes->push_back(make_pair(nId, pValue)); } -static void lcl_putNestedSprm(RTFSprms_t& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue, bool bOverwrite = false) +static void lcl_putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue, bool bOverwrite = false) { lcl_putNestedAttribute(rSprms, nParent, nId, pValue, bOverwrite, false); } -static RTFSprms_t& lcl_getLastAttributes(RTFSprms_t& rSprms, Id nId) +static RTFSprms& lcl_getLastAttributes(RTFSprms& rSprms, Id nId) { - RTFValue::Pointer_t p = RTFSprm::find(rSprms, nId); - if (p->getSprms().size()) - return p->getSprms().back().second->getAttributes(); + RTFValue::Pointer_t p = rSprms.find(nId); + if (p.get() && p->getSprms()->size()) + return p->getSprms()->back().second->getAttributes(); else { OSL_FAIL("trying to set property when no type is defined"); - return p->getSprms(); + return rSprms; } } @@ -123,40 +134,27 @@ static void lcl_putBorderProperty(std::stack<RTFParserState>& aStates, Id nId, R if (aStates.top().nBorderState == BORDER_PARAGRAPH) for (int i = 0; i < 4; i++) { - RTFValue::Pointer_t p = RTFSprm::find(aStates.top().aParagraphSprms, lcl_getParagraphBorder(i)); + RTFValue::Pointer_t p = aStates.top().aParagraphSprms.find(lcl_getParagraphBorder(i)); if (p.get()) { - RTFSprms_t& rAttributes = p->getAttributes(); - rAttributes.push_back(make_pair(nId, pValue)); + RTFSprms& rAttributes = p->getAttributes(); + rAttributes->push_back(make_pair(nId, pValue)); } } else if (aStates.top().nBorderState == BORDER_CELL) { // Attributes of the last border type - RTFSprms_t& rAttributes = lcl_getLastAttributes(aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcBorders); - rAttributes.push_back(make_pair(nId, pValue)); + RTFSprms& rAttributes = lcl_getLastAttributes(aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcBorders); + rAttributes->push_back(make_pair(nId, pValue)); } else if (aStates.top().nBorderState == BORDER_PAGE) { // Attributes of the last border type - RTFSprms_t& rAttributes = lcl_getLastAttributes(aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgBorders); - rAttributes.push_back(make_pair(nId, pValue)); + RTFSprms& rAttributes = lcl_getLastAttributes(aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgBorders); + rAttributes->push_back(make_pair(nId, pValue)); } } -static void lcl_Break(Stream& rMapper) -{ - sal_uInt8 sBreak[] = { 0xd }; - rMapper.text(sBreak, 1); -} - -static void lcl_TableBreak(Stream& rMapper) -{ - lcl_Break(rMapper); - rMapper.endParagraphGroup(); - rMapper.startParagraphGroup(); -} - // NEEDSWORK: DocxAttributeOutput's impl_AppendTwoDigits does the same. static void lcl_AppendTwoDigits(OStringBuffer &rBuffer, sal_Int32 nNum) { @@ -202,15 +200,15 @@ static OString lcl_DTTM22OString(long lDTTM) static writerfilter::Reference<Properties>::Pointer_t lcl_getBookmarkProperties(int nPos, OUString& rString) { - RTFSprms_t aAttributes; + RTFSprms aAttributes; RTFValue::Pointer_t pPos(new RTFValue(nPos)); if (rString.getLength()) { // If present, this should be sent first. RTFValue::Pointer_t pString(new RTFValue(rString)); - aAttributes.push_back(make_pair(NS_rtf::LN_BOOKMARKNAME, pString)); + aAttributes->push_back(make_pair(NS_rtf::LN_BOOKMARKNAME, pString)); } - aAttributes.push_back(make_pair(NS_rtf::LN_IBKL, pPos)); + aAttributes->push_back(make_pair(NS_rtf::LN_IBKL, pPos)); return writerfilter::Reference<Properties>::Pointer_t(new RTFReferenceProperties(aAttributes)); } @@ -220,30 +218,7 @@ static writerfilter::Reference<Properties>::Pointer_t lcl_getBookmarkProperties( return lcl_getBookmarkProperties(nPos, aStr); } -static int lcl_AsHex(char ch) -{ - int ret = 0; - if (isdigit(ch)) - ret = ch - '0'; - else - { - if (islower(ch)) - { - if (ch < 'a' || ch > 'f') - return -1; - ret = ch - 'a'; - } - else - { - if (ch < 'A' || ch > 'F') - return -1; - ret = ch - 'A'; - } - ret += 10; - } - return ret; -} - +#if OSL_DEBUG_LEVEL > 1 static const char* lcl_RtfToString(RTFKeyword nKeyword) { for (int i = 0; i < nRTFControlWords; i++) @@ -253,6 +228,14 @@ static const char* lcl_RtfToString(RTFKeyword nKeyword) } return NULL; } +#endif + +static util::DateTime lcl_getDateTime(std::stack<RTFParserState>& aStates) +{ + return util::DateTime(0 /*100sec*/, 0 /*sec*/, aStates.top().nMinute, aStates.top().nHour, + aStates.top().nDay, aStates.top().nMonth, aStates.top().nYear); +} + RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& xContext, uno::Reference<io::XInputStream> const& xInputStream, uno::Reference<lang::XComponent> const& xDstDoc, @@ -267,34 +250,53 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x m_aFontEncodings(), m_aColorTable(), m_bFirstRun(true), + m_bFirstRow(true), m_bNeedPap(false), m_aListTableSprms(), m_aSettingsTableSprms(), m_xStorage(), m_aTableBuffer(), - m_bTable(false), m_aSuperBuffer(), - m_bSuper(false), + m_aShapetextBuffer(), + m_pCurrentBuffer(0), m_bHasFootnote(false), m_bIsSubstream(false), m_nHeaderFooterPositions(), m_nGroupStartPos(0), m_aBookmarks(), - m_aAuthors() + m_aAuthors(), + m_aFormfieldSprms(), + m_aFormfieldAttributes(), + m_nFormFieldType(FORMFIELD_NONE), + m_aObjectSprms(), + m_aObjectAttributes(), + m_bObject(false), + m_pObjectData(0), + m_aFontTableEntries(), + m_nCurrentFontIndex(0), + m_aStyleTableEntries(), + m_nCurrentStyleIndex(0), + m_bEq(false) { - OSL_ENSURE(xInputStream.is(), "no input stream"); - if (!xInputStream.is()) - throw uno::RuntimeException(); - m_pInStream = utl::UcbStreamHelper::CreateStream( xInputStream, sal_True ); + OSL_ASSERT(xInputStream.is()); + m_pInStream = utl::UcbStreamHelper::CreateStream(xInputStream, sal_True); m_xModelFactory.set(m_xDstDoc, uno::UNO_QUERY); OSL_ASSERT(m_xModelFactory.is()); + uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(m_xDstDoc, uno::UNO_QUERY); + m_xDocumentProperties.set(xDocumentPropertiesSupplier->getDocumentProperties(), uno::UNO_QUERY); + m_pGraphicHelper = new oox::GraphicHelper(m_xContext, xFrame, m_xStorage); + + m_pTokenizer = new RTFTokenizer(*this, m_pInStream); + m_pSdrImport = new RTFSdrImport(*this, m_xDstDoc); } RTFDocumentImpl::~RTFDocumentImpl() { + delete m_pTokenizer; + delete m_pSdrImport; } SvStream& RTFDocumentImpl::Strm() @@ -312,6 +314,16 @@ void RTFDocumentImpl::setSubstream(bool bIsSubtream) m_bIsSubstream = bIsSubtream; } +void RTFDocumentImpl::setAuthor(rtl::OUString& rAuthor) +{ + m_aAuthor = rAuthor; +} + +bool RTFDocumentImpl::isSubstream() +{ + return m_bIsSubstream; +} + void RTFDocumentImpl::setIgnoreFirst(OUString& rIgnoreFirst) { m_aIgnoreFirst = rIgnoreFirst; @@ -329,6 +341,11 @@ void RTFDocumentImpl::resolveSubstream(sal_uInt32 nPos, Id nId, OUString& rIgnor RTFDocumentImpl::Pointer_t pImpl(new RTFDocumentImpl(m_xContext, m_xInputStream, m_xDstDoc, m_xFrame)); pImpl->setSubstream(true); pImpl->setIgnoreFirst(rIgnoreFirst); + if (m_aAuthor.getLength()) + { + pImpl->setAuthor(m_aAuthor); + m_aAuthor = OUString(); + } pImpl->seek(nPos); OSL_TRACE("substream start"); Mapper().substream(nId, pImpl); @@ -337,14 +354,56 @@ void RTFDocumentImpl::resolveSubstream(sal_uInt32 nPos, Id nId, OUString& rIgnor nPos = 0; } +void RTFDocumentImpl::checkFirstRun() +{ + if (m_bFirstRun) + { + writerfilter::Reference<Properties>::Pointer_t const pParagraphProperties( + new RTFReferenceProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms) + ); + // output settings table + RTFSprms aAttributes; + writerfilter::Reference<Properties>::Pointer_t const pProp(new RTFReferenceProperties(aAttributes, m_aSettingsTableSprms)); + RTFReferenceTable::Entries_t aSettingsTableEntries; + aSettingsTableEntries.insert(make_pair(0, pProp)); + writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aSettingsTableEntries)); + Mapper().table(NS_ooxml::LN_settings_settings, pTable); + // start initial paragraph + if (!m_bIsSubstream) + Mapper().startSectionGroup(); + Mapper().startParagraphGroup(); + Mapper().props(pParagraphProperties); + m_bFirstRun = false; + } +} + +void RTFDocumentImpl::runBreak() +{ + sal_uInt8 sBreak[] = { 0xd }; + Mapper().text(sBreak, 1); +} + +void RTFDocumentImpl::tableBreak() +{ + runBreak(); + Mapper().endParagraphGroup(); + Mapper().startParagraphGroup(); +} + void RTFDocumentImpl::parBreak() { + checkFirstRun(); // end previous paragraph Mapper().startCharacterGroup(); - lcl_Break(Mapper()); + runBreak(); Mapper().endCharacterGroup(); Mapper().endParagraphGroup(); + // If we are not in a table, then the next table row will be the first one. + RTFValue::Pointer_t pValue = m_aStates.top().aParagraphSprms.find(NS_sprm::LN_PFInTable); + if (!pValue.get()) + m_bFirstRow = true; + // start new one Mapper().startParagraphGroup(); } @@ -354,20 +413,20 @@ void RTFDocumentImpl::sectBreak(bool bFinal = false) while (m_nHeaderFooterPositions.size()) { std::pair<Id, sal_uInt32> aPair = m_nHeaderFooterPositions.front(); - m_nHeaderFooterPositions.pop_front(); + m_nHeaderFooterPositions.pop(); resolveSubstream(aPair.second, aPair.first); } - RTFValue::Pointer_t pBreak = RTFSprm::find(m_aStates.top().aSectionSprms, NS_sprm::LN_SBkc); + RTFValue::Pointer_t pBreak = m_aStates.top().aSectionSprms.find(NS_sprm::LN_SBkc); // In case the last section is a continous one, we don't need to output a section break. if (bFinal && pBreak.get() && !pBreak->getInt()) - RTFSprm::erase(m_aStates.top().aSectionSprms, NS_sprm::LN_SBkc); + m_aStates.top().aSectionSprms.erase(NS_sprm::LN_SBkc); // Section properties are a paragraph sprm. RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aSectionAttributes, m_aStates.top().aSectionSprms)); - RTFSprms_t aAttributes; - RTFSprms_t aSprms; - aSprms.push_back(make_pair(NS_ooxml::LN_CT_PPr_sectPr, pValue)); + RTFSprms aAttributes; + RTFSprms aSprms; + aSprms->push_back(make_pair(NS_ooxml::LN_CT_PPr_sectPr, pValue)); writerfilter::Reference<Properties>::Pointer_t const pProperties( new RTFReferenceProperties(aAttributes, aSprms) ); @@ -405,7 +464,7 @@ sal_uInt32 RTFDocumentImpl::getEncodingTable(sal_uInt32 nFontIndex) void RTFDocumentImpl::resolve(Stream & rMapper) { m_pMapperStream = &rMapper; - switch (resolveParse()) + switch (m_pTokenizer->resolveParse()) { case ERROR_OK: OSL_TRACE("%s: finished without errors", OSL_THIS_FUNC); @@ -422,25 +481,27 @@ void RTFDocumentImpl::resolve(Stream & rMapper) case ERROR_HEX_INVALID: OSL_TRACE("%s: invalid hex char", OSL_THIS_FUNC); break; + case ERROR_CHAR_OVER: + OSL_TRACE("%s: characters after last '}'", OSL_THIS_FUNC); + break; } } -int RTFDocumentImpl::resolvePict(char ch, bool bInline) +int RTFDocumentImpl::resolvePict(bool bInline) { SvMemoryStream aStream; int b = 0, count = 2; - // TODO this discards properties after the 'pib' property - if (!bInline) - resolveShapeProperties(m_aStates.top().aShapeProperties); - - // Read the group. - while(!Strm().IsEof() && ch != '{' && ch != '}' && ch != '\\') + // Feed the destination text to a stream. + OString aStr = OUStringToOString(m_aDestinationText.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US); + const char *str = aStr.getStr(); + for (int i = 0; i < aStr.getLength(); ++i) { + char ch = str[i]; if (ch != 0x0d && ch != 0x0a) { b = b << 4; - char parsed = lcl_AsHex(ch); + char parsed = m_pTokenizer->asHex(ch); if (parsed == -1) return ERROR_HEX_INVALID; b += parsed; @@ -452,9 +513,7 @@ int RTFDocumentImpl::resolvePict(char ch, bool bInline) b = 0; } } - Strm() >> ch; } - Strm().SeekRel(-1); // Store, and get its URL. aStream.Seek(0); @@ -468,68 +527,95 @@ int RTFDocumentImpl::resolvePict(char ch, bool bInline) OSL_ASSERT(xShape.is()); uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY); OSL_ASSERT(xPropertySet.is()); + if (m_bObject) + { + // Set bitmap + beans::PropertyValues aMediaProperties(1); + aMediaProperties[0].Name = OUString(RTL_CONSTASCII_USTRINGPARAM("URL")); + aMediaProperties[0].Value <<= aGraphicUrl; + uno::Reference<graphic::XGraphicProvider> xGraphicProvider( + m_xContext->getServiceManager()->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.graphic.GraphicProvider")), + m_xContext), + uno::UNO_QUERY_THROW); + uno::Reference<graphic::XGraphic> xGraphic = xGraphicProvider->queryGraphic(aMediaProperties); + xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Bitmap")), uno::Any(xGraphic)); + + // Set size + awt::Size aSize; + for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes->begin(); i != m_aStates.top().aCharacterAttributes->end(); ++i) + if (i->first == NS_rtf::LN_XEXT) + aSize.Width = i->second->getInt(); + else if (i->first == NS_rtf::LN_YEXT) + aSize.Height = i->second->getInt(); + xShape->setSize(aSize); + + RTFValue::Pointer_t pShapeValue(new RTFValue(xShape)); + m_aObjectAttributes->push_back(make_pair(NS_ooxml::LN_shape, pShapeValue)); + return 0; + } xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("GraphicURL")), uno::Any(aGraphicUrl)); // Send it to the dmapper. - RTFSprms_t aSprms; - RTFSprms_t aAttributes; + RTFSprms aSprms; + RTFSprms aAttributes; // shape attribute - RTFSprms_t aPicAttributes; + RTFSprms aPicAttributes; RTFValue::Pointer_t pShapeValue(new RTFValue(xShape)); - aPicAttributes.push_back(make_pair(NS_ooxml::LN_shape, pShapeValue)); + aPicAttributes->push_back(make_pair(NS_ooxml::LN_shape, pShapeValue)); // pic sprm - RTFSprms_t aGraphicDataAttributes; - RTFSprms_t aGraphicDataSprms; + RTFSprms aGraphicDataAttributes; + RTFSprms aGraphicDataSprms; RTFValue::Pointer_t pPicValue(new RTFValue(aPicAttributes)); - aGraphicDataSprms.push_back(make_pair(NS_ooxml::LN_pic_pic, pPicValue)); + aGraphicDataSprms->push_back(make_pair(NS_ooxml::LN_pic_pic, pPicValue)); // graphicData sprm - RTFSprms_t aGraphicAttributes; - RTFSprms_t aGraphicSprms; + RTFSprms aGraphicAttributes; + RTFSprms aGraphicSprms; RTFValue::Pointer_t pGraphicDataValue(new RTFValue(aGraphicDataAttributes, aGraphicDataSprms)); - aGraphicSprms.push_back(make_pair(NS_ooxml::LN_CT_GraphicalObject_graphicData, pGraphicDataValue)); + aGraphicSprms->push_back(make_pair(NS_ooxml::LN_CT_GraphicalObject_graphicData, pGraphicDataValue)); // graphic sprm RTFValue::Pointer_t pGraphicValue(new RTFValue(aGraphicAttributes, aGraphicSprms)); // extent sprm - RTFSprms_t aExtentAttributes; - for (RTFSprms_t::iterator i = m_aStates.top().aCharacterAttributes.begin(); i != m_aStates.top().aCharacterAttributes.end(); ++i) + RTFSprms aExtentAttributes; + for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes->begin(); i != m_aStates.top().aCharacterAttributes->end(); ++i) if (i->first == NS_rtf::LN_XEXT || i->first == NS_rtf::LN_YEXT) - aExtentAttributes.push_back(make_pair(i->first, i->second)); + aExtentAttributes->push_back(make_pair(i->first, i->second)); RTFValue::Pointer_t pExtentValue(new RTFValue(aExtentAttributes)); // docpr sprm - RTFSprms_t aDocprAttributes; - for (RTFSprms_t::iterator i = m_aStates.top().aCharacterAttributes.begin(); i != m_aStates.top().aCharacterAttributes.end(); ++i) + RTFSprms aDocprAttributes; + for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes->begin(); i != m_aStates.top().aCharacterAttributes->end(); ++i) if (i->first == NS_ooxml::LN_CT_NonVisualDrawingProps_name || i->first == NS_ooxml::LN_CT_NonVisualDrawingProps_descr) - aDocprAttributes.push_back(make_pair(i->first, i->second)); + aDocprAttributes->push_back(make_pair(i->first, i->second)); RTFValue::Pointer_t pDocprValue(new RTFValue(aDocprAttributes)); if (bInline) { - RTFSprms_t aInlineAttributes; - RTFSprms_t aInlineSprms; - aInlineSprms.push_back(make_pair(NS_ooxml::LN_CT_Inline_extent, pExtentValue)); - aInlineSprms.push_back(make_pair(NS_ooxml::LN_CT_Inline_docPr, pDocprValue)); - aInlineSprms.push_back(make_pair(NS_ooxml::LN_graphic_graphic, pGraphicValue)); + RTFSprms aInlineAttributes; + RTFSprms aInlineSprms; + aInlineSprms->push_back(make_pair(NS_ooxml::LN_CT_Inline_extent, pExtentValue)); + aInlineSprms->push_back(make_pair(NS_ooxml::LN_CT_Inline_docPr, pDocprValue)); + aInlineSprms->push_back(make_pair(NS_ooxml::LN_graphic_graphic, pGraphicValue)); // inline sprm RTFValue::Pointer_t pValue(new RTFValue(aInlineAttributes, aInlineSprms)); - aSprms.push_back(make_pair(NS_ooxml::LN_inline_inline, pValue)); + aSprms->push_back(make_pair(NS_ooxml::LN_inline_inline, pValue)); } else // anchored { // wrap sprm - RTFSprms_t aAnchorWrapAttributes; - for (RTFSprms_t::iterator i = m_aStates.top().aCharacterAttributes.begin(); i != m_aStates.top().aCharacterAttributes.end(); ++i) + RTFSprms aAnchorWrapAttributes; + for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes->begin(); i != m_aStates.top().aCharacterAttributes->end(); ++i) if (i->first == NS_ooxml::LN_CT_WrapSquare_wrapText) - aAnchorWrapAttributes.push_back(make_pair(i->first, i->second)); + aAnchorWrapAttributes->push_back(make_pair(i->first, i->second)); RTFValue::Pointer_t pAnchorWrapValue(new RTFValue(aAnchorWrapAttributes)); - RTFSprms_t aAnchorAttributes; - RTFSprms_t aAnchorSprms; - aAnchorSprms.push_back(make_pair(NS_ooxml::LN_CT_Anchor_extent, pExtentValue)); - if (aAnchorWrapAttributes.size()) - aAnchorSprms.push_back(make_pair(NS_ooxml::LN_EG_WrapType_wrapSquare, pAnchorWrapValue)); - aAnchorSprms.push_back(make_pair(NS_ooxml::LN_CT_Anchor_docPr, pDocprValue)); - aAnchorSprms.push_back(make_pair(NS_ooxml::LN_graphic_graphic, pGraphicValue)); + RTFSprms aAnchorAttributes; + RTFSprms aAnchorSprms; + aAnchorSprms->push_back(make_pair(NS_ooxml::LN_CT_Anchor_extent, pExtentValue)); + if (aAnchorWrapAttributes->size()) + aAnchorSprms->push_back(make_pair(NS_ooxml::LN_EG_WrapType_wrapSquare, pAnchorWrapValue)); + aAnchorSprms->push_back(make_pair(NS_ooxml::LN_CT_Anchor_docPr, pDocprValue)); + aAnchorSprms->push_back(make_pair(NS_ooxml::LN_graphic_graphic, pGraphicValue)); // anchor sprm RTFValue::Pointer_t pValue(new RTFValue(aAnchorAttributes, aAnchorSprms)); - aSprms.push_back(make_pair(NS_ooxml::LN_anchor_anchor, pValue)); + aSprms->push_back(make_pair(NS_ooxml::LN_anchor_anchor, pValue)); } writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aAttributes, aSprms)); Mapper().props(pProperties); @@ -541,10 +627,6 @@ int RTFDocumentImpl::resolveChars(char ch) { OStringBuffer aBuf; - if (m_aStates.top().nDestinationState == DESTINATION_PICT) - return resolvePict(ch, true); - else if (m_aStates.top().nDestinationState == DESTINATION_SHAPEPROPERTYVALUEPICT) - return resolvePict(ch, false); while(!Strm().IsEof() && ch != '{' && ch != '}' && ch != '\\') { if (ch != 0x0d && ch != 0x0a) @@ -594,18 +676,83 @@ void RTFDocumentImpl::text(OUString& rString) bool bRet = true; switch (m_aStates.top().nDestinationState) { + case DESTINATION_FONTTABLE: case DESTINATION_FONTENTRY: + case DESTINATION_STYLESHEET: case DESTINATION_STYLEENTRY: + case DESTINATION_REVISIONTABLE: case DESTINATION_REVISIONENTRY: - // drop the ; at the end if it's there - if (rString.endsWithAsciiL(";", 1)) - rString = rString.copy(0, rString.getLength() - 1); + { + // ; is the end of the entry + bool bEnd = false; + if (rString.endsWithAsciiL(";", 1)) + { + rString = rString.copy(0, rString.getLength() - 1); + bEnd = true; + } + m_aDestinationText.append(rString); + if (bEnd) + { + switch (m_aStates.top().nDestinationState) + { + case DESTINATION_FONTTABLE: + case DESTINATION_FONTENTRY: + { + RTFValue::Pointer_t pValue(new RTFValue(m_aDestinationText.makeStringAndClear())); + m_aStates.top().aTableAttributes->push_back(make_pair(NS_rtf::LN_XSZFFN, pValue)); + + writerfilter::Reference<Properties>::Pointer_t const pProp( + new RTFReferenceProperties(m_aStates.top().aTableAttributes, m_aStates.top().aTableSprms) + ); + m_aFontTableEntries.insert(make_pair(m_nCurrentFontIndex, pProp)); + } + break; + case DESTINATION_STYLESHEET: + case DESTINATION_STYLEENTRY: + { + RTFValue::Pointer_t pValue(new RTFValue(m_aDestinationText.makeStringAndClear())); + m_aStates.top().aTableAttributes->push_back(make_pair(NS_rtf::LN_XSTZNAME1, pValue)); + + writerfilter::Reference<Properties>::Pointer_t const pProp( + new RTFReferenceProperties(mergeAttributes(), mergeSprms()) + ); + m_aStyleTableEntries.insert(make_pair(m_nCurrentStyleIndex, pProp)); + } + break; + case DESTINATION_REVISIONTABLE: + case DESTINATION_REVISIONENTRY: + m_aAuthors[m_aAuthors.size()] = m_aDestinationText.makeStringAndClear(); + break; + default: break; + } + resetAttributes(); + resetSprms(); + } + } + break; case DESTINATION_LEVELTEXT: case DESTINATION_SHAPEPROPERTYNAME: case DESTINATION_SHAPEPROPERTYVALUE: case DESTINATION_BOOKMARKEND: + case DESTINATION_PICT: + case DESTINATION_SHAPEPROPERTYVALUEPICT: + case DESTINATION_FORMFIELDNAME: + case DESTINATION_FORMFIELDLIST: + case DESTINATION_DATAFIELD: + case DESTINATION_AUTHOR: + case DESTINATION_OPERATOR: + case DESTINATION_COMPANY: + case DESTINATION_COMMENT: + case DESTINATION_OBJDATA: + case DESTINATION_ANNOTATIONDATE: + case DESTINATION_ANNOTATIONAUTHOR: m_aDestinationText.append(rString); break; + case DESTINATION_EQINSTRUCTION: + if (rString.copy(0, 2).equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("do")) + && rString.copy(2).toInt32() > 0) + dispatchFlag(RTF_SUB); + break; default: bRet = false; break; } if (bRet) @@ -621,33 +768,15 @@ void RTFDocumentImpl::text(OUString& rString) new RTFReferenceProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms) ); - if (m_bFirstRun) - { - // output settings table - RTFSprms_t aAttributes; - writerfilter::Reference<Properties>::Pointer_t const pProp(new RTFReferenceProperties(aAttributes, m_aSettingsTableSprms)); - RTFReferenceTable::Entries_t aSettingsTableEntries; - aSettingsTableEntries.insert(make_pair(0, pProp)); - writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aSettingsTableEntries)); - Mapper().table(NS_ooxml::LN_settings_settings, pTable); - // start initial paragraph - if (!m_bIsSubstream) - Mapper().startSectionGroup(); - Mapper().startParagraphGroup(); - Mapper().props(pParagraphProperties); - m_bFirstRun = false; - } + checkFirstRun(); if (m_bNeedPap) { - if (!m_bTable && !m_bSuper) + if (!m_pCurrentBuffer) Mapper().props(pParagraphProperties); else { RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms)); - if (m_bTable) - m_aTableBuffer.push_back(make_pair(BUFFER_PROPS, pValue)); - else - m_aSuperBuffer.push_back(make_pair(BUFFER_PROPS, pValue)); + m_pCurrentBuffer->push_back(make_pair(BUFFER_PROPS, pValue)); } m_bNeedPap = false; } @@ -659,19 +788,18 @@ void RTFDocumentImpl::text(OUString& rString) return; } - if (!m_bTable && !m_bSuper && m_aStates.top().nDestinationState != DESTINATION_FOOTNOTE) + if (!m_pCurrentBuffer && m_aStates.top().nDestinationState != DESTINATION_FOOTNOTE) Mapper().startCharacterGroup(); - else + else if (m_pCurrentBuffer) { RTFValue::Pointer_t pValue; - if (m_bTable) - m_aTableBuffer.push_back(make_pair(BUFFER_STARTRUN, pValue)); - else - m_aSuperBuffer.push_back(make_pair(BUFFER_STARTRUN, pValue)); + m_pCurrentBuffer->push_back(make_pair(BUFFER_STARTRUN, pValue)); } - if (m_aStates.top().nDestinationState == DESTINATION_NORMAL || m_aStates.top().nDestinationState == DESTINATION_FIELDRESULT) + if (m_aStates.top().nDestinationState == DESTINATION_NORMAL + || m_aStates.top().nDestinationState == DESTINATION_FIELDRESULT + || m_aStates.top().nDestinationState == DESTINATION_SHAPETEXT) { - if (!m_bTable && !m_bSuper) + if (!m_pCurrentBuffer) { writerfilter::Reference<Properties>::Pointer_t const pProperties( new RTFReferenceProperties(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms) @@ -681,35 +809,26 @@ void RTFDocumentImpl::text(OUString& rString) else { RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms)); - if (m_bTable) - m_aTableBuffer.push_back(make_pair(BUFFER_PROPS, pValue)); - else - m_aSuperBuffer.push_back(make_pair(BUFFER_PROPS, pValue)); + m_pCurrentBuffer->push_back(make_pair(BUFFER_PROPS, pValue)); } } - if (!m_bTable && !m_bSuper) + if (!m_pCurrentBuffer) Mapper().utext(reinterpret_cast<sal_uInt8 const*>(rString.getStr()), rString.getLength()); else { RTFValue::Pointer_t pValue(new RTFValue(rString)); - if (m_bTable) - m_aTableBuffer.push_back(make_pair(BUFFER_UTEXT, pValue)); - else - m_aSuperBuffer.push_back(make_pair(BUFFER_UTEXT, pValue)); + m_pCurrentBuffer->push_back(make_pair(BUFFER_UTEXT, pValue)); } - if (!m_bTable && !m_bSuper && m_aStates.top().nDestinationState != DESTINATION_FOOTNOTE) + if (!m_pCurrentBuffer && m_aStates.top().nDestinationState != DESTINATION_FOOTNOTE) Mapper().endCharacterGroup(); - else + else if(m_pCurrentBuffer) { RTFValue::Pointer_t pValue; - if (m_bTable) - m_aTableBuffer.push_back(make_pair(BUFFER_ENDRUN, pValue)); - else - m_aSuperBuffer.push_back(make_pair(BUFFER_ENDRUN, pValue)); + m_pCurrentBuffer->push_back(make_pair(BUFFER_ENDRUN, pValue)); } } -void RTFDocumentImpl::replayBuffer(std::deque< std::pair<RTFBufferTypes, RTFValue::Pointer_t> >& rBuffer) +void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer) { while (rBuffer.size()) { @@ -725,12 +844,12 @@ void RTFDocumentImpl::replayBuffer(std::deque< std::pair<RTFBufferTypes, RTFValu else if (aPair.first == BUFFER_CELLEND) { RTFValue::Pointer_t pValue(new RTFValue(1)); - m_aStates.top().aTableCellSprms.push_back(make_pair(NS_sprm::LN_PCell, pValue)); + m_aStates.top().aTableCellSprms->push_back(make_pair(NS_sprm::LN_PCell, pValue)); writerfilter::Reference<Properties>::Pointer_t const pTableCellProperties( new RTFReferenceProperties(m_aStates.top().aTableCellAttributes, m_aStates.top().aTableCellSprms) ); Mapper().props(pTableCellProperties); - lcl_TableBreak(Mapper()); + tableBreak(); break; } else if (aPair.first == BUFFER_STARTRUN) @@ -771,10 +890,26 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword) break; case RTF_FLDINST: { - sal_uInt8 sFieldStart[] = { 0x13 }; - Mapper().startCharacterGroup(); - Mapper().text(sFieldStart, 1); - Mapper().endCharacterGroup(); + sal_Int32 nPos = Strm().Tell(); + OStringBuffer aBuf; + char ch; + for (int i = 0; i < 4; ++i) + { + Strm() >> ch; + aBuf.append(ch); + } + Strm().Seek(nPos); + + // EQ fields are not really fields in fact. + if (aBuf.toString().equals("{ EQ")) + m_bEq = true; + else + { + sal_uInt8 sFieldStart[] = { 0x13 }; + Mapper().startCharacterGroup(); + Mapper().text(sFieldStart, 1); + Mapper().endCharacterGroup(); + } m_aStates.top().nDestinationState = DESTINATION_FIELDINSTRUCTION; } break; @@ -856,7 +991,7 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword) case RTF_FOOTERF: nId = NS_rtf::LN_footerr; break; // same here, NS_rtf::LN_footerf could be used default: break; } - m_nHeaderFooterPositions.push_back(make_pair(nId, nPos)); + m_nHeaderFooterPositions.push(make_pair(nId, nPos)); m_aStates.top().nDestinationState = DESTINATION_SKIP; } break; @@ -878,7 +1013,7 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword) nId = NS_rtf::LN_endnote; m_bHasFootnote = true; - m_bSuper = false; + m_pCurrentBuffer = 0; bool bCustomMark = false; OUString aCustomMark; while (m_aSuperBuffer.size()) @@ -897,10 +1032,10 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword) resolveSubstream(m_nGroupStartPos - 1, nId, aCustomMark); if (bCustomMark) { - m_aStates.top().aCharacterAttributes.clear(); - m_aStates.top().aCharacterSprms.clear(); + m_aStates.top().aCharacterAttributes->clear(); + m_aStates.top().aCharacterSprms->clear(); RTFValue::Pointer_t pValue(new RTFValue(1)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_FtnEdnRef_customMarkFollows, pValue)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_FtnEdnRef_customMarkFollows, pValue)); text(aCustomMark); Mapper().endCharacterGroup(); } @@ -916,6 +1051,85 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword) case RTF_REVTBL: m_aStates.top().nDestinationState = DESTINATION_REVISIONTABLE; break; + case RTF_ANNOTATION: + if (!m_bIsSubstream) + { + resolveSubstream(m_nGroupStartPos - 1, NS_rtf::LN_annotation); + m_aStates.top().nDestinationState = DESTINATION_SKIP; + } + else + { + // If there is an author set, emit it now. + if (m_aAuthor.getLength()) + { + RTFValue::Pointer_t pValue(new RTFValue(m_aAuthor)); + RTFSprms aAttributes; + aAttributes->push_back(make_pair(NS_ooxml::LN_CT_TrackChange_author, pValue)); + writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aAttributes)); + Mapper().props(pProperties); + } + } + break; + case RTF_SHPTXT: + m_aStates.top().nDestinationState = DESTINATION_SHAPETEXT; + dispatchFlag(RTF_PARD); + m_bNeedPap = true; + OSL_ENSURE(!m_aShapetextBuffer.size(), "shapetext buffer is not empty"); + m_pCurrentBuffer = &m_aShapetextBuffer; + break; + case RTF_FORMFIELD: + if (m_aStates.top().nDestinationState == DESTINATION_FIELDINSTRUCTION) + m_aStates.top().nDestinationState = DESTINATION_FORMFIELD; + break; + case RTF_FFNAME: + m_aStates.top().nDestinationState = DESTINATION_FORMFIELDNAME; + break; + case RTF_FFL: + m_aStates.top().nDestinationState = DESTINATION_FORMFIELDLIST; + break; + case RTF_DATAFIELD: + m_aStates.top().nDestinationState = DESTINATION_DATAFIELD; + break; + case RTF_INFO: + m_aStates.top().nDestinationState = DESTINATION_INFO; + break; + case RTF_CREATIM: + m_aStates.top().nDestinationState = DESTINATION_CREATIONTIME; + break; + case RTF_REVTIM: + m_aStates.top().nDestinationState = DESTINATION_REVISIONTIME; + break; + case RTF_PRINTIM: + m_aStates.top().nDestinationState = DESTINATION_PRINTTIME; + break; + case RTF_AUTHOR: + m_aStates.top().nDestinationState = DESTINATION_AUTHOR; + break; + case RTF_OPERATOR: + m_aStates.top().nDestinationState = DESTINATION_OPERATOR; + break; + case RTF_COMPANY: + m_aStates.top().nDestinationState = DESTINATION_COMPANY; + break; + case RTF_COMMENT: + m_aStates.top().nDestinationState = DESTINATION_COMMENT; + break; + case RTF_OBJECT: + m_aStates.top().nDestinationState = DESTINATION_OBJECT; + m_bObject = true; + break; + case RTF_OBJDATA: + m_aStates.top().nDestinationState = DESTINATION_OBJDATA; + break; + case RTF_RESULT: + m_aStates.top().nDestinationState = DESTINATION_RESULT; + break; + case RTF_ATNDATE: + m_aStates.top().nDestinationState = DESTINATION_ANNOTATIONDATE; + break; + case RTF_ATNAUTHOR: + m_aStates.top().nDestinationState = DESTINATION_ANNOTATIONAUTHOR; + break; case RTF_LISTTEXT: // Should be ignored by any reader that understands Word 97 through Word 2007 numbering. case RTF_NONESTTABLES: @@ -923,7 +1137,9 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword) m_aStates.top().nDestinationState = DESTINATION_SKIP; break; default: +#if OSL_DEBUG_LEVEL > 1 OSL_TRACE("%s: TODO handle destination '%s'", OSL_THIS_FUNC, lcl_RtfToString(nKeyword)); +#endif // Make sure we skip destinations (even without \*) till we don't handle them m_aStates.top().nDestinationState = DESTINATION_SKIP; bParsed = false; @@ -972,12 +1188,12 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword) break; case RTF_PAR: { - if (!m_bTable) + if (!m_pCurrentBuffer) parBreak(); - else + else if (m_aStates.top().nDestinationState != DESTINATION_SHAPETEXT) { RTFValue::Pointer_t pValue; - m_aTableBuffer.push_back(make_pair(BUFFER_PAR, pValue)); + m_pCurrentBuffer->push_back(make_pair(BUFFER_PAR, pValue)); } // but don't emit properties yet, since they may change till the first text token arrives m_bNeedPap = true; @@ -1025,6 +1241,35 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword) case RTF_ROW: case RTF_NESTROW: { + m_bFirstRow = false; + if (m_aStates.top().nCells) + { + // Make a backup before we start popping elements + m_aStates.top().aTableInheritingCellsSprms = m_aStates.top().aTableCellsSprms; + m_aStates.top().aTableInheritingCellsAttributes = m_aStates.top().aTableCellsAttributes; + m_aStates.top().nInheritingCells = m_aStates.top().nCells; + } + else + { + // No table definition? Then inherit from the previous row + m_aStates.top().aTableCellsSprms = m_aStates.top().aTableInheritingCellsSprms; + m_aStates.top().aTableCellsAttributes = m_aStates.top().aTableInheritingCellsAttributes; + m_aStates.top().nCells = m_aStates.top().nInheritingCells; + // This can't be the first row, and we need cell width only there + while(m_aStates.top().aTableRowSprms.erase(NS_ooxml::LN_CT_TblGridBase_gridCol)); + } + for (int i = 0; i < m_aStates.top().nCells; ++i) + { + m_aStates.top().aTableCellSprms = m_aStates.top().aTableCellsSprms.front(); + m_aStates.top().aTableCellsSprms.pop_front(); + m_aStates.top().aTableCellAttributes = m_aStates.top().aTableCellsAttributes.front(); + m_aStates.top().aTableCellsAttributes.pop_front(); + replayBuffer(m_aTableBuffer); + } + m_aStates.top().nCells = 0; + m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms; + m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes; + writerfilter::Reference<Properties>::Pointer_t const pParagraphProperties( new RTFReferenceProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms) ); @@ -1034,20 +1279,22 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword) RTFValue::Pointer_t pUnitValue(new RTFValue(3)); lcl_putNestedAttribute(m_aStates.top().aTableRowSprms, NS_ooxml::LN_CT_TblPrBase_tblW, NS_ooxml::LN_CT_TblWidth_type, pUnitValue); - RTFValue::Pointer_t pWidthValue(new RTFValue(m_aStates.top().nCellX)); + RTFValue::Pointer_t pWValue(new RTFValue(m_aStates.top().nCellX)); lcl_putNestedAttribute(m_aStates.top().aTableRowSprms, - NS_ooxml::LN_CT_TblPrBase_tblW, NS_ooxml::LN_CT_TblWidth_w, pWidthValue); + NS_ooxml::LN_CT_TblPrBase_tblW, NS_ooxml::LN_CT_TblWidth_w, pWValue); RTFValue::Pointer_t pRowValue(new RTFValue(1)); - m_aStates.top().aTableRowSprms.push_back(make_pair(NS_sprm::LN_PRow, pRowValue)); + m_aStates.top().aTableRowSprms->push_back(make_pair(NS_sprm::LN_PRow, pRowValue)); writerfilter::Reference<Properties>::Pointer_t const pTableRowProperties( new RTFReferenceProperties(m_aStates.top().aTableRowAttributes, m_aStates.top().aTableRowSprms) ); Mapper().props(pTableRowProperties); - lcl_TableBreak(Mapper()); + tableBreak(); m_bNeedPap = true; m_aTableBuffer.clear(); + m_aStates.top().aTableCellsSprms.clear(); + m_aStates.top().aTableCellsAttributes.clear(); } break; case RTF_COLUMN: @@ -1062,7 +1309,9 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword) // Nothing to do, dmapper assumes this is the default. break; default: +#if OSL_DEBUG_LEVEL > 1 OSL_TRACE("%s: TODO handle symbol '%s'", OSL_THIS_FUNC, lcl_RtfToString(nKeyword)); +#endif bParsed = false; break; } @@ -1088,7 +1337,7 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) if (nParam >= 0) { RTFValue::Pointer_t pValue(new RTFValue(nParam)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_PJc, pValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_PJc, pValue)); skipDestination(bParsed); return 0; } @@ -1104,7 +1353,7 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) if (nParam >= 0) { RTFValue::Pointer_t pValue(new RTFValue(nParam)); - m_aStates.top().aTabAttributes.push_back(make_pair(NS_ooxml::LN_CT_TabStop_val, pValue)); + m_aStates.top().aTabAttributes->push_back(make_pair(NS_ooxml::LN_CT_TabStop_val, pValue)); skipDestination(bParsed); return 0; } @@ -1123,7 +1372,7 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) if (nParam >= 0) { RTFValue::Pointer_t pValue(new RTFValue(nParam)); - m_aStates.top().aTabAttributes.push_back(make_pair(NS_ooxml::LN_CT_TabStop_leader, pValue)); + m_aStates.top().aTabAttributes->push_back(make_pair(NS_ooxml::LN_CT_TabStop_leader, pValue)); skipDestination(bParsed); return 0; } @@ -1171,7 +1420,7 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) if (nParam >= 0) { RTFValue::Pointer_t pValue(new RTFValue(nParam)); - m_aStates.top().aSectionSprms.push_back(make_pair(NS_sprm::LN_SBkc, pValue)); + m_aStates.top().aSectionSprms->push_back(make_pair(NS_sprm::LN_SBkc, pValue)); skipDestination(bParsed); return 0; } @@ -1181,15 +1430,15 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) { case RTF_KEEP: nParam = NS_sprm::LN_PFKeep; break; case RTF_KEEPN: nParam = NS_sprm::LN_PFKeepFollow; break; - case RTF_WIDCTLPAR: nParam = NS_sprm::LN_PFWidowControl; break; - case RTF_INTBL: m_bTable = true; nParam = NS_sprm::LN_PFInTable; break; + case RTF_INTBL: m_pCurrentBuffer = &m_aTableBuffer; nParam = NS_sprm::LN_PFInTable; break; case RTF_PAGEBB: nParam = NS_sprm::LN_PFPageBreakBefore; break; default: break; } if (nParam >= 0) { RTFValue::Pointer_t pValue(new RTFValue(1)); - m_aStates.top().aParagraphSprms.push_back(make_pair(nParam, pValue)); + m_aStates.top().aParagraphSprms.erase(NS_sprm::LN_PFInTable); + m_aStates.top().aParagraphSprms->push_back(make_pair(nParam, pValue)); skipDestination(bParsed); return 0; } @@ -1216,7 +1465,7 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) case RTF_PARD: m_aStates.top().aParagraphSprms = m_aDefaultState.aParagraphSprms; m_aStates.top().aParagraphAttributes = m_aDefaultState.aParagraphAttributes; - m_bTable = false; + m_pCurrentBuffer = 0; break; case RTF_SECTD: m_aStates.top().aSectionSprms = m_aDefaultState.aSectionSprms; @@ -1226,23 +1475,22 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) m_aStates.top().aTableRowSprms = m_aDefaultState.aTableRowSprms; m_aStates.top().aTableRowAttributes = m_aDefaultState.aTableRowAttributes; m_aStates.top().nCellX = 0; - m_aStates.top().aTableCellsSprms = m_aDefaultState.aTableCellsSprms; - m_aStates.top().aTableCellsAttributes = m_aDefaultState.aTableCellsAttributes; break; + case RTF_WIDCTLPAR: case RTF_NOWIDCTLPAR: { - RTFValue::Pointer_t pValue(new RTFValue(0)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_PFWidowControl, pValue)); + RTFValue::Pointer_t pValue(new RTFValue(nKeyword == RTF_WIDCTLPAR)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_PFWidowControl, pValue)); } break; case RTF_BOX: { - RTFSprms_t aAttributes; + RTFSprms aAttributes; RTFValue::Pointer_t pValue(new RTFValue(aAttributes)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_PBrcTop, pValue)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_PBrcLeft, pValue)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_PBrcBottom, pValue)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_PBrcRight, pValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_PBrcTop, pValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_PBrcLeft, pValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_PBrcBottom, pValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_PBrcRight, pValue)); m_aStates.top().nBorderState = BORDER_PARAGRAPH; } break; @@ -1250,21 +1498,21 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) case RTF_RTLSECT: { RTFValue::Pointer_t pValue(new RTFValue(nKeyword == RTF_LTRSECT ? 0 : 1)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_STextFlow, pValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_STextFlow, pValue)); } break; case RTF_LTRPAR: case RTF_RTLPAR: { RTFValue::Pointer_t pValue(new RTFValue(nKeyword == RTF_LTRPAR ? 0 : 1)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_PFrameTextFlow, pValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_PFrameTextFlow, pValue)); } break; case RTF_LTRROW: case RTF_RTLROW: { RTFValue::Pointer_t pValue(new RTFValue(nKeyword == RTF_LTRROW ? 0 : 1)); - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_TTextFlow, pValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_TTextFlow, pValue)); } break; case RTF_LTRCH: @@ -1274,7 +1522,7 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) case RTF_ULNONE: { RTFValue::Pointer_t pValue(new RTFValue(0)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_sprm::LN_CKul, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_sprm::LN_CKul, pValue)); } break; case RTF_NONSHPPICT: @@ -1285,8 +1533,8 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) case RTF_CLBRDRB: case RTF_CLBRDRR: { - RTFSprms_t aAttributes; - RTFSprms_t aSprms; + RTFSprms aAttributes; + RTFSprms aSprms; RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms)); switch (nKeyword) { @@ -1305,8 +1553,8 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) case RTF_PGBRDRB: case RTF_PGBRDRR: { - RTFSprms_t aAttributes; - RTFSprms_t aSprms; + RTFSprms aAttributes; + RTFSprms aSprms; RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms)); switch (nKeyword) { @@ -1323,13 +1571,13 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) case RTF_CLVMGF: { RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_restart)); - m_aStates.top().aTableCellSprms.push_back(make_pair(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue)); + m_aStates.top().aTableCellSprms->push_back(make_pair(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue)); } break; case RTF_CLVMRG: { RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_continue)); - m_aStates.top().aTableCellSprms.push_back(make_pair(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue)); + m_aStates.top().aTableCellSprms->push_back(make_pair(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue)); } break; case RTF_CLVERTALT: @@ -1344,18 +1592,18 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) default: break; } RTFValue::Pointer_t pValue(new RTFValue(nParam)); - m_aStates.top().aTableCellSprms.push_back(make_pair(NS_ooxml::LN_CT_TcPrBase_vAlign, pValue)); + m_aStates.top().aTableCellSprms->push_back(make_pair(NS_ooxml::LN_CT_TcPrBase_vAlign, pValue)); } break; case RTF_TRKEEP: { RTFValue::Pointer_t pValue(new RTFValue(1)); - m_aStates.top().aTableRowSprms.push_back(make_pair(NS_sprm::LN_TCantSplit, pValue)); + m_aStates.top().aTableRowSprms->push_back(make_pair(NS_sprm::LN_TCantSplit, pValue)); } case RTF_SECTUNLOCKED: { RTFValue::Pointer_t pValue(new RTFValue(!nParam)); - m_aStates.top().aSectionSprms.push_back(make_pair(NS_ooxml::LN_EG_SectPrContents_formProt, pValue)); + m_aStates.top().aSectionSprms->push_back(make_pair(NS_ooxml::LN_EG_SectPrContents_formProt, pValue)); } case RTF_PGNDEC: case RTF_PGNUCRM: @@ -1379,22 +1627,22 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) case RTF_TITLEPG: { RTFValue::Pointer_t pValue(new RTFValue(1)); - m_aStates.top().aSectionSprms.push_back(make_pair(NS_ooxml::LN_EG_SectPrContents_titlePg, pValue)); + m_aStates.top().aSectionSprms->push_back(make_pair(NS_ooxml::LN_EG_SectPrContents_titlePg, pValue)); } break; case RTF_SUPER: { - m_bSuper = true; + m_pCurrentBuffer = &m_aSuperBuffer; OUString aValue(RTL_CONSTASCII_USTRINGPARAM("superscript")); RTFValue::Pointer_t pValue(new RTFValue(aValue)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue)); } break; case RTF_SUB: { OUString aValue(RTL_CONSTASCII_USTRINGPARAM("subscript")); RTFValue::Pointer_t pValue(new RTFValue(aValue)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue)); } break; case RTF_LINEPPAGE: @@ -1406,7 +1654,9 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) } break; default: +#if OSL_DEBUG_LEVEL > 1 OSL_TRACE("%s: TODO handle flag '%s'", OSL_THIS_FUNC, lcl_RtfToString(nKeyword)); +#endif bParsed = false; break; } @@ -1430,7 +1680,7 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) } if (nSprm > 0) { - m_aStates.top().aTableSprms.push_back(make_pair(nSprm, pIntValue)); + m_aStates.top().aTableSprms->push_back(make_pair(nSprm, pIntValue)); skipDestination(bParsed); return 0; } @@ -1450,7 +1700,7 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) } if (nSprm > 0) { - m_aStates.top().aCharacterSprms.push_back(make_pair(nSprm, pIntValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(nSprm, pIntValue)); skipDestination(bParsed); return 0; } @@ -1469,7 +1719,7 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) } if (nSprm > 0) { - m_aStates.top().aParagraphSprms.push_back(make_pair(nSprm, pIntValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(nSprm, pIntValue)); skipDestination(bParsed); return 0; } @@ -1483,36 +1733,38 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) } if (nSprm > 0) { - m_aStates.top().aTableAttributes.push_back(make_pair(nSprm, pIntValue)); + m_aStates.top().aTableAttributes->push_back(make_pair(nSprm, pIntValue)); skipDestination(bParsed); return 0; } - // Trivial paragraph attributes. + // Trivial character attributes. switch (nKeyword) { - // NS_sprm::LN_PDyaLine could be used, but that won't work with slmult - case RTF_SL: nSprm = NS_ooxml::LN_CT_Spacing_line; break; + case RTF_PICW: nSprm = NS_rtf::LN_XEXT; if (m_aStates.top().nPictureScaleX) nParam = m_aStates.top().nPictureScaleX * nParam; break; + case RTF_PICH: nSprm = NS_rtf::LN_YEXT; if (m_aStates.top().nPictureScaleY) nParam = m_aStates.top().nPictureScaleY * nParam; break; default: break; } if (nSprm > 0) { - m_aStates.top().aParagraphAttributes.push_back(make_pair(nSprm, pIntValue)); + RTFValue::Pointer_t pValue(new RTFValue(nParam)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(nSprm, pValue)); skipDestination(bParsed); return 0; } - // Trivial character attributes. + // Info group. switch (nKeyword) { - case RTF_PICW: nSprm = NS_rtf::LN_XEXT; if (m_aStates.top().nPictureScaleX) nParam = m_aStates.top().nPictureScaleX * nParam; break; - case RTF_PICH: nSprm = NS_rtf::LN_YEXT; if (m_aStates.top().nPictureScaleY) nParam = m_aStates.top().nPictureScaleY * nParam; break; + case RTF_YR: m_aStates.top().nYear = nParam; nSprm = 1; break; + case RTF_MO: m_aStates.top().nMonth = nParam; nSprm = 1; break; + case RTF_DY: m_aStates.top().nDay = nParam; nSprm = 1; break; + case RTF_HR: m_aStates.top().nHour = nParam; nSprm = 1; break; + case RTF_MIN: m_aStates.top().nMinute = nParam; nSprm = 1; break; default: break; } if (nSprm > 0) { - RTFValue::Pointer_t pValue(new RTFValue(nParam)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(nSprm, pValue)); skipDestination(bParsed); return 0; } @@ -1521,11 +1773,11 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) switch (nKeyword) { case RTF_F: - if (m_aStates.top().nDestinationState == DESTINATION_FONTENTRY) - m_aStates.top().nCurrentFontIndex = nParam; + if (m_aStates.top().nDestinationState == DESTINATION_FONTTABLE || m_aStates.top().nDestinationState == DESTINATION_FONTENTRY) + m_nCurrentFontIndex = nParam; else { - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_sprm::LN_CRgFtc0, pIntValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_sprm::LN_CRgFtc0, pIntValue)); m_aStates.top().nCurrentEncoding = getEncodingTable(nParam); } break; @@ -1551,43 +1803,43 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) if (i == nRTFEncodings) // not found return 0; - m_aFontEncodings[m_aStates.top().nCurrentFontIndex] = rtl_getTextEncodingFromWindowsCodePage(aRTFEncodings[i].codepage); + m_aFontEncodings[m_nCurrentFontIndex] = rtl_getTextEncodingFromWindowsCodePage(aRTFEncodings[i].codepage); } break; case RTF_CF: { // NS_sprm::LN_CIco won't work, that would be an index in a static table - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_Color_val, pIntValue)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_Color_val, pIntValue)); } break; case RTF_S: - if (m_aStates.top().nDestinationState == DESTINATION_STYLEENTRY) + if (m_aStates.top().nDestinationState == DESTINATION_STYLESHEET || m_aStates.top().nDestinationState == DESTINATION_STYLEENTRY) { - m_aStates.top().nCurrentStyleIndex = nParam; - m_aStates.top().aTableAttributes.push_back(make_pair(NS_rtf::LN_ISTD, pIntValue)); + m_nCurrentStyleIndex = nParam; + m_aStates.top().aTableAttributes->push_back(make_pair(NS_rtf::LN_ISTD, pIntValue)); } else - m_aStates.top().aParagraphAttributes.push_back(make_pair(NS_rtf::LN_ISTD, pIntValue)); + m_aStates.top().aParagraphAttributes->push_back(make_pair(NS_rtf::LN_ISTD, pIntValue)); break; case RTF_CS: - if (m_aStates.top().nDestinationState == DESTINATION_STYLEENTRY) + if (m_aStates.top().nDestinationState == DESTINATION_STYLESHEET) { - m_aStates.top().nCurrentStyleIndex = nParam; - m_aStates.top().aTableAttributes.push_back(make_pair(NS_rtf::LN_ISTD, pIntValue)); + m_nCurrentStyleIndex = nParam; + m_aStates.top().aTableAttributes->push_back(make_pair(NS_rtf::LN_ISTD, pIntValue)); RTFValue::Pointer_t pValue(new RTFValue(2)); - m_aStates.top().aTableAttributes.push_back(make_pair(NS_rtf::LN_SGC, pValue)); // character style + m_aStates.top().aTableAttributes->push_back(make_pair(NS_rtf::LN_SGC, pValue)); // character style } else - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_rtf::LN_ISTD, pIntValue)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(NS_rtf::LN_ISTD, pIntValue)); break; case RTF_DEFF: - m_aDefaultState.aCharacterSprms.push_back(make_pair(NS_sprm::LN_CRgFtc0, pIntValue)); + m_aDefaultState.aCharacterSprms->push_back(make_pair(NS_sprm::LN_CRgFtc0, pIntValue)); break; case RTF_DEFLANG: - m_aDefaultState.aCharacterSprms.push_back(make_pair(NS_sprm::LN_CRgLid0, pIntValue)); + m_aDefaultState.aCharacterSprms->push_back(make_pair(NS_sprm::LN_CRgLid0, pIntValue)); break; case RTF_ADEFLANG: - m_aDefaultState.aCharacterSprms.push_back(make_pair(NS_sprm::LN_CLidBi, pIntValue)); + m_aDefaultState.aCharacterSprms->push_back(make_pair(NS_sprm::LN_CLidBi, pIntValue)); break; case RTF_CHCBPAT: { @@ -1611,51 +1863,58 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) case RTF_ULC: { RTFValue::Pointer_t pValue(new RTFValue(getColorTable(nParam))); - m_aStates.top().aCharacterSprms.push_back(make_pair(0x6877, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(0x6877, pValue)); } break; case RTF_UP: // TODO handle when point size is not shrinking { OUString aValue(RTL_CONSTASCII_USTRINGPARAM("superscript")); RTFValue::Pointer_t pValue(new RTFValue(aValue)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue)); } break; case RTF_DN: { OUString aValue(RTL_CONSTASCII_USTRINGPARAM("subscript")); RTFValue::Pointer_t pValue(new RTFValue(aValue)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue)); } break; case RTF_HORZVERT: { RTFValue::Pointer_t pValue(new RTFValue(true)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_EastAsianLayout_vert, pValue)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_EastAsianLayout_vert, pValue)); if (nParam) // rotate fits to a single line - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_EastAsianLayout_vertCompress, pValue)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_EastAsianLayout_vertCompress, pValue)); } break; case RTF_EXPND: { RTFValue::Pointer_t pValue(new RTFValue(nParam/5)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_sprm::LN_CDxaSpace, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_sprm::LN_CDxaSpace, pValue)); } break; case RTF_TWOINONE: { RTFValue::Pointer_t pValue(new RTFValue(true)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_EastAsianLayout_combine, pValue)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_EastAsianLayout_combine, pValue)); if (nParam > 0) - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_EastAsianLayout_combineBrackets, pIntValue)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_EastAsianLayout_combineBrackets, pIntValue)); + } + break; + case RTF_SL: + if (nParam > 0) + { + // NS_sprm::LN_PDyaLine could be used, but that won't work with slmult + m_aStates.top().aParagraphAttributes->push_back(make_pair(nSprm, pIntValue)); } break; case RTF_SLMULT: if (nParam > 0) { RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_wordprocessingml_ST_LineSpacingRule_auto)); - m_aStates.top().aParagraphAttributes.push_back(make_pair(NS_ooxml::LN_CT_Spacing_lineRule, pValue)); + m_aStates.top().aParagraphAttributes->push_back(make_pair(NS_ooxml::LN_CT_Spacing_lineRule, pValue)); } break; case RTF_BRDRW: @@ -1682,16 +1941,16 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) break; case RTF_TX: { - m_aStates.top().aTabAttributes.push_back(make_pair(NS_ooxml::LN_CT_TabStop_pos, pIntValue)); + m_aStates.top().aTabAttributes->push_back(make_pair(NS_ooxml::LN_CT_TabStop_pos, pIntValue)); RTFValue::Pointer_t pValue(new RTFValue(m_aStates.top().aTabAttributes)); lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_tabs, NS_ooxml::LN_CT_Tabs_tab, pValue); - m_aStates.top().aTabAttributes.clear(); + m_aStates.top().aTabAttributes->clear(); } break; case RTF_ILVL: { - RTFSprms_t& rSprms = lcl_getNumPr(m_aStates); - rSprms.push_back(make_pair(NS_sprm::LN_PIlvl, pIntValue)); + RTFSprms& rSprms = lcl_getNumPr(m_aStates); + rSprms->push_back(make_pair(NS_sprm::LN_PIlvl, pIntValue)); } case RTF_LISTTEMPLATEID: // This one is not referenced anywhere, so it's pointless to store it at the moment. @@ -1699,19 +1958,19 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) case RTF_LISTID: { if (m_aStates.top().nDestinationState == DESTINATION_LISTENTRY) - m_aStates.top().aTableAttributes.push_back(make_pair(NS_ooxml::LN_CT_AbstractNum_abstractNumId, pIntValue)); + m_aStates.top().aTableAttributes->push_back(make_pair(NS_ooxml::LN_CT_AbstractNum_abstractNumId, pIntValue)); else if (m_aStates.top().nDestinationState == DESTINATION_LISTOVERRIDEENTRY) - m_aStates.top().aTableSprms.push_back(make_pair(NS_ooxml::LN_CT_Num_abstractNumId, pIntValue)); + m_aStates.top().aTableSprms->push_back(make_pair(NS_ooxml::LN_CT_Num_abstractNumId, pIntValue)); } break; case RTF_LS: { if (m_aStates.top().nDestinationState == DESTINATION_LISTOVERRIDEENTRY) - m_aStates.top().aTableAttributes.push_back(make_pair(NS_rtf::LN_LSID, pIntValue)); + m_aStates.top().aTableAttributes->push_back(make_pair(NS_rtf::LN_LSID, pIntValue)); else { - RTFSprms_t& rSprms = lcl_getNumPr(m_aStates); - rSprms.push_back(make_pair(NS_sprm::LN_PIlfo, pIntValue)); + RTFSprms& rSprms = lcl_getNumPr(m_aStates); + rSprms->push_back(make_pair(NS_sprm::LN_PIlfo, pIntValue)); } } break; @@ -1745,23 +2004,23 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) default: break; } RTFValue::Pointer_t pValue(new RTFValue(nValue)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_WrapSquare_wrapText, pValue)); + m_aStates.top().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_WrapSquare_wrapText, pValue)); } break; case RTF_CELLX: { int nCellX = nParam - m_aStates.top().nCellX; m_aStates.top().nCellX = nParam; - RTFValue::Pointer_t pXValue(new RTFValue(nCellX)); - m_aStates.top().aTableRowSprms.push_back(make_pair(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue)); - - replayBuffer(m_aTableBuffer); + if (m_bFirstRow) + { + RTFValue::Pointer_t pXValue(new RTFValue(nCellX)); + m_aStates.top().aTableRowSprms->push_back(make_pair(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue)); + } + m_aStates.top().nCells++; - // Reset cell properties. - RTFSprms::Pointer_t pTableCellSprms(new RTFSprms_t(m_aStates.top().aTableCellSprms)); - m_aStates.top().aTableCellsSprms.push_back(pTableCellSprms); - RTFSprms::Pointer_t pTableCellAttributes(new RTFSprms_t(m_aStates.top().aTableCellAttributes)); - m_aStates.top().aTableCellsAttributes.push_back(pTableCellAttributes); + // Push cell properties. + m_aStates.top().aTableCellsSprms.push_back(m_aStates.top().aTableCellSprms); + m_aStates.top().aTableCellsAttributes.push_back(m_aStates.top().aTableCellAttributes); m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms; m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes; } @@ -1787,8 +2046,8 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) case RTF_COLW: case RTF_COLSR: { - RTFSprms_t& rAttributes = lcl_getLastAttributes(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_cols); - rAttributes.push_back(make_pair((nKeyword == RTF_COLW ? NS_ooxml::LN_CT_Column_w : NS_ooxml::LN_CT_Column_space), + RTFSprms& rAttributes = lcl_getLastAttributes(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_cols); + rAttributes->push_back(make_pair((nKeyword == RTF_COLW ? NS_ooxml::LN_CT_Column_w : NS_ooxml::LN_CT_Column_space), pIntValue)); } break; @@ -1849,7 +2108,7 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_footer, pIntValue, true); break; case RTF_DEFTAB: - m_aSettingsTableSprms.push_back(make_pair(NS_ooxml::LN_CT_Settings_defaultTabStop, pIntValue)); + m_aSettingsTableSprms->push_back(make_pair(NS_ooxml::LN_CT_Settings_defaultTabStop, pIntValue)); break; case RTF_LINEMOD: lcl_putNestedAttribute(m_aStates.top().aSectionSprms, @@ -1881,8 +2140,84 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) NS_ooxml::LN_trackchange, NS_ooxml::LN_CT_TrackChange_date, pValue); } break; + case RTF_SHPLEFT: + m_aStates.top().aShape.nLeft = TWIP_TO_MM100(nParam); + break; + case RTF_SHPTOP: + m_aStates.top().aShape.nTop = TWIP_TO_MM100(nParam); + break; + case RTF_SHPRIGHT: + m_aStates.top().aShape.nRight = TWIP_TO_MM100(nParam); + break; + case RTF_SHPBOTTOM: + m_aStates.top().aShape.nBottom = TWIP_TO_MM100(nParam); + break; + case RTF_FFTYPE: + switch (nParam) + { + case 0: m_nFormFieldType = FORMFIELD_TEXT; break; + case 1: m_nFormFieldType = FORMFIELD_CHECKBOX; break; + case 2: m_nFormFieldType = FORMFIELD_LIST; break; + default: m_nFormFieldType = FORMFIELD_NONE; break; + } + break; + case RTF_FFDEFRES: + if (m_nFormFieldType == FORMFIELD_CHECKBOX) + m_aFormfieldSprms->push_back(make_pair(NS_ooxml::LN_CT_FFCheckBox_default, pIntValue)); + else if (m_nFormFieldType == FORMFIELD_LIST) + m_aFormfieldSprms->push_back(make_pair(NS_ooxml::LN_CT_FFDDList_default, pIntValue)); + break; + case RTF_FFRES: + if (m_nFormFieldType == FORMFIELD_CHECKBOX) + m_aFormfieldSprms->push_back(make_pair(NS_ooxml::LN_CT_FFCheckBox_checked, pIntValue)); + else if (m_nFormFieldType == FORMFIELD_LIST) + m_aFormfieldSprms->push_back(make_pair(NS_ooxml::LN_CT_FFDDList_result, pIntValue)); + break; + case RTF_EDMINS: + m_xDocumentProperties->setEditingDuration(nParam); + break; + case RTF_NOFPAGES: + case RTF_NOFWORDS: + case RTF_NOFCHARS: + case RTF_NOFCHARSWS: + { + uno::Sequence<beans::NamedValue> aSet = m_xDocumentProperties->getDocumentStatistics(); + OUString aName; + switch (nKeyword) + { + case RTF_NOFPAGES: aName = OUString(RTL_CONSTASCII_USTRINGPARAM("PageCount")); break; + case RTF_NOFWORDS: aName = OUString(RTL_CONSTASCII_USTRINGPARAM("WordCount")); break; + case RTF_NOFCHARS: aName = OUString(RTL_CONSTASCII_USTRINGPARAM("CharacterCount")); break; + case RTF_NOFCHARSWS: aName = OUString(RTL_CONSTASCII_USTRINGPARAM("NonWhitespaceCharacterCount")); break; + default: break; + } + if (aName.getLength()) + { + bool bFound = false; + int nLen = aSet.getLength(); + for (int i = 0; i < nLen; ++i) + if (aSet[i].Name.equals(aName)) + aSet[i].Value = uno::makeAny(sal_Int32(nParam)); + if (!bFound) + { + aSet.realloc(nLen + 1); + aSet[nLen].Name = aName; + aSet[nLen].Value = uno::makeAny(sal_Int32(nParam)); + } + m_xDocumentProperties->setDocumentStatistics(aSet); + } + } + break; + case RTF_VERSION: + m_xDocumentProperties->setEditingCycles(nParam); + break; + case RTF_VERN: + // Ignore this for now, later the RTF writer version could be used to add hacks for older buggy writers. + break; default: +#if OSL_DEBUG_LEVEL > 1 OSL_TRACE("%s: TODO handle value '%s'", OSL_THIS_FUNC, lcl_RtfToString(nKeyword)); +#endif bParsed = false; break; } @@ -1921,7 +2256,7 @@ int RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam if (nSprm >= 0) { RTFValue::Pointer_t pValue(new RTFValue((!bParam || nParam != 0) ? nSprm : 0)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_sprm::LN_CKul, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_sprm::LN_CKul, pValue)); skipDestination(bParsed); return 0; } @@ -1939,7 +2274,7 @@ int RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam if (nSprm >= 0) { RTFValue::Pointer_t pValue(new RTFValue((!bParam || nParam != 0) ? nSprm : 0)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_sprm::LN_CKcd, pValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(NS_sprm::LN_CKcd, pValue)); skipDestination(bParsed); return 0; } @@ -1963,7 +2298,7 @@ int RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam } if (nSprm >= 0) { - m_aStates.top().aCharacterSprms.push_back(make_pair(nSprm, pBoolValue)); + m_aStates.top().aCharacterSprms->push_back(make_pair(nSprm, pBoolValue)); skipDestination(bParsed); return 0; } @@ -1971,7 +2306,7 @@ int RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam switch (nKeyword) { case RTF_ASPALPHA: - m_aStates.top().aParagraphSprms.push_back(make_pair(NS_sprm::LN_PFAutoSpaceDE, pBoolValue)); + m_aStates.top().aParagraphSprms->push_back(make_pair(NS_sprm::LN_PFAutoSpaceDE, pBoolValue)); break; case RTF_DELETED: case RTF_REVISED: @@ -1982,7 +2317,9 @@ int RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam } break; default: +#if OSL_DEBUG_LEVEL > 1 OSL_TRACE("%s: TODO handle toggle '%s'", OSL_THIS_FUNC, lcl_RtfToString(nKeyword)); +#endif bParsed = false; break; } @@ -2003,111 +2340,6 @@ void RTFDocumentImpl::skipDestination(bool bParsed) } } -int RTFDocumentImpl::dispatchKeyword(OString& rKeyword, bool bParam, int nParam) -{ - if (m_aStates.top().nDestinationState == DESTINATION_SKIP) - return 0; - /*OSL_TRACE("%s: keyword '\\%s' with param? %d param val: '%d'", OSL_THIS_FUNC, - rKeyword.getStr(), (bParam ? 1 : 0), (bParam ? nParam : 0));*/ - int i, ret; - for (i = 0; i < nRTFControlWords; i++) - { - if (!strcmp(rKeyword.getStr(), aRTFControlWords[i].sKeyword)) - break; - } - if (i == nRTFControlWords) - { - OSL_TRACE("%s: unknown keyword '\\%s'", OSL_THIS_FUNC, rKeyword.getStr()); - skipDestination(false); - return 0; - } - - switch (aRTFControlWords[i].nControlType) - { - case CONTROL_FLAG: - // flags ignore any parameter by definition - if ((ret = dispatchFlag(aRTFControlWords[i].nIndex))) - return ret; - break; - case CONTROL_DESTINATION: - // same for destinations - if ((ret = dispatchDestination(aRTFControlWords[i].nIndex))) - return ret; - break; - case CONTROL_SYMBOL: - // and symbols - if ((ret = dispatchSymbol(aRTFControlWords[i].nIndex))) - return ret; - break; - case CONTROL_TOGGLE: - if ((ret = dispatchToggle(aRTFControlWords[i].nIndex, bParam, nParam))) - return ret; - break; - case CONTROL_VALUE: - // values require a parameter by definition - if (bParam && (ret = dispatchValue(aRTFControlWords[i].nIndex, nParam))) - return ret; - break; - } - - return 0; -} - -int RTFDocumentImpl::resolveKeyword() -{ - char ch; - OStringBuffer aBuf; - bool bNeg = false; - bool bParam = false; - int nParam = 0; - - Strm() >> ch; - if (Strm().IsEof()) - return ERROR_EOF; - - if (!isalpha(ch)) - { - aBuf.append(ch); - OString aKeyword = aBuf.makeStringAndClear(); - // control symbols aren't followed by a space, so we can return here - // without doing any SeekRel() - return dispatchKeyword(aKeyword, bParam, nParam); - } - while(isalpha(ch)) - { - aBuf.append(ch); - Strm() >> ch; - } - - if (ch == '-') - { - // in case we'll have a parameter, that will be negative - bNeg = true; - Strm() >> ch; - if (Strm().IsEof()) - return ERROR_EOF; - } - if (isdigit(ch)) - { - OStringBuffer aParameter; - - // we have a parameter - bParam = true; - while(isdigit(ch)) - { - aParameter.append(ch); - Strm() >> ch; - } - nParam = aParameter.makeStringAndClear().toInt32(); - if (bNeg) - nParam = -nParam; - } - if (ch != ' ') - Strm().SeekRel(-1); - OString aKeyword = aBuf.makeStringAndClear(); - return dispatchKeyword(aKeyword, bParam, nParam); -} - int RTFDocumentImpl::pushState() { //OSL_TRACE("%s before push: %d", OSL_THIS_FUNC, m_nGroup); @@ -2126,111 +2358,105 @@ int RTFDocumentImpl::pushState() m_aStates.top().nDestinationState = DESTINATION_FONTENTRY; else if (m_aStates.top().nDestinationState == DESTINATION_STYLESHEET) m_aStates.top().nDestinationState = DESTINATION_STYLEENTRY; - else if (m_aStates.top().nDestinationState == DESTINATION_FIELDRESULT) + else if (m_aStates.top().nDestinationState == DESTINATION_FIELDRESULT || + m_aStates.top().nDestinationState == DESTINATION_SHAPETEXT || + m_aStates.top().nDestinationState == DESTINATION_FORMFIELD || + (m_aStates.top().nDestinationState == DESTINATION_FIELDINSTRUCTION && !m_bEq)) m_aStates.top().nDestinationState = DESTINATION_NORMAL; + else if (m_aStates.top().nDestinationState == DESTINATION_FIELDINSTRUCTION && m_bEq) + m_aStates.top().nDestinationState = DESTINATION_EQINSTRUCTION; else if (m_aStates.top().nDestinationState == DESTINATION_REVISIONTABLE) m_aStates.top().nDestinationState = DESTINATION_REVISIONENTRY; + else if (m_aStates.top().nDestinationState == DESTINATION_EQINSTRUCTION) + m_aStates.top().nDestinationState = DESTINATION_NORMAL; return 0; } -RTFSprms_t RTFDocumentImpl::mergeSprms() +RTFSprms RTFDocumentImpl::mergeSprms() { - RTFSprms_t aSprms; - for (RTFSprms_t::iterator i = m_aStates.top().aTableSprms.begin(); - i != m_aStates.top().aTableSprms.end(); ++i) - aSprms.push_back(make_pair(i->first, i->second)); - for (RTFSprms_t::iterator i = m_aStates.top().aCharacterSprms.begin(); - i != m_aStates.top().aCharacterSprms.end(); ++i) - aSprms.push_back(make_pair(i->first, i->second)); - for (RTFSprms_t::iterator i = m_aStates.top().aParagraphSprms.begin(); - i != m_aStates.top().aParagraphSprms.end(); ++i) - aSprms.push_back(make_pair(i->first, i->second)); + RTFSprms aSprms; + for (RTFSprms::Iterator_t i = m_aStates.top().aTableSprms->begin(); + i != m_aStates.top().aTableSprms->end(); ++i) + aSprms->push_back(make_pair(i->first, i->second)); + for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterSprms->begin(); + i != m_aStates.top().aCharacterSprms->end(); ++i) + aSprms->push_back(make_pair(i->first, i->second)); + for (RTFSprms::Iterator_t i = m_aStates.top().aParagraphSprms->begin(); + i != m_aStates.top().aParagraphSprms->end(); ++i) + aSprms->push_back(make_pair(i->first, i->second)); return aSprms; } -RTFSprms_t RTFDocumentImpl::mergeAttributes() +void RTFDocumentImpl::resetSprms() +{ + m_aStates.top().aTableSprms->clear(); + m_aStates.top().aCharacterSprms->clear(); + m_aStates.top().aParagraphSprms->clear(); +} + +RTFSprms RTFDocumentImpl::mergeAttributes() { - RTFSprms_t aAttributes; - for (RTFSprms_t::iterator i = m_aStates.top().aTableAttributes.begin(); - i != m_aStates.top().aTableAttributes.end(); ++i) - aAttributes.push_back(make_pair(i->first, i->second)); - for (RTFSprms_t::iterator i = m_aStates.top().aCharacterAttributes.begin(); - i != m_aStates.top().aCharacterAttributes.end(); ++i) - aAttributes.push_back(make_pair(i->first, i->second)); - for (RTFSprms_t::iterator i = m_aStates.top().aParagraphAttributes.begin(); - i != m_aStates.top().aParagraphAttributes.end(); ++i) - aAttributes.push_back(make_pair(i->first, i->second)); + RTFSprms aAttributes; + for (RTFSprms::Iterator_t i = m_aStates.top().aTableAttributes->begin(); + i != m_aStates.top().aTableAttributes->end(); ++i) + aAttributes->push_back(make_pair(i->first, i->second)); + for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes->begin(); + i != m_aStates.top().aCharacterAttributes->end(); ++i) + aAttributes->push_back(make_pair(i->first, i->second)); + for (RTFSprms::Iterator_t i = m_aStates.top().aParagraphAttributes->begin(); + i != m_aStates.top().aParagraphAttributes->end(); ++i) + aAttributes->push_back(make_pair(i->first, i->second)); return aAttributes; } +void RTFDocumentImpl::resetAttributes() +{ + m_aStates.top().aTableAttributes->clear(); + m_aStates.top().aCharacterAttributes->clear(); + m_aStates.top().aParagraphAttributes->clear(); +} + int RTFDocumentImpl::popState() { //OSL_TRACE("%s before pop: m_nGroup %d, dest state: %d", OSL_THIS_FUNC, m_nGroup, m_aStates.top().nDestinationState); - RTFReferenceTable::Entry_t aEntry; - bool bFontEntryEnd = false; - bool bStyleEntryEnd = false; - RTFSprms_t aSprms; - RTFSprms_t aAttributes; + RTFSprms aSprms; + RTFSprms aAttributes; bool bListEntryEnd = false; bool bListLevelEnd = false; bool bListOverrideEntryEnd = false; bool bLevelTextEnd = false; - std::vector< std::pair<rtl::OUString, rtl::OUString> > aShapeProperties; + RTFShape aShape; bool bPopShapeProperties = false; - bool bPicPropEnd = false; + bool bPopPictureProperties = false; if (m_aStates.top().nDestinationState == DESTINATION_FONTTABLE) { - writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(m_aStates.top().aFontTableEntries)); + writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(m_aFontTableEntries)); Mapper().table(NS_rtf::LN_FONTTABLE, pTable); } else if (m_aStates.top().nDestinationState == DESTINATION_STYLESHEET) { - writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(m_aStates.top().aStyleTableEntries)); + writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(m_aStyleTableEntries)); Mapper().table(NS_rtf::LN_STYLESHEET, pTable); } else if (m_aStates.top().nDestinationState == DESTINATION_LISTOVERRIDETABLE) { - RTFSprms_t aListTableAttributes; + RTFSprms aListTableAttributes; writerfilter::Reference<Properties>::Pointer_t const pProp(new RTFReferenceProperties(aListTableAttributes, m_aListTableSprms)); RTFReferenceTable::Entries_t aListTableEntries; aListTableEntries.insert(make_pair(0, pProp)); writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aListTableEntries)); Mapper().table(NS_rtf::LN_LISTTABLE, pTable); } - else if (m_aStates.top().nDestinationState == DESTINATION_FONTENTRY) - { - RTFValue::Pointer_t pValue(new RTFValue(m_aDestinationText.makeStringAndClear())); - m_aStates.top().aTableAttributes.push_back(make_pair(NS_rtf::LN_XSZFFN, pValue)); - - bFontEntryEnd = true; - writerfilter::Reference<Properties>::Pointer_t const pProp( - new RTFReferenceProperties(m_aStates.top().aTableAttributes, m_aStates.top().aTableSprms) - ); - aEntry.first = m_aStates.top().nCurrentFontIndex; - aEntry.second = pProp; - } - else if (m_aStates.top().nDestinationState == DESTINATION_STYLEENTRY) - { - RTFValue::Pointer_t pValue(new RTFValue(m_aDestinationText.makeStringAndClear())); - m_aStates.top().aTableAttributes.push_back(make_pair(NS_rtf::LN_XSTZNAME1, pValue)); - - bStyleEntryEnd = true; - writerfilter::Reference<Properties>::Pointer_t const pProp( - new RTFReferenceProperties(mergeAttributes(), mergeSprms()) - ); - aEntry.first = m_aStates.top().nCurrentStyleIndex; - aEntry.second = pProp; - } else if (m_aStates.top().nDestinationState == DESTINATION_LISTENTRY) { aAttributes = m_aStates.top().aTableAttributes; aSprms = m_aStates.top().aTableSprms; - for (RTFSprms_t::iterator i = m_aStates.top().aListLevelEntries.begin(); - i != m_aStates.top().aListLevelEntries.end(); ++i) - aSprms.push_back(make_pair(i->first, i->second)); + for (RTFSprms::Iterator_t i = m_aStates.top().aListLevelEntries->begin(); + i != m_aStates.top().aListLevelEntries->end(); ++i) + aSprms->push_back(make_pair(i->first, i->second)); bListEntryEnd = true; } else if (m_aStates.top().nDestinationState == DESTINATION_LISTLEVEL) @@ -2247,17 +2473,36 @@ int RTFDocumentImpl::popState() } else if (m_aStates.top().nDestinationState == DESTINATION_FIELDINSTRUCTION) { - sal_uInt8 sFieldSep[] = { 0x14 }; - Mapper().startCharacterGroup(); - Mapper().text(sFieldSep, 1); - Mapper().endCharacterGroup(); + if (m_aFormfieldAttributes->size() || m_aFormfieldSprms->size()) + { + RTFValue::Pointer_t pValue(new RTFValue(m_aFormfieldAttributes, m_aFormfieldSprms)); + RTFSprms aFFAttributes; + RTFSprms aFFSprms; + aFFSprms->push_back(make_pair(NS_ooxml::LN_ffdata, pValue)); + writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aFFAttributes, aFFSprms)); + Mapper().props(pProperties); + m_aFormfieldAttributes->clear(); + m_aFormfieldSprms->clear(); + } + if (!m_bEq) + { + sal_uInt8 sFieldSep[] = { 0x14 }; + Mapper().startCharacterGroup(); + Mapper().text(sFieldSep, 1); + Mapper().endCharacterGroup(); + } } else if (m_aStates.top().nDestinationState == DESTINATION_FIELDRESULT) { - sal_uInt8 sFieldEnd[] = { 0x15 }; - Mapper().startCharacterGroup(); - Mapper().text(sFieldEnd, 1); - Mapper().endCharacterGroup(); + if (!m_bEq) + { + sal_uInt8 sFieldEnd[] = { 0x15 }; + Mapper().startCharacterGroup(); + Mapper().text(sFieldEnd, 1); + Mapper().endCharacterGroup(); + } + else + m_bEq = false; } else if (m_aStates.top().nDestinationState == DESTINATION_LEVELTEXT) { @@ -2267,15 +2512,15 @@ int RTFDocumentImpl::popState() sal_Int32 nLength(aStr.toChar()); OUString aValue = aStr.copy(1, nLength); RTFValue::Pointer_t pValue(new RTFValue(aValue, true)); - m_aStates.top().aTableAttributes.push_back(make_pair(NS_ooxml::LN_CT_LevelText_val, pValue)); + m_aStates.top().aTableAttributes->push_back(make_pair(NS_ooxml::LN_CT_LevelText_val, pValue)); aAttributes = m_aStates.top().aTableAttributes; bLevelTextEnd = true; } else if (m_aStates.top().nDestinationState == DESTINATION_LEVELNUMBERS) { - RTFSprms_t& rAttributes = RTFSprm::find(m_aStates.top().aTableSprms, NS_ooxml::LN_CT_Lvl_lvlText)->getAttributes(); - RTFValue::Pointer_t pValue = RTFSprm::find(rAttributes, NS_ooxml::LN_CT_LevelText_val); + RTFSprms& rAttributes = m_aStates.top().aTableSprms.find(NS_ooxml::LN_CT_Lvl_lvlText)->getAttributes(); + RTFValue::Pointer_t pValue = rAttributes.find(NS_ooxml::LN_CT_LevelText_val); OUString aOrig = pValue->getString(); OUStringBuffer aBuf; @@ -2298,20 +2543,20 @@ int RTFDocumentImpl::popState() || m_aStates.top().nDestinationState == DESTINATION_SHAPEPROPERTYVALUE || m_aStates.top().nDestinationState == DESTINATION_SHAPEPROPERTY) { - aShapeProperties = m_aStates.top().aShapeProperties; + aShape = m_aStates.top().aShape; + aAttributes = m_aStates.top().aCharacterAttributes; if (m_aStates.top().nDestinationState == DESTINATION_SHAPEPROPERTYNAME) - aShapeProperties.push_back(make_pair(m_aDestinationText.makeStringAndClear(), OUString())); - else if (m_aStates.top().nDestinationState == DESTINATION_SHAPEPROPERTYVALUE) - aShapeProperties.back().second = m_aDestinationText.makeStringAndClear(); + aShape.aProperties.push_back(make_pair(m_aDestinationText.makeStringAndClear(), OUString())); + else if (m_aStates.top().nDestinationState == DESTINATION_SHAPEPROPERTYVALUE && aShape.aProperties.size()) + aShape.aProperties.back().second = m_aDestinationText.makeStringAndClear(); bPopShapeProperties = true; } - else if (m_aStates.top().nDestinationState == DESTINATION_PICPROP) + else if (m_aStates.top().nDestinationState == DESTINATION_PICPROP + || m_aStates.top().nDestinationState == DESTINATION_SHAPEINSTRUCTION) { - aShapeProperties = m_aStates.top().aShapeProperties; - bPicPropEnd = true; + if (!m_bObject) + m_pSdrImport->resolve(m_aStates.top().aShape); } - else if (m_aStates.top().nDestinationState == DESTINATION_REVISIONENTRY) - m_aAuthors[m_aAuthors.size()] = m_aDestinationText.makeStringAndClear(); else if (m_aStates.top().nDestinationState == DESTINATION_BOOKMARKSTART) { OUString aStr = m_aDestinationText.makeStringAndClear(); @@ -2321,179 +2566,274 @@ int RTFDocumentImpl::popState() } else if (m_aStates.top().nDestinationState == DESTINATION_BOOKMARKEND) Mapper().props(lcl_getBookmarkProperties(m_aBookmarks[m_aDestinationText.makeStringAndClear()])); + else if (m_aStates.top().nDestinationState == DESTINATION_PICT) + resolvePict(true); + else if (m_aStates.top().nDestinationState == DESTINATION_SHAPEPROPERTYVALUEPICT) + { + bPopPictureProperties = true; + aAttributes = m_aStates.top().aCharacterAttributes; + } + else if (m_aStates.top().nDestinationState == DESTINATION_SHAPETEXT) + m_pCurrentBuffer = 0; // Just disable buffering, don't empty it yet. + else if (m_aStates.top().nDestinationState == DESTINATION_FORMFIELDNAME) + { + RTFValue::Pointer_t pValue(new RTFValue(m_aDestinationText.makeStringAndClear())); + m_aFormfieldSprms->push_back(make_pair(NS_ooxml::LN_CT_FFData_name, pValue)); + } + else if (m_aStates.top().nDestinationState == DESTINATION_FORMFIELDLIST) + { + RTFValue::Pointer_t pValue(new RTFValue(m_aDestinationText.makeStringAndClear())); + m_aFormfieldSprms->push_back(make_pair(NS_ooxml::LN_CT_FFDDList_listEntry, pValue)); + } + else if (m_aStates.top().nDestinationState == DESTINATION_DATAFIELD) + { + OString aStr = OUStringToOString(m_aDestinationText.makeStringAndClear(), m_aStates.top().nCurrentEncoding); + // decode hex dump + OStringBuffer aBuf; + const char *str = aStr.getStr(); + int b = 0, count = 2; + for (int i = 0; i < aStr.getLength(); ++i) + { + char ch = str[i]; + if (ch != 0x0d && ch != 0x0a) + { + b = b << 4; + char parsed = m_pTokenizer->asHex(ch); + if (parsed == -1) + return ERROR_HEX_INVALID; + b += parsed; + count--; + if (!count) + { + aBuf.append((char)b); + count = 2; + b = 0; + } + } + } + aStr = aBuf.makeStringAndClear(); + // ignore the first bytes + if (aStr.getLength() > 8) + aStr = aStr.copy(8); + // extract name + int nLength = aStr.toChar(); + aStr = aStr.copy(1); + OString aName = aStr.copy(0, nLength); + aStr = aStr.copy(nLength+1); // zero-terminated string + // extract default text + nLength = aStr.toChar(); + aStr = aStr.copy(1); + OString aDefaultText = aStr.copy(0, nLength); + RTFValue::Pointer_t pNValue(new RTFValue(OStringToOUString(aName, m_aStates.top().nCurrentEncoding))); + m_aFormfieldSprms->push_back(make_pair(NS_ooxml::LN_CT_FFData_name, pNValue)); + RTFValue::Pointer_t pDValue(new RTFValue(OStringToOUString(aDefaultText, m_aStates.top().nCurrentEncoding))); + m_aFormfieldSprms->push_back(make_pair(NS_ooxml::LN_CT_FFTextInput_default, pDValue)); + } + else if (m_aStates.top().nDestinationState == DESTINATION_CREATIONTIME) + m_xDocumentProperties->setCreationDate(lcl_getDateTime(m_aStates)); + else if (m_aStates.top().nDestinationState == DESTINATION_REVISIONTIME) + m_xDocumentProperties->setModificationDate(lcl_getDateTime(m_aStates)); + else if (m_aStates.top().nDestinationState == DESTINATION_PRINTTIME) + m_xDocumentProperties->setPrintDate(lcl_getDateTime(m_aStates)); + else if (m_aStates.top().nDestinationState == DESTINATION_AUTHOR) + m_xDocumentProperties->setAuthor(m_aDestinationText.makeStringAndClear()); + else if (m_aStates.top().nDestinationState == DESTINATION_COMMENT) + m_xDocumentProperties->setGenerator(m_aDestinationText.makeStringAndClear()); + else if (m_aStates.top().nDestinationState == DESTINATION_OPERATOR + || m_aStates.top().nDestinationState == DESTINATION_COMPANY) + { + OUString aName = m_aStates.top().nDestinationState == DESTINATION_OPERATOR ? + OUString(RTL_CONSTASCII_USTRINGPARAM("Operator")) : OUString(RTL_CONSTASCII_USTRINGPARAM("Company")); + uno::Reference<beans::XPropertyContainer> xUserDefinedProperties = m_xDocumentProperties->getUserDefinedProperties(); + xUserDefinedProperties->addProperty(aName, beans::PropertyAttribute::REMOVEABLE, + uno::makeAny(m_aDestinationText.makeStringAndClear())); + } + else if (m_aStates.top().nDestinationState == DESTINATION_OBJDATA) + { + m_pObjectData = new SvMemoryStream(); + int b = 0, count = 2; + + // Feed the destination text to a stream. + OString aStr = OUStringToOString(m_aDestinationText.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US); + const char *str = aStr.getStr(); + for (int i = 0; i < aStr.getLength(); ++i) + { + char ch = str[i]; + if (ch != 0x0d && ch != 0x0a) + { + b = b << 4; + char parsed = m_pTokenizer->asHex(ch); + if (parsed == -1) + return ERROR_HEX_INVALID; + b += parsed; + count--; + if (!count) + { + *m_pObjectData << (char)b; + count = 2; + b = 0; + } + } + } + + if (m_pObjectData->Tell()) + { + m_pObjectData->Seek(0); + + // Skip ObjectHeader + sal_uInt32 nData; + *m_pObjectData >> nData; // OLEVersion + *m_pObjectData >> nData; // FormatID + *m_pObjectData >> nData; // ClassName + m_pObjectData->SeekRel(nData); + *m_pObjectData >> nData; // TopicName + m_pObjectData->SeekRel(nData); + *m_pObjectData >> nData; // ItemName + m_pObjectData->SeekRel(nData); + *m_pObjectData >> nData; // NativeDataSize + } + + uno::Reference<io::XInputStream> xInputStream(new utl::OInputStreamWrapper(m_pObjectData)); + RTFValue::Pointer_t pStreamValue(new RTFValue(xInputStream)); + + RTFSprms aOLEAttributes; + aOLEAttributes->push_back(make_pair(NS_ooxml::LN_inputstream, pStreamValue)); + RTFValue::Pointer_t pValue(new RTFValue(aOLEAttributes)); + m_aObjectSprms->push_back(make_pair(NS_ooxml::LN_OLEObject_OLEObject, pValue)); + } + else if (m_aStates.top().nDestinationState == DESTINATION_OBJECT) + { + RTFSprms aObjAttributes; + RTFSprms aObjSprms; + RTFValue::Pointer_t pValue(new RTFValue(m_aObjectAttributes, m_aObjectSprms)); + aObjSprms->push_back(make_pair(NS_ooxml::LN_object, pValue)); + writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aObjAttributes, aObjSprms)); + uno::Reference<drawing::XShape> xShape; + RTFValue::Pointer_t pShape = m_aObjectAttributes.find(NS_ooxml::LN_shape); + OSL_ASSERT(pShape.get()); + if (pShape.get()) + pShape->getAny() >>= xShape; + Mapper().startShape(xShape); + Mapper().props(pProperties); + Mapper().endShape(); + m_aObjectAttributes->clear(); + m_aObjectSprms->clear(); + if (m_pObjectData) + { + delete m_pObjectData; + m_pObjectData = 0; + } + m_bObject = false; + } + else if (m_aStates.top().nDestinationState == DESTINATION_ANNOTATIONDATE) + { + OUString aStr(OStringToOUString(lcl_DTTM22OString(m_aDestinationText.makeStringAndClear().toInt32()), + m_aStates.top().nCurrentEncoding)); + RTFValue::Pointer_t pValue(new RTFValue(aStr)); + RTFSprms aAnnAttributes; + aAnnAttributes->push_back(make_pair(NS_ooxml::LN_CT_TrackChange_date, pValue)); + writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aAnnAttributes)); + Mapper().props(pProperties); + } + else if (m_aStates.top().nDestinationState == DESTINATION_ANNOTATIONAUTHOR) + m_aAuthor = m_aDestinationText.makeStringAndClear(); // See if we need to end a track change - RTFValue::Pointer_t pTrackchange = RTFSprm::find(m_aStates.top().aCharacterSprms, NS_ooxml::LN_trackchange); + RTFValue::Pointer_t pTrackchange = m_aStates.top().aCharacterSprms.find(NS_ooxml::LN_trackchange); if (pTrackchange.get()) { - RTFSprms_t aTCAttributes; + RTFSprms aTCAttributes; RTFValue::Pointer_t pValue(new RTFValue(0)); - aTCAttributes.push_back(make_pair(NS_ooxml::LN_endtrackchange, pValue)); + aTCAttributes->push_back(make_pair(NS_ooxml::LN_endtrackchange, pValue)); writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aTCAttributes)); Mapper().props(pProperties); } // This is the end of the doc, see if we need to close the last section. - if (m_nGroup == 1) + if (m_nGroup == 1 && !m_bFirstRun) sectBreak(true); m_aStates.pop(); m_nGroup--; - if (bFontEntryEnd) - m_aStates.top().aFontTableEntries.insert(make_pair(aEntry.first, aEntry.second)); - else if (bStyleEntryEnd) - m_aStates.top().aStyleTableEntries.insert(make_pair(aEntry.first, aEntry.second)); // list table - else if (bListEntryEnd) + if (bListEntryEnd) { RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms)); - m_aListTableSprms.push_back(make_pair(NS_ooxml::LN_CT_Numbering_abstractNum, pValue)); + m_aListTableSprms->push_back(make_pair(NS_ooxml::LN_CT_Numbering_abstractNum, pValue)); } else if (bListLevelEnd) { RTFValue::Pointer_t pInnerValue(new RTFValue(m_aStates.top().nListLevelNum++)); - aAttributes.push_back(make_pair(NS_ooxml::LN_CT_Lvl_ilvl, pInnerValue)); + aAttributes->push_back(make_pair(NS_ooxml::LN_CT_Lvl_ilvl, pInnerValue)); RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms)); - m_aStates.top().aListLevelEntries.push_back(make_pair(NS_ooxml::LN_CT_AbstractNum_lvl, pValue)); + m_aStates.top().aListLevelEntries->push_back(make_pair(NS_ooxml::LN_CT_AbstractNum_lvl, pValue)); } // list override table else if (bListOverrideEntryEnd) { RTFValue::Pointer_t pValue(new RTFValue(aAttributes, aSprms)); - m_aListTableSprms.push_back(make_pair(NS_ooxml::LN_CT_Numbering_num, pValue)); + m_aListTableSprms->push_back(make_pair(NS_ooxml::LN_CT_Numbering_num, pValue)); } else if (bLevelTextEnd) { RTFValue::Pointer_t pValue(new RTFValue(aAttributes)); - m_aStates.top().aTableSprms.push_back(make_pair(NS_ooxml::LN_CT_Lvl_lvlText, pValue)); + m_aStates.top().aTableSprms->push_back(make_pair(NS_ooxml::LN_CT_Lvl_lvlText, pValue)); } else if (bPopShapeProperties) - m_aStates.top().aShapeProperties = aShapeProperties; - else if (bPicPropEnd) - resolveShapeProperties(aShapeProperties); - if (m_bSuper) + { + m_aStates.top().aShape = aShape; + m_aStates.top().aCharacterAttributes = aAttributes; + } + if (bPopPictureProperties) + m_aStates.top().aCharacterAttributes = aAttributes; + if (m_pCurrentBuffer == &m_aSuperBuffer) { if (!m_bHasFootnote) replayBuffer(m_aSuperBuffer); - m_bSuper = m_bHasFootnote = false; + m_pCurrentBuffer = 0; + m_bHasFootnote = false; } return 0; } -void RTFDocumentImpl::resolveShapeProperties(std::vector< std::pair<rtl::OUString, rtl::OUString> >& rShapeProperties) +::std::string RTFDocumentImpl::getType() const { - for (std::vector< std::pair<rtl::OUString, rtl::OUString> >::iterator i = rShapeProperties.begin(); i != rShapeProperties.end(); ++i) - { - if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("shapeType"))) - { - int nValue = i->second.toInt32(); - switch (nValue) - { - case 75: // picture frame - break; - default: - OSL_TRACE("%s: TODO handle shape type '%d'", OSL_THIS_FUNC, nValue); - break; - } - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzName"))) - { - RTFValue::Pointer_t pValue(new RTFValue(i->second)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_name, pValue)); - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzDescription"))) - { - RTFValue::Pointer_t pValue(new RTFValue(i->second)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_descr, pValue)); - } - else - OSL_TRACE("%s: TODO handle shape property '%s':'%s'", OSL_THIS_FUNC, - OUStringToOString( i->first, RTL_TEXTENCODING_UTF8 ).getStr(), - OUStringToOString( i->second, RTL_TEXTENCODING_UTF8 ).getStr()); - } + return "RTFDocumentImpl"; } -int RTFDocumentImpl::resolveParse() +com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory> RTFDocumentImpl::getModelFactory() { - OSL_TRACE("%s", OSL_THIS_FUNC); - char ch; - int ret; - // for hex chars - int b = 0, count = 2; + return m_xModelFactory; +} - while ((Strm() >> ch, !Strm().IsEof())) - { - //OSL_TRACE("%s: parsing character '%c'", OSL_THIS_FUNC, ch); - if (m_nGroup < 0) - return ERROR_GROUP_UNDER; - if (!m_aStates.empty() && m_aStates.top().nInternalState == INTERNAL_BIN) - { - OSL_TRACE("%s: TODO, binary internal state", OSL_THIS_FUNC); - } - else - { - switch (ch) - { - case '{': - if ((ret = pushState())) - return ret; - break; - case '}': - if ((ret = popState())) - return ret; - if (m_bIsSubstream && m_nGroup == 0) - return 0; - break; - case '\\': - if ((ret = resolveKeyword())) - return ret; - break; - case 0x0d: - case 0x0a: - break; // ignore these - default: - if (m_aStates.top().nInternalState == INTERNAL_NORMAL) - { - if ((ret = resolveChars(ch))) - return ret; - } - else - { - OSL_TRACE("%s: hex internal state", OSL_THIS_FUNC); - b = b << 4; - char parsed = lcl_AsHex(ch); - if (parsed == -1) - return ERROR_HEX_INVALID; - b += parsed; - count--; - if (!count) - { - if ((ret = resolveChars(b))) - return ret; - count = 2; - b = 0; - m_aStates.top().nInternalState = INTERNAL_NORMAL; - } - } - break; - } - } - } +RTFParserState& RTFDocumentImpl::getState() +{ + return m_aStates.top(); +} - if (m_nGroup < 0) - return ERROR_GROUP_UNDER; - else if (m_nGroup > 0) - return ERROR_GROUP_OVER; - return 0; +int RTFDocumentImpl::getGroup() +{ + return m_nGroup; } -::std::string RTFDocumentImpl::getType() const +bool RTFDocumentImpl::isEmpty() { - return "RTFDocumentImpl"; + return m_aStates.empty(); +} + +void RTFDocumentImpl::setDestinationText(OUString& rString) +{ + m_aDestinationText.setLength(0); + m_aDestinationText.append(rString); +} + +void RTFDocumentImpl::replayShapetext() +{ + replayBuffer(m_aShapetextBuffer); } RTFParserState::RTFParserState() @@ -2512,12 +2852,10 @@ RTFParserState::RTFParserState() aTableRowAttributes(), aTableCellSprms(), aTableCellAttributes(), + aTableCellsSprms(), + aTableCellsAttributes(), aTabAttributes(), - aFontTableEntries(), - nCurrentFontIndex(0), aCurrentColor(), - aStyleTableEntries(), - nCurrentStyleIndex(0), nCurrentEncoding(0), nUc(1), nCharsToSkip(0), @@ -2526,11 +2864,15 @@ RTFParserState::RTFParserState() aLevelNumbers(), nPictureScaleX(0), nPictureScaleY(0), - aShapeProperties(), + aShape(), nCellX(0), - aTableCellsSprms(), - aTableCellsAttributes(), - bIsCjk(false) + nCells(0), + bIsCjk(false), + nYear(0), + nMonth(0), + nDay(0), + nHour(0), + nMinute(0) { } diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx index 90618a8103e0..dec202b7e4d0 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx @@ -31,11 +31,14 @@ #include <memory> #include <stack> #include <vector> +#include <queue> -#include <rtl/strbuf.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> #include <oox/helper/graphichelper.hxx> #include <oox/helper/storagebase.hxx> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <rtl/strbuf.hxx> #include <resourcemodel/WW8ResourceModel.hxx> #include <rtftok/RTFDocument.hxx> @@ -54,6 +57,9 @@ namespace writerfilter { INTERNAL_HEX }; + // Note that this is not a 1:1 mapping between destination control + // words, e.g. RTF_PICT gets mapped to DESTINATION_PICT or + // DESTINATION_SHAPEPROPERTYVALUEPICT, etc. enum RTFDesitnationState { DESTINATION_NORMAL, @@ -63,6 +69,7 @@ namespace writerfilter { DESTINATION_COLORTABLE, DESTINATION_STYLESHEET, DESTINATION_STYLEENTRY, + DESTINATION_EQINSTRUCTION, DESTINATION_FIELDINSTRUCTION, DESTINATION_FIELDRESULT, DESTINATION_LISTTABLE, @@ -86,7 +93,25 @@ namespace writerfilter { DESTINATION_BOOKMARKSTART, DESTINATION_BOOKMARKEND, DESTINATION_REVISIONTABLE, - DESTINATION_REVISIONENTRY + DESTINATION_REVISIONENTRY, + DESTINATION_SHAPETEXT, + DESTINATION_FORMFIELD, + DESTINATION_FORMFIELDNAME, + DESTINATION_FORMFIELDLIST, + DESTINATION_DATAFIELD, + DESTINATION_INFO, + DESTINATION_CREATIONTIME, + DESTINATION_REVISIONTIME, + DESTINATION_PRINTTIME, + DESTINATION_AUTHOR, + DESTINATION_OPERATOR, + DESTINATION_COMPANY, + DESTINATION_COMMENT, + DESTINATION_OBJECT, + DESTINATION_OBJDATA, + DESTINATION_RESULT, + DESTINATION_ANNOTATIONDATE, + DESTINATION_ANNOTATIONAUTHOR }; enum RTFBorderState @@ -103,19 +128,11 @@ namespace writerfilter { ERROR_GROUP_UNDER, ERROR_GROUP_OVER, ERROR_EOF, - ERROR_HEX_INVALID - }; - - enum RTFControlTypes - { - CONTROL_FLAG, // eg \sbknone takes no parameter - CONTROL_DESTINATION, // eg \fonttbl, if ignored, the whole group should be skipped - CONTROL_SYMBOL, // eg \tab - CONTROL_TOGGLE, // eg \b (between on and off) - CONTROL_VALUE // eg \fs (requires parameter) + ERROR_HEX_INVALID, + ERROR_CHAR_OVER }; - /// Minimalistic buffer elements for nested cells. + /// Minimalistic buffer of elements for nested cells. enum RTFBufferTypes { BUFFER_PROPS, @@ -126,6 +143,18 @@ namespace writerfilter { BUFFER_PAR }; + /// Form field types + enum RTFFormFieldTypes + { + FORMFIELD_NONE, + FORMFIELD_TEXT, + FORMFIELD_CHECKBOX, + FORMFIELD_LIST + }; + + /// A buffer storing dmapper calls. + typedef std::deque< std::pair<RTFBufferTypes, RTFValue::Pointer_t> > RTFBuffer_t; + /// An entry in the color table. class RTFColorTableEntry { @@ -136,6 +165,17 @@ namespace writerfilter { sal_uInt8 nBlue; }; + /// Stores the properties of a shape. + class RTFShape + { + public: + std::vector< std::pair<rtl::OUString, rtl::OUString> > aProperties; + int nLeft; + int nTop; + int nRight; + int nBottom; + }; + /// State of the parser, which gets saved / restored when changing groups. class RTFParserState { @@ -145,34 +185,34 @@ namespace writerfilter { RTFDesitnationState nDestinationState; RTFBorderState nBorderState; // font table, stylesheet table - RTFSprms_t aTableSprms; - RTFSprms_t aTableAttributes; + RTFSprms aTableSprms; + RTFSprms aTableAttributes; // reset by plain - RTFSprms_t aCharacterSprms; - RTFSprms_t aCharacterAttributes; + RTFSprms aCharacterSprms; + RTFSprms aCharacterAttributes; // reset by pard - RTFSprms_t aParagraphSprms; - RTFSprms_t aParagraphAttributes; + RTFSprms aParagraphSprms; + RTFSprms aParagraphAttributes; // reset by sectd - RTFSprms_t aSectionSprms; - RTFSprms_t aSectionAttributes; + RTFSprms aSectionSprms; + RTFSprms aSectionAttributes; // reset by trowd - RTFSprms_t aTableRowSprms; - RTFSprms_t aTableRowAttributes; + RTFSprms aTableRowSprms; + RTFSprms aTableRowAttributes; // reset by cellx - RTFSprms_t aTableCellSprms; - RTFSprms_t aTableCellAttributes; + RTFSprms aTableCellSprms; + RTFSprms aTableCellAttributes; + // reset by row/nestrow + std::deque<RTFSprms> aTableCellsSprms; + std::deque<RTFSprms> aTableCellsAttributes; + // backup of the above two, to support inheriting cell props + std::deque<RTFSprms> aTableInheritingCellsSprms; + std::deque<RTFSprms> aTableInheritingCellsAttributes; // reset by tx - RTFSprms_t aTabAttributes; - - RTFReferenceTable::Entries_t aFontTableEntries; - int nCurrentFontIndex; + RTFSprms aTabAttributes; RTFColorTableEntry aCurrentColor; - RTFReferenceTable::Entries_t aStyleTableEntries; - int nCurrentStyleIndex; - rtl_TextEncoding nCurrentEncoding; /// Current \uc value. @@ -183,24 +223,34 @@ namespace writerfilter { /// Next list level index to use when parsing list table. int nListLevelNum; /// List level entries, which will form a list entry later. - RTFSprms_t aListLevelEntries; + RTFSprms aListLevelEntries; /// List of character positions in leveltext to replace. std::vector<sal_Int32> aLevelNumbers; float nPictureScaleX; float nPictureScaleY; - std::vector< std::pair<rtl::OUString, rtl::OUString> > aShapeProperties; + RTFShape aShape; /// Current cellx value. int nCellX; - std::deque<RTFSprms::Pointer_t> aTableCellsSprms; - std::deque<RTFSprms::Pointer_t> aTableCellsAttributes; + int nCells; + int nInheritingCells; /// CJK or CTL? bool bIsCjk; + + // Info group. + int nYear; + int nMonth; + int nDay; + int nHour; + int nMinute; }; + class RTFTokenizer; + class RTFSdrImport; + /// Implementation of the RTFDocument interface. class RTFDocumentImpl : public RTFDocument @@ -215,47 +265,63 @@ namespace writerfilter { virtual void resolve(Stream & rHandler); virtual std::string getType() const; - SvStream& Strm(); Stream& Mapper(); - sal_uInt32 getColorTable(sal_uInt32 nIndex); - sal_uInt32 getEncodingTable(sal_uInt32 nFontIndex); - void skipDestination(bool bParsed); - RTFSprms_t mergeSprms(); - RTFSprms_t mergeAttributes(); void setSubstream(bool bIsSubtream); + void setAuthor(rtl::OUString& rAuthor); + bool isSubstream(); void setIgnoreFirst(rtl::OUString& rIgnoreFirst); - void resolveSubstream(sal_uInt32 nPos, Id nId); - void resolveSubstream(sal_uInt32 nPos, Id nId, rtl::OUString& rIgnoreFirst); void seek(sal_uInt32 nPos); - private: - int resolveParse(); - int resolveKeyword(); - void resolveShapeProperties(std::vector< std::pair<rtl::OUString, rtl::OUString> >& rShapeProperties); + com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory> getModelFactory(); + RTFParserState& getState(); + /// If the stack of states is empty. + bool isEmpty(); + int getGroup(); + void setDestinationText(rtl::OUString& rString); + void skipDestination(bool bParsed); + /// Resolve a picture: If not inline, then anchored. + int resolvePict(bool bInline); + void runBreak(); + void replayShapetext(); - int dispatchKeyword(rtl::OString& rKeyword, bool bParam, int nParam); + // These callbacks are invoked by the tokenizer. + int resolveChars(char ch); + int pushState(); + int popState(); int dispatchFlag(RTFKeyword nKeyword); int dispatchDestination(RTFKeyword nKeyword); int dispatchSymbol(RTFKeyword nKeyword); int dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam); int dispatchValue(RTFKeyword nKeyword, int nParam); - int resolveChars(char ch); - /// Resolve a picture: If not inline, then anchored. - int resolvePict(char ch, bool bInline); - int pushState(); - int popState(); + private: + SvStream& Strm(); + sal_uInt32 getColorTable(sal_uInt32 nIndex); + sal_uInt32 getEncodingTable(sal_uInt32 nFontIndex); + RTFSprms mergeSprms(); + RTFSprms mergeAttributes(); + void resetSprms(); + void resetAttributes(); + void resolveSubstream(sal_uInt32 nPos, Id nId); + void resolveSubstream(sal_uInt32 nPos, Id nId, rtl::OUString& rIgnoreFirst); + void text(rtl::OUString& rString); void parBreak(); + void tableBreak(); + /// If this is the first run of the document, starts the initial paragraph. + void checkFirstRun(); void sectBreak(bool bFinal); - void replayBuffer(std::deque< std::pair<RTFBufferTypes, RTFValue::Pointer_t> >& rBuffer); + void replayBuffer(RTFBuffer_t& rBuffer); com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const& m_xContext; com::sun::star::uno::Reference<com::sun::star::io::XInputStream> const& m_xInputStream; com::sun::star::uno::Reference<com::sun::star::lang::XComponent> const& m_xDstDoc; com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const& m_xFrame; com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory> m_xModelFactory; + com::sun::star::uno::Reference<com::sun::star::document::XDocumentProperties> m_xDocumentProperties; SvStream* m_pInStream; Stream* m_pMapperStream; + RTFSdrImport* m_pSdrImport; + RTFTokenizer* m_pTokenizer; /// Same as m_aStates.size(), except that this can be negative for invalid input. int m_nGroup; std::stack<RTFParserState> m_aStates; @@ -267,26 +333,31 @@ namespace writerfilter { /// Color index <-> RGB color value map std::vector<sal_uInt32> m_aColorTable; bool m_bFirstRun; + /// If this is the first row in a table - there we send cell widths. + bool m_bFirstRow; /// If paragraph properties should be emitted on next run. bool m_bNeedPap; /// The list table and list override table combined. - RTFSprms_t m_aListTableSprms; + RTFSprms m_aListTableSprms; /// The settings table. - RTFSprms_t m_aSettingsTableSprms; + RTFSprms m_aSettingsTableSprms; oox::StorageRef m_xStorage; oox::GraphicHelper* m_pGraphicHelper; /// Buffered table cells, till cell definitions are not reached. - std::deque< std::pair<RTFBufferTypes, RTFValue::Pointer_t> > m_aTableBuffer; - bool m_bTable; + RTFBuffer_t m_aTableBuffer; /// Buffered superscript, till footnote is reached (or not). - std::deque< std::pair<RTFBufferTypes, RTFValue::Pointer_t> > m_aSuperBuffer; - bool m_bSuper; + RTFBuffer_t m_aSuperBuffer; + /// Buffered shape text. + RTFBuffer_t m_aShapetextBuffer; + /// Points to the active buffer, if there is one. + RTFBuffer_t* m_pCurrentBuffer; + bool m_bHasFootnote; /// If this is a substream. bool m_bIsSubstream; - std::deque< std::pair<Id, sal_uInt32> > m_nHeaderFooterPositions; + std::queue< std::pair<Id, sal_uInt32> > m_nHeaderFooterPositions; sal_uInt32 m_nGroupStartPos; /// Ignore the first occurrence of this text. rtl::OUString m_aIgnoreFirst; @@ -294,8 +365,29 @@ namespace writerfilter { std::map<rtl::OUString, int> m_aBookmarks; /// Revision index <-> author map. std::map<int, rtl::OUString> m_aAuthors; + /// Annotation author of the next annotation. + rtl::OUString m_aAuthor; /// Text from special destinations. rtl::OUStringBuffer m_aDestinationText; + + RTFSprms m_aFormfieldSprms; + RTFSprms m_aFormfieldAttributes; + RTFFormFieldTypes m_nFormFieldType; + + RTFSprms m_aObjectSprms; + RTFSprms m_aObjectAttributes; + /// If we are in an object group. + bool m_bObject; + /// Contents of the objdata group, stored here so we can delete it when we leave the object group. + SvStream* m_pObjectData; + + RTFReferenceTable::Entries_t m_aFontTableEntries; + int m_nCurrentFontIndex; + + RTFReferenceTable::Entries_t m_aStyleTableEntries; + int m_nCurrentStyleIndex; + bool m_bEq; + }; } // namespace rtftok } // namespace writerfilter diff --git a/writerfilter/source/rtftok/rtfreferenceproperties.cxx b/writerfilter/source/rtftok/rtfreferenceproperties.cxx index 6ca5f1d68a3f..b1fb8aa0e717 100644 --- a/writerfilter/source/rtftok/rtfreferenceproperties.cxx +++ b/writerfilter/source/rtftok/rtfreferenceproperties.cxx @@ -31,13 +31,13 @@ namespace writerfilter { namespace rtftok { -RTFReferenceProperties::RTFReferenceProperties(RTFSprms_t rAttributes, RTFSprms_t rSprms) +RTFReferenceProperties::RTFReferenceProperties(RTFSprms rAttributes, RTFSprms rSprms) : m_rAttributes(rAttributes), m_rSprms(rSprms) { } -RTFReferenceProperties::RTFReferenceProperties(RTFSprms_t rAttributes) +RTFReferenceProperties::RTFReferenceProperties(RTFSprms rAttributes) : m_rAttributes(rAttributes), m_rSprms() { @@ -49,9 +49,9 @@ RTFReferenceProperties::~RTFReferenceProperties() void RTFReferenceProperties::resolve(Properties& rHandler) { - for (RTFSprms_t::iterator i = m_rAttributes.begin(); i != m_rAttributes.end(); ++i) + for (RTFSprms::Iterator_t i = m_rAttributes->begin(); i != m_rAttributes->end(); ++i) rHandler.attribute(i->first, *i->second.get()); - for (RTFSprms_t::iterator i = m_rSprms.begin(); i != m_rSprms.end(); ++i) + for (RTFSprms::Iterator_t i = m_rSprms->begin(); i != m_rSprms->end(); ++i) { RTFSprm aSprm(i->first, i->second); rHandler.sprm(aSprm); diff --git a/writerfilter/source/rtftok/rtfreferenceproperties.hxx b/writerfilter/source/rtftok/rtfreferenceproperties.hxx index a689e5f8d645..9dda8a9e2234 100644 --- a/writerfilter/source/rtftok/rtfreferenceproperties.hxx +++ b/writerfilter/source/rtftok/rtfreferenceproperties.hxx @@ -41,14 +41,14 @@ namespace writerfilter { : public writerfilter::Reference<Properties> { public: - RTFReferenceProperties(RTFSprms_t rAttributes, RTFSprms_t rSprms); - RTFReferenceProperties(RTFSprms_t rAttributes); + RTFReferenceProperties(RTFSprms rAttributes, RTFSprms rSprms); + RTFReferenceProperties(RTFSprms rAttributes); virtual ~RTFReferenceProperties(); virtual void resolve(Properties & rHandler); virtual std::string getType() const; private: - RTFSprms_t m_rAttributes; - RTFSprms_t m_rSprms; + RTFSprms m_rAttributes; + RTFSprms m_rSprms; }; } // namespace rtftok } // namespace writerfilter diff --git a/writerfilter/source/rtftok/rtfsdrimport.cxx b/writerfilter/source/rtftok/rtfsdrimport.cxx new file mode 100644 index 000000000000..888d3213d152 --- /dev/null +++ b/writerfilter/source/rtftok/rtfsdrimport.cxx @@ -0,0 +1,335 @@ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Miklos Vajna <vmiklos@frugalware.org> + * Portions created by the Initial Developer are Copyright (C) 2011 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> +#include <com/sun/star/text/WritingMode.hpp> + +#include <ooxml/resourceids.hxx> // NS_ooxml namespace + +#include <rtfsdrimport.hxx> + +using rtl::OString; +using rtl::OStringBuffer; +using rtl::OUString; +using rtl::OUStringBuffer; +using rtl::OUStringToOString; + +// NEEDSWORK: wwUtility::BGRToRGB does the same. +static sal_uInt32 lcl_BGRToRGB(sal_uInt32 nColor) +{ + sal_uInt8 + r(static_cast<sal_uInt8>(nColor&0xFF)), + g(static_cast<sal_uInt8>(((nColor)>>8)&0xFF)), + b(static_cast<sal_uInt8>((nColor>>16)&0xFF)), + t(static_cast<sal_uInt8>((nColor>>24)&0xFF)); + nColor = (t<<24) + (r<<16) + (g<<8) + b; + return nColor; +} + +namespace writerfilter { +namespace rtftok { + +RTFSdrImport::RTFSdrImport(RTFDocumentImpl& rDocument, + uno::Reference<lang::XComponent> const& xDstDoc) + : m_rImport(rDocument) +{ + uno::Reference<drawing::XDrawPageSupplier> xDrawings(xDstDoc, uno::UNO_QUERY); + OSL_ASSERT(xDrawings.is()); + m_xDrawPage.set(xDrawings->getDrawPage(), uno::UNO_QUERY); + OSL_ASSERT(m_xDrawPage.is()); +} + +RTFSdrImport::~RTFSdrImport() +{ +} + +void RTFSdrImport::createShape(OUString aStr, uno::Reference<drawing::XShape>& xShape, uno::Reference<beans::XPropertySet>& xPropertySet) +{ + xShape.set(m_rImport.getModelFactory()->createInstance(aStr), uno::UNO_QUERY); + xPropertySet.set(xShape, uno::UNO_QUERY); +} + +void RTFSdrImport::resolve(RTFShape& rShape) +{ + int nType = -1; + bool bPib = false; + bool bCustom = false; + + uno::Reference<drawing::XShape> xShape; + uno::Reference<beans::XPropertySet> xPropertySet; + // Create this early, as custom shapes may have properties before the type arrives. + createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CustomShape")), xShape, xPropertySet); + uno::Any aAny; + beans::PropertyValue aPropertyValue; + awt::Rectangle aViewBox; + std::vector<beans::PropertyValue> aPathPropVec; + + for (std::vector< std::pair<rtl::OUString, rtl::OUString> >::iterator i = rShape.aProperties.begin(); + i != rShape.aProperties.end(); ++i) + { + if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("shapeType"))) + { + nType = i->second.toInt32(); + switch (nType) + { + case 20: // Line + createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.LineShape")), xShape, xPropertySet); + break; + default: + bCustom = true; + break; + } + + // Defaults + aAny <<= (sal_uInt32)0xffffff; // White in Word, kind of blue in Writer. + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzName"))) + { + RTFValue::Pointer_t pValue(new RTFValue(i->second)); + m_rImport.getState().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_name, pValue)); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzDescription"))) + { + RTFValue::Pointer_t pValue(new RTFValue(i->second)); + m_rImport.getState().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_descr, pValue)); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pib"))) + { + m_rImport.setDestinationText(i->second); + bPib = true; + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillColor"))) + { + aAny <<= lcl_BGRToRGB(i->second.toInt32()); + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillBackColor"))) + ; // Ignore: complementer of fillColor + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineColor"))) + { + aAny <<= lcl_BGRToRGB(i->second.toInt32()); + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineColor")), aAny); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineBackColor"))) + ; // Ignore: complementer of lineColor + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("txflTextFlow"))) + { + if (i->second.toInt32() == 1) + { + aAny <<= text::WritingMode_TB_RL; + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("TextWritingMode")), aAny); + } + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fLine"))) + { + if (i->second.toInt32() == 0) + { + aAny <<= drawing::LineStyle_NONE; + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineStyle")), aAny); + } + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pVerticies"))) + { + uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aCoordinates; + sal_Int32 nSize = 0; // Size of a token (it's value is hardwired in the exporter) + sal_Int32 nCount = 0; // Number of tokens + sal_Int32 nCharIndex = 0; // Character index + sal_Int32 nIndex = 0; // Array index + do + { + OUString aToken = i->second.getToken(0, ';', nCharIndex); + if (!nSize) + nSize = aToken.toInt32(); + else if (!nCount) + { + nCount = aToken.toInt32(); + aCoordinates.realloc(nCount); + } + else + { + // The coordinates are in an (x,y) form. + aToken = aToken.copy(1, aToken.getLength() - 2); + sal_Int32 nI = 0; + sal_Int32 nX = 0; + sal_Int32 nY = 0; + do + { + OUString aPoint = aToken.getToken(0, ',', nI); + if (!nX) + nX = aPoint.toInt32(); + else + nY = aPoint.toInt32(); + } + while (nI >= 0); + aCoordinates[nIndex].First.Value <<= nX; + aCoordinates[nIndex].Second.Value <<= nY; + nIndex++; + } + } + while (nCharIndex >= 0); + aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Coordinates")); + aPropertyValue.Value <<= aCoordinates; + aPathPropVec.push_back(aPropertyValue); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pSegmentInfo"))) + { + uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments; + sal_Int32 nSize = 0; + sal_Int32 nCount = 0; + sal_Int32 nCharIndex = 0; + sal_Int32 nIndex = 0; + do + { + sal_Int32 nSeg = i->second.getToken(0, ';', nCharIndex).toInt32(); + if (!nSize) + nSize = nSeg; + else if (!nCount) + { + nCount = nSeg; + aSegments.realloc(nCount); + } + else + { + switch (nSeg) + { + case 0x0001: // lineto + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO; + aSegments[nIndex].Count = sal_Int32(1); + break; + case 0x4000: // moveto + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO; + aSegments[nIndex].Count = sal_Int32(1); + break; + case 0x2001: // curveto + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO; + aSegments[nIndex].Count = sal_Int32(1); + break; + case 0xb300: // arcto + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO; + aSegments[nIndex].Count = sal_Int32(0); + break; + case 0xac00: + case 0xaa00: // nofill + case 0xab00: // nostroke + case 0x6001: // close + break; + case 0x8000: // end + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH; + aSegments[nIndex].Count = sal_Int32(0); + break; + default: + OSL_TRACE("%s: unhandled segment '%x' in the path", OSL_THIS_FUNC, nSeg); + break; + } + nIndex++; + } + } + while (nCharIndex >= 0); + aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Segments")); + aPropertyValue.Value <<= aSegments; + aPathPropVec.push_back(aPropertyValue); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoLeft"))) + aViewBox.X = i->second.toInt32(); + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoTop"))) + aViewBox.Y = i->second.toInt32(); + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoRight"))) + aViewBox.Width = i->second.toInt32(); + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoBottom"))) + aViewBox.Height = i->second.toInt32(); + else + OSL_TRACE("%s: TODO handle shape property '%s':'%s'", OSL_THIS_FUNC, + OUStringToOString( i->first, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( i->second, RTL_TEXTENCODING_UTF8 ).getStr()); + } + + if (nType == 75) // picture frame + { + if (bPib) + m_rImport.resolvePict(false); + return; + } + + m_xDrawPage->add(xShape); + if (bCustom) + { + uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY); + xDefaulter->createCustomShapeDefaults(OUString::valueOf(sal_Int32(nType))); + } + + // Creating Path property + uno::Sequence<beans::PropertyValue> aPathPropSeq(aPathPropVec.size()); + beans::PropertyValue* pPathValues = aPathPropSeq.getArray(); + for (std::vector<beans::PropertyValue>::iterator i = aPathPropVec.begin(); i != aPathPropVec.end(); ++i) + *pPathValues++ = *i; + + // Creating CustomShapeGeometry property + std::vector<beans::PropertyValue> aGeomPropVec; + if (aViewBox.X || aViewBox.Y || aViewBox.Width || aViewBox.Height) + { + aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("ViewBox")); + aPropertyValue.Value <<= aViewBox; + aGeomPropVec.push_back(aPropertyValue); + } + if (aPathPropSeq.getLength()) + { + aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Path")); + aPropertyValue.Value <<= aPathPropSeq; + aGeomPropVec.push_back(aPropertyValue); + } + uno::Sequence<beans::PropertyValue> aGeomPropSeq(aGeomPropVec.size()); + beans::PropertyValue* pGeomValues = aGeomPropSeq.getArray(); + for (std::vector<beans::PropertyValue>::iterator i = aGeomPropVec.begin(); i != aGeomPropVec.end(); ++i) + *pGeomValues++ = *i; + if (aGeomPropSeq.getLength()) + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CustomShapeGeometry")), uno::Any(aGeomPropSeq)); + + // Set position and size + xShape->setPosition(awt::Point(rShape.nLeft, rShape.nTop)); + xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop)); + + // Send it to dmapper + m_rImport.Mapper().startShape(xShape); + m_rImport.Mapper().startParagraphGroup(); + m_rImport.replayShapetext(); + m_rImport.Mapper().startCharacterGroup(); + m_rImport.runBreak(); + m_rImport.Mapper().endCharacterGroup(); + m_rImport.Mapper().endParagraphGroup(); + m_rImport.Mapper().endShape(); +} + +} // namespace rtftok +} // namespace writerfilter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/rtftok/rtfsdrimport.hxx b/writerfilter/source/rtftok/rtfsdrimport.hxx new file mode 100644 index 000000000000..5bc981cc68b8 --- /dev/null +++ b/writerfilter/source/rtftok/rtfsdrimport.hxx @@ -0,0 +1,59 @@ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Miklos Vajna <vmiklos@frugalware.org> + * Portions created by the Initial Developer are Copyright (C) 2011 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef _RTFSDRIMPORT_HXX_ +#define _RTFSDRIMPORT_HXX_ + +#include <com/sun/star/drawing/XDrawPage.hpp> + +#include <rtfdocumentimpl.hxx> + +namespace writerfilter { + namespace rtftok { + /// Handles the import of drawings using RTF markup. + class RTFSdrImport + { + public: + RTFSdrImport(RTFDocumentImpl& rImport, + com::sun::star::uno::Reference<com::sun::star::lang::XComponent> const& xDstDoc); + virtual ~RTFSdrImport(); + + void resolve(RTFShape& rShape); + private: + void createShape(rtl::OUString aService, + com::sun::star::uno::Reference<drawing::XShape>& xShape, + com::sun::star::uno::Reference<beans::XPropertySet>& xPropertySet); + + RTFDocumentImpl& m_rImport; + com::sun::star::uno::Reference<com::sun::star::drawing::XDrawPage> m_xDrawPage; + }; + } // namespace rtftok +} // namespace writerfilter + +#endif // _RTFSDRIPORT_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/rtftok/rtfsprm.cxx b/writerfilter/source/rtftok/rtfsprm.cxx index e5d3e263d98a..976505f78292 100644 --- a/writerfilter/source/rtftok/rtfsprm.cxx +++ b/writerfilter/source/rtftok/rtfsprm.cxx @@ -96,23 +96,40 @@ std::string RTFSprm::toString() const return aBuf.makeStringAndClear().getStr(); } -RTFValue::Pointer_t RTFSprm::find(RTFSprms_t &rVector, Id nKeyword) +RTFValue::Pointer_t RTFSprms::find(Id nKeyword) { - for (RTFSprms_t::iterator i = rVector.begin(); i != rVector.end(); ++i) + for (RTFSprms::Iterator_t i = m_aSprms.begin(); i != m_aSprms.end(); ++i) if (i->first == nKeyword) return i->second; RTFValue::Pointer_t pValue; return pValue; } -void RTFSprm::erase(RTFSprms_t &rVector, Id nKeyword) +bool RTFSprms::erase(Id nKeyword) { - for (RTFSprms_t::iterator i = rVector.begin(); i != rVector.end(); ++i) + for (RTFSprms::Iterator_t i = m_aSprms.begin(); i != m_aSprms.end(); ++i) if (i->first == nKeyword) { - rVector.erase(i); - return; + m_aSprms.erase(i); + return true; } + return false; +} + +RTFSprms::RTFSprms() + : m_aSprms() +{ +} + +RTFSprms::RTFSprms(const RTFSprms& rSprms) +{ + for (std::vector< std::pair<Id, RTFValue::Pointer_t> >::const_iterator i = rSprms.m_aSprms.begin(); i != rSprms.m_aSprms.end(); ++i) + m_aSprms.push_back(std::make_pair(i->first, RTFValue::Pointer_t(i->second->Clone()))); +} + +std::vector< std::pair<Id, RTFValue::Pointer_t> >* RTFSprms::operator->() +{ + return &m_aSprms; } } // namespace rtftok diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx index 441c7e9aa8b0..1f3472083dad 100644 --- a/writerfilter/source/rtftok/rtfsprm.hxx +++ b/writerfilter/source/rtftok/rtfsprm.hxx @@ -35,11 +35,21 @@ namespace writerfilter { namespace rtftok { - /// A list of RTFSprm - typedef std::vector< std::pair<Id, RTFValue::Pointer_t> > RTFSprms_t; - namespace RTFSprms { - typedef ::boost::shared_ptr<RTFSprms_t> Pointer_t; - } + /// A list of RTFSprm with a copy constructor that performs a deep copy. + class RTFSprms + { + public: + typedef ::boost::shared_ptr<RTFSprms> Pointer_t; + typedef std::vector< std::pair<Id, RTFValue::Pointer_t> >::iterator Iterator_t; + RTFSprms(); + RTFSprms(const RTFSprms& rSprms); + std::vector< std::pair<Id, RTFValue::Pointer_t> >* operator->(); + RTFValue::Pointer_t find(Id nKeyword); + bool erase(Id nKeyword); + private: + std::vector< std::pair<Id, RTFValue::Pointer_t> > m_aSprms; + }; + /// RTF keyword with a parameter class RTFSprm : public Sprm @@ -54,8 +64,6 @@ namespace writerfilter { virtual Kind getKind(); virtual std::string getName() const; virtual std::string toString() const; - static RTFValue::Pointer_t find(RTFSprms_t& rVector, Id nKeyword); - static void erase(RTFSprms_t& rVector, Id nKeyword); private: Id m_nKeyword; RTFValue::Pointer_t& m_pValue; diff --git a/writerfilter/source/rtftok/rtftokenizer.cxx b/writerfilter/source/rtftok/rtftokenizer.cxx new file mode 100644 index 000000000000..46d967df2a7c --- /dev/null +++ b/writerfilter/source/rtftok/rtftokenizer.cxx @@ -0,0 +1,264 @@ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Miklos Vajna <vmiklos@frugalware.org> + * Portions created by the Initial Developer are Copyright (C) 2011 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include <tools/stream.hxx> + +#include <rtftokenizer.hxx> + +using rtl::OString; +using rtl::OStringBuffer; +using rtl::OUString; +using rtl::OUStringBuffer; +using rtl::OUStringToOString; + +namespace writerfilter { +namespace rtftok { + +RTFTokenizer::RTFTokenizer(RTFDocumentImpl& rImport, SvStream* pInStream) + : m_rImport(rImport), + m_pInStream(pInStream) +{ +} + +RTFTokenizer::~RTFTokenizer() +{ +} + +SvStream& RTFTokenizer::Strm() +{ + return *m_pInStream; +} + +int RTFTokenizer::resolveParse() +{ + OSL_TRACE("%s", OSL_THIS_FUNC); + char ch; + int ret; + // for hex chars + int b = 0, count = 2; + + while ((Strm() >> ch, !Strm().IsEof())) + { + //OSL_TRACE("%s: parsing character '%c'", OSL_THIS_FUNC, ch); + if (m_rImport.getGroup() < 0) + return ERROR_GROUP_UNDER; + if (!m_rImport.isEmpty() && m_rImport.getState().nInternalState == INTERNAL_BIN) + { + OSL_TRACE("%s: TODO, binary internal state", OSL_THIS_FUNC); + } + else + { + switch (ch) + { + case '{': + if ((ret = m_rImport.pushState())) + return ret; + break; + case '}': + if ((ret = m_rImport.popState())) + return ret; + if (m_rImport.isSubstream() && m_rImport.getGroup() == 0) + return 0; + break; + case '\\': + if ((ret = resolveKeyword())) + return ret; + break; + case 0x0d: + case 0x0a: + break; // ignore these + default: + if (m_rImport.isEmpty()) + return ERROR_CHAR_OVER; + if (m_rImport.getState().nInternalState == INTERNAL_NORMAL) + { + if ((ret = m_rImport.resolveChars(ch))) + return ret; + } + else + { + OSL_TRACE("%s: hex internal state", OSL_THIS_FUNC); + b = b << 4; + char parsed = asHex(ch); + if (parsed == -1) + return ERROR_HEX_INVALID; + b += parsed; + count--; + if (!count) + { + if ((ret = m_rImport.resolveChars(b))) + return ret; + count = 2; + b = 0; + m_rImport.getState().nInternalState = INTERNAL_NORMAL; + } + } + break; + } + } + } + + if (m_rImport.getGroup() < 0) + return ERROR_GROUP_UNDER; + else if (m_rImport.getGroup() > 0) + return ERROR_GROUP_OVER; + return 0; +} + +int RTFTokenizer::asHex(char ch) +{ + int ret = 0; + if (isdigit(ch)) + ret = ch - '0'; + else + { + if (islower(ch)) + { + if (ch < 'a' || ch > 'f') + return -1; + ret = ch - 'a'; + } + else + { + if (ch < 'A' || ch > 'F') + return -1; + ret = ch - 'A'; + } + ret += 10; + } + return ret; +} + +int RTFTokenizer::resolveKeyword() +{ + char ch; + OStringBuffer aBuf; + bool bNeg = false; + bool bParam = false; + int nParam = 0; + + Strm() >> ch; + if (Strm().IsEof()) + return ERROR_EOF; + + if (!isalpha(ch)) + { + aBuf.append(ch); + OString aKeyword = aBuf.makeStringAndClear(); + // control symbols aren't followed by a space, so we can return here + // without doing any SeekRel() + return dispatchKeyword(aKeyword, bParam, nParam); + } + while(isalpha(ch)) + { + aBuf.append(ch); + Strm() >> ch; + } + + if (ch == '-') + { + // in case we'll have a parameter, that will be negative + bNeg = true; + Strm() >> ch; + if (Strm().IsEof()) + return ERROR_EOF; + } + if (isdigit(ch)) + { + OStringBuffer aParameter; + + // we have a parameter + bParam = true; + while(isdigit(ch)) + { + aParameter.append(ch); + Strm() >> ch; + } + nParam = aParameter.makeStringAndClear().toInt32(); + if (bNeg) + nParam = -nParam; + } + if (ch != ' ') + Strm().SeekRel(-1); + OString aKeyword = aBuf.makeStringAndClear(); + return dispatchKeyword(aKeyword, bParam, nParam); +} + +int RTFTokenizer::dispatchKeyword(OString& rKeyword, bool bParam, int nParam) +{ + if (m_rImport.getState().nDestinationState == DESTINATION_SKIP) + return 0; + /*OSL_TRACE("%s: keyword '\\%s' with param? %d param val: '%d'", OSL_THIS_FUNC, + rKeyword.getStr(), (bParam ? 1 : 0), (bParam ? nParam : 0));*/ + int i, ret; + for (i = 0; i < nRTFControlWords; i++) + { + if (!strcmp(rKeyword.getStr(), aRTFControlWords[i].sKeyword)) + break; + } + if (i == nRTFControlWords) + { + OSL_TRACE("%s: unknown keyword '\\%s'", OSL_THIS_FUNC, rKeyword.getStr()); + m_rImport.skipDestination(false); + return 0; + } + + switch (aRTFControlWords[i].nControlType) + { + case CONTROL_FLAG: + // flags ignore any parameter by definition + if ((ret = m_rImport.dispatchFlag(aRTFControlWords[i].nIndex))) + return ret; + break; + case CONTROL_DESTINATION: + // same for destinations + if ((ret = m_rImport.dispatchDestination(aRTFControlWords[i].nIndex))) + return ret; + break; + case CONTROL_SYMBOL: + // and symbols + if ((ret = m_rImport.dispatchSymbol(aRTFControlWords[i].nIndex))) + return ret; + break; + case CONTROL_TOGGLE: + if ((ret = m_rImport.dispatchToggle(aRTFControlWords[i].nIndex, bParam, nParam))) + return ret; + break; + case CONTROL_VALUE: + // values require a parameter by definition + if (bParam && (ret = m_rImport.dispatchValue(aRTFControlWords[i].nIndex, nParam))) + return ret; + break; + } + + return 0; +} + +} // namespace rtftok +} // namespace writerfilter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/rtftok/rtftokenizer.hxx b/writerfilter/source/rtftok/rtftokenizer.hxx new file mode 100644 index 000000000000..3556f9cb9097 --- /dev/null +++ b/writerfilter/source/rtftok/rtftokenizer.hxx @@ -0,0 +1,59 @@ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Miklos Vajna <vmiklos@frugalware.org> + * Portions created by the Initial Developer are Copyright (C) 2011 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef _RTFTOKENIZER_HXX_ +#define _RTFTOKENIZER_HXX_ + +#include <rtfdocumentimpl.hxx> + +class SvStream; + +namespace writerfilter { + namespace rtftok { + /// RTF tokenizer that separates control words from text. + class RTFTokenizer + { + public: + RTFTokenizer(RTFDocumentImpl& rImport, SvStream* pInStream); + virtual ~RTFTokenizer(); + + int resolveParse(); + int asHex(char ch); + private: + SvStream& Strm(); + int resolveKeyword(); + int dispatchKeyword(rtl::OString& rKeyword, bool bParam, int nParam); + + RTFDocumentImpl& m_rImport; + SvStream* m_pInStream; + }; + } // namespace rtftok +} // namespace writerfilter + +#endif // _RTFTOKENIZER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/rtftok/rtfvalue.cxx b/writerfilter/source/rtftok/rtfvalue.cxx index 54fbd6cbe790..961f6d758402 100644 --- a/writerfilter/source/rtftok/rtfvalue.cxx +++ b/writerfilter/source/rtftok/rtfvalue.cxx @@ -36,65 +36,89 @@ namespace rtftok { using rtl::OString; using rtl::OUString; -RTFValue::RTFValue(int nValue, rtl::OUString sValue, RTFSprms_t rAttributes, - RTFSprms_t rSprms, uno::Reference<drawing::XShape> rShape) +RTFValue::RTFValue(int nValue, rtl::OUString sValue, RTFSprms rAttributes, + RTFSprms rSprms, uno::Reference<drawing::XShape> rShape, + uno::Reference<io::XInputStream> rStream) : m_nValue(nValue), m_sValue(sValue), - m_rAttributes(rAttributes), - m_rSprms(rSprms), m_rShape(rShape), + m_rStream(rStream), m_bForceString(false) { + m_pAttributes = new RTFSprms(rAttributes); + m_pSprms = new RTFSprms(rSprms); } RTFValue::RTFValue(int nValue) : m_nValue(nValue), m_sValue(), - m_rAttributes(), - m_rSprms(), m_rShape(), + m_rStream(), m_bForceString(false) { + m_pAttributes = new RTFSprms(); + m_pSprms = new RTFSprms(); } RTFValue::RTFValue(OUString sValue, bool bForce) : m_nValue(), m_sValue(sValue), - m_rAttributes(), - m_rSprms(), m_rShape(), + m_rStream(), m_bForceString(bForce) { + m_pAttributes = new RTFSprms(); + m_pSprms = new RTFSprms(); } -RTFValue::RTFValue(RTFSprms_t rAttributes) +RTFValue::RTFValue(RTFSprms rAttributes) : m_nValue(), m_sValue(), - m_rAttributes(rAttributes), - m_rSprms(), m_rShape(), + m_rStream(), m_bForceString(false) { + m_pAttributes = new RTFSprms(rAttributes); + m_pSprms = new RTFSprms(); } -RTFValue::RTFValue(RTFSprms_t rAttributes, RTFSprms_t rSprms) +RTFValue::RTFValue(RTFSprms rAttributes, RTFSprms rSprms) : m_nValue(), m_sValue(), - m_rAttributes(rAttributes), - m_rSprms(rSprms), m_rShape(), + m_rStream(), m_bForceString(false) { + m_pAttributes = new RTFSprms(rAttributes); + m_pSprms = new RTFSprms(rSprms); } RTFValue::RTFValue(uno::Reference<drawing::XShape> rShape) : m_nValue(), m_sValue(), - m_rAttributes(), - m_rSprms(), m_rShape(rShape), + m_rStream(), m_bForceString(false) { + m_pAttributes = new RTFSprms(); + m_pSprms = new RTFSprms(); +} + +RTFValue::RTFValue(uno::Reference<io::XInputStream> rStream) + : m_nValue(), + m_sValue(), + m_rShape(), + m_rStream(rStream), + m_bForceString(false) +{ + m_pAttributes = new RTFSprms(); + m_pSprms = new RTFSprms(); +} + +RTFValue::~RTFValue() +{ + delete m_pAttributes; + delete m_pSprms; } int RTFValue::getInt() const @@ -122,6 +146,8 @@ uno::Any RTFValue::getAny() const ret <<= m_sValue; else if (m_rShape.is()) ret <<= m_rShape; + else if (m_rStream.is()) + ret <<= m_rStream; else ret <<= static_cast<sal_Int32>(m_nValue); return ret; @@ -130,7 +156,7 @@ uno::Any RTFValue::getAny() const writerfilter::Reference<Properties>::Pointer_t RTFValue::getProperties() { writerfilter::Reference<Properties>::Pointer_t const pProperties( - new RTFReferenceProperties(m_rAttributes, m_rSprms) + new RTFReferenceProperties(*m_pAttributes, *m_pSprms) ); return pProperties; } @@ -155,17 +181,17 @@ std::string RTFValue::toString() const RTFValue* RTFValue::Clone() { - return new RTFValue(m_nValue, m_sValue, m_rAttributes, m_rSprms, m_rShape); + return new RTFValue(m_nValue, m_sValue, *m_pAttributes, *m_pSprms, m_rShape, m_rStream); } -RTFSprms_t& RTFValue::getAttributes() +RTFSprms& RTFValue::getAttributes() { - return m_rAttributes; + return *m_pAttributes; } -RTFSprms_t& RTFValue::getSprms() +RTFSprms& RTFValue::getSprms() { - return m_rSprms; + return *m_pSprms; } } // namespace rtftok diff --git a/writerfilter/source/rtftok/rtfvalue.hxx b/writerfilter/source/rtftok/rtfvalue.hxx index e03971936ac9..db9005f02832 100644 --- a/writerfilter/source/rtftok/rtfvalue.hxx +++ b/writerfilter/source/rtftok/rtfvalue.hxx @@ -32,23 +32,26 @@ #include <map> #include <rtl/ustrbuf.hxx> #include <resourcemodel/WW8ResourceModel.hxx> +#include <com/sun/star/io/XInputStream.hpp> namespace writerfilter { namespace rtftok { + class RTFSprms; /// Value of an RTF keyword class RTFValue : public Value { public: typedef ::boost::shared_ptr<RTFValue> Pointer_t; - RTFValue(int nValue, rtl::OUString sValue, std::vector< std::pair<Id, RTFValue::Pointer_t> > rAttributes, - std::vector< std::pair<Id, RTFValue::Pointer_t> > rSprms, uno::Reference<drawing::XShape> rShape); + RTFValue(int nValue, rtl::OUString sValue, RTFSprms rAttributes, RTFSprms rSprms, uno::Reference<drawing::XShape> rShape, + uno::Reference<io::XInputStream> rStream); RTFValue(int nValue); RTFValue(rtl::OUString sValue, bool bForce = false); - RTFValue(std::vector< std::pair<Id, RTFValue::Pointer_t> > rAttributes); - RTFValue(std::vector< std::pair<Id, RTFValue::Pointer_t> > rAttributes, - std::vector< std::pair<Id, RTFValue::Pointer_t> > rSprms); + RTFValue(RTFSprms rAttributes); + RTFValue(RTFSprms rAttributes, RTFSprms rSprms); RTFValue(uno::Reference<drawing::XShape> rShape); + RTFValue(uno::Reference<io::XInputStream> rStream); + virtual ~RTFValue(); void setString(rtl::OUString sValue); virtual int getInt() const; virtual rtl::OUString getString() const; @@ -58,14 +61,15 @@ namespace writerfilter { virtual writerfilter::Reference<BinaryObj>::Pointer_t getBinary(); virtual std::string toString() const; virtual RTFValue* Clone(); - std::vector< std::pair<Id, RTFValue::Pointer_t> >& getAttributes(); - std::vector< std::pair<Id, RTFValue::Pointer_t> >& getSprms(); + RTFSprms& getAttributes(); + RTFSprms& getSprms(); private: int m_nValue; rtl::OUString m_sValue; - std::vector< std::pair<Id, RTFValue::Pointer_t> > m_rAttributes; - std::vector< std::pair<Id, RTFValue::Pointer_t> > m_rSprms; + RTFSprms* m_pAttributes; + RTFSprms* m_pSprms; uno::Reference<drawing::XShape> m_rShape; + uno::Reference<io::XInputStream> m_rStream; bool m_bForceString; }; } // namespace rtftok |