diff options
Diffstat (limited to 'sw/source/filter/xml')
41 files changed, 19009 insertions, 0 deletions
diff --git a/sw/source/filter/xml/DocSettingNames.hxx b/sw/source/filter/xml/DocSettingNames.hxx new file mode 100644 index 000000000000..4062f148daae --- /dev/null +++ b/sw/source/filter/xml/DocSettingNames.hxx @@ -0,0 +1,26 @@ +const char* aNmArr[] = { + "ForbiddenCharacters" , + "IsKernAsianPunctuation" , + "CharacterCompressionType" , + "LinkUpdateMode" , + "FieldAutoUpdate" , + "ChartAutoUpdate" , + "AddParaTableSpacing" , + "AddParaTableSpacingAtStart" , + "PrintAnnotationMode" , + "PrintBlackFonts" , + "PrintControls" , + "PrintDrawings" , + "PrintGraphics" , + "PrintLeftPages" , + "PrintPageBackground" , + "PrintProspect" , + "PrintReversed" , + "PrintRightPages" , + "PrintFaxName" , + "PrintPaperFromSetup" , + "PrintTables" , + "PrintSingleJobs", + "UpdateFromTemplate", + "PrintEmptyPages", +}; diff --git a/sw/source/filter/xml/ForbiddenCharactersEnum.hxx b/sw/source/filter/xml/ForbiddenCharactersEnum.hxx new file mode 100644 index 000000000000..721d44a93621 --- /dev/null +++ b/sw/source/filter/xml/ForbiddenCharactersEnum.hxx @@ -0,0 +1,41 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FORBIDDEN_CHARACTERS_ENUM_HXX +#define _FORBIDDEN_CHARACTERS_ENUM_HXX + +enum ForbiddenCharactersEnum +{ + SW_FORBIDDEN_CHARACTER_LANGUAGE, + SW_FORBIDDEN_CHARACTER_COUNTRY, + SW_FORBIDDEN_CHARACTER_VARIANT, + SW_FORBIDDEN_CHARACTER_BEGIN_LINE, + SW_FORBIDDEN_CHARACTER_END_LINE, + SW_FORBIDDEN_CHARACTER_MAX +}; + +#endif diff --git a/sw/source/filter/xml/XMLRedlineImportHelper.cxx b/sw/source/filter/xml/XMLRedlineImportHelper.cxx new file mode 100644 index 000000000000..2b9e95d10c26 --- /dev/null +++ b/sw/source/filter/xml/XMLRedlineImportHelper.cxx @@ -0,0 +1,754 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include "XMLRedlineImportHelper.hxx" +#include <unotextcursor.hxx> +#include <unotextrange.hxx> +#include <unocrsr.hxx> +#include "doc.hxx" +#include <tools/datetime.hxx> +#include "poolfmt.hxx" +#include "unoredline.hxx" +#include <xmloff/xmltoken.hxx> +#include <com/sun/star/frame/XModel.hpp> + +// for locking SolarMutex: svapp + mutex +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::xmloff::token; + +using ::rtl::OUString; +using ::com::sun::star::frame::XModel; +using ::com::sun::star::text::XTextCursor; +using ::com::sun::star::text::XTextRange; +using ::com::sun::star::text::XText; +using ::com::sun::star::text::XWordCursor; +using ::com::sun::star::lang::XUnoTunnel; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::beans::XPropertySetInfo; +// collision with tools/DateTime: use UNO DateTime as util::DateTime +// using util::DateTime; + + +// +// a few helper functions +// + +SwDoc* lcl_GetDocViaTunnel( Reference<XTextCursor> & rCursor ) +{ + Reference<XUnoTunnel> xTunnel( rCursor, UNO_QUERY); + DBG_ASSERT( xTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper* pSwXCursor = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >(xTunnel->getSomething(OTextCursorHelper::getUnoTunnelId())) ); + DBG_ASSERT( NULL != pSwXCursor, "OTextCursorHelper missing" ); + return pSwXCursor->GetDoc(); +} + +SwDoc* lcl_GetDocViaTunnel( Reference<XTextRange> & rRange ) +{ + Reference<XUnoTunnel> xTunnel(rRange, UNO_QUERY); + DBG_ASSERT(xTunnel.is(), "Can't tunnel XTextRange"); + SwXTextRange *pRange = reinterpret_cast< SwXTextRange *>( + sal::static_int_cast< sal_IntPtr >(xTunnel->getSomething(SwXTextRange::getUnoTunnelId())) ); + DBG_ASSERT( NULL != pRange, "SwXTextRange missing" ); + return pRange->GetDoc(); +} + + +// +// XTextRangeOrNodeIndexPosition: store a position into the text +// *either* as an XTextRange or as an SwNodeIndex. The reason is that +// we must store either pointers to StartNodes (because redlines may +// start on start nodes) or to a text position, and there appears to +// be no existing type that could do both. Things are complicated by +// the matter that (e.g in section import) we delete a few characters, +// which may cause bookmarks (as used by XTextRange) to be deleted. +// + +class XTextRangeOrNodeIndexPosition +{ + Reference<XTextRange> xRange; + SwNodeIndex* pIndex; /// pIndex will point to the *previous* node + +public: + XTextRangeOrNodeIndexPosition(); + ~XTextRangeOrNodeIndexPosition(); + + void Set( Reference<XTextRange> & rRange ); + void Set( SwNodeIndex& rIndex ); + void SetAsNodeIndex( Reference<XTextRange> & rRange ); + + void CopyPositionInto(SwPosition& rPos); + SwDoc* GetDoc(); + + sal_Bool IsValid(); +}; + +XTextRangeOrNodeIndexPosition::XTextRangeOrNodeIndexPosition() : + xRange(NULL), + pIndex(NULL) +{ +} + +XTextRangeOrNodeIndexPosition::~XTextRangeOrNodeIndexPosition() +{ + delete pIndex; +} + +void XTextRangeOrNodeIndexPosition::Set( Reference<XTextRange> & rRange ) +{ + xRange = rRange->getStart(); // set bookmark + if (NULL != pIndex) + { + delete pIndex; + pIndex = NULL; + } +} + +void XTextRangeOrNodeIndexPosition::Set( SwNodeIndex& rIndex ) +{ + if (NULL != pIndex) + delete pIndex; + + pIndex = new SwNodeIndex(rIndex); + (*pIndex)-- ; // previous node!!! + xRange = NULL; +} + +void XTextRangeOrNodeIndexPosition::SetAsNodeIndex( + Reference<XTextRange> & rRange ) +{ + // XTextRange -> XTunnel -> SwXTextRange + SwDoc* pDoc = lcl_GetDocViaTunnel(rRange); + + // SwXTextRange -> PaM + SwUnoInternalPaM aPaM(*pDoc); +#ifdef DBG_UTIL + sal_Bool bSuccess = +#endif + ::sw::XTextRangeToSwPaM(aPaM, rRange); + DBG_ASSERT(bSuccess, "illegal range"); + + // PaM -> Index + Set(aPaM.GetPoint()->nNode); +} + +void XTextRangeOrNodeIndexPosition::CopyPositionInto(SwPosition& rPos) +{ + DBG_ASSERT(IsValid(), "Can't get Position"); + + // create PAM from start cursor (if no node index is present) + if (NULL == pIndex) + { + SwUnoInternalPaM aUnoPaM(*GetDoc()); +#ifdef DBG_UTIL + sal_Bool bSuccess = +#endif + ::sw::XTextRangeToSwPaM(aUnoPaM, xRange); + DBG_ASSERT(bSuccess, "illegal range"); + + rPos = *aUnoPaM.GetPoint(); + } + else + { + rPos.nNode = *pIndex; + rPos.nNode++; // pIndex points to previous index !!! + rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 ); + } +} + +SwDoc* XTextRangeOrNodeIndexPosition::GetDoc() +{ + DBG_ASSERT(IsValid(), "Can't get Doc"); + + return (NULL != pIndex) ? pIndex->GetNodes().GetDoc() : lcl_GetDocViaTunnel(xRange); +} + +sal_Bool XTextRangeOrNodeIndexPosition::IsValid() +{ + return ( xRange.is() || (pIndex != NULL) ); +} + + +// +// RedlineInfo: temporary storage for redline data +// + +class RedlineInfo +{ +public: + RedlineInfo(); + ~RedlineInfo(); + + /// redline type (insert, delete, ...) + RedlineType_t eType; + + // info fields: + OUString sAuthor; /// change author string + OUString sComment; /// change comment string + util::DateTime aDateTime; /// change DateTime + sal_Bool bMergeLastParagraph; /// the SwRedline::IsDelLastPara flag + + // each position can may be either empty, an XTextRange, or an SwNodeIndex + + // start pos of anchor (may be empty) + XTextRangeOrNodeIndexPosition aAnchorStart; + + // end pos of anchor (may be empty) + XTextRangeOrNodeIndexPosition aAnchorEnd; + + /// index of content node (maybe NULL) + SwNodeIndex* pContentIndex; + + /// next redline info (for hierarchical redlines) + RedlineInfo* pNextRedline; + + /// store whether we expect an adjustment for this redline + sal_Bool bNeedsAdjustment; +}; + +RedlineInfo::RedlineInfo() : + eType(nsRedlineType_t::REDLINE_INSERT), + sAuthor(), + sComment(), + aDateTime(), + bMergeLastParagraph( sal_False ), + aAnchorStart(), + aAnchorEnd(), + pContentIndex(NULL), + pNextRedline(NULL), + bNeedsAdjustment( sal_False ) +{ +} + +RedlineInfo::~RedlineInfo() +{ + delete pContentIndex; + delete pNextRedline; +} + + +// +// XMLRedlineImportHelper +// + +XMLRedlineImportHelper::XMLRedlineImportHelper( + sal_Bool bNoRedlinesPlease, + const Reference<XPropertySet> & rModel, + const Reference<XPropertySet> & rImportInfo ) : + sEmpty(), + sInsertion( GetXMLToken( XML_INSERTION )), + sDeletion( GetXMLToken( XML_DELETION )), + sFormatChange( GetXMLToken( XML_FORMAT_CHANGE )), + sShowChanges(RTL_CONSTASCII_USTRINGPARAM("ShowChanges")), + sRecordChanges(RTL_CONSTASCII_USTRINGPARAM("RecordChanges")), + sRedlineProtectionKey(RTL_CONSTASCII_USTRINGPARAM("RedlineProtectionKey")), + aRedlineMap(), + bIgnoreRedlines(bNoRedlinesPlease), + xModelPropertySet(rModel), + xImportInfoPropertySet(rImportInfo) +{ + // check to see if redline mode is handled outside of component + sal_Bool bHandleShowChanges = sal_True; + sal_Bool bHandleRecordChanges = sal_True; + sal_Bool bHandleProtectionKey = sal_True; + if ( xImportInfoPropertySet.is() ) + { + Reference<XPropertySetInfo> xInfo = + xImportInfoPropertySet->getPropertySetInfo(); + + bHandleShowChanges = ! xInfo->hasPropertyByName( sShowChanges ); + bHandleRecordChanges = ! xInfo->hasPropertyByName( sRecordChanges ); + bHandleProtectionKey = ! xInfo->hasPropertyByName( sRedlineProtectionKey ); + } + + // get redline mode + bShowChanges = *(sal_Bool*) + ( bHandleShowChanges ? xModelPropertySet : xImportInfoPropertySet ) + ->getPropertyValue( sShowChanges ).getValue(); + bRecordChanges = *(sal_Bool*) + ( bHandleRecordChanges ? xModelPropertySet : xImportInfoPropertySet ) + ->getPropertyValue( sRecordChanges ).getValue(); + { + Any aAny = (bHandleProtectionKey ? xModelPropertySet + : xImportInfoPropertySet ) + ->getPropertyValue( sRedlineProtectionKey ); + aAny >>= aProtectionKey; + } + + // set redline mode to "don't record changes" + if( bHandleRecordChanges ) + { + Any aAny; + sal_Bool bTmp = sal_False; + aAny.setValue( &bTmp, ::getBooleanCppuType() ); + xModelPropertySet->setPropertyValue( sRecordChanges, aAny ); + } +} + +XMLRedlineImportHelper::~XMLRedlineImportHelper() +{ + // delete all left over (and obviously incomplete) RedlineInfos (and map) + RedlineMapType::iterator aFind = aRedlineMap.begin(); + for( ; aRedlineMap.end() != aFind; aFind++ ) + { + RedlineInfo* pInfo = aFind->second; + + // left-over redlines. Insert them if possible (but assert), + // and delete the incomplete ones. Finally, delete it. + if( IsReady(pInfo) ) + { + DBG_ERROR("forgotten RedlineInfo; now inserted"); + InsertIntoDocument( pInfo ); + } + else + { + // try if only the adjustment was missing + pInfo->bNeedsAdjustment = sal_False; + if( IsReady(pInfo) ) + { + DBG_ERROR("RedlineInfo without adjustment; now inserted"); + InsertIntoDocument( pInfo ); + } + else + { + // this situation occurs if redlines aren't closed + // (i.e. end without start, or start without + // end). This may well be a problem in the file, + // rather than the code. + DBG_ERROR("incomplete redline (maybe file was corrupt); " + "now deleted"); + } + } + delete pInfo; + } + aRedlineMap.clear(); + + // set redline mode, either to info property set, or directly to + // the document + sal_Bool bHandleShowChanges = sal_True; + sal_Bool bHandleRecordChanges = sal_True; + sal_Bool bHandleProtectionKey = sal_True; + if ( xImportInfoPropertySet.is() ) + { + Reference<XPropertySetInfo> xInfo = + xImportInfoPropertySet->getPropertySetInfo(); + + bHandleShowChanges = ! xInfo->hasPropertyByName( sShowChanges ); + bHandleRecordChanges = ! xInfo->hasPropertyByName( sRecordChanges ); + bHandleProtectionKey = ! xInfo->hasPropertyByName( sRedlineProtectionKey ); + } + + // set redline mode & key + Any aAny; + + aAny.setValue( &bShowChanges, ::getBooleanCppuType() ); + if ( bHandleShowChanges ) + xModelPropertySet->setPropertyValue( sShowChanges, aAny ); + else + xImportInfoPropertySet->setPropertyValue( sShowChanges, aAny ); + + aAny.setValue( &bRecordChanges, ::getBooleanCppuType() ); + if ( bHandleRecordChanges ) + xModelPropertySet->setPropertyValue( sRecordChanges, aAny ); + else + xImportInfoPropertySet->setPropertyValue( sRecordChanges, aAny ); + + aAny <<= aProtectionKey; + if ( bHandleProtectionKey ) + xModelPropertySet->setPropertyValue( sRedlineProtectionKey, aAny ); + else + xImportInfoPropertySet->setPropertyValue( sRedlineProtectionKey, aAny); +} + +void XMLRedlineImportHelper::Add( + const OUString& rType, + const OUString& rId, + const OUString& rAuthor, + const OUString& rComment, + const util::DateTime& rDateTime, + sal_Bool bMergeLastPara) +{ + // we need to do the following: + // 1) parse type string + // 2) create RedlineInfo and fill it with data + // 3) check for existing redline with same ID + // 3a) insert redline into map + // 3b) attach to existing redline + + // ad 1) + RedlineType_t eType; + if (rType.equals(sInsertion)) + { + eType = nsRedlineType_t::REDLINE_INSERT; + } + else if (rType.equals(sDeletion)) + { + eType = nsRedlineType_t::REDLINE_DELETE; + } + else if (rType.equals(sFormatChange)) + { + eType = nsRedlineType_t::REDLINE_FORMAT; + } + else + { + // no proper type found: early out! + return; + } + + // ad 2) create a new RedlineInfo + RedlineInfo* pInfo = new RedlineInfo(); + + // fill entries + pInfo->eType = eType; + pInfo->sAuthor = rAuthor; + pInfo->sComment = rComment; + pInfo->aDateTime = rDateTime; + pInfo->bMergeLastParagraph = bMergeLastPara; + + + // ad 3) + if (aRedlineMap.end() == aRedlineMap.find(rId)) + { + // 3a) insert into map + aRedlineMap[rId] = pInfo; + } + else + { + // 3b) we already have a redline with this name: hierarchical redlines + // insert pInfo as last element in the chain. + // (hierarchy sanity checking happens on insertino into the document) + + // find last element + RedlineInfo* pInfoChain; + for( pInfoChain = aRedlineMap[rId]; + NULL != pInfoChain->pNextRedline; + pInfoChain = pInfoChain->pNextRedline) ; // empty loop + + // insert as last element + pInfoChain->pNextRedline = pInfo; + } +} + +Reference<XTextCursor> XMLRedlineImportHelper::CreateRedlineTextSection( + Reference<XTextCursor> xOldCursor, + const OUString& rId) +{ + Reference<XTextCursor> xReturn; + + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + // get RedlineInfo + RedlineMapType::iterator aFind = aRedlineMap.find(rId); + if (aRedlineMap.end() != aFind) + { + // get document from old cursor (via tunnel) + SwDoc* pDoc = lcl_GetDocViaTunnel(xOldCursor); + + // create text section for redline + SwTxtFmtColl *pColl = pDoc->GetTxtCollFromPool + (RES_POOLCOLL_STANDARD, false ); + SwStartNode* pRedlineNode = pDoc->GetNodes().MakeTextSection( + pDoc->GetNodes().GetEndOfRedlines(), + SwNormalStartNode, + pColl); + + // remember node-index in RedlineInfo + SwNodeIndex aIndex(*pRedlineNode); + aFind->second->pContentIndex = new SwNodeIndex(aIndex); + + // create XText for document + SwXText* pXText = new SwXRedlineText(pDoc, aIndex); + Reference<XText> xText = pXText; // keep Reference until end of method + + // create (UNO-) cursor + SwPosition aPos(*pRedlineNode); + SwXTextCursor *const pXCursor = + new SwXTextCursor(*pDoc, pXText, CURSOR_REDLINE, aPos); + pXCursor->GetCursor()->Move(fnMoveForward, fnGoNode); + // cast to avoid ambiguity + xReturn = static_cast<text::XWordCursor*>(pXCursor); + } + // else: unknown redline -> Ignore + + return xReturn; +} + +void XMLRedlineImportHelper::SetCursor( + const OUString& rId, + sal_Bool bStart, + Reference<XTextRange> & rRange, + sal_Bool bIsOutsideOfParagraph) +{ + RedlineMapType::iterator aFind = aRedlineMap.find(rId); + if (aRedlineMap.end() != aFind) + { + // RedlineInfo found; now set Cursor + RedlineInfo* pInfo = aFind->second; + if (bIsOutsideOfParagraph) + { + // outside of paragraph: remember SwNodeIndex + if (bStart) + { + pInfo->aAnchorStart.SetAsNodeIndex(rRange); + } + else + { + pInfo->aAnchorEnd.SetAsNodeIndex(rRange); + } + + // also remember that we expect an adjustment for this redline + pInfo->bNeedsAdjustment = sal_True; + } + else + { + // inside of a paragraph: use regular XTextRanges (bookmarks) + if (bStart) + pInfo->aAnchorStart.Set(rRange); + else + pInfo->aAnchorEnd.Set(rRange); + } + + // if this Cursor was the last missing info, we insert the + // node into the document + // then we can remove the entry from the map and destroy the object + if (IsReady(pInfo)) + { + InsertIntoDocument(pInfo); + aRedlineMap.erase(rId); + delete pInfo; + } + } + // else: unknown Id -> ignore +} + +void XMLRedlineImportHelper::AdjustStartNodeCursor( + const OUString& rId, /// ID used in RedlineAdd() call + sal_Bool /*bStart*/, + Reference<XTextRange> & /*rRange*/) +{ + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + // start + end nodes are treated the same. For either it's + // necessary that the target node already exists. + + RedlineMapType::iterator aFind = aRedlineMap.find(rId); + if (aRedlineMap.end() != aFind) + { + // RedlineInfo found; now set Cursor + RedlineInfo* pInfo = aFind->second; + + pInfo->bNeedsAdjustment = sal_False; + + // if now ready, insert into document + if( IsReady(pInfo) ) + { + InsertIntoDocument(pInfo); + aRedlineMap.erase(rId); + delete pInfo; + } + } + // else: can't find redline -> ignore +} + + +inline sal_Bool XMLRedlineImportHelper::IsReady(RedlineInfo* pRedline) +{ + // we can insert a redline if we have start & end, and we don't + // expect adjustments for either of these + return ( pRedline->aAnchorEnd.IsValid() && + pRedline->aAnchorStart.IsValid() && + !pRedline->bNeedsAdjustment ); +} + +void XMLRedlineImportHelper::InsertIntoDocument(RedlineInfo* pRedlineInfo) +{ + DBG_ASSERT(NULL != pRedlineInfo, "need redline info"); + DBG_ASSERT(IsReady(pRedlineInfo), "redline info not complete yet!"); + + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + // Insert the Redline as described by pRedlineInfo into the + // document. If we are in insert mode, don't insert any redlines + // (and delete 'deleted' inline redlines) + + // get the document (from one of the positions) + SwDoc* pDoc = pRedlineInfo->aAnchorStart.GetDoc(); + + // now create the PaM for the redline + SwPaM aPaM(pDoc->GetNodes().GetEndOfContent()); + pRedlineInfo->aAnchorStart.CopyPositionInto(*aPaM.GetPoint()); + aPaM.SetMark(); + pRedlineInfo->aAnchorEnd.CopyPositionInto(*aPaM.GetPoint()); + + // collapse PaM if (start == end) + if (*aPaM.GetPoint() == *aPaM.GetMark()) + { + aPaM.DeleteMark(); + } + + + // cover three cases: + // 1) empty redlines (no range, no content) #100921# + // 2) check for: + // a) bIgnoreRedline (e.g. insert mode) + // b) illegal PaM range (CheckNodesRange()) + // 3) normal case: insert redline + if( !aPaM.HasMark() && (pRedlineInfo->pContentIndex == NULL) ) + { + // these redlines have no function, and will thus be ignored (just as + // in sw3io), so no action here + } + else if ( bIgnoreRedlines || + !CheckNodesRange( aPaM.GetPoint()->nNode, + aPaM.GetMark()->nNode, + sal_True ) ) + { + // ignore redline (e.g. file loaded in insert mode): + // delete 'deleted' redlines and forget about the whole thing + if (nsRedlineType_t::REDLINE_DELETE == pRedlineInfo->eType) + { + pDoc->DeleteRange(aPaM); + // And what about the "deleted nodes"? + // They have to be deleted as well (#i80689)! + if( bIgnoreRedlines && pRedlineInfo->pContentIndex != NULL ) + { + SwNodeIndex aIdx( *pRedlineInfo->pContentIndex ); + const SwNode* pEnd = aIdx.GetNode().EndOfSectionNode(); + if( pEnd ) + { + SwNodeIndex aEnd( *pEnd, 1 ); + SwPaM aDel( aIdx, aEnd ); + pDoc->DeleteRange(aDel); + } + } + } + } + else + { + // regular file loading: insert redline + + // create redline (using pRedlineData which gets copied in SwRedline()) + SwRedlineData* pRedlineData = ConvertRedline(pRedlineInfo, pDoc); + SwRedline* pRedline = + new SwRedline( pRedlineData, *aPaM.GetPoint(), TRUE, + !pRedlineInfo->bMergeLastParagraph, FALSE ); + + // set mark + if( aPaM.HasMark() ) + { + pRedline->SetMark(); + *(pRedline->GetMark()) = *aPaM.GetMark(); + } + + // set content node (if necessary) + if (NULL != pRedlineInfo->pContentIndex) + { + ULONG nPoint = aPaM.GetPoint()->nNode.GetIndex(); + if( nPoint < pRedlineInfo->pContentIndex->GetIndex() || + nPoint > pRedlineInfo->pContentIndex->GetNode().EndOfSectionIndex() ) + pRedline->SetContentIdx(pRedlineInfo->pContentIndex); +#ifdef DBG_UTIL + else + ASSERT( false, "Recursive change tracking" ); +#endif + } + + // set redline mode (without doing the associated book-keeping) + pDoc->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_ON); + pDoc->AppendRedline(pRedline, false); + pDoc->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_NONE); + } +} + +SwRedlineData* XMLRedlineImportHelper::ConvertRedline( + RedlineInfo* pRedlineInfo, + SwDoc* pDoc) +{ + // convert info: + // 1) Author String -> Author ID (default to zero) + sal_uInt16 nAuthorId = (NULL == pDoc) ? 0 : + pDoc->InsertRedlineAuthor( pRedlineInfo->sAuthor ); + + // 2) util::DateTime -> DateTime + DateTime aDT; + aDT.SetYear( pRedlineInfo->aDateTime.Year ); + aDT.SetMonth( pRedlineInfo->aDateTime.Month ); + aDT.SetDay( pRedlineInfo->aDateTime.Day ); + aDT.SetHour( pRedlineInfo->aDateTime.Hours ); + aDT.SetMin( pRedlineInfo->aDateTime.Minutes ); + aDT.SetSec( pRedlineInfo->aDateTime.Seconds ); + aDT.Set100Sec( pRedlineInfo->aDateTime.HundredthSeconds ); + + // 3) recursively convert next redline + // ( check presence and sanity of hierarchical redline info ) + SwRedlineData* pNext = NULL; + if ( (NULL != pRedlineInfo->pNextRedline) && + (nsRedlineType_t::REDLINE_DELETE == pRedlineInfo->eType) && + (nsRedlineType_t::REDLINE_INSERT == pRedlineInfo->pNextRedline->eType) ) + { + pNext = ConvertRedline(pRedlineInfo->pNextRedline, pDoc); + } + + // create redline data + SwRedlineData* pData = new SwRedlineData(pRedlineInfo->eType, + nAuthorId, aDT, + pRedlineInfo->sComment, + pNext, // next data (if available) + NULL); // no extra data + + return pData; +} + + +void XMLRedlineImportHelper::SetShowChanges( sal_Bool bShow ) +{ + bShowChanges = bShow; +} + +void XMLRedlineImportHelper::SetRecordChanges( sal_Bool bRecord ) +{ + bRecordChanges = bRecord; +} + +void XMLRedlineImportHelper::SetProtectionKey( + const Sequence<sal_Int8> & rKey ) +{ + aProtectionKey = rKey; +} diff --git a/sw/source/filter/xml/XMLRedlineImportHelper.hxx b/sw/source/filter/xml/XMLRedlineImportHelper.hxx new file mode 100644 index 000000000000..ab8f31f5e3a0 --- /dev/null +++ b/sw/source/filter/xml/XMLRedlineImportHelper.hxx @@ -0,0 +1,164 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _XMLREDLINEIMPORTHELPER_HXX +#define _XMLREDLINEIMPORTHELPER_HXX + +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/util/DateTime.hpp> +#include "redline.hxx" + +#include <map> + +class RedlineInfo; +class SwRedlineData; +class SwDoc; +namespace com { namespace sun { namespace star { + namespace text { class XTextCursor; } + namespace text { class XTextRange; } + namespace frame { class XModel; } +} } } + + +typedef ::std::map< ::rtl::OUString, RedlineInfo* > RedlineMapType; + +class XMLRedlineImportHelper +{ + const ::rtl::OUString sEmpty; + const ::rtl::OUString sInsertion; + const ::rtl::OUString sDeletion; + const ::rtl::OUString sFormatChange; + const ::rtl::OUString sShowChanges; + const ::rtl::OUString sRecordChanges; + const ::rtl::OUString sRedlineProtectionKey; + + RedlineMapType aRedlineMap; + + /// if sal_True, no redlines should be inserted into document + /// (This typically happen when a document is loaded in 'insert'-mode.) + sal_Bool bIgnoreRedlines; + + /// save information for saving and reconstruction of the redline mode + ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> xModelPropertySet; + ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> xImportInfoPropertySet; + sal_Bool bShowChanges; + sal_Bool bRecordChanges; + ::com::sun::star::uno::Sequence<sal_Int8> aProtectionKey; + +public: + + XMLRedlineImportHelper( + sal_Bool bIgnoreRedlines, /// ignore redlines mode + + // property sets of model + import info for saving + restoring the + // redline mode + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> & rModel, + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> & rImportInfoSet ); + virtual ~XMLRedlineImportHelper(); + + /// create a redline object + /// (The redline will be inserted into the document after both start + /// and end cursor has been set.) + void Add( + const ::rtl::OUString& rType, /// redline type (insert, del,... ) + const ::rtl::OUString& rId, /// use to identify this redline + const ::rtl::OUString& rAuthor, /// name of the author + const ::rtl::OUString& rComment, /// redline comment + const ::com::sun::star::util::DateTime& rDateTime, /// date+time + sal_Bool bMergeLastParagraph); /// merge last paragraph? + + /// create a text section for the redline, and return an + /// XText/XTextCursor that may be used to write into it. + ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextCursor> CreateRedlineTextSection( + ::com::sun::star::uno::Reference< /// needed to get the document + ::com::sun::star::text::XTextCursor> xOldCursor, + const ::rtl::OUString& rId); /// ID used to RedlineAdd() call + + /// Set start or end position for a redline in the text body. + /// Accepts XTextRange objects. + void SetCursor( + const ::rtl::OUString& rId, /// ID used in RedlineAdd() call + sal_Bool bStart, /// start or end Range + ::com::sun::star::uno::Reference< /// the actual XTextRange + ::com::sun::star::text::XTextRange> & rRange, + /// text range is (from an XML view) outside of a paragraph + /// (i.e. before a table) + sal_Bool bIsOusideOfParagraph); + + /** + * Adjust the start (end) position for a redline that begins in a + * start node. It takes the cursor positions _inside_ the redlined + * element (e.g. section or table). + * + * We will do sanity checking of the given text range: It will + * only be considered valid if it points to the next text node + * after the position given in a previous SetCursor */ + void AdjustStartNodeCursor( + const ::rtl::OUString& rId, /// ID used in RedlineAdd() call + sal_Bool bStart, + /// XTextRange _inside_ a table/section + ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange> & rRange); + + /// set redline mode: show changes + void SetShowChanges( sal_Bool bShowChanges ); + + /// set redline mode: record changes + void SetRecordChanges( sal_Bool bRecordChanges ); + + /// set redline protection key + void SetProtectionKey( + const ::com::sun::star::uno::Sequence<sal_Int8> & rKey ); + +private: + + inline sal_Bool IsReady(RedlineInfo* pRedline); + + void InsertIntoDocument(RedlineInfo* pRedline); + + SwRedlineData* ConvertRedline( + RedlineInfo* pRedline, /// RedlineInfo to be converted + SwDoc* pDoc); /// document needed for Author-ID conversion + + /** save the redline mode (if rPropertySet is non-null) */ + void SaveRedlineMode( + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> & rPropertySet); + + /** don't restore the saved redline mode */ + void DontRestoreRedlineMode(); + +}; + +#endif + diff --git a/sw/source/filter/xml/makefile.mk b/sw/source/filter/xml/makefile.mk new file mode 100644 index 000000000000..c1191fe3faf1 --- /dev/null +++ b/sw/source/filter/xml/makefile.mk @@ -0,0 +1,94 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=sw +TARGET=xml + +# --- Settings ----------------------------------------------------- + +.INCLUDE : $(PRJ)$/inc$/swpre.mk +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/inc$/sw.mk + +.IF "$(mydebug)" != "" +CDEFS=$(CDEFS) -Dmydebug +.ENDIF + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/swxml.obj \ + $(SLO)$/xmlimp.obj \ + $(SLO)$/wrtxml.obj \ + $(SLO)$/xmlexp.obj \ + $(SLO)$/xmltext.obj \ + $(SLO)$/xmltexte.obj \ + $(SLO)$/xmltexti.obj \ + $(SLO)$/xmltbli.obj \ + $(SLO)$/xmltble.obj \ + $(SLO)$/xmlfmt.obj \ + $(SLO)$/xmlfmte.obj \ + $(SLO)$/xmlmeta.obj \ + $(SLO)$/xmlscript.obj \ + $(SLO)$/xmlitemm.obj \ + $(SLO)$/xmlitemi.obj \ + $(SLO)$/xmliteme.obj \ + $(SLO)$/xmlithlp.obj \ + $(SLO)$/xmlbrsh.obj \ + $(SLO)$/xmlfonte.obj \ + $(SLO)$/XMLRedlineImportHelper.obj \ + $(SLO)$/xmlitem.obj \ + $(SLO)$/xmlitmpr.obj \ + $(SLO)$/xmlimpit.obj \ + $(SLO)$/xmlexpit.obj + +EXCEPTIONSFILES= \ + $(SLO)$/swxml.obj \ + $(SLO)$/xmlimp.obj \ + $(SLO)$/wrtxml.obj \ + $(SLO)$/xmlexp.obj \ + $(SLO)$/xmltext.obj \ + $(SLO)$/xmltexti.obj \ + $(SLO)$/xmltexte.obj \ + $(SLO)$/xmltbli.obj \ + $(SLO)$/xmltble.obj \ + $(SLO)$/xmlfmt.obj \ + $(SLO)$/xmlfmte.obj \ + $(SLO)$/xmlmeta.obj \ + $(SLO)$/xmlscript.obj \ + $(SLO)$/xmlitemi.obj \ + $(SLO)$/xmliteme.obj \ + $(SLO)$/xmlithlp.obj \ + $(SLO)$/xmlbrsh.obj \ + $(SLO)$/xmlfonte.obj \ + $(SLO)$/XMLRedlineImportHelper.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/sw/source/filter/xml/swxml.cxx b/sw/source/filter/xml/swxml.cxx new file mode 100644 index 000000000000..92b0c08e3b8d --- /dev/null +++ b/sw/source/filter/xml/swxml.cxx @@ -0,0 +1,1143 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + + + +#define _SVSTDARR_STRINGS +#include <rsc/rscsfx.hxx> +#include <tools/urlobj.hxx> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/componentcontext.hxx> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/io/XActiveDataControl.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/task/XStatusIndicatorFactory.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/packages/WrongPasswordException.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <svl/svstdarr.hxx> +#include <sfx2/docfile.hxx> +#include <svtools/sfxecode.hxx> +#include <svl/stritem.hxx> +#include <unotools/streamwrap.hxx> +#include <svx/xmlgrhlp.hxx> +#include <svx/xmleohlp.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <rtl/logfile.hxx> + +#include <sfx2/frame.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <swerror.h> +#include <errhdl.hxx> +#include <fltini.hxx> +#include <doc.hxx> +#include <docsh.hxx> +#include <unotextrange.hxx> +#include <swmodule.hxx> +#include <SwXMLSectionList.hxx> + +#include <statstr.hrc> + +// --> OD 2005-09-06 #i44177# +#include <SwStyleNameMapper.hxx> +#include <poolfmt.hxx> +#include <numrule.hxx> +#include <paratr.hxx> +// <-- + +// --> OD 2006-02-22 #b6382898# +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svditer.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdograf.hxx> +// <-- + +// --> OD 2008-12-17 #i70748# +#include <sfx2/docfilt.hxx> +// <-- + +#include <istyleaccess.hxx> +#define LOGFILE_AUTHOR "mb93740" + +#include <sfx2/DocumentMetadataAccess.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using ::rtl::OUString; + + +void lcl_EnsureValidPam( SwPaM& rPam ) +{ + if( rPam.GetCntntNode() != NULL ) + { + // set proper point content + if( rPam.GetCntntNode() != rPam.GetPoint()->nContent.GetIdxReg() ) + { + rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 ); + } + // else: point was already valid + + // if mark is invalid, we delete it + if( ( rPam.GetCntntNode( FALSE ) == NULL ) || + ( rPam.GetCntntNode( FALSE ) != rPam.GetMark()->nContent.GetIdxReg() ) ) + { + rPam.DeleteMark(); + } + } + else + { + // point is not valid, so move it into the first content + rPam.DeleteMark(); + rPam.GetPoint()->nNode = + *rPam.GetDoc()->GetNodes().GetEndOfContent().StartOfSectionNode(); + ++ rPam.GetPoint()->nNode; + rPam.Move( fnMoveForward, fnGoCntnt ); // go into content + } +} + +XMLReader::XMLReader() +{ +} + +int XMLReader::GetReaderType() +{ + return SW_STORAGE_READER; +} + +/// read a component (file + filter version) +sal_Int32 ReadThroughComponent( + uno::Reference<io::XInputStream> xInputStream, + uno::Reference<XComponent> xModelComponent, + const String& rStreamName, + uno::Reference<lang::XMultiServiceFactory> & rFactory, + const sal_Char* pFilterName, + const Sequence<Any>& rFilterArguments, + const OUString& rName, + sal_Bool bMustBeSuccessfull, + sal_Bool bEncrypted ) +{ + DBG_ASSERT(xInputStream.is(), "input stream missing"); + DBG_ASSERT(xModelComponent.is(), "document missing"); + DBG_ASSERT(rFactory.is(), "factory missing"); + DBG_ASSERT(NULL != pFilterName,"I need a service name for the component!"); + + RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "sw", LOGFILE_AUTHOR, "ReadThroughComponent" ); + + // prepare ParserInputSrouce + xml::sax::InputSource aParserInput; + aParserInput.sSystemId = rName; + aParserInput.aInputStream = xInputStream; + + // get parser + uno::Reference< xml::sax::XParser > xParser( + rFactory->createInstance( + OUString::createFromAscii("com.sun.star.xml.sax.Parser") ), + UNO_QUERY ); + DBG_ASSERT( xParser.is(), "Can't create parser" ); + if( !xParser.is() ) + return ERR_SWG_READ_ERROR; + RTL_LOGFILE_CONTEXT_TRACE( aLog, "parser created" ); + + // get filter + uno::Reference< xml::sax::XDocumentHandler > xFilter( + rFactory->createInstanceWithArguments( + OUString::createFromAscii(pFilterName), rFilterArguments), + UNO_QUERY ); + DBG_ASSERT( xFilter.is(), "Can't instantiate filter component." ); + if( !xFilter.is() ) + return ERR_SWG_READ_ERROR; + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "%s created", pFilterName ); + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + // connect model and filter + uno::Reference < XImporter > xImporter( xFilter, UNO_QUERY ); + xImporter->setTargetDocument( xModelComponent ); + + +#ifdef TIMELOG + // if we do profiling, we want to know the stream + ByteString aString( (String)rStreamName, RTL_TEXTENCODING_ASCII_US ); + RTL_LOGFILE_TRACE_AUTHOR1( "sw", LOGFILE_AUTHOR, + "ReadThroughComponent : parsing \"%s\"", aString.GetBuffer() ); +#endif + + // finally, parser the stream + try + { + xParser->parseStream( aParserInput ); + } + catch( xml::sax::SAXParseException& r ) + { + // sax parser sends wrapped exceptions, + // try to find the original one + xml::sax::SAXException aSaxEx = *(xml::sax::SAXException*)(&r); + sal_Bool bTryChild = sal_True; + + while( bTryChild ) + { + xml::sax::SAXException aTmp; + if ( aSaxEx.WrappedException >>= aTmp ) + aSaxEx = aTmp; + else + bTryChild = sal_False; + } + + packages::zip::ZipIOException aBrokenPackage; + if ( aSaxEx.WrappedException >>= aBrokenPackage ) + return ERRCODE_IO_BROKENPACKAGE; + + if( bEncrypted ) + return ERRCODE_SFX_WRONGPASSWORD; + +#if OSL_DEBUG_LEVEL > 1 + ByteString aError( "SAX parse exception catched while importing:\n" ); + aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US ); + DBG_ERROR( aError.GetBuffer() ); +#endif + + String sErr( String::CreateFromInt32( r.LineNumber )); + sErr += ','; + sErr += String::CreateFromInt32( r.ColumnNumber ); + + if( rStreamName.Len() ) + { + return *new TwoStringErrorInfo( + (bMustBeSuccessfull ? ERR_FORMAT_FILE_ROWCOL + : WARN_FORMAT_FILE_ROWCOL), + rStreamName, sErr, + ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR ); + } + else + { + ASSERT( bMustBeSuccessfull, "Warnings are not supported" ); + return *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr, + ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR ); + } + } + catch( xml::sax::SAXException& r) + { + packages::zip::ZipIOException aBrokenPackage; + if ( r.WrappedException >>= aBrokenPackage ) + return ERRCODE_IO_BROKENPACKAGE; + + if( bEncrypted ) + return ERRCODE_SFX_WRONGPASSWORD; + +#if OSL_DEBUG_LEVEL > 1 + ByteString aError( "SAX exception catched while importing:\n" ); + aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US ); + DBG_ERROR( aError.GetBuffer() ); +#endif + + return ERR_SWG_READ_ERROR; + } + catch( packages::zip::ZipIOException& r) + { + (void)r; +#if OSL_DEBUG_LEVEL > 1 + ByteString aError( "Zip exception catched while importing:\n" ); + aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US ); + DBG_ERROR( aError.GetBuffer() ); +#endif + return ERRCODE_IO_BROKENPACKAGE; + } + catch( io::IOException& r) + { + (void)r; +#if OSL_DEBUG_LEVEL > 1 + ByteString aError( "IO exception catched while importing:\n" ); + aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US ); + DBG_ERROR( aError.GetBuffer() ); +#endif + return ERR_SWG_READ_ERROR; + } + catch( uno::Exception& r) + { + (void)r; +#if OSL_DEBUG_LEVEL > 1 + ByteString aError( "uno exception catched while importing:\n" ); + aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US ); + DBG_ERROR( aError.GetBuffer() ); +#endif + return ERR_SWG_READ_ERROR; + } + + // success! + return 0; +} + +/// read a component (storage version) +sal_Int32 ReadThroughComponent( + uno::Reference<embed::XStorage> xStorage, + uno::Reference<XComponent> xModelComponent, + const sal_Char* pStreamName, + const sal_Char* pCompatibilityStreamName, + uno::Reference<lang::XMultiServiceFactory> & rFactory, + const sal_Char* pFilterName, + const Sequence<Any>& rFilterArguments, + const OUString& rName, + sal_Bool bMustBeSuccessfull) +{ + DBG_ASSERT(xStorage.is(), "Need storage!"); + DBG_ASSERT(NULL != pStreamName, "Please, please, give me a name!"); + + // open stream (and set parser input) + OUString sStreamName = OUString::createFromAscii(pStreamName); + sal_Bool bContainsStream = sal_False; + try + { + bContainsStream = xStorage->isStreamElement(sStreamName); + } + catch( container::NoSuchElementException& ) + { + } + + if (!bContainsStream ) + { + // stream name not found! Then try the compatibility name. + // if no stream can be opened, return immediatly with OK signal + + // do we even have an alternative name? + if ( NULL == pCompatibilityStreamName ) + return 0; + + // if so, does the stream exist? + sStreamName = OUString::createFromAscii(pCompatibilityStreamName); + try + { + bContainsStream = xStorage->isStreamElement(sStreamName); + } + catch( container::NoSuchElementException& ) + { + } + + if (! bContainsStream ) + return 0; + } + + // set Base URL + uno::Reference< beans::XPropertySet > xInfoSet; + if( rFilterArguments.getLength() > 0 ) + rFilterArguments.getConstArray()[0] >>= xInfoSet; + DBG_ASSERT( xInfoSet.is(), "missing property set" ); + if( xInfoSet.is() ) + { + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamName") ); + xInfoSet->setPropertyValue( sPropName, makeAny( sStreamName ) ); + } + + try + { + // get input stream + uno::Reference <io::XStream> xStream = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ ); + uno::Reference <beans::XPropertySet > xProps( xStream, uno::UNO_QUERY ); + + Any aAny = xProps->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("Encrypted") ) ); + + sal_Bool bEncrypted = aAny.getValueType() == ::getBooleanCppuType() && + *(sal_Bool *)aAny.getValue(); + + uno::Reference <io::XInputStream> xInputStream = xStream->getInputStream(); + + // read from the stream + return ReadThroughComponent( + xInputStream, xModelComponent, sStreamName, rFactory, + pFilterName, rFilterArguments, + rName, bMustBeSuccessfull, bEncrypted ); + } + catch ( packages::WrongPasswordException& ) + { + return ERRCODE_SFX_WRONGPASSWORD; + } + catch( packages::zip::ZipIOException& ) + { + return ERRCODE_IO_BROKENPACKAGE; + } + catch ( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Error on import!\n" ); + // TODO/LATER: error handling + } + + return ERR_SWG_READ_ERROR; +} + +// --> OD 2005-09-06 #i44177# +void lcl_AdjustOutlineStylesForOOo( SwDoc& _rDoc ) +{ + // array containing the names of the default outline styles ('Heading 1', + // 'Heading 2', ..., 'Heading 10') + String aDefOutlStyleNames[ MAXLEVEL ]; + { + String sStyleName; + for ( BYTE i = 0; i < MAXLEVEL; ++i ) + { + sStyleName = + SwStyleNameMapper::GetProgName( static_cast< sal_uInt16 >(RES_POOLCOLL_HEADLINE1 + i), + sStyleName ); + aDefOutlStyleNames[i] = sStyleName; + } + } + + // array indicating, which outline level already has a style assigned. + bool aOutlineLevelAssigned[ MAXLEVEL ]; + // array of the default outline styles, which are created for the document. + SwTxtFmtColl* aCreatedDefaultOutlineStyles[ MAXLEVEL ]; + + { + for ( BYTE i = 0; i < MAXLEVEL; ++i ) + { + aOutlineLevelAssigned[ i ] = false; + aCreatedDefaultOutlineStyles[ i ] = 0L; + } + } + + // determine, which outline level has already a style assigned and + // which of the default outline styles is created. + const SwTxtFmtColls& rColls = *(_rDoc.GetTxtFmtColls()); + for ( USHORT n = 1; n < rColls.Count(); ++n ) + { + SwTxtFmtColl* pColl = rColls[ n ]; + //if ( pColl->GetOutlineLevel() != NO_NUMBERING ) //#outline level zhaojianwei + if ( pColl->IsAssignedToListLevelOfOutlineStyle() ) + { + // aOutlineLevelAssigned[ pColl->GetOutlineLevel() ] = true; + aOutlineLevelAssigned[ pColl->GetAssignedOutlineStyleLevel() ] = true;//<-end,zhaojianwei + } + + for ( BYTE i = 0; i < MAXLEVEL; ++i ) + { + if ( aCreatedDefaultOutlineStyles[ i ] == 0L && + pColl->GetName() == aDefOutlStyleNames[i] ) + { + aCreatedDefaultOutlineStyles[ i ] = pColl; + break; + } + } + } + + // assign already created default outline style to outline level, which + // doesn't have a style assigned to it. + const SwNumRule* pOutlineRule = _rDoc.GetOutlineNumRule(); + for ( BYTE i = 0; i < MAXLEVEL; ++i ) + { + // --> OD 2007-01-11 #i73361# + // Do not change assignment of already created default outline style + // to a certain outline level. +// if ( aCreatedDefaultOutlineStyles[ i ] != 0 && !aOutlineLevelAssigned[ i ] ) + if ( !aOutlineLevelAssigned[ i ] && + aCreatedDefaultOutlineStyles[ i ] != 0 && + ! aCreatedDefaultOutlineStyles[ i ]->IsAssignedToListLevelOfOutlineStyle() ) + // <-- + { + // apply outline level at created default outline style + //aCreatedDefaultOutlineStyles[ i ]->SetOutlineLevel( i ); + aCreatedDefaultOutlineStyles[ i ]->AssignToListLevelOfOutlineStyle(i);//#outline level added by zhaojianwei + + // apply outline numbering rule, if none is set. + const SfxPoolItem& rItem = + aCreatedDefaultOutlineStyles[ i ]->GetFmtAttr( RES_PARATR_NUMRULE, FALSE ); + if ( static_cast<const SwNumRuleItem&>(rItem).GetValue().Len() == 0 ) + { + SwNumRuleItem aItem( pOutlineRule->GetName() ); + aCreatedDefaultOutlineStyles[ i ]->SetFmtAttr( aItem ); + } + } + } + +} +// <-- + +// --> OD 2006-02-22 #b6382898# +void lcl_ConvertSdrOle2ObjsToSdrGrafObjs( SwDoc& _rDoc ) +{ + if ( _rDoc.GetDrawModel() && + _rDoc.GetDrawModel()->GetPage( 0 ) ) + { + const SdrPage& rSdrPage( *(_rDoc.GetDrawModel()->GetPage( 0 )) ); + + // iterate recursive with group objects over all shapes on the draw page + SdrObjListIter aIter( rSdrPage ); + while( aIter.IsMore() ) + { + SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( aIter.Next() ); + if( pOle2Obj ) + { + // found an ole2 shape + SdrObjList* pObjList = pOle2Obj->GetObjList(); + + // get its graphic + Graphic aGraphic; + pOle2Obj->Connect(); + Graphic* pGraphic = pOle2Obj->GetGraphic(); + if( pGraphic ) + aGraphic = *pGraphic; + pOle2Obj->Disconnect(); + + // create new graphic shape with the ole graphic and shape size + SdrGrafObj* pGraphicObj = new SdrGrafObj( aGraphic, pOle2Obj->GetCurrentBoundRect() ); + // apply layer of ole2 shape at graphic shape + pGraphicObj->SetLayer( pOle2Obj->GetLayer() ); + + // replace ole2 shape with the new graphic object and delete the ol2 shape + SdrObject* pReplaced = pObjList->ReplaceObject( pGraphicObj, pOle2Obj->GetOrdNum() ); + SdrObject::Free( pReplaced ); + } + } + } +} +// <-- + + +ULONG XMLReader::Read( SwDoc &rDoc, const String& rBaseURL, SwPaM &rPaM, const String & rName ) +{ + // Get service factory + uno::Reference< lang::XMultiServiceFactory > xServiceFactory = + comphelper::getProcessServiceFactory(); + ASSERT( xServiceFactory.is(), + "XMLReader::Read: got no service manager" ); + if( !xServiceFactory.is() ) + return ERR_SWG_READ_ERROR; + + uno::Reference< io::XActiveDataSource > xSource; + uno::Reference< XInterface > xPipe; + uno::Reference< document::XGraphicObjectResolver > xGraphicResolver; + SvXMLGraphicHelper *pGraphicHelper = 0; + uno::Reference< document::XEmbeddedObjectResolver > xObjectResolver; + SvXMLEmbeddedObjectHelper *pObjectHelper = 0; + + // get the input stream (storage or stream) + uno::Reference<io::XInputStream> xInputStream; + uno::Reference<embed::XStorage> xStorage; + if( pMedium ) + xStorage = pMedium->GetStorage(); + else + xStorage = xStg; + + if( !xStorage.is() ) + return ERR_SWG_READ_ERROR; + + pGraphicHelper = SvXMLGraphicHelper::Create( xStorage, + GRAPHICHELPER_MODE_READ, + sal_False ); + xGraphicResolver = pGraphicHelper; + SfxObjectShell *pPersist = rDoc.GetPersist(); + if( pPersist ) + { + pObjectHelper = SvXMLEmbeddedObjectHelper::Create( + xStorage, *pPersist, + EMBEDDEDOBJECTHELPER_MODE_READ, + sal_False ); + xObjectResolver = pObjectHelper; + } + + // Get the docshell, the model, and finally the model's component + SwDocShell *pDocSh = rDoc.GetDocShell(); + ASSERT( pDocSh, "XMLReader::Read: got no doc shell" ); + if( !pDocSh ) + return ERR_SWG_READ_ERROR; + uno::Reference< lang::XComponent > xModelComp( pDocSh->GetModel(), UNO_QUERY ); + ASSERT( xModelComp.is(), + "XMLReader::Read: got no model" ); + if( !xModelComp.is() ) + return ERR_SWG_READ_ERROR; + + + // create and prepare the XPropertySet that gets passed through + // the components, and the XStatusIndicator that shows progress to + // the user. + + // create XPropertySet with three properties for status indicator + comphelper::PropertyMapEntry aInfoMap[] = + { + { "ProgressRange", sizeof("ProgressRange")-1, 0, + &::getCppuType((sal_Int32*)0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "ProgressMax", sizeof("ProgressMax")-1, 0, + &::getCppuType((sal_Int32*)0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "ProgressCurrent", sizeof("ProgressCurrent")-1, 0, + &::getCppuType((sal_Int32*)0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "NumberStyles", sizeof("NumberStyles")-1, 0, + &::getCppuType( (uno::Reference<container::XNameContainer> *) 0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "RecordChanges", sizeof("RecordChanges")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "ShowChanges", sizeof("ShowChanges")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "RedlineProtectionKey", sizeof("RedlineProtectionKey")-1, 0, +#if (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) + new uno::Type(::getCppuType((Sequence<sal_Int8>*)0)), +#else + &::getCppuType((Sequence<sal_Int8>*)0), +#endif + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "PrivateData", sizeof("PrivateData")-1, 0, + &::getCppuType( (uno::Reference<XInterface> *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "BaseURI", sizeof("BaseURI")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StreamRelPath", sizeof("StreamRelPath")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StreamName", sizeof("StreamName")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + // properties for insert modes + { "StyleInsertModeFamilies", sizeof("StyleInsertModeFamilies")-1, 0, + &::getCppuType((Sequence<OUString>*)0), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StyleInsertModeOverwrite", sizeof("StyleInsertModeOverwrite")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "TextInsertModeRange", sizeof("TextInsertModeRange")-1, 0, + &::getCppuType( (uno::Reference<text::XTextRange> *) 0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "AutoTextMode", sizeof("AutoTextMode")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "OrganizerMode", sizeof("OrganizerMode")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + // --> OD 2004-08-10 #i28749# - Add property, which indicates, if the + // shape position attributes are given in horizontal left-to-right layout. + // This is the case for the OpenOffice.org file format. + { "ShapePositionInHoriL2R", sizeof("ShapePositionInHoriL2R")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + // <-- + { "BuildId", sizeof("BuildId")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + // --> OD 2007-12-19 #152540# + // Add property, which indicates, if a text document in OpenOffice.org + // file format is read. + // Note: Text documents read via the binary filter are also finally + // read using the OpenOffice.org file format. Thus, e.g. for text + // documents in StarOffice 5.2 binary file format this property + // will be TRUE. + { "TextDocInOOoFileFormat", sizeof("TextDocInOOoFileFormat")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + // <-- + { NULL, 0, 0, NULL, 0, 0 } + }; + uno::Reference< beans::XPropertySet > xInfoSet( + comphelper::GenericPropertySet_CreateInstance( + new comphelper::PropertySetInfo( aInfoMap ) ) ); + + // ---- get BuildId from parent container if available + + uno::Reference< container::XChild > xChild( xModelComp, uno::UNO_QUERY ); + if( xChild.is() ) + { + uno::Reference< beans::XPropertySet > xParentSet( xChild->getParent(), uno::UNO_QUERY ); + if( xParentSet.is() ) + { + uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xParentSet->getPropertySetInfo() ); + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("BuildId" ) ); + if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(sPropName) ) + { + xInfoSet->setPropertyValue( sPropName, xParentSet->getPropertyValue(sPropName) ); + } + } + } + + // try to get an XStatusIndicator from the Medium + uno::Reference<task::XStatusIndicator> xStatusIndicator; + + if (pDocSh->GetMedium()) + { + SfxItemSet* pSet = pDocSh->GetMedium()->GetItemSet(); + if (pSet) + { + const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>( + pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) ); + if (pItem) + { + pItem->GetValue() >>= xStatusIndicator; + } + } + } + + + // set progress range and start status indicator + sal_Int32 nProgressRange(1000000); + if (xStatusIndicator.is()) + { + xStatusIndicator->start(SW_RESSTR(STR_STATSTR_SWGREAD), nProgressRange); + } + uno::Any aProgRange; + aProgRange <<= nProgressRange; + OUString sProgressRange(RTL_CONSTASCII_USTRINGPARAM("ProgressRange")); + xInfoSet->setPropertyValue(sProgressRange, aProgRange); + + ::comphelper::ComponentContext aContext( xServiceFactory ); + Reference< container::XNameAccess > xLateInitSettings( + aContext.createComponent( "com.sun.star.document.NamedPropertyValues" ), UNO_QUERY_THROW ); + beans::NamedValue aLateInitSettings( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LateInitSettings" ) ), + makeAny( xLateInitSettings ) + ); + + // prepare filter arguments, WARNING: the order is important! + Sequence<Any> aFilterArgs( 5 ); + Any *pArgs = aFilterArgs.getArray(); + *pArgs++ <<= xInfoSet; + *pArgs++ <<= xStatusIndicator; + *pArgs++ <<= xGraphicResolver; + *pArgs++ <<= xObjectResolver; + *pArgs++ <<= aLateInitSettings; + + Sequence<Any> aEmptyArgs( 3 ); + pArgs = aEmptyArgs.getArray(); + *pArgs++ <<= xInfoSet; + *pArgs++ <<= xStatusIndicator; + + // prepare for special modes + if( aOpt.IsFmtsOnly() ) + { + sal_Int32 nCount = + (aOpt.IsFrmFmts() ? 1 : 0) + + (aOpt.IsPageDescs() ? 1 : 0) + + (aOpt.IsTxtFmts() ? 2 : 0) + + (aOpt.IsNumRules() ? 1 : 0); + + Sequence< OUString> aFamiliesSeq( nCount ); + OUString *pSeq = aFamiliesSeq.getArray(); + if( aOpt.IsFrmFmts() ) + // SFX_STYLE_FAMILY_FRAME; + *pSeq++ = OUString::createFromAscii("FrameStyles"); + if( aOpt.IsPageDescs() ) + // SFX_STYLE_FAMILY_PAGE; + *pSeq++ = OUString::createFromAscii("PageStyles"); + if( aOpt.IsTxtFmts() ) + { + // (SFX_STYLE_FAMILY_CHAR|SFX_STYLE_FAMILY_PARA); + *pSeq++ = OUString::createFromAscii("CharacterStyles"); + *pSeq++ = OUString::createFromAscii("ParagraphStyles"); + } + if( aOpt.IsNumRules() ) + // SFX_STYLE_FAMILY_PSEUDO; + *pSeq++ = OUString::createFromAscii("NumberingStyles"); + + OUString sStyleInsertModeFamilies( + RTL_CONSTASCII_USTRINGPARAM("StyleInsertModeFamilies")); + xInfoSet->setPropertyValue( sStyleInsertModeFamilies, + makeAny(aFamiliesSeq) ); + + OUString sStyleInsertModeOverwrite( + RTL_CONSTASCII_USTRINGPARAM("StyleInsertModeOverwrite")); + sal_Bool bTmp = !aOpt.IsMerge(); + Any aAny; + aAny.setValue( &bTmp, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sStyleInsertModeOverwrite, aAny ); + } + else if( bInsertMode ) + { + const uno::Reference<text::XTextRange> xInsertTextRange = + SwXTextRange::CreateXTextRange(rDoc, *rPaM.GetPoint(), 0); + OUString sTextInsertModeRange( + RTL_CONSTASCII_USTRINGPARAM("TextInsertModeRange")); + xInfoSet->setPropertyValue( sTextInsertModeRange, + makeAny(xInsertTextRange) ); + } + else + { + rPaM.GetBound(true).nContent.Assign(0, 0); + rPaM.GetBound(false).nContent.Assign(0, 0); + } + + if( IsBlockMode() ) + { + OUString sAutoTextMode( + RTL_CONSTASCII_USTRINGPARAM("AutoTextMode")); + sal_Bool bTmp = sal_True; + Any aAny; + aAny.setValue( &bTmp, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sAutoTextMode, aAny ); + } + if( IsOrganizerMode() ) + { + OUString sOrganizerMode( + RTL_CONSTASCII_USTRINGPARAM("OrganizerMode")); + sal_Bool bTmp = sal_True; + Any aAny; + aAny.setValue( &bTmp, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sOrganizerMode, aAny ); + } + + // Set base URI + // there is ambiguity which medium should be used here + // for now the own medium has a preference + SfxMedium* pMedDescrMedium = pMedium ? pMedium : pDocSh->GetMedium(); + OSL_ENSURE( pMedDescrMedium, "There is no medium to get MediaDescriptor from!\n" ); + + ::rtl::OUString aBaseURL( rBaseURL ); + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("BaseURI") ); + xInfoSet->setPropertyValue( sPropName, makeAny( aBaseURL ) ); + + // TODO/LATER: separate links from usual embedded objects + ::rtl::OUString StreamPath; + if( SFX_CREATE_MODE_EMBEDDED == rDoc.GetDocShell()->GetCreateMode() ) + { + if ( pMedDescrMedium && pMedDescrMedium->GetItemSet() ) + { + const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>( + pMedDescrMedium->GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) ); + if ( pDocHierarchItem ) + StreamPath = pDocHierarchItem->GetValue(); + } + else + { + StreamPath = ::rtl::OUString::createFromAscii( "dummyObjectName" ); + } + + if( StreamPath.getLength() ) + { + sPropName = OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath")); + xInfoSet->setPropertyValue( sPropName, makeAny( StreamPath ) ); + } + } + + rDoc.acquire(); // prevent deletion + sal_uInt32 nRet = 0; + + // save redline mode into import info property set + Any aAny; + sal_Bool bTmp; + OUString sShowChanges( RTL_CONSTASCII_USTRINGPARAM("ShowChanges") ); + bTmp = IDocumentRedlineAccess::IsShowChanges( rDoc.GetRedlineMode() ); + aAny.setValue( &bTmp, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sShowChanges, aAny ); + OUString sRecordChanges( RTL_CONSTASCII_USTRINGPARAM("RecordChanges") ); + bTmp = IDocumentRedlineAccess::IsRedlineOn(rDoc.GetRedlineMode()); + aAny.setValue( &bTmp, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sRecordChanges, aAny ); + OUString sRedlineProtectionKey( RTL_CONSTASCII_USTRINGPARAM("RedlineProtectionKey") ); + aAny <<= rDoc.GetRedlinePassword(); + xInfoSet->setPropertyValue( sRedlineProtectionKey, aAny ); + + + // force redline mode to "none" + rDoc.SetRedlineMode_intern( nsRedlineMode_t::REDLINE_NONE ); + + const sal_Bool bOASIS = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 ); + // --> OD 2004-08-10 #i28749# - set property <ShapePositionInHoriL2R> + { + const sal_Bool bShapePositionInHoriL2R = !bOASIS; + xInfoSet->setPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("ShapePositionInHoriL2R")), + makeAny( bShapePositionInHoriL2R ) ); + } + // <-- + // --> OD 2007-12-19 #152540# + { + const sal_Bool bTextDocInOOoFileFormat = !bOASIS; + xInfoSet->setPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("TextDocInOOoFileFormat")), + makeAny( bTextDocInOOoFileFormat ) ); + } + // <-- + + sal_uInt32 nWarnRDF = 0; + if ( !(IsOrganizerMode() || IsBlockMode() || aOpt.IsFmtsOnly() || + bInsertMode) ) + { + // RDF metadata - must be read before styles/content + // N.B.: embedded documents have their own manifest.rdf! + try + { + const uno::Reference<rdf::XDocumentMetadataAccess> xDMA(xModelComp, + uno::UNO_QUERY_THROW); + const uno::Reference<rdf::XURI> xBaseURI( ::sfx2::createBaseURI( + aContext.getUNOContext(), xStorage, aBaseURL, StreamPath) ); + const uno::Reference<task::XInteractionHandler> xHandler( + pDocSh->GetMedium()->GetInteractionHandler() ); + xDMA->loadMetadataFromStorage(xStorage, xBaseURI, xHandler); + } + catch (lang::WrappedTargetException & e) + { + ucb::InteractiveAugmentedIOException iaioe; + if (e.TargetException >>= iaioe) + { + // import error that was not ignored by InteractionHandler! + nWarnRDF = ERR_SWG_READ_ERROR; + } + else + { + nWarnRDF = WARN_SWG_FEATURES_LOST; // uhh... something wrong? + } + } + catch (uno::Exception &) + { + nWarnRDF = WARN_SWG_FEATURES_LOST; // uhh... something went wrong? + } + } + + sal_uInt32 nWarn = 0; + sal_uInt32 nWarn2 = 0; + // read storage streams + if( !(IsOrganizerMode() || IsBlockMode() || aOpt.IsFmtsOnly() || + bInsertMode) ) + { + nWarn = ReadThroughComponent( + xStorage, xModelComp, "meta.xml", "Meta.xml", xServiceFactory, + (bOASIS ? "com.sun.star.comp.Writer.XMLOasisMetaImporter" + : "com.sun.star.comp.Writer.XMLMetaImporter"), + aEmptyArgs, rName, sal_False ); + + nWarn2 = ReadThroughComponent( + xStorage, xModelComp, "settings.xml", NULL, xServiceFactory, + (bOASIS ? "com.sun.star.comp.Writer.XMLOasisSettingsImporter" + : "com.sun.star.comp.Writer.XMLSettingsImporter"), + aFilterArgs, rName, sal_False ); + } + + nRet = ReadThroughComponent( + xStorage, xModelComp, "styles.xml", NULL, xServiceFactory, + (bOASIS ? "com.sun.star.comp.Writer.XMLOasisStylesImporter" + : "com.sun.star.comp.Writer.XMLStylesImporter"), + aFilterArgs, rName, sal_True ); + + if( !nRet && !(IsOrganizerMode() || aOpt.IsFmtsOnly()) ) + nRet = ReadThroughComponent( + xStorage, xModelComp, "content.xml", "Content.xml", xServiceFactory, + (bOASIS ? "com.sun.star.comp.Writer.XMLOasisContentImporter" + : "com.sun.star.comp.Writer.XMLContentImporter"), + aFilterArgs, rName, sal_True ); + + if( !(IsOrganizerMode() || IsBlockMode() || bInsertMode || + aOpt.IsFmtsOnly() ) ) + { + OUString sStreamName( RTL_CONSTASCII_USTRINGPARAM("layout-cache") ); + try + { + uno::Reference < io::XStream > xStm = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ ); + SvStream* pStrm2 = utl::UcbStreamHelper::CreateStream( xStm ); + if( !pStrm2->GetError() ) + rDoc.ReadLayoutCache( *pStrm2 ); + delete pStrm2; + } + catch ( uno::Exception& ) + { + } + } + + // Notify math objects + if( bInsertMode ) + rDoc.PrtOLENotify( FALSE ); + else if ( rDoc.IsOLEPrtNotifyPending() ) + rDoc.PrtOLENotify( TRUE ); + + nRet = nRet ? nRet : (nWarn ? nWarn : (nWarn2 ? nWarn2 : nWarnRDF ) ); + + aOpt.ResetAllFmtsOnly(); + + // redline password + aAny = xInfoSet->getPropertyValue( sRedlineProtectionKey ); + Sequence<sal_Int8> aKey; + aAny >>= aKey; + rDoc.SetRedlinePassword( aKey ); + + // restore redline mode from import info property set + sal_Int16 nRedlineMode = nsRedlineMode_t::REDLINE_SHOW_INSERT; + aAny = xInfoSet->getPropertyValue( sShowChanges ); + if ( *(sal_Bool*)aAny.getValue() ) + nRedlineMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE; + aAny = xInfoSet->getPropertyValue( sRecordChanges ); + if ( *(sal_Bool*)aAny.getValue() || (aKey.getLength() > 0) ) + nRedlineMode |= nsRedlineMode_t::REDLINE_ON; + else + nRedlineMode |= nsRedlineMode_t::REDLINE_NONE; + + // ... restore redline mode + // (First set bogus mode to make sure the mode in SetRedlineMode() + // is different from it's previous mode.) + rDoc.SetRedlineMode_intern((RedlineMode_t)( ~nRedlineMode )); + rDoc.SetRedlineMode( (RedlineMode_t)( nRedlineMode )); + + // #103728# move Pam into valid content + lcl_EnsureValidPam( rPaM ); + + if( pGraphicHelper ) + SvXMLGraphicHelper::Destroy( pGraphicHelper ); + xGraphicResolver = 0; + if( pObjectHelper ) + SvXMLEmbeddedObjectHelper::Destroy( pObjectHelper ); + xObjectResolver = 0; + rDoc.release(); + + if ( !bOASIS ) + { + // --> OD 2005-09-06 #i44177# - assure that for documents in OpenOffice.org + // file format the relation between outline numbering rule and styles is + // filled-up accordingly. + // Note: The OpenOffice.org file format, which has no content that applys + // a certain style, which is related to the outline numbering rule, + // has lost the information, that this certain style is related to + // the outline numbering rule. + // --> OD 2008-12-17 #i70748# - only for templates + if ( pMedium && pMedium->GetFilter() && + pMedium->GetFilter()->IsOwnTemplateFormat() ) + { + lcl_AdjustOutlineStylesForOOo( rDoc ); + } + // <-- + // Fix #i58251#: Unfortunately is the static default different to SO7 behaviour, + // so we have to set a dynamic default after importing SO7 + rDoc.SetDefault( SfxBoolItem( RES_ROW_SPLIT, FALSE ) ); + } + // <-- + + rDoc.PropagateOutlineRule(); + + // --> OD 2006-03-14 #i62875# + if ( rDoc.get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) && !docfunc::ExistsDrawObjs( rDoc ) ) + { + rDoc.set(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, false); + } + // <-- + + // --> OD 2006-02-22 #b6382898# + // Convert all instances of <SdrOle2Obj> into <SdrGrafObj>, because the + // Writer doesn't support such objects. + lcl_ConvertSdrOle2ObjsToSdrGrafObjs( rDoc ); + // <-- + + // set BuildId on XModel for later OLE object loading + if( xInfoSet.is() ) + { + uno::Reference< beans::XPropertySet > xModelSet( xModelComp, uno::UNO_QUERY ); + if( xModelSet.is() ) + { + uno::Reference< beans::XPropertySetInfo > xModelSetInfo( xModelSet->getPropertySetInfo() ); + OUString sName( RTL_CONSTASCII_USTRINGPARAM("BuildId" ) ); + if( xModelSetInfo.is() && xModelSetInfo->hasPropertyByName(sName) ) + { + xModelSet->setPropertyValue( sName, xInfoSet->getPropertyValue(sName) ); + } + } + } + + if (xStatusIndicator.is()) + { + xStatusIndicator->end(); + } + + rDoc.GetIStyleAccess().clearCaches(); // Clear Automatic-Style-Caches(shared_pointer!) + return nRet; +} + + // read the sections of the document, which is equal to the medium. + // returns the count of it +USHORT XMLReader::GetSectionList( SfxMedium& rMedium, + SvStrings& rStrings ) const +{ + uno::Reference< lang::XMultiServiceFactory > xServiceFactory = + comphelper::getProcessServiceFactory(); + ASSERT( xServiceFactory.is(), + "XMLReader::Read: got no service manager" ); + uno::Reference < embed::XStorage > xStg2; + if( xServiceFactory.is() && ( xStg2 = rMedium.GetStorage() ).is() ) + { + try + { + + xml::sax::InputSource aParserInput; + OUString sDocName( RTL_CONSTASCII_USTRINGPARAM( "content.xml" ) ); + aParserInput.sSystemId = sDocName; + + uno::Reference < io::XStream > xStm = xStg2->openStreamElement( sDocName, embed::ElementModes::READ ); + aParserInput.aInputStream = xStm->getInputStream(); + + // get parser + uno::Reference< XInterface > xXMLParser = xServiceFactory->createInstance( + OUString::createFromAscii("com.sun.star.xml.sax.Parser") ); + ASSERT( xXMLParser.is(), + "XMLReader::Read: com.sun.star.xml.sax.Parser service missing" ); + if( xXMLParser.is() ) + { + // get filter + // #110680# + // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLSectionList( rStrings ); + uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLSectionList( xServiceFactory, rStrings ); + + // connect parser and filter + uno::Reference< xml::sax::XParser > xParser( xXMLParser, UNO_QUERY ); + xParser->setDocumentHandler( xFilter ); + + // parse + xParser->parseStream( aParserInput ); + } + } + catch( xml::sax::SAXParseException& ) + { + // re throw ? + } + catch( xml::sax::SAXException& ) + { + // re throw ? + } + catch( io::IOException& ) + { + // re throw ? + } + catch( packages::WrongPasswordException& ) + { + // re throw ? + } + } + return rStrings.Count(); +} + diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx new file mode 100644 index 000000000000..4107657e8554 --- /dev/null +++ b/sw/source/filter/xml/wrtxml.cxx @@ -0,0 +1,701 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/task/XStatusIndicatorFactory.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/document/XExporter.hpp> +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/frame/XModule.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <unotools/streamwrap.hxx> +#include <svx/xmlgrhlp.hxx> +#include <svx/xmleohlp.hxx> +#include <unotools/saveopt.hxx> +#include <tools/urlobj.hxx> +#include <svl/stritem.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/docfile.hxx> +#include <pam.hxx> +#include <doc.hxx> +#include <docstat.hxx> +#include <docsh.hxx> + +#include <unotools/ucbstreamhelper.hxx> +#include <errhdl.hxx> +#include <swerror.h> +#include <wrtxml.hxx> +#include <statstr.hrc> +#include <rtl/logfile.hxx> + +#include <comphelper/documentconstants.hxx> +#include <comphelper/makesequence.hxx> +#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp> + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; + +#define LOGFILE_AUTHOR "mb93740" + +SwXMLWriter::SwXMLWriter( const String& rBaseURL ) +{ + SetBaseURL( rBaseURL ); +} + + +__EXPORT SwXMLWriter::~SwXMLWriter() +{ +} + + +sal_uInt32 SwXMLWriter::_Write( SfxMedium* pTargetMedium ) +{ + DBG_ASSERT( pTargetMedium, "No medium is provided!" ); + // Get service factory + uno::Reference< lang::XMultiServiceFactory > xServiceFactory = + comphelper::getProcessServiceFactory(); + ASSERT( xServiceFactory.is(), + "SwXMLWriter::Write: got no service manager" ); + if( !xServiceFactory.is() ) + return ERR_SWG_WRITE_ERROR; + + // Get data sink ... + uno::Reference< io::XOutputStream > xOut; + SvStorageStreamRef xDocStream; + uno::Reference< document::XGraphicObjectResolver > xGraphicResolver; + SvXMLGraphicHelper *pGraphicHelper = 0; + uno::Reference< document::XEmbeddedObjectResolver > xObjectResolver; + SvXMLEmbeddedObjectHelper *pObjectHelper = 0; + + ASSERT( xStg.is(), "Where is my storage?" ); +pGraphicHelper = SvXMLGraphicHelper::Create( xStg, + GRAPHICHELPER_MODE_WRITE, + sal_False ); + xGraphicResolver = pGraphicHelper; + + SfxObjectShell *pPersist = pDoc->GetPersist(); + if( pPersist ) + { + pObjectHelper = SvXMLEmbeddedObjectHelper::Create( + xStg, *pPersist, + EMBEDDEDOBJECTHELPER_MODE_WRITE, + sal_False ); + xObjectResolver = pObjectHelper; + } + + // create and prepare the XPropertySet that gets passed through + // the components, and the XStatusIndicator that shows progress to + // the user. + + // create XPropertySet with three properties for status indicator + comphelper::PropertyMapEntry aInfoMap[] = + { + { "ProgressRange", sizeof("ProgressRange")-1, 0, + &::getCppuType((sal_Int32*)0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "ProgressMax", sizeof("ProgressMax")-1, 0, + &::getCppuType((sal_Int32*)0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "ProgressCurrent", sizeof("ProgressCurrent")-1, 0, + &::getCppuType((sal_Int32*)0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "WrittenNumberStyles", sizeof("WrittenNumberStyles")-1, 0, + &::getCppuType((uno::Sequence<sal_Int32> *)0), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "UsePrettyPrinting", sizeof("UsePrettyPrinting")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "ShowChanges", sizeof("ShowChanges")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "RedlineProtectionKey", sizeof("RedlineProtectionKey")-1, 0, +#if (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) + new uno::Type(::getCppuType((Sequence<sal_Int8>*)0)), +#else + &::getCppuType((Sequence<sal_Int8>*)0), +#endif + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "BaseURI", sizeof("BaseURI")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StreamRelPath", sizeof("StreamRelPath")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StreamName", sizeof("StreamName")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "AutoTextMode", sizeof("AutoTextMode")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StyleNames", sizeof("StyleNames")-1, 0, + &::getCppuType( (Sequence<OUString>*)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StyleFamilies", sizeof("StyleFamilies")-1, 0, + &::getCppuType( (Sequence<sal_Int32>*)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + // --> OD 2006-09-26 #i69627# + { "OutlineStyleAsNormalListStyle", sizeof("OutlineStyleAsNormalListStyle")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + // <-- + { "TargetStorage", sizeof("TargetStorage")-1,0, &embed::XStorage::static_type(), + ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 }, + + { NULL, 0, 0, NULL, 0, 0 } + }; + uno::Reference< beans::XPropertySet > xInfoSet( + comphelper::GenericPropertySet_CreateInstance( + new comphelper::PropertySetInfo( aInfoMap ) ) ); + + const OUString sTargetStorage( RTL_CONSTASCII_USTRINGPARAM("TargetStorage") ); + xInfoSet->setPropertyValue( sTargetStorage, Any( xStg ) ); + + // create XStatusIndicator + uno::Reference<task::XStatusIndicator> xStatusIndicator; + + uno::Any aAny; + if (bShowProgress) + { + // retrieve status indicator from the medium MediaDescriptor + if ( pTargetMedium ) + { + const SfxUnoAnyItem* pStatusBarItem = static_cast<const SfxUnoAnyItem*>( + pTargetMedium->GetItemSet()->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) ); + + if ( pStatusBarItem ) + pStatusBarItem->GetValue() >>= xStatusIndicator; + } + +// try +// { +// uno::Reference<frame::XModel> xModel( pDoc->GetDocShell()->GetModel()); +// if (xModel.is()) +// { +// uno::Sequence< beans::PropertyValue > xMediaDescr +// uno::Reference<frame::XController> xController( +// xModel->getCurrentController()); +// if( xController.is()) +// { +// uno::Reference<frame::XFrame> xFrame( xController->getFrame()); +// if( xFrame.is()) +// { +// uno::Reference<task::XStatusIndicatorFactory> xFactory( +// xFrame, uno::UNO_QUERY ); +// if( xFactory.is()) +// { +// xStatusIndicator = +// xFactory->createStatusIndicator(); +// } +// } +// } +// } +// } +// catch( const RuntimeException& ) +// { +// xStatusIndicator = 0; +// } + + // set progress range and start status indicator + sal_Int32 nProgressRange(1000000); + if (xStatusIndicator.is()) + { + xStatusIndicator->start(SW_RESSTR( STR_STATSTR_SWGWRITE), + nProgressRange); + } + aAny <<= nProgressRange; + OUString sProgressRange(RTL_CONSTASCII_USTRINGPARAM("ProgressRange")); + xInfoSet->setPropertyValue(sProgressRange, aAny); + + aAny <<= static_cast < sal_Int32 >( -1 ); + OUString sProgressMax(RTL_CONSTASCII_USTRINGPARAM("ProgressMax")); + xInfoSet->setPropertyValue(sProgressMax, aAny); + } + SvtSaveOptions aSaveOpt; + OUString sUsePrettyPrinting(RTL_CONSTASCII_USTRINGPARAM("UsePrettyPrinting")); + sal_Bool bUsePrettyPrinting( aSaveOpt.IsPrettyPrinting() ); + aAny.setValue( &bUsePrettyPrinting, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sUsePrettyPrinting, aAny ); + + // save show redline mode ... + OUString sShowChanges(RTL_CONSTASCII_USTRINGPARAM("ShowChanges")); + sal_uInt16 nRedlineMode = pDoc->GetRedlineMode(); + sal_Bool bShowChanges( IDocumentRedlineAccess::IsShowChanges( nRedlineMode ) ); + aAny.setValue( &bShowChanges, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sShowChanges, aAny ); + // ... and hide redlines for export + nRedlineMode &= ~nsRedlineMode_t::REDLINE_SHOW_MASK; + nRedlineMode |= nsRedlineMode_t::REDLINE_SHOW_INSERT; + pDoc->SetRedlineMode((RedlineMode_t)( nRedlineMode )); + + // Set base URI + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("BaseURI") ); + xInfoSet->setPropertyValue( sPropName, makeAny( ::rtl::OUString( GetBaseURL() ) ) ); + + if( SFX_CREATE_MODE_EMBEDDED == pDoc->GetDocShell()->GetCreateMode() ) + { + OUString aName; + if ( pTargetMedium && pTargetMedium->GetItemSet() ) + { + const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>( + pTargetMedium->GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) ); + if ( pDocHierarchItem ) + aName = pDocHierarchItem->GetValue(); + } + else + aName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "dummyObjectName" ) ); + + if( aName.getLength() ) + { + sPropName = OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath")); + xInfoSet->setPropertyValue( sPropName, makeAny( aName ) ); + } + } + + if( bBlock ) + { + OUString sAutoTextMode( + RTL_CONSTASCII_USTRINGPARAM("AutoTextMode")); + sal_Bool bTmp = sal_True; + Any aAny2; + aAny2.setValue( &bTmp, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sAutoTextMode, aAny2 ); + } + + // --> OD 2006-09-26 #i69627# + const sal_Bool bOASIS = ( SotStorage::GetVersion( xStg ) > SOFFICE_FILEFORMAT_60 ); + if ( bOASIS && + docfunc::HasOutlineStyleToBeWrittenAsNormalListStyle( *pDoc ) ) + { + OUString sOutlineStyleAsNormalListStyle( + RTL_CONSTASCII_USTRINGPARAM("OutlineStyleAsNormalListStyle") ); + xInfoSet->setPropertyValue( sOutlineStyleAsNormalListStyle, makeAny( sal_True ) ); + } + // <-- + + // filter arguments + // - graphics + object resolver for styles + content + // - status indicator + // - info property set + // - else empty + sal_Int32 nArgs = 1; + if( xStatusIndicator.is() ) + nArgs++; + + Sequence < Any > aEmptyArgs( nArgs ); + Any *pArgs = aEmptyArgs.getArray(); + *pArgs++ <<= xInfoSet; + if( xStatusIndicator.is() ) + *pArgs++ <<= xStatusIndicator; + + if( xGraphicResolver.is() ) + nArgs++; + if( xObjectResolver.is() ) + nArgs++; + + Sequence < Any > aFilterArgs( nArgs ); + pArgs = aFilterArgs.getArray(); + *pArgs++ <<= xInfoSet; + if( xGraphicResolver.is() ) + *pArgs++ <<= xGraphicResolver; + if( xObjectResolver.is() ) + *pArgs++ <<= xObjectResolver; + if( xStatusIndicator.is() ) + *pArgs++ <<= xStatusIndicator; + + //Get model + uno::Reference< lang::XComponent > xModelComp( + pDoc->GetDocShell()->GetModel(), UNO_QUERY ); + ASSERT( xModelComp.is(), "XMLWriter::Write: got no model" ); + if( !xModelComp.is() ) + return ERR_SWG_WRITE_ERROR; + + PutNumFmtFontsInAttrPool(); + PutEditEngFontsInAttrPool(); + + // properties + Sequence < PropertyValue > aProps( pOrigFileName ? 1 : 0 ); + if( pOrigFileName ) + { + PropertyValue *pProps = aProps.getArray(); + pProps->Name = OUString( RTL_CONSTASCII_USTRINGPARAM("FileName") ); + (pProps++)->Value <<= OUString( *pOrigFileName ); + } + + // export sub streams for package, else full stream into a file + sal_Bool bWarn = sal_False, bErr = sal_False; + String sWarnFile, sErrFile; + + // RDF metadata: export if ODF >= 1.2 + // N.B.: embedded documents have their own manifest.rdf! + if ( bOASIS ) + { + const uno::Reference<beans::XPropertySet> xPropSet(xStg, + uno::UNO_QUERY_THROW); + const ::rtl::OUString VersionProp( + ::rtl::OUString::createFromAscii("Version")); + try + { + ::rtl::OUString Version; + // ODF >= 1.2 + if ((xPropSet->getPropertyValue(VersionProp) >>= Version) + && !Version.equals(ODFVER_010_TEXT) + && !Version.equals(ODFVER_011_TEXT)) + { + const uno::Reference<rdf::XDocumentMetadataAccess> xDMA( + xModelComp, uno::UNO_QUERY_THROW); + xDMA->storeMetadataToStorage(xStg); + } + } + catch (beans::UnknownPropertyException &) + { /* ignore */ } + catch (uno::Exception &) + { + bWarn = sal_True; + } + } + + sal_Bool bStoreMeta = ( SFX_CREATE_MODE_EMBEDDED != pDoc->GetDocShell()->GetCreateMode() ); + if ( !bStoreMeta ) + { + try + { + Reference< frame::XModule > xModule( xModelComp, UNO_QUERY ); + if ( xModule.is() ) + { + ::rtl::OUString aModuleID = xModule->getIdentifier(); + bStoreMeta = ( aModuleID.getLength() + && ( aModuleID.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.FormDesign" ) ) ) + || aModuleID.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.TextReportDesign" ) ) ) ) ); + } + } + catch( uno::Exception& ) + {} + } + + if( !bOrganizerMode && !bBlock && bStoreMeta ) + { + if( !WriteThroughComponent( + xModelComp, "meta.xml", xServiceFactory, + (bOASIS ? "com.sun.star.comp.Writer.XMLOasisMetaExporter" + : "com.sun.star.comp.Writer.XMLMetaExporter"), + aEmptyArgs, aProps, sal_True ) ) + { + bWarn = sal_True; + sWarnFile = String( RTL_CONSTASCII_STRINGPARAM("meta.xml"), + RTL_TEXTENCODING_ASCII_US ); + } + } + + if( !bErr ) + { + if( !bBlock ) + { + if( !WriteThroughComponent( + xModelComp, "settings.xml", xServiceFactory, + (bOASIS ? "com.sun.star.comp.Writer.XMLOasisSettingsExporter" + : "com.sun.star.comp.Writer.XMLSettingsExporter"), + aEmptyArgs, aProps, sal_False ) ) + { + if( !bWarn ) + { + bWarn = sal_True; + sWarnFile = String( RTL_CONSTASCII_STRINGPARAM("settings.xml"), + RTL_TEXTENCODING_ASCII_US ); + } + } + } + } + + if( !WriteThroughComponent( + xModelComp, "styles.xml", xServiceFactory, + (bOASIS ? "com.sun.star.comp.Writer.XMLOasisStylesExporter" + : "com.sun.star.comp.Writer.XMLStylesExporter"), + aFilterArgs, aProps, sal_False ) ) + { + bErr = sal_True; + sErrFile = String( RTL_CONSTASCII_STRINGPARAM("styles.xml"), + RTL_TEXTENCODING_ASCII_US ); + } + + + if( !bOrganizerMode && !bErr ) + { + if( !WriteThroughComponent( + xModelComp, "content.xml", xServiceFactory, + (bOASIS ? "com.sun.star.comp.Writer.XMLOasisContentExporter" + : "com.sun.star.comp.Writer.XMLContentExporter"), + aFilterArgs, aProps, sal_False ) ) + { + bErr = sal_True; + sErrFile = String( RTL_CONSTASCII_STRINGPARAM("content.xml"), + RTL_TEXTENCODING_ASCII_US ); + } + } + + if( pDoc->GetRootFrm() && pDoc->GetDocStat().nPage > 1 && + !(bOrganizerMode || bBlock || bErr) ) + { +// DBG_ASSERT( !pDoc->GetDocStat().bModified, +// "doc stat is modified!" ); + OUString sStreamName( RTL_CONSTASCII_USTRINGPARAM("layout-cache") ); + try + { + uno::Reference < io::XStream > xStm = xStg->openStreamElement( sStreamName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); + SvStream* pStream = utl::UcbStreamHelper::CreateStream( xStm ); + if( !pStream->GetError() ) + { + uno::Reference < beans::XPropertySet > xSet( xStm, UNO_QUERY ); + String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); + OUString aMime( RTL_CONSTASCII_USTRINGPARAM("application/binary") ); + uno::Any aAny2; + aAny2 <<= aMime; + xSet->setPropertyValue( aPropName, aAny2 ); + pDoc->WriteLayoutCache( *pStream ); + } + + delete pStream; + } + catch ( uno::Exception& ) + { + } + } + + if( pGraphicHelper ) + SvXMLGraphicHelper::Destroy( pGraphicHelper ); + xGraphicResolver = 0; + + if( pObjectHelper ) + SvXMLEmbeddedObjectHelper::Destroy( pObjectHelper ); + xObjectResolver = 0; + + // restore redline mode + aAny = xInfoSet->getPropertyValue( sShowChanges ); + nRedlineMode = pDoc->GetRedlineMode(); + nRedlineMode &= ~nsRedlineMode_t::REDLINE_SHOW_MASK; + nRedlineMode |= nsRedlineMode_t::REDLINE_SHOW_INSERT; + if ( *(sal_Bool*)aAny.getValue() ) + nRedlineMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE; + pDoc->SetRedlineMode((RedlineMode_t)( nRedlineMode )); + + if (xStatusIndicator.is()) + { + xStatusIndicator->end(); + } + + if( bErr ) + { + if( sErrFile.Len() ) + return *new StringErrorInfo( ERR_WRITE_ERROR_FILE, sErrFile, + ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR ); + else + return ERR_SWG_WRITE_ERROR; + } + else if( bWarn ) + { + if( sWarnFile.Len() ) + return *new StringErrorInfo( WARN_WRITE_ERROR_FILE, sWarnFile, + ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR ); + else + return WARN_SWG_FEATURES_LOST; + } + + return 0; +} + +ULONG SwXMLWriter::WriteStorage() +{ + return _Write(); +} + +ULONG SwXMLWriter::WriteMedium( SfxMedium& aTargetMedium ) +{ + return _Write( &aTargetMedium ); +} + +ULONG SwXMLWriter::Write( SwPaM& rPaM, SfxMedium& rMed, + const String* pFileName ) +{ + return IsStgWriter() + ? ((StgWriter *)this)->Write( rPaM, rMed.GetOutputStorage(), pFileName, &rMed ) + : ((Writer *)this)->Write( rPaM, *rMed.GetOutStream(), pFileName ); +} + +sal_Bool SwXMLWriter::WriteThroughComponent( + const uno::Reference<XComponent> & xComponent, + const sal_Char* pStreamName, + const uno::Reference<lang::XMultiServiceFactory> & rFactory, + const sal_Char* pServiceName, + const Sequence<Any> & rArguments, + const Sequence<beans::PropertyValue> & rMediaDesc, + sal_Bool bPlainStream ) +{ + DBG_ASSERT( xStg.is(), "Need storage!" ); + DBG_ASSERT( NULL != pStreamName, "Need stream name!" ); + DBG_ASSERT( NULL != pServiceName, "Need service name!" ); + + RTL_LOGFILE_TRACE_AUTHOR1( "sw", LOGFILE_AUTHOR, + "SwXMLWriter::WriteThroughComponent : stream %s", + pStreamName ); + + // open stream + sal_Bool bRet = sal_False; + try + { + OUString sStreamName = OUString::createFromAscii( pStreamName ); + uno::Reference<io::XStream> xStream = + xStg->openStreamElement( sStreamName, + embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); + + uno::Reference <beans::XPropertySet > xSet( xStream, uno::UNO_QUERY ); + if( !xSet.is() ) + return sal_False; + + String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); + OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); + uno::Any aAny; + aAny <<= aMime; + xSet->setPropertyValue( aPropName, aAny ); + + OUString aUseCommonPassPropName( RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption") ); + if( bPlainStream ) + { + OUString aCompressPropName( RTL_CONSTASCII_USTRINGPARAM("Compressed") ); + sal_Bool bFalse = sal_False; + aAny.setValue( &bFalse, ::getBooleanCppuType() ); + xSet->setPropertyValue( aCompressPropName, aAny ); + } + + // even plain stream should be encrypted in encrypted documents + sal_Bool bTrue = sal_True; + aAny.setValue( &bTrue, ::getBooleanCppuType() ); + xSet->setPropertyValue( aUseCommonPassPropName, aAny ); + + // set buffer and create outputstream + uno::Reference< io::XOutputStream > xOutputStream = xStream->getOutputStream(); + + // set Base URL + uno::Reference< beans::XPropertySet > xInfoSet; + if( rArguments.getLength() > 0 ) + rArguments.getConstArray()[0] >>= xInfoSet; + DBG_ASSERT( xInfoSet.is(), "missing property set" ); + if( xInfoSet.is() ) + { + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamName") ); + xInfoSet->setPropertyValue( sPropName, makeAny( sStreamName ) ); + } + + // write the stuff + bRet = WriteThroughComponent( + xOutputStream, xComponent, rFactory, + pServiceName, rArguments, rMediaDesc ); + } + catch ( uno::Exception& ) + { + } + + return bRet; + +} + +sal_Bool SwXMLWriter::WriteThroughComponent( + const uno::Reference<io::XOutputStream> & xOutputStream, + const uno::Reference<XComponent> & xComponent, + const uno::Reference<XMultiServiceFactory> & rFactory, + const sal_Char* pServiceName, + const Sequence<Any> & rArguments, + const Sequence<PropertyValue> & rMediaDesc ) +{ + ASSERT( xOutputStream.is(), "I really need an output stream!" ); + ASSERT( xComponent.is(), "Need component!" ); + ASSERT( NULL != pServiceName, "Need component name!" ); + + RTL_LOGFILE_CONTEXT_AUTHOR( aFilterLog, "sw", LOGFILE_AUTHOR, + "SwXMLWriter::WriteThroughComponent" ); + + // get component + uno::Reference< io::XActiveDataSource > xSaxWriter( + rFactory->createInstance( + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.xml.sax.Writer")) ), + UNO_QUERY ); + ASSERT( xSaxWriter.is(), "can't instantiate XML writer" ); + if(!xSaxWriter.is()) + return sal_False; + + RTL_LOGFILE_CONTEXT_TRACE( aFilterLog, "SAX-Writer created" ); + + // connect XML writer to output stream + xSaxWriter->setOutputStream( xOutputStream ); + + // prepare arguments (prepend doc handler to given arguments) + uno::Reference<xml::sax::XDocumentHandler> xDocHandler( xSaxWriter,UNO_QUERY); + Sequence<Any> aArgs( 1 + rArguments.getLength() ); + aArgs[0] <<= xDocHandler; + for(sal_Int32 i = 0; i < rArguments.getLength(); i++) + aArgs[i+1] = rArguments[i]; + + // get filter component + uno::Reference< document::XExporter > xExporter( + rFactory->createInstanceWithArguments( + OUString::createFromAscii(pServiceName), aArgs), UNO_QUERY); + ASSERT( xExporter.is(), + "can't instantiate export filter component" ); + if( !xExporter.is() ) + return sal_False; + RTL_LOGFILE_CONTEXT_TRACE1( aFilterLog, "%s instantiated.", pServiceName ); + + // connect model and filter + xExporter->setSourceDocument( xComponent ); + + // filter! + RTL_LOGFILE_CONTEXT_TRACE( aFilterLog, "call filter()" ); + uno::Reference<XFilter> xFilter( xExporter, UNO_QUERY ); + return xFilter->filter( rMediaDesc ); +} + + +// ----------------------------------------------------------------------- + +void GetXMLWriter( const String& /*rName*/, const String& rBaseURL, WriterRef& xRet ) +{ + xRet = new SwXMLWriter( rBaseURL ); +} + +// ----------------------------------------------------------------------- diff --git a/sw/source/filter/xml/wrtxml.hxx b/sw/source/filter/xml/wrtxml.hxx new file mode 100644 index 000000000000..b5dbe191776b --- /dev/null +++ b/sw/source/filter/xml/wrtxml.hxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _WRTXML_HXX +#define _WRTXML_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <shellio.hxx> + +class SwPaM; +class SfxMedium; + +namespace com { namespace sun { namespace star { + namespace uno { template<class A> class Reference; } + namespace uno { template<class A> class Sequence; } + namespace uno { class Any; } + namespace lang { class XComponent; } + namespace lang { class XMultiServiceFactory; } + namespace beans { struct PropertyValue; } +} } } + + +class SwXMLWriter : public StgWriter +{ + sal_uInt32 _Write( SfxMedium* pTargetMedium = NULL ); + + using StgWriter::Write; + +protected: + virtual ULONG WriteStorage(); + virtual ULONG WriteMedium( SfxMedium& aTargetMedium ); + +public: + + SwXMLWriter( const String& rBaseURL ); + virtual ~SwXMLWriter(); + + virtual ULONG Write( SwPaM&, SfxMedium&, const String* = 0 ); + +private: + + // helper methods to write XML streams + + /// write a single XML stream into the package + sal_Bool WriteThroughComponent( + /// the component we export + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XComponent> & xComponent, + const sal_Char* pStreamName, /// the stream name + /// service factory for pServiceName + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory> & rFactory, + const sal_Char* pServiceName, /// service name of the component + /// the argument (XInitialization) + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Any> & rArguments, + /// output descriptor + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue> & rMediaDesc, + sal_Bool bPlainStream ); /// neither compress nor encrypt + + /// write a single output stream + /// (to be called either directly or by WriteThroughComponent(...)) + sal_Bool WriteThroughComponent( + const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XOutputStream> & xOutputStream, + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XComponent> & xComponent, + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory> & rFactory, + const sal_Char* pServiceName, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Any> & rArguments, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue> & rMediaDesc ); +}; + + +#endif // _WRTXML_HXX + diff --git a/sw/source/filter/xml/xmlbrsh.cxx b/sw/source/filter/xml/xmlbrsh.cxx new file mode 100644 index 000000000000..7235617f8666 --- /dev/null +++ b/sw/source/filter/xml/xmlbrsh.cxx @@ -0,0 +1,258 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + + +#include "hintids.hxx" +#include <tools/debug.hxx> +#include <com/sun/star/io/XOutputStream.hpp> +#include <editeng/memberids.hrc> + +#include <xmloff/nmspmap.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/xmltkmap.hxx> +#include <xmloff/XMLBase64ImportContext.hxx> +#include <svtools/grfmgr.hxx> +#include <svx/unomid.hxx> +#include <editeng/brshitem.hxx> +#include <xmloff/xmluconv.hxx> + +#include "xmlbrshi.hxx" +#include "xmlbrshe.hxx" +#include "xmlexp.hxx" +#include "xmlimpit.hxx" +#include "xmlexpit.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::xmloff::token; + +enum SvXMLTokenMapAttrs +{ + XML_TOK_BGIMG_HREF, + XML_TOK_BGIMG_TYPE, + XML_TOK_BGIMG_ACTUATE, + XML_TOK_BGIMG_SHOW, + XML_TOK_BGIMG_POSITION, + XML_TOK_BGIMG_REPEAT, + XML_TOK_BGIMG_FILTER, + XML_TOK_NGIMG_END=XML_TOK_UNKNOWN +}; + +static __FAR_DATA SvXMLTokenMapEntry aBGImgAttributesAttrTokenMap[] = +{ + { XML_NAMESPACE_XLINK, XML_HREF, XML_TOK_BGIMG_HREF }, + { XML_NAMESPACE_XLINK, XML_TYPE, XML_TOK_BGIMG_TYPE }, + { XML_NAMESPACE_XLINK, XML_ACTUATE, XML_TOK_BGIMG_ACTUATE }, + { XML_NAMESPACE_XLINK, XML_SHOW, XML_TOK_BGIMG_SHOW }, + { XML_NAMESPACE_STYLE, XML_POSITION, XML_TOK_BGIMG_POSITION }, + { XML_NAMESPACE_STYLE, XML_REPEAT, XML_TOK_BGIMG_REPEAT }, + { XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TOK_BGIMG_FILTER }, + XML_TOKEN_MAP_END +}; + +TYPEINIT1( SwXMLBrushItemImportContext, SvXMLImportContext ); + +void SwXMLBrushItemImportContext::ProcessAttrs( + const uno::Reference< xml::sax::XAttributeList >& xAttrList, + const SvXMLUnitConverter& rUnitConv ) +{ + SvXMLTokenMap aTokenMap( aBGImgAttributesAttrTokenMap ); + + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + OUString aLocalName; + sal_uInt16 nPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + const OUString& rValue = xAttrList->getValueByIndex( i ); + + switch( aTokenMap.Get( nPrefix, aLocalName ) ) + { + case XML_TOK_BGIMG_HREF: + SvXMLImportItemMapper::PutXMLValue( + *pItem, GetImport().ResolveGraphicObjectURL( rValue,sal_False), + MID_GRAPHIC_LINK, rUnitConv ); + break; + case XML_TOK_BGIMG_TYPE: + case XML_TOK_BGIMG_ACTUATE: + case XML_TOK_BGIMG_SHOW: + break; + case XML_TOK_BGIMG_POSITION: + SvXMLImportItemMapper::PutXMLValue( + *pItem, rValue, MID_GRAPHIC_POSITION, rUnitConv ); + break; + case XML_TOK_BGIMG_REPEAT: + SvXMLImportItemMapper::PutXMLValue( + *pItem, rValue, MID_GRAPHIC_REPEAT, rUnitConv ); + break; + case XML_TOK_BGIMG_FILTER: + SvXMLImportItemMapper::PutXMLValue( + *pItem, rValue, MID_GRAPHIC_FILTER, rUnitConv ); + break; + } + } + +} + +SvXMLImportContext *SwXMLBrushItemImportContext::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + if( xmloff::token::IsXMLToken( rLocalName, + xmloff::token::XML_BINARY_DATA ) ) + { + if( !xBase64Stream.is() && !pItem->GetGraphicLink() ) + { + const GraphicObject *pGrObj = pItem->GetGraphicObject(); + if( !pGrObj || GRAPHIC_NONE == pGrObj->GetType() ) + { + xBase64Stream = + GetImport().GetStreamForGraphicObjectURLFromBase64(); + if( xBase64Stream.is() ) + pContext = new XMLBase64ImportContext( GetImport(), nPrefix, + rLocalName, xAttrList, + xBase64Stream ); + } + } + } + if( !pContext ) + { + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + } + + return pContext; +} + +void SwXMLBrushItemImportContext::EndElement() +{ + if( xBase64Stream.is() ) + { + OUString sURL( GetImport().ResolveGraphicObjectURLFromBase64( xBase64Stream ) ); + xBase64Stream = 0; + SvXMLImportItemMapper::PutXMLValue( *pItem, sURL, MID_GRAPHIC_LINK, GetImport().GetMM100UnitConverter() ); + } + + if( !(pItem->GetGraphicLink() || pItem->GetGraphic() ) ) + pItem->SetGraphicPos( GPOS_NONE ); + else if( GPOS_NONE == pItem->GetGraphicPos() ) + pItem->SetGraphicPos( GPOS_TILED ); +} + +SwXMLBrushItemImportContext::SwXMLBrushItemImportContext( + SvXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList >& xAttrList, + const SvXMLUnitConverter& rUnitConv, + const SvxBrushItem& rItem ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + pItem( new SvxBrushItem( rItem ) ) +{ + // delete any grephic that is existing + pItem->SetGraphicPos( GPOS_NONE ); + + ProcessAttrs( xAttrList, rUnitConv ); +} + +SwXMLBrushItemImportContext::SwXMLBrushItemImportContext( + SvXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList, + const SvXMLUnitConverter& rUnitConv, + sal_uInt16 nWhich ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + pItem( new SvxBrushItem( nWhich ) ) +{ + ProcessAttrs( xAttrList, rUnitConv ); +} + +SwXMLBrushItemImportContext::~SwXMLBrushItemImportContext() +{ + delete pItem; +} + +SwXMLBrushItemExport::SwXMLBrushItemExport( SwXMLExport& rExp ) : + rExport( rExp ) +{ +} + +SwXMLBrushItemExport::~SwXMLBrushItemExport() +{ +} + + +void SwXMLBrushItemExport::exportXML( const SvxBrushItem& rItem ) +{ + GetExport().CheckAttrList(); + + OUString sValue, sURL; + const SvXMLUnitConverter& rUnitConv = GetExport().GetTwipUnitConverter(); + if( SvXMLExportItemMapper::QueryXMLValue( + rItem, sURL, MID_GRAPHIC_LINK, rUnitConv ) ) + { + sValue = GetExport().AddEmbeddedGraphicObject( sURL ); + if( sValue.getLength() ) + { + GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sValue ); + GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE ); + // AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, ACP2WS(sXML_embed) ); + GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD ); + } + + if( SvXMLExportItemMapper::QueryXMLValue( + rItem, sValue, MID_GRAPHIC_POSITION, rUnitConv ) ) + GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_POSITION, sValue ); + + if( SvXMLExportItemMapper::QueryXMLValue( + rItem, sValue, MID_GRAPHIC_REPEAT, rUnitConv ) ) + GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REPEAT, sValue ); + + if( SvXMLExportItemMapper::QueryXMLValue( + rItem, sValue, MID_GRAPHIC_FILTER, rUnitConv ) ) + GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_FILTER_NAME, sValue ); + } + + { + SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE, + sal_True, sal_True ); + if( sURL.getLength() ) + { + // optional office:binary-data + GetExport().AddEmbeddedGraphicObjectAsBase64( sURL ); + } + } +} + + diff --git a/sw/source/filter/xml/xmlbrshe.hxx b/sw/source/filter/xml/xmlbrshe.hxx new file mode 100644 index 000000000000..47acea0e7bb1 --- /dev/null +++ b/sw/source/filter/xml/xmlbrshe.hxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLBRSHE_HXX +#define _XMLBRSHE_HXX + +#include <rtl/ustring.hxx> +#include <xmloff/attrlist.hxx> + + +class SvxBrushItem; +class SwXMLExport; + +class SwXMLBrushItemExport +{ + SwXMLExport& rExport; + +protected: + + SwXMLExport& GetExport() { return rExport; } +public: + + SwXMLBrushItemExport( SwXMLExport& rExport ); + ~SwXMLBrushItemExport(); + + // core API + void exportXML( const SvxBrushItem& rItem ); +}; + + +#endif // _XMLBRSHE_HXX + diff --git a/sw/source/filter/xml/xmlbrshi.hxx b/sw/source/filter/xml/xmlbrshi.hxx new file mode 100644 index 000000000000..eb7f68c56703 --- /dev/null +++ b/sw/source/filter/xml/xmlbrshi.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLBRSHI_HXX +#define _XMLBRSHI_HXX + +class SvXMLImport; +class SvXMLUnitConverter; +class SvxBrushItem; + +namespace rtl { class OUString; } +namespace com { namespace sun { namespace star { + namespace io { class XOutputStream; } +} } } + +class SwXMLBrushItemImportContext : public SvXMLImportContext +{ +private: + ::com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > xBase64Stream; + SvxBrushItem *pItem; + + void ProcessAttrs( + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + const SvXMLUnitConverter& rUnitConv ); + +public: + TYPEINFO(); + + SwXMLBrushItemImportContext( + SvXMLImport& rImport, + sal_uInt16 nPrfx, + const ::rtl::OUString& rLName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + const SvXMLUnitConverter& rUnitConv, + const SvxBrushItem& rItem ); + + SwXMLBrushItemImportContext( + SvXMLImport& rImport, + sal_uInt16 nPrfx, + const ::rtl::OUString& rLName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + const SvXMLUnitConverter& rUnitConv, + sal_uInt16 nWhich ); + + virtual ~SwXMLBrushItemImportContext(); + + virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList ); + + virtual void EndElement(); + + const SvxBrushItem& GetItem() const { return *pItem; } +}; + + +#endif // _XMLBRSHI_HXX + diff --git a/sw/source/filter/xml/xmlexp.cxx b/sw/source/filter/xml/xmlexp.cxx new file mode 100644 index 000000000000..77dd1e63f53c --- /dev/null +++ b/sw/source/filter/xml/xmlexp.cxx @@ -0,0 +1,995 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <com/sun/star/text/XTextDocument.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/xforms/XFormsSupplier.hpp> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/xmleohlp.hxx> +#include <svx/xmlgrhlp.hxx> +#include <editeng/eeitem.hxx> +#include <svx/svddef.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <editeng/xmlcnitm.hxx> +#include <xmloff/ProgressBarHelper.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/xformsexport.hxx> +#include <pam.hxx> +#include <doc.hxx> +#include <swmodule.hxx> +#include <docsh.hxx> +#include <docstat.hxx> +#include <swerror.h> +#include <unotext.hxx> +#include <xmltexte.hxx> +#include <xmlexp.hxx> +#include <sfx2/viewsh.hxx> +#include <comphelper/processfactory.hxx> +#include <docary.hxx> +#include <editeng/unolingu.hxx> +#include <editeng/forbiddencharacterstable.hxx> +#include <ForbiddenCharactersEnum.hxx> + +// for locking SolarMutex: svapp + mutex +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +// --> OD 2007-03-30 #i73788# +#include <pausethreadstarting.hxx> +// <-- + + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::xforms; +using namespace ::xmloff::token; + +#ifdef XML_CORE_API +void SwXMLExport::SetCurPaM( SwPaM& rPaM, sal_Bool bWhole, sal_Bool bTabOnly ) +{ + if( !pCurPaM ) + { + pCurPaM = new SwPaM( *rPaM.End(), *rPaM.Start() ); + } + else + { + *pCurPaM->GetPoint() = *rPaM.Start(); + *pCurPaM->GetMark() = *rPaM.End(); + } + + // Set PaM to table/section start node if whole doc should be exported + if( bWhole ) + { + SwTableNode *pTblNd = pCurPaM->GetNode()->FindTableNode(); + if( pTblNd ) + { + pCurPaM->GetPoint()->nNode = *pTblNd; + + if( bTabOnly ) + pCurPaM->GetMark()->nNode = *pTblNd->EndOfSectionNode(); + } + + SwSectionNode * pSectNd = pCurPaM->GetNode()->FindSectionNode(); + while( pSectNd ) + { + pCurPaM->GetPoint()->nNode = *pSectNd; + + // SwSectionNode::FindSectionNode() returns the section node itself + pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode(); + } + } +} +#endif + +// #110680# +SwXMLExport::SwXMLExport( + const uno::Reference< lang::XMultiServiceFactory > xServiceFactory, + sal_uInt16 nExportFlags) +: SvXMLExport( xServiceFactory, MAP_INCH, XML_TEXT, nExportFlags ), +#ifdef XML_CORE_API + pCurPaM( 0 ), + pOrigPaM( &rPaM ), +#endif + pTableItemMapper( 0 ), + pTableLines( 0 ), +#ifdef XML_CORE_API + bExportWholeDoc( bExpWholeDoc ), + bExportFirstTableOnly( bExpFirstTableOnly ), +#endif + bBlock( sal_False ), + bShowProgress( sal_True ), + sNumberFormat(RTL_CONSTASCII_USTRINGPARAM("NumberFormat")), + sIsProtected(RTL_CONSTASCII_USTRINGPARAM("IsProtected")), + sCell(RTL_CONSTASCII_USTRINGPARAM("Cell")) +{ + _InitItemExport(); +} + +#ifdef XML_CORE_API +// #110680# +SwXMLExport::SwXMLExport( + const uno::Reference< lang::XMultiServiceFactory > xServiceFactory, + const Reference< XModel >& rModel, + SwPaM& rPaM, + const OUString& rFileName, + const Reference< XDocumentHandler > & rHandler, + const Reference< XGraphicObjectResolver > & rEmbeddedGrfObjs, + sal_Bool bExpWholeDoc, sal_Bool bExpFirstTableOnly, + sal_Bool bShowProg ) +: SvXMLExport( xServiceFactory, rFileName, rHandler, rModel, rEmbeddedGrfObjs, + SW_MOD()->GetMetric( rPaM.GetDoc()->get(IDocumentSettingAccess::HTML_MODE) ) ), + pCurPaM( 0 ), + pOrigPaM( &rPaM ), + pTableItemMapper( 0 ), + pTableLines( 0 ), + bExportWholeDoc( bExpWholeDoc ), + bExportFirstTableOnly( bExpFirstTableOnly ), + bShowProgress( bShowProg ), + sNumberFormat(RTL_CONSTASCII_USTRINGPARAM("NumberFormat")), + sIsProtected(RTL_CONSTASCII_USTRINGPARAM("IsProtected")), + sCell(RTL_CONSTASCII_USTRINGPARAM("Cell")) +{ + _InitItemExport(); +} +#endif + +void SwXMLExport::setBlockMode() +{ + bBlock = sal_True; + +} + +sal_uInt32 SwXMLExport::exportDoc( enum XMLTokenEnum eClass ) +{ + if( !GetModel().is() ) + return ERR_SWG_WRITE_ERROR; + + // --> OD 2007-03-30 #i73788# + SwPauseThreadStarting aPauseThreadStarting; + // <-- + + Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY ); + Reference < XText > xText = xTextDoc->getText(); + Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY); + ASSERT( xTextTunnel.is(), "missing XUnoTunnel for Cursor" ); + if( !xTextTunnel.is() ) + return ERR_SWG_WRITE_ERROR; + + // from here, we use core interfaces -> lock Solar-Mutex (#91949#) + vos::OGuard aGuard(Application::GetSolarMutex()); + + { + Reference<XPropertySet> rInfoSet = getExportInfo(); + if( rInfoSet.is() ) + { + OUString sAutoTextMode( + RTL_CONSTASCII_USTRINGPARAM("AutoTextMode")); + if( rInfoSet->getPropertySetInfo()->hasPropertyByName( + sAutoTextMode ) ) + { + Any aAny = rInfoSet->getPropertyValue(sAutoTextMode); + if( aAny.getValueType() == ::getBooleanCppuType() && + *static_cast<const sal_Bool*>(aAny.getValue()) ) + setBlockMode(); + } + } + } + + SwXText *pText = reinterpret_cast< SwXText * >( + sal::static_int_cast< sal_IntPtr >( xTextTunnel->getSomething( SwXText::getUnoTunnelId() ))); + ASSERT( pText, "SwXText missing" ); + if( !pText ) + return ERR_SWG_WRITE_ERROR; + + SwDoc *pDoc = pText->GetDoc(); + + sal_Bool bExtended = sal_False; + if( (getExportFlags() & (EXPORT_FONTDECLS|EXPORT_STYLES| + EXPORT_MASTERSTYLES|EXPORT_CONTENT)) != 0 ) + { + GetTextParagraphExport()->SetBlockMode( bBlock ); + + const SfxPoolItem* pItem; + const SfxItemPool& rPool = pDoc->GetAttrPool(); + sal_uInt16 aWhichIds[5] = { RES_UNKNOWNATR_CONTAINER, + RES_TXTATR_UNKNOWN_CONTAINER, + SDRATTR_XMLATTRIBUTES, + EE_PARA_XMLATTRIBS, + EE_CHAR_XMLATTRIBS }; + + sal_uInt16 nWhichIds = rPool.GetSecondaryPool() ? 5 : 2; + for( sal_uInt16 j=0; j < nWhichIds; j++ ) + { + sal_uInt16 nWhichId = aWhichIds[j]; + sal_uInt16 i=0, nItems = rPool.GetItemCount( nWhichId ); + for( i = 0; i < nItems; ++i ) + { + if( 0 != (pItem = rPool.GetItem( nWhichId , i ) ) ) + { + const SvXMLAttrContainerItem *pUnknown = + PTR_CAST( SvXMLAttrContainerItem, pItem ); + ASSERT( pUnknown, "illegal attribute container item" ); + if( pUnknown && (pUnknown->GetAttrCount() > 0) ) + { + sal_uInt16 nIdx = pUnknown->GetFirstNamespaceIndex(); + while( USHRT_MAX != nIdx ) + { + const OUString& rPrefix = + pUnknown->GetPrefix( nIdx ); + _GetNamespaceMap().Add( rPrefix, + pUnknown->GetNamespace( nIdx ), + XML_NAMESPACE_UNKNOWN ); + nIdx = pUnknown->GetNextNamespaceIndex( nIdx ); + } + bExtended = sal_True; + } + } + } + } + } + + MapUnit eUnit = + SvXMLUnitConverter::GetMapUnit( SW_MOD()->GetMetric(pDoc->get(IDocumentSettingAccess::HTML_MODE)) ); + if( GetMM100UnitConverter().getXMLMeasureUnit() != eUnit ) + { + GetMM100UnitConverter().setXMLMeasureUnit( eUnit ); + pTwipUnitConv->setXMLMeasureUnit( eUnit ); + } + + SetExtended( bExtended ); + + SwDocStat aDocStat( pDoc->GetDocStat() ); + if( (getExportFlags() & EXPORT_META) != 0 ) + { + // Update doc stat, so that correct values are exported and + // the progress works correctly. + if( aDocStat.bModified ) + pDoc->UpdateDocStat( aDocStat ); + + SfxObjectShell* pObjSh = pDoc->GetDocShell(); + if( pObjSh ) + pObjSh->UpdateDocInfoForSave(); // update information + } + if( bShowProgress ) + { + ProgressBarHelper *pProgress = GetProgressBarHelper(); + if( -1 == pProgress->GetReference() ) + { + // progress isn't initialized: + // We assume that the whole doc is exported, and the following + // durations: + // - meta information: 2 + // - settings: 4 (TODO: not now!) + // - styles (except page styles): 2 + // - page styles: 2 (TODO: not now!) + 2 for each paragraph + // - paragraph: 2 (1 for automatic styles and one for content) + + // If required, update doc stat, so that + // the progress works correctly. + if( aDocStat.bModified ) + pDoc->UpdateDocStat( aDocStat ); + + // count each item once, and then multiply by two to reach the + // figures given above + // The styles in pDoc also count the default style that never + // gets exported -> subtract one. + sal_Int32 nRef = 1; // meta.xml + nRef += pDoc->GetCharFmts()->Count() - 1; + nRef += pDoc->GetFrmFmts()->Count() - 1; + nRef += pDoc->GetTxtFmtColls()->Count() - 1; +// nRef += pDoc->GetPageDescCnt(); + nRef *= 2; // for the above styles, xmloff will increment by 2! + // #i93174#: count all paragraphs for the progress bar + nRef += aDocStat.nAllPara; // 1: only content, no autostyle + pProgress->SetReference( nRef ); + pProgress->SetValue( 0 ); + } + } + + if( (getExportFlags() & (EXPORT_MASTERSTYLES|EXPORT_CONTENT)) != 0 ) + { + //Auf die Korrektheit der OrdNums sind wir schon angewiesen. + SdrModel* pModel = pDoc->GetDrawModel(); + if( pModel ) + pModel->GetPage( 0 )->RecalcObjOrdNums(); + } + + // adjust document class (eClass) + if (pDoc->get(IDocumentSettingAccess::GLOBAL_DOCUMENT)) + { + eClass = XML_TEXT_GLOBAL; + + // additionally, we take care of the save-linked-sections-thingy + mbSaveLinkedSections = pDoc->get(IDocumentSettingAccess::GLOBAL_DOCUMENT_SAVE_LINKS); + } + // MIB: 03/26/04: The Label information is saved in the settings, so + // we don't need it here. + // else: keep default pClass that we received + + SvXMLGraphicHelper *pGraphicResolver = 0; + if( !GetGraphicResolver().is() ) + { + pGraphicResolver = SvXMLGraphicHelper::Create( GRAPHICHELPER_MODE_WRITE ); + Reference< XGraphicObjectResolver > xGraphicResolver( pGraphicResolver ); + SetGraphicResolver( xGraphicResolver ); + } + + SvXMLEmbeddedObjectHelper *pEmbeddedResolver = 0; + if( !GetEmbeddedResolver().is() ) + { + SfxObjectShell *pPersist = pDoc->GetPersist(); + if( pPersist ) + { + pEmbeddedResolver = SvXMLEmbeddedObjectHelper::Create( + *pPersist, + EMBEDDEDOBJECTHELPER_MODE_WRITE ); + Reference< XEmbeddedObjectResolver > xEmbeddedResolver( pEmbeddedResolver ); + SetEmbeddedResolver( xEmbeddedResolver ); + } + } + + // set redline mode if we export STYLES or CONTENT, unless redline + // mode is taken care of outside (through info XPropertySet) + sal_Bool bSaveRedline = + ( (getExportFlags() & (EXPORT_CONTENT|EXPORT_STYLES)) != 0 ); + if( bSaveRedline ) + { + // if the info property set has a ShowChanges property, + // then change tracking is taken care of on the outside, + // so we don't have to! + Reference<XPropertySet> rInfoSet = getExportInfo(); + if( rInfoSet.is() ) + { + OUString sShowChanges( RTL_CONSTASCII_USTRINGPARAM("ShowChanges")); + bSaveRedline = ! rInfoSet->getPropertySetInfo()->hasPropertyByName( + sShowChanges ); + } + } + sal_uInt16 nRedlineMode = 0; + bSavedShowChanges = IDocumentRedlineAccess::IsShowChanges( pDoc->GetRedlineMode() ); + if( bSaveRedline ) + { + // now save and switch redline mode + nRedlineMode = pDoc->GetRedlineMode(); + pDoc->SetRedlineMode( + (RedlineMode_t)(( nRedlineMode & nsRedlineMode_t::REDLINE_SHOW_MASK ) | nsRedlineType_t::REDLINE_INSERT )); + } + + sal_uInt32 nRet = SvXMLExport::exportDoc( eClass ); + + // now we can restore the redline mode (if we changed it previously) + if( bSaveRedline ) + { + pDoc->SetRedlineMode( (RedlineMode_t)(nRedlineMode )); + } + + + if( pGraphicResolver ) + SvXMLGraphicHelper::Destroy( pGraphicResolver ); + if( pEmbeddedResolver ) + SvXMLEmbeddedObjectHelper::Destroy( pEmbeddedResolver ); + + ASSERT( !pTableLines, "there are table columns infos left" ); + + return nRet; +} + +XMLTextParagraphExport* SwXMLExport::CreateTextParagraphExport() +{ + return new SwXMLTextParagraphExport( *this, *GetAutoStylePool().get() ); +} + +XMLShapeExport* SwXMLExport::CreateShapeExport() +{ + XMLShapeExport* pShapeExport = new XMLShapeExport( *this, XMLTextParagraphExport::CreateShapeExtPropMapper( *this ) ); + Reference < XDrawPageSupplier > xDPS( GetModel(), UNO_QUERY ); + if( xDPS.is() ) + { + Reference < XShapes > xShapes( xDPS->getDrawPage(), UNO_QUERY ); + pShapeExport->seekShapes( xShapes ); + } + + return pShapeExport; +} + +__EXPORT SwXMLExport::~SwXMLExport() +{ + _FinitItemExport(); +} + + +void SwXMLExport::_ExportFontDecls() +{ + GetFontAutoStylePool(); // make sure the pool is created + SvXMLExport::_ExportFontDecls(); +} + +#define NUM_EXPORTED_VIEW_SETTINGS 11 +void SwXMLExport::GetViewSettings(Sequence<PropertyValue>& aProps) +{ + Reference< XMultiServiceFactory > xServiceFactory = + comphelper::getProcessServiceFactory(); + ASSERT( xServiceFactory.is(), + "XMLReader::Read: got no service manager" ); + if( !xServiceFactory.is() ) + return; + + aProps.realloc( NUM_EXPORTED_VIEW_SETTINGS ); + // Currently exporting 9 properties + PropertyValue *pValue = aProps.getArray(); + sal_Int32 nIndex = 0; + + Reference < XIndexContainer > xBox (xServiceFactory->createInstance + (OUString( RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.document.IndexedPropertyValues") ) ), UNO_QUERY); + if (xBox.is() ) + { + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "Views") ); + pValue[nIndex++].Value <<= Reference < XIndexAccess > ( xBox, UNO_QUERY ); + } + + Reference < XText > xText; + SwXText *pText = 0; + + if( GetModel().is() ) + { + Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY ); + xText = xTextDoc->getText(); + Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY); + ASSERT( xTextTunnel.is(), "missing XUnoTunnel for Cursor" ); + if( xTextTunnel.is() ) + { + pText = reinterpret_cast< SwXText * >( + sal::static_int_cast< sal_IntPtr >( xTextTunnel->getSomething( SwXText::getUnoTunnelId()) )); + ASSERT( pText, "SwXText missing" ); + } + } + + if( !pText ) + { + aProps.realloc(nIndex); + return; + } + + SwDoc *pDoc = pText->GetDoc(); + const Rectangle rRect = + pDoc->GetDocShell()->GetVisArea( ASPECT_CONTENT ); + sal_Bool bTwip = pDoc->GetDocShell()->GetMapUnit ( ) == MAP_TWIP; + + ASSERT ( bTwip, "Map unit for visible area is not in TWIPS!" ); + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaTop") ); + pValue[nIndex++].Value <<= bTwip ? TWIP_TO_MM100 ( rRect.Top() ) : rRect.Top(); + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaLeft") ); + pValue[nIndex++].Value <<= bTwip ? TWIP_TO_MM100 ( rRect.Left() ) : rRect.Left(); + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaWidth") ); + pValue[nIndex++].Value <<= bTwip ? TWIP_TO_MM100 ( rRect.GetWidth() ) : rRect.GetWidth(); + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaHeight") ); + pValue[nIndex++].Value <<= bTwip ? TWIP_TO_MM100 ( rRect.GetHeight() ) : rRect.GetHeight(); + + // "show redline mode" cannot simply be read from the document + // since it gets changed during execution. If it's in the info + // XPropertySet, we take it from there. + sal_Bool bShowRedlineChanges = bSavedShowChanges; + Reference<XPropertySet> xInfoSet( getExportInfo() ); + if ( xInfoSet.is() ) + { + OUString sShowChanges( RTL_CONSTASCII_USTRINGPARAM( "ShowChanges" )); + if( xInfoSet->getPropertySetInfo()->hasPropertyByName( sShowChanges ) ) + { + bShowRedlineChanges = *(sal_Bool*) xInfoSet-> + getPropertyValue( sShowChanges ).getValue(); + } + } + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ShowRedlineChanges") ); + pValue[nIndex++].Value.setValue( &bShowRedlineChanges, ::getBooleanCppuType() ); + + sal_Bool bInBrowse = pDoc->get(IDocumentSettingAccess::BROWSE_MODE); + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "InBrowseMode") ); + pValue[nIndex++].Value.setValue( &bInBrowse, ::getBooleanCppuType() ); + + if ( nIndex < NUM_EXPORTED_VIEW_SETTINGS ) + aProps.realloc(nIndex); +} +#undef NUM_EXPORTED_VIEW_SETTINGS + +void SwXMLExport::GetConfigurationSettings( Sequence < PropertyValue >& rProps) +{ + Reference< XMultiServiceFactory > xFac( GetModel(), UNO_QUERY ); + if( xFac.is() ) + { + Reference< XPropertySet > xProps( xFac->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.Settings" ) ) ), UNO_QUERY ); + if( xProps.is() ) + SvXMLUnitConverter::convertPropertySet( rProps, xProps ); + } +} + +sal_Int32 SwXMLExport::GetDocumentSpecificSettings( ::std::list< SettingsGroup >& _out_rSettings ) +{ + // the only doc-specific settings group we know so far are the XForms settings + uno::Sequence<beans::PropertyValue> aXFormsSettings; + Reference< XFormsSupplier > xXFormsSupp( GetModel(), UNO_QUERY ); + Reference< XNameAccess > xXForms; + if ( xXFormsSupp.is() ) + xXForms = xXFormsSupp->getXForms().get(); + if ( xXForms.is() ) + { + getXFormsSettings( xXForms, aXFormsSettings ); + _out_rSettings.push_back( SettingsGroup( XML_XFORM_MODEL_SETTINGS, aXFormsSettings ) ); + } + + return aXFormsSettings.getLength() + SvXMLExport::GetDocumentSpecificSettings( _out_rSettings ); +} + +void SwXMLExport::SetBodyAttributes() +{ + Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY ); + Reference < XText > xText = xTextDoc->getText(); + // export use of soft page breaks + { + Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY); + ASSERT( xTextTunnel.is(), "missing XUnoTunnel for Cursor" ); + if( xTextTunnel.is() ) + { + SwXText *pText = reinterpret_cast< SwXText * >( + sal::static_int_cast< sal_IntPtr >( xTextTunnel->getSomething( SwXText::getUnoTunnelId() ))); + ASSERT( pText, "SwXText missing" ); + if( pText ) + { + SwDoc *pDoc = pText->GetDoc(); + if( pDoc && pDoc->GetPageCount() > 1 ) + { + sal_Bool bValue = sal_True; + rtl::OUStringBuffer sBuffer; + GetMM100UnitConverter().convertBool(sBuffer, bValue); + AddAttribute(XML_NAMESPACE_TEXT, XML_USE_SOFT_PAGE_BREAKS, + sBuffer.makeStringAndClear()); + } + } + } + } +} + + +void SwXMLExport::_ExportContent() +{ + // export forms + Reference<XDrawPageSupplier> xDrawPageSupplier(GetModel(), UNO_QUERY); + if (xDrawPageSupplier.is()) + { + // export only if we actually have elements + Reference<XDrawPage> xPage = xDrawPageSupplier->getDrawPage(); + if (xPage.is()) + { + // #103597# prevent export of form controls which are embedded in + // mute sections + Reference<XIndexAccess> xIAPage( xPage, UNO_QUERY ); + GetTextParagraphExport()->PreventExportOfControlsInMuteSections( + xIAPage, GetFormExport() ); + + // #i36597# / 2004-12-13 / fs@openoffice.org + if ( GetFormExport()->pageContainsForms( xPage ) || GetFormExport()->documentContainsXForms() ) + { + ::xmloff::OOfficeFormsExport aOfficeForms(*this); + + GetFormExport()->exportXForms(); + + GetFormExport()->seekPage(xPage); + GetFormExport()->exportForms(xPage); + } + } + } + + Reference<XPropertySet> xPropSet(GetModel(), UNO_QUERY); + if (xPropSet.is()) + { + OUString sTwoDigitYear(RTL_CONSTASCII_USTRINGPARAM("TwoDigitYear")); + + Any aAny = xPropSet->getPropertyValue( sTwoDigitYear ); + aAny <<= (sal_Int16)1930; + + sal_Int16 nYear = 0; + aAny >>= nYear; + if (nYear != 1930 ) + { + rtl::OUStringBuffer sBuffer; + GetMM100UnitConverter().convertNumber(sBuffer, nYear); + AddAttribute(XML_NAMESPACE_TABLE, XML_NULL_YEAR, sBuffer.makeStringAndClear()); + SvXMLElementExport aCalcSettings(*this, XML_NAMESPACE_TABLE, XML_CALCULATION_SETTINGS, sal_True, sal_True); + } + } + + GetTextParagraphExport()->exportTrackedChanges( sal_False ); + GetTextParagraphExport()->exportTextDeclarations(); + Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY ); + Reference < XText > xText = xTextDoc->getText(); + + GetTextParagraphExport()->exportFramesBoundToPage( bShowProgress ); + GetTextParagraphExport()->exportText( xText, bShowProgress ); +} + + + +// +// uno component registration +// helper functions for export service(s) +// + +// OOo +OUString SAL_CALL SwXMLExportOOO_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportOOO_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportOOO_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportOOO_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*)new SwXMLExport( rSMgr, EXPORT_ALL); +} + +OUString SAL_CALL SwXMLExportStylesOOO_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLStylesExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportStylesOOO_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportStylesOOO_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportStylesOOO_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*)new SwXMLExport( rSMgr, + EXPORT_STYLES | EXPORT_MASTERSTYLES | EXPORT_AUTOSTYLES | + EXPORT_FONTDECLS ); +} + +OUString SAL_CALL SwXMLExportContentOOO_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLContentExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportContentOOO_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportContentOOO_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportContentOOO_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*)new SwXMLExport(rSMgr, + EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_SCRIPTS | + EXPORT_FONTDECLS ); +} + +OUString SAL_CALL SwXMLExportMetaOOO_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLMetaExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportMetaOOO_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportMetaOOO_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportMetaOOO_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*)new SwXMLExport( rSMgr, EXPORT_META); +} + +OUString SAL_CALL SwXMLExportSettingsOOO_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLSettingsExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportSettingsOOO_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportSettingsOOO_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportSettingsOOO_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*)new SwXMLExport( rSMgr, EXPORT_SETTINGS); +} + +// OASIS +OUString SAL_CALL SwXMLExport_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExport_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExport_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExport_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*)new SwXMLExport( rSMgr, EXPORT_ALL|EXPORT_OASIS); +} + +OUString SAL_CALL SwXMLExportStyles_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisStylesExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportStyles_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportStyles_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportStyles_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + // #110680# + //return (cppu::OWeakObject*)new SwXMLExport( + // EXPORT_STYLES | EXPORT_MASTERSTYLES | EXPORT_AUTOSTYLES | + // EXPORT_FONTDECLS ); + return (cppu::OWeakObject*)new SwXMLExport( rSMgr, + EXPORT_STYLES | EXPORT_MASTERSTYLES | EXPORT_AUTOSTYLES | + EXPORT_FONTDECLS|EXPORT_OASIS ); +} + +OUString SAL_CALL SwXMLExportContent_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisContentExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportContent_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportContent_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportContent_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + // #110680# + //return (cppu::OWeakObject*)new SwXMLExport( + // EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_SCRIPTS | + // EXPORT_FONTDECLS ); + return (cppu::OWeakObject*)new SwXMLExport( + rSMgr, + EXPORT_AUTOSTYLES | EXPORT_CONTENT | EXPORT_SCRIPTS | + EXPORT_FONTDECLS|EXPORT_OASIS ); +} + +OUString SAL_CALL SwXMLExportMeta_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisMetaExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportMeta_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportMeta_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportMeta_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*)new SwXMLExport(rSMgr, EXPORT_META|EXPORT_OASIS); +} + +OUString SAL_CALL SwXMLExportSettings_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisSettingsExporter" ) ); +} + +Sequence< OUString > SAL_CALL SwXMLExportSettings_getSupportedServiceNames() + throw() +{ + const OUString aServiceName(SwXMLExportSettings_getImplementationName()); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL SwXMLExportSettings_createInstance( + const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*)new SwXMLExport(rSMgr, EXPORT_SETTINGS|EXPORT_OASIS); +} + +const Sequence< sal_Int8 > & SwXMLExport::getUnoTunnelId() throw() +{ + static Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId(); + return aSeq; +} + +sal_Int64 SAL_CALL SwXMLExport::getSomething( const Sequence< sal_Int8 >& rId ) + throw(RuntimeException) +{ + if( rId.getLength() == 16 + && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) ); + } + return SvXMLExport::getSomething( rId ); +} + + +// XServiceInfo +// override empty method from parent class +OUString SAL_CALL SwXMLExport::getImplementationName() + throw(RuntimeException) +{ + switch( getExportFlags() ) + { + case EXPORT_ALL: + return SwXMLExport_getImplementationName(); + case (EXPORT_STYLES|EXPORT_MASTERSTYLES|EXPORT_AUTOSTYLES|EXPORT_FONTDECLS): + return SwXMLExportStyles_getImplementationName(); + case (EXPORT_AUTOSTYLES|EXPORT_CONTENT|EXPORT_SCRIPTS|EXPORT_FONTDECLS): + return SwXMLExportContent_getImplementationName(); + case EXPORT_META: + return SwXMLExportMeta_getImplementationName(); + case EXPORT_SETTINGS: + return SwXMLExportSettings_getImplementationName(); + default: + // generic name for 'unknown' cases + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.SwXMLExport" ) ); + } +} + + +#ifdef XML_CORE_API +void SwXMLExport::ExportCurPaM( sal_Bool bExportWholePaM ) +{ + sal_Bool bFirstNode = sal_True; + sal_Bool bExportWholeNode = bExportWholePaM; + + SwXMLNumRuleInfo aPrevNumInfo; + SwXMLNumRuleInfo aNextNumInfo; + + while( pCurPaM->GetPoint()->nNode.GetIndex() < + pCurPaM->GetMark()->nNode.GetIndex() || + ( pCurPaM->GetPoint()->nNode.GetIndex() == + pCurPaM->GetMark()->nNode.GetIndex() && + pCurPaM->GetPoint()->nContent.GetIndex() <= + pCurPaM->GetMark()->nContent.GetIndex() ) ) + { + SwNode *pNd = pCurPaM->GetNode(); + + aNextNumInfo.Set( *pNd ); + ExportListChange( aPrevNumInfo, aNextNumInfo ); + + ASSERT( !(pNd->IsGrfNode() || pNd->IsOLENode()), + "SwXMLExport::exportCurPaM: grf or OLE node unexpected" ); + if( pNd->IsTxtNode() ) + { + SwTxtNode* pTxtNd = pNd->GetTxtNode(); + + if( !bFirstNode ) + pCurPaM->GetPoint()->nContent.Assign( pTxtNd, 0 ); + + ExportTxtNode( *pTxtNd, 0, STRING_LEN, bExportWholeNode ); + } + else if( pNd->IsTableNode() ) + { + ExportTable( *pNd->GetTableNode() ); + } + else if( pNd->IsSectionNode() ) + { + ExportSection( *pNd->GetSectionNode() ); + } + else if( pNd == &pDoc->GetNodes().GetEndOfContent() ) + break; + + pCurPaM->GetPoint()->nNode++; // next node + + sal_uInt32 nPos = pCurPaM->GetPoint()->nNode.GetIndex(); + + // if not everything should be exported, the WriteAll flag must be + // set for all but the first and last node anyway. + bExportWholeNode = bExportWholePaM || + nPos != pCurPaM->GetMark()->nNode.GetIndex(); + bFirstNode = sal_False; + + aPrevNumInfo = aNextNumInfo; + } + aNextNumInfo.Reset(); + ExportListChange( aPrevNumInfo, aNextNumInfo ); +} +#endif diff --git a/sw/source/filter/xml/xmlexp.hxx b/sw/source/filter/xml/xmlexp.hxx new file mode 100644 index 000000000000..5568995c5ca3 --- /dev/null +++ b/sw/source/filter/xml/xmlexp.hxx @@ -0,0 +1,190 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLEXP_HXX +#define _XMLEXP_HXX + +#include <xmloff/xmlexp.hxx> +#include "xmlitmap.hxx" +#include <xmloff/uniref.hxx> +#include <xmloff/xmltoken.hxx> + +class SwPaM; +class SwFmt; +class SwFrmFmt; +class SvXMLUnitConverter; +class SvXMLExportItemMapper; +class SvXMLAutoStylePoolP; +class SwTableLine; +class SwTableLines; +class SwTableBox; +class SwXMLTableColumn_Impl; +class SwXMLTableLines_Impl; +class SwXMLTableLinesCache_Impl; +class SwXMLTableColumnsSortByWidth_Impl; +class SwXMLTableFrmFmtsSort_Impl; +class SwXMLTableInfo_Impl; +class SwTableNode; +class XMLPropertySetMapper; + +class SwXMLExport : public SvXMLExport +{ + friend class SwXMLExpContext; + +#ifdef XML_CORE_API + SwPaM *pCurPaM; // the current PaM + SwPaM *pOrigPaM; // the original PaM +#endif + + SvXMLUnitConverter *pTwipUnitConv; + + SvXMLExportItemMapper *pTableItemMapper; + SwXMLTableLinesCache_Impl *pTableLines; + + SvXMLItemMapEntriesRef xTableItemMap; + SvXMLItemMapEntriesRef xTableRowItemMap; + SvXMLItemMapEntriesRef xTableCellItemMap; + UniReference < XMLPropertySetMapper > xParaPropMapper; + + sal_Bool bExportWholeDoc : 1;// export whole document? + sal_Bool bBlock : 1; // export text block? + sal_Bool bExportFirstTableOnly : 1; + sal_Bool bShowProgress : 1; + sal_Bool bSavedShowChanges : 1; + + void _InitItemExport(); + void _FinitItemExport(); + void ExportTableLinesAutoStyles( const SwTableLines& rLines, + sal_uInt32 nAbsWidth, + sal_uInt32 nBaseWidth, + const ::rtl::OUString& rNamePrefix, + SwXMLTableColumnsSortByWidth_Impl& rExpCols, + SwXMLTableFrmFmtsSort_Impl& rExpRows, + SwXMLTableFrmFmtsSort_Impl& rExpCells, + SwXMLTableInfo_Impl& rTblInfo, + sal_Bool bTop=sal_False ); + + + void ExportFmt( const SwFmt& rFmt, enum ::xmloff::token::XMLTokenEnum eClass = ::xmloff::token::XML_TOKEN_INVALID ); + void ExportTableFmt( const SwFrmFmt& rFmt, sal_uInt32 nAbsWidth ); + + void ExportTableColumnStyle( const SwXMLTableColumn_Impl& rCol ); + void ExportTableBox( const SwTableBox& rBox, sal_uInt16 nColSpan, sal_uInt16 nRowSpan, + SwXMLTableInfo_Impl& rTblInfo ); + void ExportTableLine( const SwTableLine& rLine, + const SwXMLTableLines_Impl& rLines, + SwXMLTableInfo_Impl& rTblInfo ); + void ExportTableLines( const SwTableLines& rLines, + SwXMLTableInfo_Impl& rTblInfo, + USHORT nHeaderRows = 0 ); + + virtual void _ExportMeta(); + virtual void _ExportFontDecls(); + virtual void _ExportStyles( sal_Bool bUsed ); + virtual void _ExportAutoStyles(); + virtual void _ExportMasterStyles(); + virtual void SetBodyAttributes(); + virtual void _ExportContent(); + virtual void GetViewSettings(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps); + virtual void GetConfigurationSettings(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps); + virtual sal_Int32 GetDocumentSpecificSettings( ::std::list< SettingsGroup >& _out_rSettings ); + +#ifdef XML_CORE_API + void SetCurPaM( SwPaM& rPaM, sal_Bool bWhole, sal_Bool bTabOnly ); +#endif + + // string constants for table cell export + const ::rtl::OUString sNumberFormat; + const ::rtl::OUString sIsProtected; + const ::rtl::OUString sCell; + + void setBlockMode(); + +protected: + + virtual XMLTextParagraphExport* CreateTextParagraphExport(); + virtual SvXMLAutoStylePoolP* CreateAutoStylePool(); + virtual XMLPageExport* CreatePageExport(); + virtual XMLShapeExport* CreateShapeExport(); + virtual XMLFontAutoStylePool* CreateFontAutoStylePool(); + +public: + + // #110680# + SwXMLExport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + sal_uInt16 nExportFlags = EXPORT_ALL); + +#ifdef XML_CORE_API + // #110680# + SwXMLExport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & rModel, + SwPaM& rPaM, + const ::rtl::OUString& rFileName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > & rHandler, + const ::com::sun::star::uno::Reference< ::com::sun::star::document::XGraphicObjectResolver > &, + sal_Bool bExpWholeDoc, + sal_Bool bExpFirstTableOnly, + sal_Bool bShowProgr ); +#endif + virtual ~SwXMLExport(); + + virtual sal_uInt32 exportDoc( enum ::xmloff::token::XMLTokenEnum eClass = ::xmloff::token::XML_TOKEN_INVALID ); + + inline const SvXMLUnitConverter& GetTwipUnitConverter() const; + + void ExportTableAutoStyles( const SwTableNode& rTblNd ); + void ExportTable( const SwTableNode& rTblNd ); + + SvXMLExportItemMapper& GetTableItemMapper() { return *pTableItemMapper; } + const UniReference < XMLPropertySetMapper >& GetParaPropMapper() + { + return xParaPropMapper; + } + + sal_Bool IsShowProgress() const { return bShowProgress; } + void SetShowProgress( sal_Bool b ) { bShowProgress = b; } + sal_Bool IsBlockMode() const { return bBlock; } + + // XUnoTunnel + static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId() throw(); + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo (override parent method) + ::rtl::OUString SAL_CALL getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); +}; + +inline const SvXMLUnitConverter& SwXMLExport::GetTwipUnitConverter() const +{ + return *pTwipUnitConv; +} + + +#endif // _XMLEXP_HXX + diff --git a/sw/source/filter/xml/xmlexpit.cxx b/sw/source/filter/xml/xmlexpit.cxx new file mode 100644 index 000000000000..07a4c911fc7e --- /dev/null +++ b/sw/source/filter/xml/xmlexpit.cxx @@ -0,0 +1,1048 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include "xmlexpit.hxx" + +#include <xmloff/xmluconv.hxx> +#include <rtl/ustrbuf.hxx> +#include <svl/itempool.hxx> +#include <svl/poolitem.hxx> +#include <svl/itemset.hxx> +#include <xmloff/attrlist.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <editeng/xmlcnitm.hxx> +#include <xmloff/xmlexp.hxx> +#include <editeng/memberids.hrc> + +#ifndef _SVSTDARR_USHORTS +#define _SVSTDARR_USHORTS +#include <svl/svstdarr.hxx> +#endif + + +#include "hintids.hxx" +#include "unomid.h" +#include <svx/unomid.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/shaditem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/brkitem.hxx> +#include <editeng/keepitem.hxx> +#include <editeng/brshitem.hxx> +#include "fmtpdsc.hxx" +#include "fmtornt.hxx" +#include "fmtfsize.hxx" + +#ifndef _FMTLSPLT_HXX +#include "fmtlsplt.hxx" +#endif +#include "xmlithlp.hxx" + +#include "fmtrowsplt.hxx" + + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; +using namespace ::xmloff::token; +using uno::Any; + +/** fills the given attribute list with the items in the given set */ +void SvXMLExportItemMapper::exportXML( const SvXMLExport& rExport, + SvXMLAttributeList& rAttrList, + const SfxItemSet& rSet, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap, + sal_uInt16 nFlags, + SvUShorts* pIndexArray ) const +{ + const sal_uInt16 nCount = mrMapEntries->getCount(); + sal_uInt16 nIndex = 0; + + while( nIndex < nCount ) + { + SvXMLItemMapEntry* pEntry = mrMapEntries->getByIndex( nIndex ); + + // we have a valid map entry here, so lets use it... + if( 0 == (pEntry->nMemberId & MID_SW_FLAG_NO_ITEM_EXPORT) ) + { + const SfxPoolItem* pItem = GetItem( rSet, pEntry->nWhichId, + nFlags ); + // do we have an item? + if(pItem) + { + if( 0 != (pEntry->nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT) ) + { + // element items do not add any properties, + // we export it later + if( pIndexArray ) + pIndexArray->Insert( nIndex, pIndexArray->Count() ); + + } + else + { + exportXML( rExport, rAttrList, *pItem, *pEntry, rUnitConverter, + rNamespaceMap, nFlags, &rSet ); + } + } + } + else + { + handleNoItem( rAttrList, *pEntry, rUnitConverter, rNamespaceMap, + rSet ); + } + nIndex++; + } +} + +void SvXMLExportItemMapper::exportXML( const SvXMLExport& rExport, + SvXMLAttributeList& rAttrList, + const SfxPoolItem& rItem, + const SvXMLItemMapEntry& rEntry, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap, + sal_uInt16 /*nFlags*/, + const SfxItemSet *pSet ) const +{ + if( 0 != (rEntry.nMemberId & MID_SW_FLAG_SPECIAL_ITEM_EXPORT) ) + { + if( rItem.ISA( SwFmtRowSplit ) ) + { + OUString aValue; + bool bAddAttribute = true; + if( rEntry.nNameSpace == XML_NAMESPACE_STYLE ) + { + if( (rExport.getExportFlags() & EXPORT_SAVEBACKWARDCOMPATIBLE ) == 0 || + !QueryXMLValue(rItem, aValue, + static_cast< sal_uInt16 >( rEntry.nMemberId & MID_SW_FLAG_MASK ), + rUnitConverter ) ) + { + bAddAttribute = false; + } + } + else + { + OUStringBuffer aOut; + const SfxBoolItem* pSplit = PTR_CAST(SfxBoolItem, &rItem); + DBG_ASSERT( pSplit != NULL, "Wrong Which-ID" ); + sal_uInt16 eEnum = pSplit->GetValue() ? 1 : 0; + rUnitConverter.convertEnum( aOut, eEnum, aXML_KeepTogetherType ); + aValue = aOut.makeStringAndClear(); + } + if( bAddAttribute ) + { + OUString sName( rNamespaceMap.GetQNameByKey( rEntry.nNameSpace, + GetXMLToken(rEntry.eLocalName) ) ); + rAttrList.AddAttribute( sName, aValue ); + } + } + if( rItem.ISA( SvXMLAttrContainerItem ) ) + { + SvXMLNamespaceMap *pNewNamespaceMap = 0; + const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap; + + const SvXMLAttrContainerItem *pUnknown = + PTR_CAST( SvXMLAttrContainerItem, &rItem ); + + sal_uInt16 nCount = pUnknown->GetAttrCount(); + OUStringBuffer sName; + for( sal_uInt16 i=0; i < nCount; i++ ) + { + OUString sPrefix( pUnknown->GetAttrPrefix( i ) ); + if( sPrefix.getLength() ) + { + OUString sNamespace( pUnknown->GetAttrNamespace( i ) ); + + // if the prefix isn't defined yet or has another meaning, + // we have to redefine it now. + sal_uInt16 nIdx = pNamespaceMap->GetIndexByPrefix( sPrefix ); + if( USHRT_MAX == nIdx || + pNamespaceMap->GetNameByIndex( nIdx ) != sNamespace ) + { + if( !pNewNamespaceMap ) + { + pNewNamespaceMap = + new SvXMLNamespaceMap( rNamespaceMap ); + pNamespaceMap = pNewNamespaceMap; + } + pNewNamespaceMap->Add( sPrefix, sNamespace ); + + sName.append( GetXMLToken(XML_XMLNS) ); + sName.append( sal_Unicode(':') ); + sName.append( sPrefix ); + rAttrList.AddAttribute( sName.makeStringAndClear(), + sNamespace ); + } + + sName.append( sPrefix ); + sName.append( sal_Unicode(':') ); + } + + sName.append( pUnknown->GetAttrLName( i ) ); + rAttrList.AddAttribute( sName.makeStringAndClear(), + pUnknown->GetAttrValue(i) ); + } + + delete pNewNamespaceMap; + } + else + { + handleSpecialItem( rAttrList, rEntry, rItem, rUnitConverter, + rNamespaceMap, pSet ); + } + } + else if( 0 == (rEntry.nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT) ) + { + OUString aValue; + if( QueryXMLValue(rItem, aValue, + static_cast< sal_uInt16 >( + rEntry.nMemberId & MID_SW_FLAG_MASK ), + rUnitConverter ) ) + { + OUString sName( + rNamespaceMap.GetQNameByKey( rEntry.nNameSpace, + GetXMLToken(rEntry.eLocalName))); + rAttrList.AddAttribute( sName, aValue ); + } + } +} + +void SvXMLExportItemMapper::exportElementItems( + SvXMLExport& rExport, + const SvXMLUnitConverter& rUnitConverter, + const SfxItemSet &rSet, + sal_uInt16 nFlags, + const SvUShorts& rIndexArray ) const +{ + const sal_uInt16 nCount = rIndexArray.Count(); + + sal_Bool bItemsExported = sal_False; + for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ ) + { + const sal_uInt16 nElement = rIndexArray.GetObject( nIndex ); + SvXMLItemMapEntry* pEntry = mrMapEntries->getByIndex( nElement ); + DBG_ASSERT( 0 != (pEntry->nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT), + "wrong mid flag!" ); + + const SfxPoolItem* pItem = GetItem( rSet, pEntry->nWhichId, nFlags ); + // do we have an item? + if(pItem) + { + rExport.IgnorableWhitespace(); + handleElementItem( rExport, *pEntry, *pItem, rUnitConverter, + rSet, nFlags); + bItemsExported = sal_True; + } + } + + if( bItemsExported ) + rExport.IgnorableWhitespace(); +} + +/** returns the item with the givin WhichId from the given ItemSet if its + set or its default item if its not set and the XML_EXPORT_FLAG_DEEP + is set in the flags +*/ +const SfxPoolItem* SvXMLExportItemMapper::GetItem( const SfxItemSet& rSet, + sal_uInt16 nWhichId, + sal_uInt16 nFlags ) +{ + // first get item from itemset + const SfxPoolItem* pItem; + SfxItemState eState = + rSet.GetItemState( nWhichId, + ( nFlags & XML_EXPORT_FLAG_DEEP ) != 0, + &pItem ); + + if( SFX_ITEM_SET == eState ) + { + return pItem; + } + else if( (nFlags & XML_EXPORT_FLAG_DEFAULTS) != 0 && + SFX_WHICH_MAX > nWhichId ) + { + // if its not set, try the pool if we export defaults + return &rSet.GetPool()->GetDefaultItem(nWhichId); + } + else + { + return NULL; + } +} + +SvXMLExportItemMapper::SvXMLExportItemMapper( SvXMLItemMapEntriesRef rMapEntries ) +{ + mrMapEntries = rMapEntries; +} + +SvXMLExportItemMapper::~SvXMLExportItemMapper() +{ +} + +void SvXMLExportItemMapper::exportXML( SvXMLExport& rExport, + const SfxItemSet& rSet, + const SvXMLUnitConverter& rUnitConverter, + XMLTokenEnum ePropToken, + sal_uInt16 nFlags ) const +{ + SvUShorts aIndexArray; + + exportXML( rExport, rExport.GetAttrList(), rSet, rUnitConverter, + rExport.GetNamespaceMap(), nFlags, &aIndexArray ); + + if( rExport.GetAttrList().getLength() > 0L || + (nFlags & XML_EXPORT_FLAG_EMPTY) != 0 || + aIndexArray.Count() != 0 ) + { + if( (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0 ) + { + rExport.IgnorableWhitespace(); + } + + SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, ePropToken, + sal_False, sal_False ); + exportElementItems( rExport, rUnitConverter, + rSet, nFlags, aIndexArray ); + } +} + +/** this method is called for every item that has the + MID_SW_FLAG_SPECIAL_ITEM_EXPORT flag set */ +void SvXMLExportItemMapper::handleSpecialItem( SvXMLAttributeList& /*rAttrList*/, + const SvXMLItemMapEntry& /*rEntry*/, + const SfxPoolItem& /*rItem*/, + const SvXMLUnitConverter& /*rUnitConverter*/, + const SvXMLNamespaceMap& /*rNamespaceMap*/, + const SfxItemSet* /*pSet*/ /* = NULL */ ) const +{ + DBG_ERROR( "special item not handled in xml export" ); +} + +/** this method is called for every item that has the + MID_SW_FLAG_NO_ITEM_EXPORT flag set */ +void SvXMLExportItemMapper::handleNoItem( SvXMLAttributeList& /*rAttrList*/, + const SvXMLItemMapEntry& /*rEntry*/, + const SvXMLUnitConverter& /*rUnitConverter*/, + const SvXMLNamespaceMap& /*rNamespaceMap*/, + const SfxItemSet& /*rSet*/ ) const +{ + DBG_ERROR( "no item not handled in xml export" ); +} + +/** this method is called for every item that has the + MID_SW_FLAG_ELEMENT_EXPORT flag set */ +void SvXMLExportItemMapper::handleElementItem( + SvXMLExport& /*rExport*/, + const SvXMLItemMapEntry& /*rEntry*/, + const SfxPoolItem& /*rItem*/, + const SvXMLUnitConverter& /*rUnitConverter*/, + const SfxItemSet& /*rSet*/, + sal_uInt16 /*nFlags*/ ) const +{ + DBG_ERROR( "element item not handled in xml export" ); +} + + +sal_Bool SvXMLExportItemMapper::QueryXMLValue( + const SfxPoolItem& rItem, + OUString& rValue, + sal_uInt16 nMemberId, + const SvXMLUnitConverter& rUnitConverter ) +{ + sal_Bool bOk = sal_False; + OUStringBuffer aOut; + + switch ( rItem.Which() ) + { + + case RES_LR_SPACE: + { + const SvxLRSpaceItem* pLRSpace = PTR_CAST(SvxLRSpaceItem, &rItem); + DBG_ASSERT( pLRSpace != NULL, "Wrong Which-ID!" ); + + bOk = sal_True; + switch( nMemberId ) + { + case MID_L_MARGIN: + if(pLRSpace->GetPropLeft() != 100) + rUnitConverter.convertPercent( aOut, pLRSpace->GetPropLeft() ); + else + rUnitConverter.convertMeasure( aOut, pLRSpace->GetLeft() ); + break; + + case MID_R_MARGIN: + if(pLRSpace->GetPropRight() != 100) + rUnitConverter.convertPercent( aOut, pLRSpace->GetPropRight() ); + else + rUnitConverter.convertMeasure( aOut, pLRSpace->GetRight() ); + break; + + case MID_FIRST_AUTO: + if( pLRSpace->IsAutoFirst() ) + rUnitConverter.convertBool( aOut, pLRSpace->IsAutoFirst() ); + else + bOk = sal_False; + break; + + case MID_FIRST_LINE_INDENT: + if( !pLRSpace->IsAutoFirst() ) + { + if(pLRSpace->GetPropTxtFirstLineOfst() != 100) + rUnitConverter.convertPercent( + aOut, pLRSpace->GetPropTxtFirstLineOfst() ); + else + rUnitConverter.convertMeasure( aOut, pLRSpace->GetTxtFirstLineOfst() ); + } + else + bOk = sal_False; + break; + + default: + DBG_ERROR( "unknown member id!"); + bOk = sal_False; + break; + } + } + break; + + case RES_UL_SPACE: + { + const SvxULSpaceItem* pULSpace = PTR_CAST(SvxULSpaceItem, &rItem); + DBG_ASSERT( pULSpace != NULL, "Wrong Which-ID!" ); + + switch( nMemberId ) + { + case MID_UP_MARGIN: + if( pULSpace->GetPropUpper() != 100 ) + rUnitConverter.convertPercent( aOut, pULSpace->GetPropUpper() ); + else + rUnitConverter.convertMeasure( aOut, pULSpace->GetUpper() ); + break; + + case MID_LO_MARGIN: + if( pULSpace->GetPropLower() != 100 ) + rUnitConverter.convertPercent( aOut, pULSpace->GetPropLower() ); + else + rUnitConverter.convertMeasure( aOut, pULSpace->GetLower() ); + break; + + default: + DBG_ERROR("unknown MemberId"); + }; + + bOk = sal_True; + } + break; + + case RES_SHADOW: + { + const SvxShadowItem* pShadow = PTR_CAST(SvxShadowItem, &rItem); + DBG_ASSERT( pShadow != NULL, "Wrong Which-ID" ); + + sal_Int32 nX = 1, nY = 1; + switch( pShadow->GetLocation() ) + { + case SVX_SHADOW_TOPLEFT: + nX = -1; + nY = -1; + break; + case SVX_SHADOW_TOPRIGHT: + nY = -1; + break; + case SVX_SHADOW_BOTTOMLEFT: + nX = -1; + break; + case SVX_SHADOW_BOTTOMRIGHT: + break; + case SVX_SHADOW_NONE: + default: + rValue = GetXMLToken(XML_NONE); + return sal_True; + } + + nX *= pShadow->GetWidth(); + nY *= pShadow->GetWidth(); + + rUnitConverter.convertColor( aOut, pShadow->GetColor() ); + aOut.append( sal_Unicode(' ') ); + rUnitConverter.convertMeasure( aOut, nX ); + aOut.append( sal_Unicode(' ') ); + rUnitConverter.convertMeasure( aOut, nY ); + + bOk = sal_True; + } + break; + + case RES_BOX: + { + SvxBoxItem* pBox = PTR_CAST(SvxBoxItem, &rItem); + DBG_ASSERT( pBox != NULL, "Wrong WHich-ID" ); + + /** + xml -> MemberId + + border-padding ALL_BORDER_PADDING + border-padding-before LEFT_BORDER_PADDING + border-padding-after RIGHT_BORDER_PADDING + border-padding-start TOP_BORDER_PADDING + border-padding-end BOTTOM_BORDER_PADDING + + border ALL_BORDER + border-before LEFT_BORDER + border-after RIGHT_BORDER + border-start TOP_BORDER + border-end BOTTOM_BORDER + + border-line-width ALL_BORDER_LINE_WIDTH + border-line-width-before LEFT_BORDER_LINE_WIDTH + border-line-width-after RIGHT_BORDER_LINE_WIDTH + border-line-width-start TOP_BORDER_LINE_WIDTH + border-line-width-end BOTTOM_BORDER_LINE_WIDTH + */ + + const SvxBorderLine* pLeft = pBox->GetLeft(); + const SvxBorderLine* pRight = pBox->GetRight(); + const SvxBorderLine* pTop = pBox->GetTop(); + const SvxBorderLine* pBottom = pBox->GetBottom(); + sal_uInt16 nTopDist = pBox->GetDistance( BOX_LINE_TOP ); + sal_uInt16 nBottomDist = pBox->GetDistance( BOX_LINE_BOTTOM ); + sal_uInt16 nLeftDist = pBox->GetDistance( BOX_LINE_LEFT ); + sal_uInt16 nRightDist = pBox->GetDistance( BOX_LINE_RIGHT ); + + + // check if we need to export it + switch( nMemberId ) + { + case ALL_BORDER_PADDING: + case LEFT_BORDER_PADDING: + case RIGHT_BORDER_PADDING: + case TOP_BORDER_PADDING: + case BOTTOM_BORDER_PADDING: + { + sal_Bool bEqual = nLeftDist == nRightDist && + nLeftDist == nTopDist && + nLeftDist == nBottomDist; + // don't export individual paddings if all paddings are equal and + // don't export all padding if some paddings are not equal + if( (bEqual && ALL_BORDER_PADDING != nMemberId) || + (!bEqual && ALL_BORDER_PADDING == nMemberId) ) + return sal_False; + } + break; + case ALL_BORDER: + case LEFT_BORDER: + case RIGHT_BORDER: + case TOP_BORDER: + case BOTTOM_BORDER: + { + sal_Bool bEqual = ( NULL == pTop && NULL == pBottom && + NULL == pLeft && NULL == pRight ) || + ( pTop && pBottom && pLeft && pRight && + *pTop == *pBottom && *pTop == *pLeft && + *pTop == *pRight ); + + // don't export individual borders if all are the same and + // don't export all borders if some are not equal + if( (bEqual && ALL_BORDER != nMemberId) || + (!bEqual && ALL_BORDER == nMemberId) ) + return sal_False; + } + break; + case ALL_BORDER_LINE_WIDTH: + case LEFT_BORDER_LINE_WIDTH: + case RIGHT_BORDER_LINE_WIDTH: + case TOP_BORDER_LINE_WIDTH: + case BOTTOM_BORDER_LINE_WIDTH: + { + // if no line is set, there is nothing to export + if( !pTop && !pBottom && !pLeft && !pRight ) + return sal_False; + + sal_Bool bEqual = NULL != pTop && + NULL != pBottom && + NULL != pLeft && + NULL != pRight; + + if( bEqual ) + { + const sal_uInt16 nDistance = pTop->GetDistance(); + const sal_uInt16 nInWidth = pTop->GetInWidth(); + const sal_uInt16 nOutWidth = pTop->GetOutWidth(); + + bEqual = nDistance == pLeft->GetDistance() && + nInWidth == pLeft->GetInWidth() && + nOutWidth == pLeft->GetOutWidth() && + nDistance == pRight->GetDistance() && + nInWidth == pRight->GetInWidth() && + nOutWidth == pRight->GetOutWidth() && + nDistance == pBottom->GetDistance() && + nInWidth == pBottom->GetInWidth() && + nOutWidth == pBottom->GetOutWidth(); + } + + switch( nMemberId ) + { + case ALL_BORDER_LINE_WIDTH: + if( !bEqual || pTop->GetDistance() == 0 ) + return sal_False; + break; + case LEFT_BORDER_LINE_WIDTH: + if( bEqual || NULL == pLeft || + 0 == pLeft->GetDistance() ) + return sal_False; + break; + case RIGHT_BORDER_LINE_WIDTH: + if( bEqual || NULL == pRight || + 0 == pRight->GetDistance() ) + return sal_False; + break; + case TOP_BORDER_LINE_WIDTH: + if( bEqual || NULL == pTop || + 0 == pTop->GetDistance() ) + return sal_False; + break; + case BOTTOM_BORDER_LINE_WIDTH: + if( bEqual || NULL == pBottom || + 0 == pBottom->GetDistance() ) + return sal_False; + break; + } + } + break; + } + + // now export it export + switch( nMemberId ) + { + // padding + case ALL_BORDER_PADDING: + case LEFT_BORDER_PADDING: + rUnitConverter.convertMeasure( aOut, nLeftDist ); + break; + case RIGHT_BORDER_PADDING: + rUnitConverter.convertMeasure( aOut, nRightDist ); + break; + case TOP_BORDER_PADDING: + rUnitConverter.convertMeasure( aOut, nTopDist ); + break; + case BOTTOM_BORDER_PADDING: + rUnitConverter.convertMeasure( aOut, nBottomDist ); + break; + + // border + case ALL_BORDER: + case LEFT_BORDER: + case RIGHT_BORDER: + case TOP_BORDER: + case BOTTOM_BORDER: + { + const SvxBorderLine* pLine; + switch( nMemberId ) + { + case ALL_BORDER: + case LEFT_BORDER: + pLine = pLeft; + break; + case RIGHT_BORDER: + pLine = pRight; + break; + case TOP_BORDER: + pLine = pTop; + break; + case BOTTOM_BORDER: + pLine = pBottom; + break; + default: + pLine = NULL; + break; + } + + if( NULL != pLine ) + { + sal_Int32 nWidth = pLine->GetOutWidth(); + const sal_uInt16 nDistance = pLine->GetDistance(); + if( 0 != nDistance ) + { + nWidth += nDistance; + nWidth += pLine->GetInWidth(); + } + + enum XMLTokenEnum eStyle = + (0 == nDistance) ? XML_SOLID : XML_DOUBLE; + + rUnitConverter.convertMeasure( aOut, nWidth ); + aOut.append( sal_Unicode( ' ' ) ); + aOut.append( GetXMLToken( eStyle ) ); + aOut.append( sal_Unicode( ' ' ) ); + rUnitConverter.convertColor( aOut, pLine->GetColor() ); + + } + else + { + aOut.append( GetXMLToken(XML_NONE) ); + } + } + break; + + // width + case ALL_BORDER_LINE_WIDTH: + case LEFT_BORDER_LINE_WIDTH: + case RIGHT_BORDER_LINE_WIDTH: + case TOP_BORDER_LINE_WIDTH: + case BOTTOM_BORDER_LINE_WIDTH: + const SvxBorderLine* pLine; + switch( nMemberId ) + { + case ALL_BORDER_LINE_WIDTH: + case LEFT_BORDER_LINE_WIDTH: + pLine = pLeft; + break; + case RIGHT_BORDER_LINE_WIDTH: + pLine = pRight; + break; + case TOP_BORDER_LINE_WIDTH: + pLine = pTop; + break; + case BOTTOM_BORDER_LINE_WIDTH: + pLine = pBottom; + break; + default: + return sal_False; + } + rUnitConverter.convertMeasure( aOut, pLine->GetInWidth() ); + aOut.append( sal_Unicode( ' ' ) ); + rUnitConverter.convertMeasure( aOut, pLine->GetDistance() ); + aOut.append( sal_Unicode( ' ' ) ); + rUnitConverter.convertMeasure( aOut, pLine->GetOutWidth() ); + break; + } + + bOk = sal_True; + } + break; + + case RES_BREAK: + { + const SvxFmtBreakItem* pFmtBreak = PTR_CAST(SvxFmtBreakItem, &rItem); + DBG_ASSERT( pFmtBreak != NULL, "Wrong Which-ID" ); + + sal_uInt16 eEnum = 0; + + switch( nMemberId ) + { + case MID_BREAK_BEFORE: + switch( pFmtBreak->GetValue() ) + { + case SVX_BREAK_COLUMN_BEFORE: + eEnum = 1; + break; + case SVX_BREAK_PAGE_BEFORE: + eEnum = 2; + break; + case SVX_BREAK_NONE: + eEnum = 0; + break; + default: + return sal_False; + } + break; + case MID_BREAK_AFTER: + switch( pFmtBreak->GetValue() ) + { + case SVX_BREAK_COLUMN_AFTER: + eEnum = 1; + break; + case SVX_BREAK_PAGE_AFTER: + eEnum = 2; + break; + case SVX_BREAK_NONE: + eEnum = 0; + break; + default: + return sal_False; + } + break; + } + + bOk = rUnitConverter.convertEnum( aOut, eEnum, psXML_BreakType ); + } + break; + + case RES_KEEP: + { + SvxFmtKeepItem* pFmtKeep = PTR_CAST(SvxFmtKeepItem, &rItem); + DBG_ASSERT( pFmtKeep != NULL, "Wrong Which-ID" ); + + aOut.append( pFmtKeep->GetValue() + ? GetXMLToken( XML_ALWAYS ) + : GetXMLToken( XML_AUTO ) ); + bOk = sal_True; + } + break; + + case RES_BACKGROUND: + { + SvxBrushItem* pBrush = PTR_CAST(SvxBrushItem, &rItem); + DBG_ASSERT( pBrush != NULL, "Wrong Which-ID" ); + + // note: the graphic is only exported if nMemberId equals + // MID_GRAPHIC.. + // If not, only the color or transparency is exported + + switch( nMemberId ) + { + case MID_BACK_COLOR: + if ( pBrush->GetColor().GetTransparency() ) + aOut.append( GetXMLToken(XML_TRANSPARENT) ); + else + rUnitConverter.convertColor( aOut, pBrush->GetColor()); + bOk = sal_True; + break; + + case MID_GRAPHIC_LINK: + if( pBrush->GetGraphicPos() != GPOS_NONE ) + { + uno::Any aAny; + pBrush->QueryValue( aAny, MID_GRAPHIC_URL ); + OUString sTmp; + aAny >>= sTmp; + aOut.append( sTmp ); + bOk = sal_True; + } + break; + + case MID_GRAPHIC_POSITION: + switch( pBrush->GetGraphicPos() ) + { + case GPOS_LT: + case GPOS_MT: + case GPOS_RT: + aOut.append( GetXMLToken(XML_TOP) ); + bOk = sal_True; + break; + case GPOS_LM: + case GPOS_MM: + case GPOS_RM: + aOut.append( GetXMLToken(XML_CENTER) ); + bOk = sal_True; + break; + case GPOS_LB: + case GPOS_MB: + case GPOS_RB: + aOut.append( GetXMLToken(XML_BOTTOM) ); + bOk = sal_True; + break; + default: + ; + } + + if( bOk ) + { + aOut.append( sal_Unicode( ' ' ) ); + + switch( pBrush->GetGraphicPos() ) + { + case GPOS_LT: + case GPOS_LB: + case GPOS_LM: + aOut.append( GetXMLToken(XML_LEFT) ); + break; + case GPOS_MT: + case GPOS_MM: + case GPOS_MB: + aOut.append( GetXMLToken(XML_CENTER) ); + break; + case GPOS_RM: + case GPOS_RT: + case GPOS_RB: + aOut.append( GetXMLToken(XML_RIGHT) ); + break; + default: + ; + } + } + break; + + case MID_GRAPHIC_REPEAT: + { + SvxGraphicPosition eGraphicPos = pBrush->GetGraphicPos(); + if( GPOS_AREA == eGraphicPos ) + { + aOut.append( GetXMLToken(XML_BACKGROUND_STRETCH) ); + bOk = sal_True; + } + else if( GPOS_NONE != eGraphicPos && GPOS_TILED != eGraphicPos ) + { + aOut.append( GetXMLToken(XML_BACKGROUND_NO_REPEAT) ); + bOk = sal_True; + } + } + break; + + case MID_GRAPHIC_FILTER: + if( pBrush->GetGraphicPos() != GPOS_NONE && + pBrush->GetGraphicFilter() ) + { + aOut.append( pBrush->GetGraphicFilter()->GetBuffer() ); + bOk = sal_True; + } + break; + } + } + break; + + case RES_PAGEDESC: + { + const SwFmtPageDesc* pPageDesc = PTR_CAST(SwFmtPageDesc, &rItem); + DBG_ASSERT( pPageDesc != NULL, "Wrong Which-ID" ); + + if( MID_PAGEDESC_PAGENUMOFFSET==nMemberId ) + { + sal_Int32 const number(pPageDesc->GetNumOffset()); + if (0 >= number) + { + aOut.append(GetXMLToken(XML_AUTO)); + } + else // #i114163# positiveInteger only! + { + rUnitConverter.convertNumber(aOut, number); + } + bOk = sal_True; + } + } + break; + + case RES_LAYOUT_SPLIT: + case RES_ROW_SPLIT: + { + const SfxBoolItem* pSplit = PTR_CAST(SfxBoolItem, &rItem); + DBG_ASSERT( pSplit != NULL, "Wrong Which-ID" ); + + rUnitConverter.convertBool( aOut, pSplit->GetValue() ); + bOk = sal_True; + } + break; + + case RES_HORI_ORIENT: + { + SwFmtHoriOrient* pHoriOrient = PTR_CAST(SwFmtHoriOrient, &rItem); + DBG_ASSERT( pHoriOrient != NULL, "Wrong Which-ID" ); + + rUnitConverter.convertEnum( aOut, pHoriOrient->GetHoriOrient(), + aXMLTableAlignMap ); + bOk = sal_True; + } + break; + + case RES_VERT_ORIENT: + { + SwFmtVertOrient* pVertOrient = PTR_CAST(SwFmtVertOrient, &rItem); + DBG_ASSERT( pVertOrient != NULL, "Wrong Which-ID" ); + + rUnitConverter.convertEnum( aOut, pVertOrient->GetVertOrient(), + aXMLTableVAlignMap ); + bOk = sal_True; + } + break; + + case RES_FRM_SIZE: + { + SwFmtFrmSize* pFrmSize = PTR_CAST(SwFmtFrmSize, &rItem); + DBG_ASSERT( pFrmSize != NULL, "Wrong Which-ID" ); + + sal_Bool bOutHeight = sal_False; + switch( nMemberId ) + { + case MID_FRMSIZE_REL_WIDTH: + if( pFrmSize->GetWidthPercent() ) + { + rUnitConverter.convertPercent( aOut, pFrmSize->GetWidthPercent() ); + bOk = sal_True; + } + break; + case MID_FRMSIZE_MIN_HEIGHT: + if( ATT_MIN_SIZE == pFrmSize->GetHeightSizeType() ) + bOutHeight = sal_True; + break; + case MID_FRMSIZE_FIX_HEIGHT: + if( ATT_FIX_SIZE == pFrmSize->GetHeightSizeType() ) + bOutHeight = sal_True; + break; + } + + if( bOutHeight ) + { + rUnitConverter.convertMeasure( aOut, pFrmSize->GetHeight() ); + bOk = sal_True; + } + } + break; + + case RES_FRAMEDIR: + { + Any aAny; + bOk = rItem.QueryValue( aAny ); + if( bOk ) + { + const XMLPropertyHandler* pWritingModeHandler = + XMLPropertyHandlerFactory::CreatePropertyHandler( + XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT ); + OUString sValue; + bOk = pWritingModeHandler->exportXML( sValue, aAny, + rUnitConverter ); + if( bOk ) + aOut.append( sValue ); + } + } + break; + + case RES_COLLAPSING_BORDERS: + { + const SfxBoolItem* pBorders = PTR_CAST(SfxBoolItem, &rItem); + DBG_ASSERT( pBorders != NULL, "Wrong RES-ID" ); + + aOut.append( pBorders->GetValue() + ? GetXMLToken( XML_COLLAPSING ) + : GetXMLToken( XML_SEPARATING ) ); + bOk = sal_True; + } + break; + + default: + DBG_ERROR("GetXMLValue not implemented for this item."); + break; + } + + if ( bOk ) + rValue = aOut.makeStringAndClear(); + + return bOk; +} diff --git a/sw/source/filter/xml/xmlexpit.hxx b/sw/source/filter/xml/xmlexpit.hxx new file mode 100644 index 000000000000..306e5bb31df5 --- /dev/null +++ b/sw/source/filter/xml/xmlexpit.hxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLITMPR_HXX +#define _XMLITMPR_HXX + +#include <tools/solar.h> +#include <tools/ref.hxx> +#include "xmlitmap.hxx" + +#define XML_EXPORT_FLAG_DEFAULTS 0x0001 // export also default items +#define XML_EXPORT_FLAG_DEEP 0x0002 // export also items from + // parent item sets +#define XML_EXPORT_FLAG_EMPTY 0x0004 // export attribs element + // even if its empty +#define XML_EXPORT_FLAG_IGN_WS 0x0008 + +namespace rtl { class OUString; } +class SvXMLUnitConverter; +class SfxPoolItem; +class SfxItemSet; +class SvXMLAttributeList; +class SvXMLNamespaceMap; +class SvUShorts; +class SvXMLExport; + + +class SvXMLExportItemMapper +{ +protected: + SvXMLItemMapEntriesRef mrMapEntries; + + /** fills the given attribute list with the items in the given set */ + void exportXML( const SvXMLExport& rExport, + SvXMLAttributeList& rAttrList, + const SfxItemSet& rSet, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap, + sal_uInt16 nFlags, + SvUShorts* pIndexArray ) const; + + void exportXML( const SvXMLExport& rExport, + SvXMLAttributeList& rAttrList, + const SfxPoolItem& rItem, + const SvXMLItemMapEntry &rEntry, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap, + sal_uInt16 nFlags, + const SfxItemSet *pSet ) const; + + + void exportElementItems( SvXMLExport& rExport, + const SvXMLUnitConverter& rUnitConverter, + const SfxItemSet &rSet, + sal_uInt16 nFlags, + const SvUShorts& rIndexArray ) const; + + static const SfxPoolItem* GetItem( const SfxItemSet &rSet, + sal_uInt16 nWhichId, + sal_uInt16 nFlags ); + +public: + SvXMLExportItemMapper( SvXMLItemMapEntriesRef rMapEntries ); + virtual ~SvXMLExportItemMapper(); + + void exportXML( SvXMLExport& rExport, + const SfxItemSet& rSet, + const SvXMLUnitConverter& rUnitConverter, + ::xmloff::token::XMLTokenEnum ePropToken, + sal_uInt16 nFlags = 0 ) const; + + /** this method is called for every item that has the + MID_SW_FLAG_SPECIAL_ITEM_EXPORT flag set */ + virtual void handleSpecialItem( SvXMLAttributeList& rAttrList, + const SvXMLItemMapEntry& rEntry, + const SfxPoolItem& rItem, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap, + const SfxItemSet *pSet = NULL ) const; + + + /** this method is called for every item that has the + MID_SW_FLAG_NO_ITEM_EXPORT flag set */ + virtual void handleNoItem( SvXMLAttributeList& rAttrList, + const SvXMLItemMapEntry& rEntry, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap, + const SfxItemSet& rSet ) const; + + /** this method is called for every item that has the + MID_SW_FLAG_ELEMENT_EXPORT flag set */ + virtual void handleElementItem( SvXMLExport& rExport, + const SvXMLItemMapEntry& rEntry, + const SfxPoolItem& rItem, + const SvXMLUnitConverter& rUnitConverter, + const SfxItemSet& rSet, + sal_uInt16 nFlags ) const; + + inline void setMapEntries( SvXMLItemMapEntriesRef rMapEntries ); + + static sal_Bool QueryXMLValue( const SfxPoolItem& rItem, + ::rtl::OUString& rValue, sal_uInt16 nMemberId, + const SvXMLUnitConverter& rUnitConverter ); +}; + +inline void +SvXMLExportItemMapper::setMapEntries( SvXMLItemMapEntriesRef rMapEntries ) +{ + mrMapEntries = rMapEntries; +} + +#endif // _XMLITMPR_HXX diff --git a/sw/source/filter/xml/xmlfmt.cxx b/sw/source/filter/xml/xmlfmt.cxx new file mode 100644 index 000000000000..050f498c10c5 --- /dev/null +++ b/sw/source/filter/xml/xmlfmt.cxx @@ -0,0 +1,1134 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <rtl/ustrbuf.hxx> +#include <tools/urlobj.hxx> + +#ifndef _SVSTDARR_STRINGSSORT_DECL +#define _SVSTDARR_STRINGSSORT +#include <svl/svstdarr.hxx> +#endif +#include <xmloff/nmspmap.hxx> +#include <format.hxx> +#include <fmtcol.hxx> +#include <hints.hxx> +#include <poolfmt.hxx> +#include <charfmt.hxx> +#include <paratr.hxx> +#include <doc.hxx> +#include "docary.hxx" +#include "unostyle.hxx" +#include "fmtpdsc.hxx" +#include "pagedesc.hxx" +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/i18nmap.hxx> +#include <xmloff/xmltkmap.hxx> +#include "xmlitem.hxx" +#include <xmloff/xmlstyle.hxx> +#include <xmloff/txtstyli.hxx> +#include <xmloff/txtimp.hxx> +#include <xmloff/families.hxx> +#include <xmloff/XMLTextMasterStylesContext.hxx> +#include <xmloff/XMLTextShapeStyleContext.hxx> +#include <xmloff/XMLGraphicsDefaultStyle.hxx> +#include "xmlimp.hxx" +#include "xmltbli.hxx" +#include "cellatr.hxx" +#include <SwStyleNameMapper.hxx> +#include <xmloff/attrlist.hxx> +#include <unotxdoc.hxx> +#include <docsh.hxx> + + +using namespace ::com::sun::star; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::xmloff::token; + +class SwXMLConditionParser_Impl +{ + OUString sInput; + + sal_uInt32 nCondition; + sal_uInt32 nSubCondition; + + sal_Int32 nPos; + sal_Int32 nLength; + + inline sal_Bool SkipWS(); + inline sal_Bool MatchChar( sal_Unicode c ); + inline sal_Bool MatchName( OUString& rName ); + inline sal_Bool MatchNumber( sal_uInt32& rNumber ); + +public: + + SwXMLConditionParser_Impl( const OUString& rInp ); + + sal_Bool IsValid() const { return 0 != nCondition; } + + sal_uInt32 GetCondition() const { return nCondition; } + sal_uInt32 GetSubCondition() const { return nSubCondition; } +}; + +inline sal_Bool SwXMLConditionParser_Impl::SkipWS() +{ + while( nPos < nLength && ' ' == sInput[nPos] ) + nPos++; + return sal_True; +} + +inline sal_Bool SwXMLConditionParser_Impl::MatchChar( sal_Unicode c ) +{ + sal_Bool bRet = sal_False; + if( nPos < nLength && c == sInput[nPos] ) + { + nPos++; + bRet = sal_True; + } + return bRet; +} + +inline sal_Bool SwXMLConditionParser_Impl::MatchName( OUString& rName ) +{ + OUStringBuffer sBuffer( nLength ); + while( nPos < nLength && + ( ('a' <= sInput[nPos] && sInput[nPos] <= 'z') || + '-' == sInput[nPos] ) ) + { + sBuffer.append( sInput[nPos] ); + nPos++; + } + rName = sBuffer.makeStringAndClear(); + return rName.getLength() > 0; +} + +inline sal_Bool SwXMLConditionParser_Impl::MatchNumber( sal_uInt32& rNumber ) +{ + OUStringBuffer sBuffer( nLength ); + while( nPos < nLength && '0' <= sInput[nPos] && sInput[nPos] <= '9' ) + { + sBuffer.append( sInput[nPos] ); + nPos++; + } + + OUString sNum( sBuffer.makeStringAndClear() ); + if( sNum.getLength() ) + rNumber = sNum.toInt32(); + return sNum.getLength() > 0; +} + +SwXMLConditionParser_Impl::SwXMLConditionParser_Impl( const OUString& rInp ) : + sInput( rInp ), + nCondition( 0 ), + nSubCondition( 0 ), + nPos( 0 ), + nLength( rInp.getLength() ) +{ + OUString sFunc; + sal_Bool bHasSub = sal_False; + sal_uInt32 nSub = 0; + sal_Bool bOK = SkipWS() && MatchName( sFunc ) && SkipWS() && + MatchChar( '(' ) && SkipWS() && MatchChar( ')' ) && SkipWS(); + if( bOK && MatchChar( '=' ) ) + { + bOK = SkipWS() && MatchNumber( nSub ) && SkipWS(); + bHasSub = sal_True; + } + + bOK &= nPos == nLength; + + if( bOK ) + { + if( IsXMLToken( sFunc, XML_ENDNOTE ) && !bHasSub ) + nCondition = PARA_IN_ENDNOTE; + else if( IsXMLToken( sFunc, XML_FOOTER ) && !bHasSub ) + nCondition = PARA_IN_FOOTER; + else if( IsXMLToken( sFunc, XML_FOOTNOTE ) && !bHasSub ) + nCondition = PARA_IN_FOOTENOTE; + else if( IsXMLToken( sFunc, XML_HEADER ) && !bHasSub ) + nCondition = PARA_IN_HEADER; + else if( IsXMLToken( sFunc, XML_LIST_LEVEL) && + nSub >=1 && nSub <= MAXLEVEL ) + { + nCondition = PARA_IN_LIST; + nSubCondition = nSub-1; + } + else if( IsXMLToken( sFunc, XML_OUTLINE_LEVEL) && + nSub >=1 && nSub <= MAXLEVEL ) + { + nCondition = PARA_IN_OUTLINE; + nSubCondition = nSub-1; + } + else if( IsXMLToken( sFunc, XML_SECTION ) && !bHasSub ) + { + nCondition = PARA_IN_SECTION; + } + else if( IsXMLToken( sFunc, XML_TABLE ) && !bHasSub ) + { + nCondition = PARA_IN_TABLEBODY; + } + else if( IsXMLToken( sFunc, XML_TABLE_HEADER ) && !bHasSub ) + { + nCondition = PARA_IN_TABLEHEAD; + } + else if( IsXMLToken( sFunc, XML_TEXT_BOX ) && !bHasSub ) + { + nCondition = PARA_IN_FRAME; + } + } +} + +// --------------------------------------------------------------------- + +class SwXMLConditionContext_Impl : public SvXMLImportContext +{ + sal_uInt32 nCondition; + sal_uInt32 nSubCondition; + + OUString sApplyStyle; + + void ParseCondition( const OUString& rCond ); + +public: + + SwXMLConditionContext_Impl( + SvXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ); + virtual ~SwXMLConditionContext_Impl(); + + TYPEINFO(); + + sal_Bool IsValid() const { return 0 != nCondition; } + + sal_uInt32 GetCondition() const { return nCondition; } + sal_uInt32 GetSubCondition() const { return nSubCondition; } + const OUString& GetApplyStyle() const { return sApplyStyle; } +}; + +SwXMLConditionContext_Impl::SwXMLConditionContext_Impl( + SvXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + nCondition( 0 ), + nSubCondition( 0 ) +{ + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + OUString aLocalName; + sal_uInt16 nPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + const OUString& rValue = xAttrList->getValueByIndex( i ); + + // TODO: use a map here + if( XML_NAMESPACE_STYLE == nPrefix ) + { + if( IsXMLToken( aLocalName, XML_CONDITION ) ) + { + SwXMLConditionParser_Impl aCondParser( rValue ); + if( aCondParser.IsValid() ) + { + nCondition = aCondParser.GetCondition(); + nSubCondition = aCondParser.GetSubCondition(); + } + } + else if( IsXMLToken( aLocalName, XML_APPLY_STYLE_NAME ) ) + { + sApplyStyle = rValue; + } + } + } +} + +SwXMLConditionContext_Impl::~SwXMLConditionContext_Impl() +{ +} + +TYPEINIT1( SwXMLConditionContext_Impl, XMLTextStyleContext ); + +// --------------------------------------------------------------------- + +typedef SwXMLConditionContext_Impl *SwXMLConditionContextPtr; +SV_DECL_PTRARR( SwXMLConditions_Impl, SwXMLConditionContextPtr, 5, 2 ) + +class SwXMLTextStyleContext_Impl : public XMLTextStyleContext +{ + SwXMLConditions_Impl *pConditions; + +protected: + + virtual uno::Reference < style::XStyle > Create(); + +public: + + TYPEINFO(); + + SwXMLTextStyleContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList, + sal_uInt16 nFamily, + SvXMLStylesContext& rStyles ); + virtual ~SwXMLTextStyleContext_Impl(); + + virtual SvXMLImportContext *CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ); + + virtual void Finish( sal_Bool bOverwrite ); +}; + +TYPEINIT1( SwXMLTextStyleContext_Impl, XMLTextStyleContext ); + +uno::Reference < style::XStyle > SwXMLTextStyleContext_Impl::Create() +{ + uno::Reference < style::XStyle > xNewStyle; + + if( pConditions && XML_STYLE_FAMILY_TEXT_PARAGRAPH == GetFamily() ) + { + uno::Reference< lang::XMultiServiceFactory > xFactory( GetImport().GetModel(), + uno::UNO_QUERY ); + if( xFactory.is() ) + { + OUString sServiceName( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.style.ConditionalParagraphStyle" ) ); + uno::Reference < uno::XInterface > xIfc = + xFactory->createInstance( sServiceName ); + if( xIfc.is() ) + xNewStyle = uno::Reference < style::XStyle >( xIfc, uno::UNO_QUERY ); + } + } + else + { + xNewStyle = XMLTextStyleContext::Create(); + } + + return xNewStyle; +} + +SwXMLTextStyleContext_Impl::SwXMLTextStyleContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList, + sal_uInt16 nFamily, + SvXMLStylesContext& rStyles ) : + XMLTextStyleContext( rImport, nPrfx, rLName, xAttrList, rStyles, nFamily ), + pConditions( 0 ) +{ +} + +SwXMLTextStyleContext_Impl::~SwXMLTextStyleContext_Impl() +{ + if( pConditions ) + { + while( pConditions->Count() ) + { + SwXMLConditionContext_Impl *pCond = pConditions->GetObject(0); + pConditions->Remove( 0UL ); + pCond->ReleaseRef(); + } + delete pConditions; + } +} + +SvXMLImportContext *SwXMLTextStyleContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + if( XML_NAMESPACE_STYLE == nPrefix && IsXMLToken( rLocalName, XML_MAP ) ) + { + SwXMLConditionContext_Impl *pCond = + new SwXMLConditionContext_Impl( GetImport(), nPrefix, + rLocalName, xAttrList ); + if( pCond->IsValid() ) + { + if( !pConditions ) + pConditions = new SwXMLConditions_Impl; + pConditions->Insert( pCond, pConditions->Count() ); + pCond->AddRef(); + } + pContext = pCond; + } + + if( !pContext ) + pContext = XMLTextStyleContext::CreateChildContext( nPrefix, rLocalName, + xAttrList ); + + return pContext; +} + +void SwXMLTextStyleContext_Impl::Finish( sal_Bool bOverwrite ) +{ + XMLTextStyleContext::Finish( bOverwrite ); + + if( !pConditions || XML_STYLE_FAMILY_TEXT_PARAGRAPH != GetFamily() ) + return; + + uno::Reference < style::XStyle > xStyle = GetStyle(); + if( !xStyle.is() ) + return; + + const SwXStyle* pStyle = 0; + uno::Reference<lang::XUnoTunnel> xStyleTunnel( xStyle, uno::UNO_QUERY); + if( xStyleTunnel.is() ) + { + pStyle = reinterpret_cast< SwXStyle * >( + sal::static_int_cast< sal_IntPtr >( xStyleTunnel->getSomething( SwXStyle::getUnoTunnelId() ))); + } + if( !pStyle ) + return; + + const SwDoc *pDoc = pStyle->GetDoc(); + + SwTxtFmtColl *pColl = pDoc->FindTxtFmtCollByName( pStyle->GetStyleName() ); + ASSERT( pColl, "Text collection not found" ); + if( !pColl || RES_CONDTXTFMTCOLL != pColl->Which() ) + return; + + sal_uInt16 nCount = pConditions->Count(); + String aString; + OUString sName; + for( sal_uInt16 i = 0; i < nCount; i++ ) + { + const SwXMLConditionContext_Impl *pCond = (*pConditions)[i]; + OUString aDisplayName( + GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_PARAGRAPH, + pCond->GetApplyStyle() ) ); + SwStyleNameMapper::FillUIName( aDisplayName, + aString, + nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, + sal_True); + sName = aString; + SwTxtFmtColl* pCondColl = pDoc->FindTxtFmtCollByName( sName ); + ASSERT( pCondColl, + "SwXMLItemSetStyleContext_Impl::ConnectConditions: cond coll missing" ); + if( pCondColl ) + { + SwCollCondition aCond( pCondColl, pCond->GetCondition(), + pCond->GetSubCondition() ); + ((SwConditionTxtFmtColl*)pColl)->InsertCondition( aCond ); + } + } +} + +// --------------------------------------------------------------------- + +class SwXMLItemSetStyleContext_Impl : public SvXMLStyleContext +{ + OUString sMasterPageName; + SfxItemSet *pItemSet; + SwXMLTextStyleContext_Impl *pTextStyle; + SvXMLStylesContext &rStyles; + + OUString sDataStyleName; + + sal_Bool bHasMasterPageName : 1; + sal_Bool bPageDescConnected : 1; + sal_Bool bDataStyleIsResolved; + + SvXMLImportContext *CreateItemSetContext( + sal_uInt16 nPrefix, + const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList); + +protected: + + virtual void SetAttribute( sal_uInt16 nPrefixKey, + const OUString& rLocalName, + const OUString& rValue ); + + const SwXMLImport& GetSwImport() const + { return (const SwXMLImport&)GetImport(); } + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } + +public: + + TYPEINFO(); + + SwXMLItemSetStyleContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList, + SvXMLStylesContext& rStylesC, + sal_uInt16 nFamily); + virtual ~SwXMLItemSetStyleContext_Impl(); + + virtual void CreateAndInsert( sal_Bool bOverwrite ); + virtual SvXMLImportContext *CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ); + + // The item set may be empty! + SfxItemSet *GetItemSet() { return pItemSet; } + const SfxItemSet *GetItemSet() const { return pItemSet; } + + const OUString& GetMasterPageName() const { return sMasterPageName; } + sal_Bool HasMasterPageName() const { return bHasMasterPageName; } + + sal_Bool IsPageDescConnected() const { return bPageDescConnected; } + void ConnectPageDesc(); + + sal_Bool ResolveDataStyleName(); +}; + +void SwXMLItemSetStyleContext_Impl::SetAttribute( sal_uInt16 nPrefixKey, + const OUString& rLocalName, + const OUString& rValue ) +{ + if( XML_NAMESPACE_STYLE == nPrefixKey ) + { + if ( IsXMLToken( rLocalName, XML_MASTER_PAGE_NAME ) ) + { + sMasterPageName = rValue; + bHasMasterPageName = sal_True; + } + else if ( IsXMLToken( rLocalName, XML_DATA_STYLE_NAME ) ) + { + // if we have a valid data style name + if (rValue.getLength() > 0) + { + sDataStyleName = rValue; + bDataStyleIsResolved = sal_False; // needs to be resolved + } + } + else + { + SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); + } + } + else + { + SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); + } +} + +SvXMLImportContext *SwXMLItemSetStyleContext_Impl::CreateItemSetContext( + sal_uInt16 nPrefix, const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) +{ + ASSERT( !pItemSet, + "SwXMLItemSetStyleContext_Impl::CreateItemSetContext: item set exists" ); + + SvXMLImportContext *pContext = 0; + + SwDoc* pDoc = SwImport::GetDocFromXMLImport( GetSwImport() ); + + SfxItemPool& rItemPool = pDoc->GetAttrPool(); + switch( GetFamily() ) + { + case XML_STYLE_FAMILY_TABLE_TABLE: + pItemSet = new SfxItemSet( rItemPool, aTableSetRange ); + break; + case XML_STYLE_FAMILY_TABLE_COLUMN: + pItemSet = new SfxItemSet( rItemPool, RES_FRM_SIZE, RES_FRM_SIZE, 0 ); + break; + case XML_STYLE_FAMILY_TABLE_ROW: + pItemSet = new SfxItemSet( rItemPool, aTableLineSetRange ); + break; + case XML_STYLE_FAMILY_TABLE_CELL: + pItemSet = new SfxItemSet( rItemPool, aTableBoxSetRange ); + break; + default: + ASSERT( !this, + "SwXMLItemSetStyleContext_Impl::CreateItemSetContext: unknown family" ); + break; + } + if( pItemSet ) + pContext = GetSwImport().CreateTableItemImportContext( + nPrefix, rLName, xAttrList, GetFamily(), + *pItemSet ); + if( !pContext ) + { + delete pItemSet; + pItemSet = 0; + } + + return pContext; +} + +TYPEINIT1( SwXMLItemSetStyleContext_Impl, SvXMLStyleContext ); + +SwXMLItemSetStyleContext_Impl::SwXMLItemSetStyleContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList, + SvXMLStylesContext& rStylesC, + sal_uInt16 nFamily ) : + SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, nFamily ), + pItemSet( 0 ), + pTextStyle( 0 ), + rStyles( rStylesC ), + bHasMasterPageName( sal_False ), + bPageDescConnected( sal_False ), + bDataStyleIsResolved( sal_True ) +{ +} + +SwXMLItemSetStyleContext_Impl::~SwXMLItemSetStyleContext_Impl() +{ + delete pItemSet; +} + +void SwXMLItemSetStyleContext_Impl::CreateAndInsert( sal_Bool bOverwrite ) +{ + if( pTextStyle ) + pTextStyle->CreateAndInsert( bOverwrite ); +} + +SvXMLImportContext *SwXMLItemSetStyleContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + if( XML_NAMESPACE_STYLE == nPrefix ) + { + if( IsXMLToken( rLocalName, XML_TABLE_PROPERTIES ) || + IsXMLToken( rLocalName, XML_TABLE_COLUMN_PROPERTIES ) || + IsXMLToken( rLocalName, XML_TABLE_ROW_PROPERTIES ) || + IsXMLToken( rLocalName, XML_TABLE_CELL_PROPERTIES ) ) + { + pContext = CreateItemSetContext( nPrefix, rLocalName, xAttrList ); + } + else if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) || + IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES )) + { + if( !pTextStyle ) + { + SvXMLAttributeList *pTmp = new SvXMLAttributeList; + OUString aStr = GetImport().GetNamespaceMap().GetQNameByKey( nPrefix, GetXMLToken(XML_NAME) ); + pTmp->AddAttribute( aStr, GetName() ); + uno::Reference <xml::sax::XAttributeList> xTmpAttrList = pTmp; + pTextStyle = new SwXMLTextStyleContext_Impl( GetSwImport(), nPrefix, + rLocalName, xTmpAttrList, XML_STYLE_FAMILY_TEXT_PARAGRAPH, rStyles ); + pTextStyle->StartElement( xTmpAttrList ); + rStyles.AddStyle( *pTextStyle ); + } + pContext = pTextStyle->CreateChildContext( nPrefix, rLocalName, xAttrList ); + } + } + + if( !pContext ) + pContext = SvXMLStyleContext::CreateChildContext( nPrefix, rLocalName, + xAttrList ); + + return pContext; +} + +void SwXMLItemSetStyleContext_Impl::ConnectPageDesc() +{ + if( bPageDescConnected || !HasMasterPageName() ) + return; + bPageDescConnected = sal_True; + + SwDoc *pDoc = SwImport::GetDocFromXMLImport( GetSwImport() ); + + String sName; + // --> OD 2005-02-01 #i40788# - first determine the display name of the + // page style, then map this name to the corresponding user interface name. + sName = GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_MASTER_PAGE, + GetMasterPageName() ); + SwStyleNameMapper::FillUIName( sName, + sName, + nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, + sal_True); + // <-- + SwPageDesc *pPageDesc = pDoc->FindPageDescByName( sName ); + if( !pPageDesc ) + { + // If the page style is a pool style, then we maybe have to create it + // first if it hasn't been used by now. + sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sName, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC ); + if( USHRT_MAX != nPoolId ) + pPageDesc = pDoc->GetPageDescFromPool( nPoolId, false ); + } + + if( !pPageDesc ) + return; + + if( !pItemSet ) + { + SfxItemPool& rItemPool = pDoc->GetAttrPool(); + pItemSet = new SfxItemSet( rItemPool, aTableSetRange ); + } + + const SfxPoolItem *pItem; + SwFmtPageDesc *pFmtPageDesc = 0; + if( SFX_ITEM_SET == pItemSet->GetItemState( RES_PAGEDESC, sal_False, + &pItem ) ) + { + if( ((SwFmtPageDesc *)pItem)->GetPageDesc() != pPageDesc ) + pFmtPageDesc = new SwFmtPageDesc( *(SwFmtPageDesc *)pItem ); + } + else + pFmtPageDesc = new SwFmtPageDesc(); + + if( pFmtPageDesc ) + { + pPageDesc->Add( pFmtPageDesc ); + pItemSet->Put( *pFmtPageDesc ); + delete pFmtPageDesc; + } +} + +sal_Bool SwXMLItemSetStyleContext_Impl::ResolveDataStyleName() +{ + // resolve, if not already done + if (! bDataStyleIsResolved) + { + // get the format key + sal_Int32 nFormat = + GetImport().GetTextImport()->GetDataStyleKey(sDataStyleName); + + // if the key is valid, insert Item into ItemSet + if( -1 != nFormat ) + { + if( !pItemSet ) + { + SwDoc *pDoc = SwImport::GetDocFromXMLImport( GetSwImport() ); + + SfxItemPool& rItemPool = pDoc->GetAttrPool(); + pItemSet = new SfxItemSet( rItemPool, aTableBoxSetRange ); + } + SwTblBoxNumFormat aNumFormatItem(nFormat); + pItemSet->Put(aNumFormatItem); + } + + // now resolved + bDataStyleIsResolved = sal_True; + return sal_True; + } + else + { + // was already resolved; nothing to do + return sal_False; + } +} + +// --------------------------------------------------------------------- +// +class SwXMLStylesContext_Impl : public SvXMLStylesContext +{ + SwXMLItemSetStyleContext_Impl *GetSwStyle( sal_uInt16 i ) const; + + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } + const SwXMLImport& GetSwImport() const + { return (const SwXMLImport&)GetImport(); } + +protected: + + virtual SvXMLStyleContext *CreateStyleStyleChildContext( sal_uInt16 nFamily, + sal_uInt16 nPrefix, const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ); + virtual SvXMLStyleContext *CreateDefaultStyleStyleChildContext( + sal_uInt16 nFamily, sal_uInt16 nPrefix, const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ); + // HACK + virtual UniReference < SvXMLImportPropertyMapper > GetImportPropertyMapper( + sal_uInt16 nFamily ) const; + + virtual uno::Reference < container::XNameContainer > + GetStylesContainer( sal_uInt16 nFamily ) const; + virtual ::rtl::OUString GetServiceName( sal_uInt16 nFamily ) const; + // HACK + +public: + + TYPEINFO(); + + SwXMLStylesContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName , + const uno::Reference< xml::sax::XAttributeList > & xAttrList, + sal_Bool bAuto ); + virtual ~SwXMLStylesContext_Impl(); + + virtual sal_Bool InsertStyleFamily( sal_uInt16 nFamily ) const; + + virtual void EndElement(); +}; + +TYPEINIT1( SwXMLStylesContext_Impl, SvXMLStylesContext ); + +inline SwXMLItemSetStyleContext_Impl *SwXMLStylesContext_Impl::GetSwStyle( + sal_uInt16 i ) const +{ + return PTR_CAST( SwXMLItemSetStyleContext_Impl, GetStyle( i ) ); +} + +SvXMLStyleContext *SwXMLStylesContext_Impl::CreateStyleStyleChildContext( + sal_uInt16 nFamily, sal_uInt16 nPrefix, const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLStyleContext *pStyle = 0; + + switch( nFamily ) + { + case XML_STYLE_FAMILY_TEXT_PARAGRAPH: + pStyle = new SwXMLTextStyleContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList, nFamily, *this ); + break; + case XML_STYLE_FAMILY_TABLE_TABLE: + case XML_STYLE_FAMILY_TABLE_COLUMN: + case XML_STYLE_FAMILY_TABLE_ROW: + case XML_STYLE_FAMILY_TABLE_CELL: + pStyle = new SwXMLItemSetStyleContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList, *this, nFamily ); + break; + case XML_STYLE_FAMILY_SD_GRAPHICS_ID: + // As long as there are no element items, we can use the text + // style class. + pStyle = new XMLTextShapeStyleContext( GetImport(), nPrefix, + rLocalName, xAttrList, *this, nFamily ); + break; + default: + pStyle = SvXMLStylesContext::CreateStyleStyleChildContext( nFamily, + nPrefix, + rLocalName, + xAttrList ); + break; + } + + return pStyle; +} + +SvXMLStyleContext *SwXMLStylesContext_Impl::CreateDefaultStyleStyleChildContext( + sal_uInt16 nFamily, sal_uInt16 nPrefix, const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLStyleContext *pStyle = 0; + + switch( nFamily ) + { + case XML_STYLE_FAMILY_TEXT_PARAGRAPH: + case XML_STYLE_FAMILY_TABLE_TABLE: + case XML_STYLE_FAMILY_TABLE_ROW: + pStyle = new XMLTextStyleContext( GetImport(), nPrefix, rLocalName, + xAttrList, *this, nFamily, + sal_True ); + break; + case XML_STYLE_FAMILY_SD_GRAPHICS_ID: + // There are no writer specific defaults for graphic styles! + pStyle = new XMLGraphicsDefaultStyle( GetImport(), nPrefix, + rLocalName, xAttrList, *this ); + break; + default: + pStyle = SvXMLStylesContext::CreateDefaultStyleStyleChildContext( nFamily, + nPrefix, + rLocalName, + xAttrList ); + break; + } + + return pStyle; +} + + +SwXMLStylesContext_Impl::SwXMLStylesContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList, + sal_Bool bAuto ) : + SvXMLStylesContext( rImport, nPrfx, rLName, xAttrList, bAuto ) +{ +} + +SwXMLStylesContext_Impl::~SwXMLStylesContext_Impl() +{ +} + +sal_Bool SwXMLStylesContext_Impl::InsertStyleFamily( sal_uInt16 nFamily ) const +{ + const SwXMLImport& rSwImport = GetSwImport(); + sal_uInt16 nStyleFamilyMask = rSwImport.GetStyleFamilyMask(); + + sal_Bool bIns = sal_True; + switch( nFamily ) + { + case XML_STYLE_FAMILY_TEXT_PARAGRAPH: + bIns = (nStyleFamilyMask & SFX_STYLE_FAMILY_PARA) != 0; + break; + case XML_STYLE_FAMILY_TEXT_TEXT: + bIns = (nStyleFamilyMask & SFX_STYLE_FAMILY_CHAR) != 0; + break; + case XML_STYLE_FAMILY_SD_GRAPHICS_ID: + bIns = (nStyleFamilyMask & SFX_STYLE_FAMILY_FRAME) != 0; + break; + case XML_STYLE_FAMILY_TEXT_LIST: + bIns = (nStyleFamilyMask & SFX_STYLE_FAMILY_PSEUDO) != 0; + break; + case XML_STYLE_FAMILY_TEXT_OUTLINE: + case XML_STYLE_FAMILY_TEXT_FOOTNOTECONFIG: + case XML_STYLE_FAMILY_TEXT_ENDNOTECONFIG: + case XML_STYLE_FAMILY_TEXT_LINENUMBERINGCONFIG: + case XML_STYLE_FAMILY_TEXT_BIBLIOGRAPHYCONFIG: + bIns = !(rSwImport.IsInsertMode() || rSwImport.IsStylesOnlyMode() || + rSwImport.IsBlockMode()); + break; + default: + bIns = SvXMLStylesContext::InsertStyleFamily( nFamily ); + break; + } + + return bIns; +} + +UniReference < SvXMLImportPropertyMapper > SwXMLStylesContext_Impl::GetImportPropertyMapper( + sal_uInt16 nFamily ) const +{ + UniReference < SvXMLImportPropertyMapper > xMapper; + if( nFamily == XML_STYLE_FAMILY_TABLE_TABLE ) + xMapper = XMLTextImportHelper::CreateTableDefaultExtPropMapper( + const_cast<SwXMLStylesContext_Impl*>( this )->GetImport() ); + else if( nFamily == XML_STYLE_FAMILY_TABLE_ROW ) + xMapper = XMLTextImportHelper::CreateTableRowDefaultExtPropMapper( + const_cast<SwXMLStylesContext_Impl*>( this )->GetImport() ); + else + xMapper = SvXMLStylesContext::GetImportPropertyMapper( nFamily ); + return xMapper; +} + +uno::Reference < container::XNameContainer > SwXMLStylesContext_Impl::GetStylesContainer( + sal_uInt16 nFamily ) const +{ + uno::Reference < container::XNameContainer > xStyles; + if( XML_STYLE_FAMILY_SD_GRAPHICS_ID == nFamily ) + xStyles = ((SvXMLImport *)&GetImport())->GetTextImport()->GetFrameStyles(); + else + xStyles = SvXMLStylesContext::GetStylesContainer( nFamily ); + + return xStyles; +} + +OUString SwXMLStylesContext_Impl::GetServiceName( sal_uInt16 nFamily ) const +{ + String sServiceName; + if( XML_STYLE_FAMILY_SD_GRAPHICS_ID == nFamily ) + sServiceName = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.style.FrameStyle") ); + else + sServiceName = SvXMLStylesContext::GetServiceName( nFamily ); + + return sServiceName; +} + +void SwXMLStylesContext_Impl::EndElement() +{ + GetSwImport().InsertStyles( IsAutomaticStyle() ); + // --> OD 2006-10-11 #i69629# + // assign paragraph styles to list levels of outline style after all styles + // are imported and finished. +// if( !bAutoStyles ) +// GetImport().GetTextImport()->SetOutlineStyles( sal_True ); + // <-- +} + +// --------------------------------------------------------------------- +// +class SwXMLMasterStylesContext_Impl : public XMLTextMasterStylesContext +{ +protected: + virtual sal_Bool InsertStyleFamily( sal_uInt16 nFamily ) const; + + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } + const SwXMLImport& GetSwImport() const + { return (const SwXMLImport&)GetImport(); } + +public: + + TYPEINFO(); + + SwXMLMasterStylesContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName , + const uno::Reference< xml::sax::XAttributeList > & xAttrList ); + virtual ~SwXMLMasterStylesContext_Impl(); + virtual void EndElement(); +}; + +TYPEINIT1( SwXMLMasterStylesContext_Impl, XMLTextMasterStylesContext ); + +SwXMLMasterStylesContext_Impl::SwXMLMasterStylesContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName , + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) : + XMLTextMasterStylesContext( rImport, nPrfx, rLName, xAttrList ) +{ +} + +SwXMLMasterStylesContext_Impl::~SwXMLMasterStylesContext_Impl() +{ +} + +sal_Bool SwXMLMasterStylesContext_Impl::InsertStyleFamily( sal_uInt16 nFamily ) const +{ + sal_Bool bIns; + + const SwXMLImport& rSwImport = GetSwImport(); + sal_uInt16 nStyleFamilyMask = rSwImport.GetStyleFamilyMask(); + if( XML_STYLE_FAMILY_MASTER_PAGE == nFamily ) + bIns = (nStyleFamilyMask & SFX_STYLE_FAMILY_PAGE) != 0; + else + bIns = XMLTextMasterStylesContext::InsertStyleFamily( nFamily ); + + return bIns; +} + +void SwXMLMasterStylesContext_Impl::EndElement() +{ + FinishStyles( !GetSwImport().IsInsertMode() ); + GetSwImport().FinishStyles(); +} +// --------------------------------------------------------------------- + +SvXMLImportContext *SwXMLImport::CreateStylesContext( + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList, + sal_Bool bAuto ) +{ + SvXMLStylesContext *pContext = + new SwXMLStylesContext_Impl( *this, XML_NAMESPACE_OFFICE, rLocalName, + xAttrList, bAuto ); + if( bAuto ) + SetAutoStyles( pContext ); + else + SetStyles( pContext ); + + return pContext; +} + +SvXMLImportContext *SwXMLImport::CreateMasterStylesContext( + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLStylesContext *pContext = + new SwXMLMasterStylesContext_Impl( *this, XML_NAMESPACE_OFFICE, rLocalName, + xAttrList ); + SetMasterStyles( pContext ); + + return pContext; +} + +void SwXMLImport::InsertStyles( sal_Bool bAuto ) +{ + if( bAuto && GetAutoStyles() ) + GetAutoStyles()->CopyAutoStylesToDoc(); + if( !bAuto && GetStyles() ) + GetStyles()->CopyStylesToDoc( !IsInsertMode(), sal_False ); +} + +void SwXMLImport::FinishStyles() +{ + if( GetStyles() ) + GetStyles()->FinishStyles( !IsInsertMode() ); +} + +void SwXMLImport::UpdateTxtCollConditions( SwDoc *pDoc ) +{ + if( !pDoc ) + pDoc = SwImport::GetDocFromXMLImport( *this ); + + const SwTxtFmtColls& rColls = *pDoc->GetTxtFmtColls(); + sal_uInt16 nCount = rColls.Count(); + for( sal_uInt16 i=0; i < nCount; i++ ) + { + SwTxtFmtColl *pColl = rColls[i]; + if( pColl && RES_CONDTXTFMTCOLL == pColl->Which() ) + { + const SwFmtCollConditions& rConditions = + ((const SwConditionTxtFmtColl *)pColl)->GetCondColls(); + sal_Bool bSendModify = sal_False; + for( sal_uInt16 j=0; j < rConditions.Count() && !bSendModify; j++ ) + { + const SwCollCondition& rCond = *rConditions[j]; + switch( rCond.GetCondition() ) + { + case PARA_IN_TABLEHEAD: + case PARA_IN_TABLEBODY: + case PARA_IN_FOOTER: + case PARA_IN_HEADER: + bSendModify = sal_True; + break; + } + } + if( bSendModify ) + { + SwCondCollCondChg aMsg( pColl ); + pColl->Modify( &aMsg, &aMsg ); + } + } + } +} + +sal_Bool SwXMLImport::FindAutomaticStyle( + sal_uInt16 nFamily, + const OUString& rName, + const SfxItemSet **ppItemSet, + OUString *pParent ) const +{ + SwXMLItemSetStyleContext_Impl *pStyle = 0; + if( GetAutoStyles() ) + { + pStyle = PTR_CAST( SwXMLItemSetStyleContext_Impl, + GetAutoStyles()-> + FindStyleChildContext( nFamily, rName, + sal_True ) ); + if( pStyle ) + { + if( ppItemSet ) + { + if( XML_STYLE_FAMILY_TABLE_TABLE == pStyle->GetFamily() && + pStyle->HasMasterPageName() && + !pStyle->IsPageDescConnected() ) + pStyle->ConnectPageDesc(); + (*ppItemSet) = pStyle->GetItemSet(); + + // resolve data style name late + if( XML_STYLE_FAMILY_TABLE_CELL == pStyle->GetFamily() && + pStyle->ResolveDataStyleName() ) + { + (*ppItemSet) = pStyle->GetItemSet(); + } + + } + + if( pParent ) + *pParent = pStyle->GetParentName(); + } + } + + return pStyle != 0; +} diff --git a/sw/source/filter/xml/xmlfmte.cxx b/sw/source/filter/xml/xmlfmte.cxx new file mode 100644 index 000000000000..ab1bc8d9be2b --- /dev/null +++ b/sw/source/filter/xml/xmlfmte.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <com/sun/star/text/XTextDocument.hpp> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/attrlist.hxx> +#include "xmlexpit.hxx" +#include <xmloff/nmspmap.hxx> +#include <xmloff/XMLTextListAutoStylePool.hxx> +#include <xmloff/XMLTextMasterPageExport.hxx> + +#include <xmloff/txtprmap.hxx> +#include <xmloff/xmlaustp.hxx> +#include <xmloff/families.hxx> +#include <format.hxx> +#include <fmtpdsc.hxx> +#include <pagedesc.hxx> +#include <unostyle.hxx> +#include <cellatr.hxx> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include "xmlexp.hxx" +#include <SwStyleNameMapper.hxx> + + +using ::rtl::OUString; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::lang; +using namespace ::xmloff::token; + +void SwXMLExport::ExportFmt( const SwFmt& rFmt, enum XMLTokenEnum eFamily ) +{ + // <style:style ...> + CheckAttrList(); + + // style:family="..." + DBG_ASSERT( RES_FRMFMT==rFmt.Which(), "frame format expected" ); + if( RES_FRMFMT != rFmt.Which() ) + return; + DBG_ASSERT( eFamily != XML_TOKEN_INVALID, "family must be specified" ); + // style:name="..." + sal_Bool bEncoded = sal_False; + AddAttribute( XML_NAMESPACE_STYLE, XML_NAME, EncodeStyleName( + rFmt.GetName(), &bEncoded ) ); + if( bEncoded ) + AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rFmt.GetName() ); + + + if( eFamily != XML_TOKEN_INVALID ) + AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, eFamily ); + +#ifdef DBG_UTIL + // style:parent-style-name="..." (if its not the default only) + const SwFmt* pParent = rFmt.DerivedFrom(); + // Parent-Namen nur uebernehmen, wenn kein Default + ASSERT( !pParent || pParent->IsDefault(), "unexpected parent" ); + + ASSERT( USHRT_MAX == rFmt.GetPoolFmtId(), "pool ids arent'supported" ); + ASSERT( USHRT_MAX == rFmt.GetPoolHelpId(), "help ids arent'supported" ); + ASSERT( USHRT_MAX == rFmt.GetPoolHelpId() || + UCHAR_MAX == rFmt.GetPoolHlpFileId(), "help file ids aren't supported" ); +#endif + + // style:master-page-name + if( RES_FRMFMT == rFmt.Which() && XML_TABLE == eFamily ) + { + const SfxPoolItem *pItem; + if( SFX_ITEM_SET == rFmt.GetAttrSet().GetItemState( RES_PAGEDESC, + sal_False, &pItem ) ) + { + String sName; + const SwPageDesc *pPageDesc = + ((const SwFmtPageDesc *)pItem)->GetPageDesc(); + if( pPageDesc ) + SwStyleNameMapper::FillProgName( + pPageDesc->GetName(), + sName, + nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, + sal_True); + AddAttribute( XML_NAMESPACE_STYLE, XML_MASTER_PAGE_NAME, + EncodeStyleName( sName ) ); + } + } + + if( XML_TABLE_CELL == eFamily ) + { + DBG_ASSERT(RES_FRMFMT == rFmt.Which(), "only frame format"); + + const SfxPoolItem *pItem; + if( SFX_ITEM_SET == + rFmt.GetAttrSet().GetItemState( RES_BOXATR_FORMAT, + sal_False, &pItem ) ) + { + sal_Int32 nFormat = (sal_Int32) + ((const SwTblBoxNumFormat *)pItem)->GetValue(); + + if ( (nFormat != -1) && (nFormat != NUMBERFORMAT_TEXT) ) + { + // if we have a format, register and then export + // (Careful: here we assume that data styles will be + // written after cell styles) + addDataStyle(nFormat); + OUString sDataStyleName = getDataStyleName(nFormat); + if( sDataStyleName.getLength() > 0 ) + AddAttribute( XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, + sDataStyleName ); + } + } + } + + { + SvXMLElementExport aElem( *this, XML_NAMESPACE_STYLE, XML_STYLE, + sal_True, sal_True ); + + SvXMLItemMapEntriesRef xItemMap; + XMLTokenEnum ePropToken = XML_TABLE_PROPERTIES; + if( XML_TABLE == eFamily ) + { + xItemMap = xTableItemMap; + } + else if( XML_TABLE_ROW == eFamily ) + { + xItemMap = xTableRowItemMap; + ePropToken = XML_TABLE_ROW_PROPERTIES; + } + else if( XML_TABLE_CELL == eFamily ) + { + xItemMap = xTableCellItemMap; + ePropToken = XML_TABLE_CELL_PROPERTIES; + } + + if( xItemMap.Is() ) + { + SvXMLExportItemMapper& rItemMapper = GetTableItemMapper(); + rItemMapper.setMapEntries( xItemMap ); + + GetTableItemMapper().exportXML( *this, + rFmt.GetAttrSet(), + GetTwipUnitConverter(), + ePropToken, + XML_EXPORT_FLAG_IGN_WS ); + } + } +} + + +void SwXMLExport::_ExportStyles( sal_Bool bUsed ) +{ + SvXMLExport::_ExportStyles( bUsed ); + + // drawing defaults + GetShapeExport()->ExportGraphicDefaults(); + + GetTextParagraphExport()->exportTextStyles( bUsed + ,IsShowProgress() + ); + //page defaults + GetPageExport()->exportDefaultStyle(); +} + +void SwXMLExport::_ExportAutoStyles() +{ + // The order in which styles are collected *MUST* be the same as + // the order in which they are exported. Otherwise, caching will + // fail. + + if( (getExportFlags() & (EXPORT_MASTERSTYLES|EXPORT_CONTENT)) != 0 ) + { + if( (getExportFlags() & EXPORT_CONTENT) == 0 ) + { + // only master pages are exported => styles for frames bound + // to frames (but none for frames bound to pages) need to be + // collected. + // TODO: exclude PageBoundFrames on export + } + } + + // exported in _ExportMasterStyles + if( (getExportFlags() & EXPORT_MASTERSTYLES) != 0 ) + GetPageExport()->collectAutoStyles( sal_False ); + + // if we don't export styles (i.e. in content stream only, but not + // in single-stream case), then we can save ourselves a bit of + // work and memory by not collecting field masters + if( (getExportFlags() & EXPORT_STYLES ) == 0 ) + GetTextParagraphExport()->exportUsedDeclarations( sal_False ); + + // exported in _ExportContent + if( (getExportFlags() & EXPORT_CONTENT) != 0 ) + { + GetTextParagraphExport()->exportTrackedChanges( sal_True ); + Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY ); + Reference < XText > xText = xTextDoc->getText(); + + // collect form autostyle + // (do this before collectTextAutoStyles, 'cause the shapes need the results of the work + // done by examineForms) + Reference<XDrawPageSupplier> xDrawPageSupplier( GetModel(), UNO_QUERY ); + if (xDrawPageSupplier.is() && GetFormExport().is()) + { + Reference<XDrawPage> xPage = xDrawPageSupplier->getDrawPage(); + if (xPage.is()) + GetFormExport()->examineForms(xPage); + } + + GetTextParagraphExport()->collectTextAutoStylesOptimized( bShowProgress ); + //GetTextParagraphExport()->collectTextAutoStyles( xText, bShowProgress, sal_True, bPortions ); + } + + GetTextParagraphExport()->exportTextAutoStyles(); + GetShapeExport()->exportAutoStyles(); + if( (getExportFlags() & EXPORT_MASTERSTYLES) != 0 ) + GetPageExport()->exportAutoStyles(); + + // we rely on data styles being written after cell styles in the + // ExportFmt() method; so be careful when changing order. + exportAutoDataStyles(); + + sal_uInt16 nContentAutostyles = EXPORT_CONTENT | EXPORT_AUTOSTYLES; + if ( ( getExportFlags() & nContentAutostyles ) == nContentAutostyles ) + GetFormExport()->exportAutoStyles(); +} + +XMLPageExport* SwXMLExport::CreatePageExport() +{ + return new XMLTextMasterPageExport( *this ); +} + +void SwXMLExport::_ExportMasterStyles() +{ + // export master styles + GetPageExport()->exportMasterStyles( sal_False ); +} + +// --------------------------------------------------------------------- +class SwXMLAutoStylePoolP : public SvXMLAutoStylePoolP +{ + SvXMLExport& rExport; + const OUString sListStyleName; + const OUString sMasterPageName; + const OUString sCDATA; + +protected: + + virtual void exportStyleAttributes( + SvXMLAttributeList& rAttrList, + sal_Int32 nFamily, + const ::std::vector< XMLPropertyState >& rProperties, + const SvXMLExportPropertyMapper& rPropExp + , const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap + ) const; +public: + + SwXMLAutoStylePoolP( SvXMLExport& rExport ); + virtual ~SwXMLAutoStylePoolP(); +}; + +void SwXMLAutoStylePoolP::exportStyleAttributes( + SvXMLAttributeList& rAttrList, + sal_Int32 nFamily, + const ::std::vector< XMLPropertyState >& rProperties, + const SvXMLExportPropertyMapper& rPropExp + , const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap + ) const +{ + SvXMLAutoStylePoolP::exportStyleAttributes( rAttrList, nFamily, rProperties, rPropExp, rUnitConverter, rNamespaceMap); + + if( XML_STYLE_FAMILY_TEXT_PARAGRAPH == nFamily ) + { + for( ::std::vector< XMLPropertyState >::const_iterator + aProperty = rProperties.begin(); + aProperty != rProperties.end(); + aProperty++ ) + { + if (aProperty->mnIndex != -1) // #i26762# + { + switch( rPropExp.getPropertySetMapper()-> + GetEntryContextId( aProperty->mnIndex ) ) + { + case CTF_NUMBERINGSTYLENAME: + { + OUString sStyleName; + aProperty->maValue >>= sStyleName; + // --> OD 2008-11-19 #i70748# + // export also empty list styles + if( sStyleName.getLength() ) + { + OUString sTmp = rExport.GetTextParagraphExport()->GetListAutoStylePool().Find( sStyleName ); + if( sTmp.getLength() ) + sStyleName = sTmp; + } + GetExport().AddAttribute( XML_NAMESPACE_STYLE, + sListStyleName, + GetExport().EncodeStyleName( sStyleName ) ); + // <-- + } + break; + case CTF_PAGEDESCNAME: + { + OUString sStyleName; + aProperty->maValue >>= sStyleName; + GetExport().AddAttribute( XML_NAMESPACE_STYLE, + sMasterPageName, + GetExport().EncodeStyleName( sStyleName ) ); + } + break; + } + } + } + } +} + +SwXMLAutoStylePoolP::SwXMLAutoStylePoolP(SvXMLExport& rExp ) : + SvXMLAutoStylePoolP( rExp ), + rExport( rExp ), + sListStyleName( GetXMLToken( XML_LIST_STYLE_NAME ) ), + sMasterPageName( GetXMLToken( XML_MASTER_PAGE_NAME ) ), + sCDATA( GetXMLToken( XML_CDATA ) ) +{ +} + + +SwXMLAutoStylePoolP::~SwXMLAutoStylePoolP() +{ +} + +SvXMLAutoStylePoolP* SwXMLExport::CreateAutoStylePool() +{ + return new SwXMLAutoStylePoolP( *this ); +} diff --git a/sw/source/filter/xml/xmlfonte.cxx b/sw/source/filter/xml/xmlfonte.cxx new file mode 100644 index 000000000000..80c8e982c0dd --- /dev/null +++ b/sw/source/filter/xml/xmlfonte.cxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include "hintids.hxx" +#include <com/sun/star/text/XTextDocument.hpp> +#include <xmloff/XMLFontAutoStylePool.hxx> +#include <editeng/fontitem.hxx> +#include <unotext.hxx> +#include <doc.hxx> +#include <xmlexp.hxx> + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::text; + +class SwXMLFontAutoStylePool_Impl: public XMLFontAutoStylePool +{ + public: + + SwXMLFontAutoStylePool_Impl( SwXMLExport& rExport ); + +}; + +SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl( + SwXMLExport& _rExport ) : + XMLFontAutoStylePool( _rExport ) +{ + sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, + RES_CHRATR_CTL_FONT }; + + Reference < XTextDocument > xTextDoc( _rExport.GetModel(), UNO_QUERY ); + Reference < XText > xText = xTextDoc->getText(); + Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY); + ASSERT( xTextTunnel.is(), "missing XUnoTunnel for Cursor" ); + if( !xTextTunnel.is() ) + return; + + SwXText *pText = reinterpret_cast< SwXText *>( + sal::static_int_cast< sal_IntPtr >( xTextTunnel->getSomething( SwXText::getUnoTunnelId() ))); + ASSERT( pText, "SwXText missing" ); + if( !pText ) + return; + + const SfxItemPool& rPool = pText->GetDoc()->GetAttrPool(); + const SfxPoolItem* pItem; + for( sal_uInt16 i=0; i<3; i++ ) + { + sal_uInt16 nWhichId = aWhichIds[i]; + + const SvxFontItem& rFont = + (const SvxFontItem&)rPool.GetDefaultItem( nWhichId ); + Add( rFont.GetFamilyName(), rFont.GetStyleName(), + static_cast< sal_uInt16 >(rFont.GetFamily()), static_cast< sal_uInt16 >(rFont.GetPitch()), + rFont.GetCharSet() ); + sal_uInt16 nItems = rPool.GetItemCount( nWhichId ); + for( sal_uInt16 j = 0; j < nItems; ++j ) + { + if( 0 != (pItem = rPool.GetItem( nWhichId, j ) ) ) + { + const SvxFontItem *pFont = + (const SvxFontItem *)pItem; + Add( pFont->GetFamilyName(), pFont->GetStyleName(), + static_cast< sal_uInt16 >(pFont->GetFamily()), static_cast< sal_uInt16 >(pFont->GetPitch()), + pFont->GetCharSet() ); + } + } + } +} + + +XMLFontAutoStylePool* SwXMLExport::CreateFontAutoStylePool() +{ + return new SwXMLFontAutoStylePool_Impl( *this ); +} diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx new file mode 100644 index 000000000000..a883f8dbae2a --- /dev/null +++ b/sw/source/filter/xml/xmlimp.cxx @@ -0,0 +1,1745 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <com/sun/star/text/XTextDocument.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmltkmap.hxx> +#include <xmloff/xmlictxt.hxx> +#include <xmloff/txtimp.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/XMLTextShapeImportHelper.hxx> +#include <xmloff/XMLFontStylesContext.hxx> +#include <xmloff/ProgressBarHelper.hxx> +#include <com/sun/star/i18n/XForbiddenCharacters.hpp> +#include <com/sun/star/document/PrinterIndependentLayout.hpp> +#include <doc.hxx> +#include <TextCursorHelper.hxx> +#include <unotext.hxx> +#include <unotextrange.hxx> +#include "unocrsr.hxx" +#include <poolfmt.hxx> +#include <ndtxt.hxx> +#include <editsh.hxx> +#include "xmlimp.hxx" +#include <xmloff/DocumentSettingsContext.hxx> +#include <docsh.hxx> +#include <editeng/unolingu.hxx> +#include <svx/svdmodel.hxx> +#include <svx/xmlgrhlp.hxx> +#include <svx/xmleohlp.hxx> +#include <sfx2/printer.hxx> +#include <ForbiddenCharactersEnum.hxx> +#include <xmloff/xmluconv.hxx> +#include <unotools/saveopt.hxx> +#include <tools/diagnose_ex.h> +#include <hash_set> +#include <stringhash.hxx> + +// for locking SolarMutex: svapp + mutex +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <unotxdoc.hxx> // for initXForms() + +#include <xmloff/xmlmetai.hxx> +#include <xmloff/xformsimport.hxx> + +using ::rtl::OUString; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::xforms; +using namespace ::xmloff::token; +using namespace ::std; + +struct OUStringEquals +{ + sal_Bool operator()( const rtl::OUString &r1, + const rtl::OUString &r2) const + { + return r1 == r2; + } +}; + +//---------------------------------------------------------------------------- + +enum SwXMLDocTokens +{ + XML_TOK_DOC_FONTDECLS, + XML_TOK_DOC_STYLES, + XML_TOK_DOC_AUTOSTYLES, + XML_TOK_DOC_MASTERSTYLES, + XML_TOK_DOC_META, + XML_TOK_DOC_BODY, + XML_TOK_DOC_SCRIPT, + XML_TOK_DOC_SETTINGS, + XML_TOK_DOC_XFORMS, + XML_TOK_OFFICE_END=XML_TOK_UNKNOWN +}; + +static __FAR_DATA SvXMLTokenMapEntry aDocTokenMap[] = +{ + { XML_NAMESPACE_OFFICE, XML_FONT_FACE_DECLS, XML_TOK_DOC_FONTDECLS }, + { XML_NAMESPACE_OFFICE, XML_STYLES, XML_TOK_DOC_STYLES }, + { XML_NAMESPACE_OFFICE, XML_AUTOMATIC_STYLES, XML_TOK_DOC_AUTOSTYLES }, + { XML_NAMESPACE_OFFICE, XML_MASTER_STYLES, XML_TOK_DOC_MASTERSTYLES }, + { XML_NAMESPACE_OFFICE, XML_META, XML_TOK_DOC_META }, + { XML_NAMESPACE_OFFICE, XML_BODY, XML_TOK_DOC_BODY }, + { XML_NAMESPACE_OFFICE, XML_SCRIPTS, XML_TOK_DOC_SCRIPT }, + { XML_NAMESPACE_OFFICE, XML_SETTINGS, XML_TOK_DOC_SETTINGS }, + { XML_NAMESPACE_XFORMS, XML_MODEL, XML_TOK_DOC_XFORMS }, + XML_TOKEN_MAP_END +}; + +// ---------------------------------------------------------------------------- + +class SwXMLBodyContext_Impl : public SvXMLImportContext +{ + const SwXMLImport& GetSwImport() const + { return (const SwXMLImport&)GetImport(); } + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } + +public: + + SwXMLBodyContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList ); + virtual ~SwXMLBodyContext_Impl(); + + TYPEINFO(); + + virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ); +}; + +SwXMLBodyContext_Impl::SwXMLBodyContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, const OUString& rLName, + const Reference< xml::sax::XAttributeList > & /*xAttrList*/ ) : + SvXMLImportContext( rImport, nPrfx, rLName ) +{ +} + +SwXMLBodyContext_Impl::~SwXMLBodyContext_Impl() +{ +} + +TYPEINIT1( SwXMLBodyContext_Impl, SvXMLImportContext ); + +SvXMLImportContext *SwXMLBodyContext_Impl::CreateChildContext( + sal_uInt16 /*nPrefix*/, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & /*xAttrList*/ ) +{ + return GetSwImport().CreateBodyContentContext( rLocalName ); +} + +// ---------------------------------------------------------------------------- + +// --> OD 2006-10-11 #i69629# +// enhance class <SwXMLDocContext_Impl> in order to be able to create subclasses +// NB: virtually inherit so we can multiply inherit properly +// in SwXMLOfficeDocContext_Impl +class SwXMLDocContext_Impl : public virtual SvXMLImportContext +{ +// --> OD 2006-10-11 #i69629# +protected: +// <-- + const SwXMLImport& GetSwImport() const + { return (const SwXMLImport&)GetImport(); } + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } + +public: + + SwXMLDocContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList ); + virtual ~SwXMLDocContext_Impl(); + + TYPEINFO(); + + virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ); +}; + +SwXMLDocContext_Impl::SwXMLDocContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, const OUString& rLName, + const Reference< xml::sax::XAttributeList > & /*xAttrList*/ ) : + SvXMLImportContext( rImport, nPrfx, rLName ) +{ +} + +SwXMLDocContext_Impl::~SwXMLDocContext_Impl() +{ +} + +TYPEINIT1( SwXMLDocContext_Impl, SvXMLImportContext ); + +SvXMLImportContext *SwXMLDocContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + const SvXMLTokenMap& rTokenMap = GetSwImport().GetDocElemTokenMap(); + switch( rTokenMap.Get( nPrefix, rLocalName ) ) + { + case XML_TOK_DOC_FONTDECLS: + pContext = GetSwImport().CreateFontDeclsContext( rLocalName, + xAttrList ); + break; + case XML_TOK_DOC_STYLES: + GetSwImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); + pContext = GetSwImport().CreateStylesContext( rLocalName, xAttrList, + sal_False ); + break; + case XML_TOK_DOC_AUTOSTYLES: + // don't use the autostyles from the styles-document for the progress + if ( ! IsXMLToken( GetLocalName(), XML_DOCUMENT_STYLES ) ) + GetSwImport().GetProgressBarHelper()->Increment + ( PROGRESS_BAR_STEP ); + pContext = GetSwImport().CreateStylesContext( rLocalName, xAttrList, + sal_True ); + break; +// case XML_TOK_DOC_USESTYLES: +// pContext = GetSwImport().CreateUseStylesContext( rLocalName, +// xAttrList ); +// break; + case XML_TOK_DOC_MASTERSTYLES: + pContext = GetSwImport().CreateMasterStylesContext( rLocalName, + xAttrList ); + break; + case XML_TOK_DOC_META: + DBG_WARNING("XML_TOK_DOC_META: should not have come here, maybe document is invalid?"); + break; + case XML_TOK_DOC_SCRIPT: + pContext = GetSwImport().CreateScriptContext( rLocalName ); + break; + case XML_TOK_DOC_BODY: + GetSwImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); + pContext = new SwXMLBodyContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList ); + break; + case XML_TOK_DOC_SETTINGS: + pContext = new XMLDocumentSettingsContext( GetImport(), nPrefix, rLocalName, xAttrList ); + break; + case XML_TOK_DOC_XFORMS: + pContext = createXFormsModelContext(GetImport(), nPrefix, rLocalName); + break; + } + + if( !pContext ) + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + + + return pContext; +} + +// --> OD 2006-10-11 #i69629# +// new subclass <SwXMLOfficeDocContext_Impl> of class <SwXMLDocContext_Impl> +class SwXMLOfficeDocContext_Impl : + public SwXMLDocContext_Impl, public SvXMLMetaDocumentContext +{ +public: + + SwXMLOfficeDocContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + const Reference< document::XDocumentProperties >& xDocProps, + const Reference< xml::sax::XDocumentHandler >& xDocBuilder); + virtual ~SwXMLOfficeDocContext_Impl(); + + TYPEINFO(); + + virtual SvXMLImportContext *CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ); +}; + +SwXMLOfficeDocContext_Impl::SwXMLOfficeDocContext_Impl( + SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + const Reference< document::XDocumentProperties >& xDocProps, + const Reference< xml::sax::XDocumentHandler >& xDocBuilder) : + SvXMLImportContext( rImport, nPrfx, rLName ), + SwXMLDocContext_Impl( rImport, nPrfx, rLName, xAttrList ), + SvXMLMetaDocumentContext( rImport, nPrfx, rLName, xDocProps, xDocBuilder) +{ +} + +SwXMLOfficeDocContext_Impl::~SwXMLOfficeDocContext_Impl() +{ +} + +TYPEINIT1( SwXMLOfficeDocContext_Impl, SwXMLDocContext_Impl ); + +SvXMLImportContext* SwXMLOfficeDocContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + const SvXMLTokenMap& rTokenMap = GetSwImport().GetDocElemTokenMap(); + + // assign paragraph styles to list levels of outline style after all styles + // are imported and finished. This is the case, when <office:body> starts + // in flat OpenDocument file format. + { + if ( rTokenMap.Get( nPrefix, rLocalName ) == XML_TOK_DOC_BODY ) + { + GetImport().GetTextImport()->SetOutlineStyles( sal_True ); + } + } + + // behave like meta base class iff we encounter office:meta + if ( XML_TOK_DOC_META == rTokenMap.Get( nPrefix, rLocalName ) ) { + return SvXMLMetaDocumentContext::CreateChildContext( + nPrefix, rLocalName, xAttrList ); + } else { + return SwXMLDocContext_Impl::CreateChildContext( + nPrefix, rLocalName, xAttrList ); + } +} +// <-- + +// --> OD 2006-10-11 #i69629# +// new subclass <SwXMLDocStylesContext_Impl> of class <SwXMLDocContext_Impl> +class SwXMLDocStylesContext_Impl : public SwXMLDocContext_Impl +{ +public: + + SwXMLDocStylesContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList ); + virtual ~SwXMLDocStylesContext_Impl(); + + TYPEINFO(); + + virtual void EndElement(); +}; + +SwXMLDocStylesContext_Impl::SwXMLDocStylesContext_Impl( + SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + SwXMLDocContext_Impl( rImport, nPrfx, rLName, xAttrList ) +{ +} + +SwXMLDocStylesContext_Impl::~SwXMLDocStylesContext_Impl() +{ +} + +TYPEINIT1( SwXMLDocStylesContext_Impl, SwXMLDocContext_Impl ); + +void SwXMLDocStylesContext_Impl::EndElement() +{ + // assign paragraph styles to list levels of outline style after all styles + // are imported and finished. + SwXMLImport& rSwImport = dynamic_cast<SwXMLImport&>( GetImport()); + GetImport().GetTextImport()->SetOutlineStyles( + (rSwImport.GetStyleFamilyMask() & SFX_STYLE_FAMILY_PARA ) ? sal_True : sal_False); + // <-- +} +// <-- +//---------------------------------------------------------------------------- + +const SvXMLTokenMap& SwXMLImport::GetDocElemTokenMap() +{ + if( !pDocElemTokenMap ) + pDocElemTokenMap = new SvXMLTokenMap( aDocTokenMap ); + + return *pDocElemTokenMap; +} + +SvXMLImportContext *SwXMLImport::CreateContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + // --> OD 2006-10-11 #i69629# + // own subclasses for <office:document> and <office:document-styles> + if( XML_NAMESPACE_OFFICE==nPrefix && +// ( IsXMLToken( rLocalName, XML_DOCUMENT ) || +// ( IsXMLToken( rLocalName, XML_DOCUMENT_META ) || + ( IsXMLToken( rLocalName, XML_DOCUMENT_SETTINGS ) || +// IsXMLToken( rLocalName, XML_DOCUMENT_STYLES ) || + IsXMLToken( rLocalName, XML_DOCUMENT_CONTENT ) )) + pContext = new SwXMLDocContext_Impl( *this, nPrefix, rLocalName, + xAttrList ); + else if ( XML_NAMESPACE_OFFICE==nPrefix && + IsXMLToken( rLocalName, XML_DOCUMENT_META ) ) + { + pContext = CreateMetaContext(rLocalName); + } + else if ( XML_NAMESPACE_OFFICE==nPrefix && + IsXMLToken( rLocalName, XML_DOCUMENT ) ) + { + uno::Reference<xml::sax::XDocumentHandler> xDocBuilder( + mxServiceFactory->createInstance(::rtl::OUString::createFromAscii( + "com.sun.star.xml.dom.SAXDocumentBuilder")), + uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + GetModel(), UNO_QUERY_THROW); + // flat OpenDocument file format + pContext = new SwXMLOfficeDocContext_Impl( *this, nPrefix, rLocalName, + xAttrList, xDPS->getDocumentProperties(), xDocBuilder); + } + else if ( XML_NAMESPACE_OFFICE==nPrefix && + IsXMLToken( rLocalName, XML_DOCUMENT_STYLES ) ) + { + pContext = new SwXMLDocStylesContext_Impl( *this, nPrefix, rLocalName, + xAttrList ); + } + // <-- + else + pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList ); + + return pContext; +} + +// #110680# +SwXMLImport::SwXMLImport( + const uno::Reference< lang::XMultiServiceFactory > xServiceFactory, + sal_uInt16 nImportFlags) +: SvXMLImport( xServiceFactory, nImportFlags ), + pSttNdIdx( 0 ), + pTableItemMapper( 0 ), + pDocElemTokenMap( 0 ), + pTableElemTokenMap( 0 ), + pTableCellAttrTokenMap( 0 ), + pGraphicResolver( 0 ), + pEmbeddedResolver( 0 ), + nStyleFamilyMask( SFX_STYLE_FAMILY_ALL ), + bLoadDoc( sal_True ), + bInsert( sal_False ), + bBlock( sal_False ), + bShowProgress( sal_True ), + bOrganizerMode( sal_False ), + bInititedXForms( sal_False ), + bPreserveRedlineMode( sal_True ) +{ + _InitItemImport(); + +} + +#ifdef XML_CORE_API +// #110680# +SwXMLImport::SwXMLImport( + const uno::Reference< lang::XMultiServiceFactory > xServiceFactory, + SwDoc& rDoc, + const SwPaM& rPaM, + sal_Bool bLDoc, + sal_Bool bInsertMode, + sal_uInt16 nStyleFamMask, + const uno::Reference< frame::XModel > & rModel, + const uno::Reference< document::XGraphicObjectResolver > & rEGO, + SvStorage *pPkg ) +: SvXMLImport( xServiceFactory, rModel, rEGO ), + bLoadDoc( bLDoc ), + bInsert( bInsertMode ), + nStyleFamilyMask( nStyleFamMask ), + pDocElemTokenMap( 0 ), + pTableElemTokenMap( 0 ), + pTableCellAttrTokenMap( 0 ), + pTableItemMapper( 0 ), + pSttNdIdx( 0 ), + bShowProgress( sal_True ), + bPreserveRedlineMode( sal_True ), + xPackage( pPkg ) +{ + _InitItemImport(); + + Reference < XTextRange > xTextRange = + SwXTextRange::CreateTextRangeFromPosition( &rDoc, *rPaM.GetPoint(), 0 ); + Reference < XText > xText = xTextRange->getText(); + Reference < XTextCursor > xTextCursor = + xText->createTextCursorByRange( xTextRange ); + GetTextImport()->SetCursor( xTextCursor ); +} +#endif + +SwXMLImport::~SwXMLImport() throw () +{ + delete pDocElemTokenMap; + delete pTableElemTokenMap; + delete pTableCellAttrTokenMap; + _FinitItemImport(); +} + +void SwXMLImport::setTextInsertMode( + const Reference< XTextRange > & rInsertPos ) +{ + bInsert = sal_True; + + Reference < XText > xText = rInsertPos->getText(); + Reference < XTextCursor > xTextCursor = + xText->createTextCursorByRange( rInsertPos ); + GetTextImport()->SetCursor( xTextCursor ); +} + +void SwXMLImport::setStyleInsertMode( sal_uInt16 nFamilies, + sal_Bool bOverwrite ) +{ + bInsert = !bOverwrite; + nStyleFamilyMask = nFamilies; + bLoadDoc = sal_False; +} + +void SwXMLImport::setBlockMode( ) +{ + bBlock = sal_True; +} + +void SwXMLImport::setOrganizerMode( ) +{ + bOrganizerMode = sal_True; +} + +const Sequence< sal_Int8 > & SwXMLImport::getUnoTunnelId() throw() +{ + static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId(); + return aSeq; +} + +sal_Int64 SAL_CALL SwXMLImport::getSomething( const Sequence< sal_Int8 >& rId ) + throw(RuntimeException) +{ + if( rId.getLength() == 16 + && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) ); + } + return SvXMLImport::getSomething( rId ); +} + +OTextCursorHelper *lcl_xml_GetSwXTextCursor( const Reference < XTextCursor >& rTextCursor ) +{ + Reference<XUnoTunnel> xCrsrTunnel( rTextCursor, UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + if( !xCrsrTunnel.is() ) + return 0; + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper *>( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + return pTxtCrsr; +} + +void SwXMLImport::startDocument( void ) + throw( xml::sax::SAXException, uno::RuntimeException ) +{ + // delegate to parent + SvXMLImport::startDocument(); + + DBG_ASSERT( GetModel().is(), "model is missing" ); + if( !GetModel().is() ) + return; + + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + + Reference< XPropertySet > xImportInfo( getImportInfo() ); + Reference< XPropertySetInfo > xPropertySetInfo; + if( xImportInfo.is() ) + xPropertySetInfo = xImportInfo->getPropertySetInfo(); + if( xPropertySetInfo.is() ) + { + Any aAny; + // insert style mode? + OUString sStyleInsertModeFamilies( + RTL_CONSTASCII_USTRINGPARAM("StyleInsertModeFamilies")); + if( xPropertySetInfo->hasPropertyByName(sStyleInsertModeFamilies) ) + { + aAny = xImportInfo->getPropertyValue(sStyleInsertModeFamilies); + Sequence< OUString> aFamiliesSeq; + if( aAny >>= aFamiliesSeq ) + { + OUString sFrameStyles( RTL_CONSTASCII_USTRINGPARAM ( "FrameStyles" ) ); + OUString sPageStyles( RTL_CONSTASCII_USTRINGPARAM ( "PageStyles" ) ); + OUString sCharacterStyles( RTL_CONSTASCII_USTRINGPARAM ( "CharacterStyles" ) ); + OUString sParagraphStyles( RTL_CONSTASCII_USTRINGPARAM ( "ParagraphStyles" ) ); + OUString sNumberingStyles( RTL_CONSTASCII_USTRINGPARAM ( "NumberingStyles" ) ); + sal_uInt16 nFamilyMask = 0U; + sal_Int32 nCount = aFamiliesSeq.getLength(); + const OUString *pSeq = aFamiliesSeq.getConstArray(); + for( sal_Int32 i=0; i < nCount; i++ ) + { + const OUString& rFamily = pSeq[i]; + if( rFamily==sFrameStyles ) + nFamilyMask |= SFX_STYLE_FAMILY_FRAME; + else if( rFamily==sPageStyles ) + nFamilyMask |= SFX_STYLE_FAMILY_PAGE; + else if( rFamily==sCharacterStyles ) + nFamilyMask |= SFX_STYLE_FAMILY_CHAR; + else if( rFamily==sParagraphStyles ) + nFamilyMask |= SFX_STYLE_FAMILY_PARA; + else if( rFamily==sNumberingStyles ) + nFamilyMask |= SFX_STYLE_FAMILY_PSEUDO; + } + + sal_Bool bOverwrite = sal_False; + OUString sStyleInsertModeOverwrite( + RTL_CONSTASCII_USTRINGPARAM("StyleInsertModeOverwrite")); + if( xPropertySetInfo->hasPropertyByName(sStyleInsertModeOverwrite) ) + { + aAny = xImportInfo->getPropertyValue(sStyleInsertModeOverwrite); + if( aAny.getValueType() == ::getBooleanCppuType() && + *static_cast<const sal_Bool*>(aAny.getValue()) ) + bOverwrite = sal_True; + } + + setStyleInsertMode( nFamilyMask, bOverwrite ); + } + } + + // text insert mode? + OUString sTextInsertModeRange( + RTL_CONSTASCII_USTRINGPARAM("TextInsertModeRange")); + if( xPropertySetInfo->hasPropertyByName(sTextInsertModeRange) ) + { + aAny = xImportInfo->getPropertyValue(sTextInsertModeRange); + Reference<XTextRange> xInsertTextRange; + if( aAny >>= xInsertTextRange ) + setTextInsertMode( xInsertTextRange ); + } + + // auto text mode + OUString sAutoTextMode( + RTL_CONSTASCII_USTRINGPARAM("AutoTextMode")); + if( xPropertySetInfo->hasPropertyByName(sAutoTextMode) ) + { + aAny = xImportInfo->getPropertyValue(sAutoTextMode); + if( aAny.getValueType() == ::getBooleanCppuType() && + *static_cast<const sal_Bool*>(aAny.getValue()) ) + setBlockMode(); + } + + // organizer mode + OUString sOrganizerMode( + RTL_CONSTASCII_USTRINGPARAM("OrganizerMode")); + if( xPropertySetInfo->hasPropertyByName(sOrganizerMode) ) + { + aAny = xImportInfo->getPropertyValue(sOrganizerMode); + if( aAny.getValueType() == ::getBooleanCppuType() && + *static_cast<const sal_Bool*>(aAny.getValue()) ) + setOrganizerMode(); + } + } + + // There only is a text cursor by now if we are in insert mode. In any + // other case we have to create one at the start of the document. + // We also might change into the insert mode later, so we have to make + // sure to first set the insert mode and then create the text import + // helper. Otherwise it won't have the insert flag set! + OTextCursorHelper *pTxtCrsr = 0; + Reference < XTextCursor > xTextCursor; + if( HasTextImport() ) + xTextCursor = GetTextImport()->GetCursor(); + if( !xTextCursor.is() ) + { + Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY ); + Reference < XText > xText = xTextDoc->getText(); + xTextCursor = xText->createTextCursor(); + SwCrsrShell *pCrsrSh = 0; + SwDoc *pDoc = 0; + if( IMPORT_ALL == getImportFlags() ) + { + pTxtCrsr = lcl_xml_GetSwXTextCursor( xTextCursor ); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + if( !pTxtCrsr ) + return; + + pDoc = pTxtCrsr->GetDoc(); + ASSERT( pDoc, "SwDoc missing" ); + if( !pDoc ) + return; + + // Is there a edit shell. If yes, then we are currently inserting + // a document. We then have to insert at the current edit shell's + // cursor position. That not quite clean code, but there is no other + // way currently. + pCrsrSh = pDoc->GetEditShell(); + } + if( pCrsrSh ) + { + const uno::Reference<text::XTextRange> xInsertTextRange( + SwXTextRange::CreateXTextRange( + *pDoc, *pCrsrSh->GetCrsr()->GetPoint(), 0 ) ); + setTextInsertMode( xInsertTextRange ); + xTextCursor = GetTextImport()->GetCursor(); + pTxtCrsr = 0; + } + else + GetTextImport()->SetCursor( xTextCursor ); + } + + if( (getImportFlags() & (IMPORT_CONTENT|IMPORT_MASTERSTYLES)) == 0 ) + return; + + if( !pTxtCrsr ) + pTxtCrsr = lcl_xml_GetSwXTextCursor( xTextCursor ); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + if( !pTxtCrsr ) + return; + + SwDoc *pDoc = pTxtCrsr->GetDoc(); + ASSERT( pDoc, "SwDoc missing" ); + if( !pDoc ) + return; + + if( (getImportFlags() & IMPORT_CONTENT) != 0 && !IsStylesOnlyMode() ) + { + pSttNdIdx = new SwNodeIndex( pDoc->GetNodes() ); + if( IsInsertMode() ) + { + SwPaM *pPaM = pTxtCrsr->GetPaM(); + const SwPosition* pPos = pPaM->GetPoint(); + + // Split once and remember the node that has been splitted. + pDoc->SplitNode( *pPos, false ); + *pSttNdIdx = pPos->nNode.GetIndex()-1; + + // Split again. + pDoc->SplitNode( *pPos, false ); + + // Insert all content into the new node + pPaM->Move( fnMoveBackward ); + pDoc->SetTxtFmtColl + ( *pPaM, pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false ) ); + } + } + + // We need a draw model to be able to set the z order + // --> OD 2005-08-08 #i52858# - method name changed + pDoc->GetOrCreateDrawModel(); + // <-- + + // SJ: #i49801# locking the modell to disable repaints + SdrModel* pDrawModel = pDoc->GetDrawModel(); + if ( pDrawModel ) + pDrawModel->setLock( sal_True ); + + if( !GetGraphicResolver().is() ) + { + pGraphicResolver = SvXMLGraphicHelper::Create( GRAPHICHELPER_MODE_READ ); + Reference< document::XGraphicObjectResolver > xGraphicResolver( pGraphicResolver ); + SetGraphicResolver( xGraphicResolver ); + } + + if( !GetEmbeddedResolver().is() ) + { + SfxObjectShell *pPersist = pDoc->GetPersist(); + if( pPersist ) + { + pEmbeddedResolver = SvXMLEmbeddedObjectHelper::Create( + *pPersist, + EMBEDDEDOBJECTHELPER_MODE_READ ); + Reference< document::XEmbeddedObjectResolver > xEmbeddedResolver( pEmbeddedResolver ); + SetEmbeddedResolver( xEmbeddedResolver ); + } + } +} + +void SwXMLImport::endDocument( void ) + throw( xml::sax::SAXException, uno::RuntimeException ) +{ + DBG_ASSERT( GetModel().is(), "model missing; maybe startDocument wasn't called?" ); + if( !GetModel().is() ) + return; + + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + if( pGraphicResolver ) + SvXMLGraphicHelper::Destroy( pGraphicResolver ); + if( pEmbeddedResolver ) + SvXMLEmbeddedObjectHelper::Destroy( pEmbeddedResolver ); + // Clear the shape import to sort the shapes (and not in the + // destructor that might be called after the import has finished + // for Java filters. + if( HasShapeImport() ) + ClearShapeImport(); + + + SwDoc *pDoc = 0; + if( (getImportFlags() & IMPORT_CONTENT) != 0 && !IsStylesOnlyMode() ) + { + Reference<XUnoTunnel> xCrsrTunnel( GetTextImport()->GetCursor(), + UNO_QUERY); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper *>( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + SwPaM *pPaM = pTxtCrsr->GetPaM(); + if( IsInsertMode() && pSttNdIdx->GetIndex() ) + { + // If we are in insert mode, join the splitted node that is in front + // of the new content with the first new node. Or in other words: + // Revert the first split node. + SwTxtNode* pTxtNode = pSttNdIdx->GetNode().GetTxtNode(); + SwNodeIndex aNxtIdx( *pSttNdIdx ); + if( pTxtNode && pTxtNode->CanJoinNext( &aNxtIdx ) && + pSttNdIdx->GetIndex() + 1 == aNxtIdx.GetIndex() ) + { + // If the PaM points to the first new node, move the PaM to the + // end of the previous node. + if( pPaM && pPaM->GetPoint()->nNode == aNxtIdx ) + { + pPaM->GetPoint()->nNode = *pSttNdIdx; + pPaM->GetPoint()->nContent.Assign( pTxtNode, + pTxtNode->GetTxt().Len() ); + } + +#ifdef DBG_UTIL + // !!! This should be impossible !!!! + ASSERT( pSttNdIdx->GetIndex()+1 != + pPaM->GetBound( sal_True ).nNode.GetIndex(), + "PaM.Bound1 point to new node " ); + ASSERT( pSttNdIdx->GetIndex()+1 != + pPaM->GetBound( sal_False ).nNode.GetIndex(), + "PaM.Bound2 points to new node" ); + + if( pSttNdIdx->GetIndex()+1 == + pPaM->GetBound( sal_True ).nNode.GetIndex() ) + { + sal_uInt16 nCntPos = + pPaM->GetBound( sal_True ).nContent.GetIndex(); + pPaM->GetBound( sal_True ).nContent.Assign( pTxtNode, + pTxtNode->GetTxt().Len() + nCntPos ); + } + if( pSttNdIdx->GetIndex()+1 == + pPaM->GetBound( sal_False ).nNode.GetIndex() ) + { + sal_uInt16 nCntPos = + pPaM->GetBound( sal_False ).nContent.GetIndex(); + pPaM->GetBound( sal_False ).nContent.Assign( pTxtNode, + pTxtNode->GetTxt().Len() + nCntPos ); + } +#endif + // If the first new node isn't empty, convert the node's text + // attributes into hints. Otherwise, set the new node's + // paragraph style at the previous (empty) node. + SwTxtNode* pDelNd = aNxtIdx.GetNode().GetTxtNode(); + if( pTxtNode->GetTxt().Len() ) + pDelNd->FmtToTxtAttr( pTxtNode ); + else + pTxtNode->ChgFmtColl( pDelNd->GetTxtColl() ); + pTxtNode->JoinNext(); + } + } + + SwPosition* pPos = pPaM->GetPoint(); + DBG_ASSERT( !pPos->nContent.GetIndex(), "last paragraph isn't empty" ); + if( !pPos->nContent.GetIndex() ) + { + SwTxtNode* pCurrNd; + ULONG nNodeIdx = pPos->nNode.GetIndex(); + pDoc = pPaM->GetDoc(); + + DBG_ASSERT( pPos->nNode.GetNode().IsCntntNode(), + "insert position is not a content node" ); + if( !IsInsertMode() ) + { + // If we're not in insert mode, the last node is deleted. + const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1]; + if( pPrev->IsCntntNode() || + ( pPrev->IsEndNode() && + pPrev->StartOfSectionNode()->IsSectionNode() ) ) + { + SwCntntNode* pCNd = pPaM->GetCntntNode(); + if( pCNd && pCNd->StartOfSectionIndex()+2 < + pCNd->EndOfSectionIndex() ) + { + pPaM->GetBound(sal_True).nContent.Assign( 0, 0 ); + pPaM->GetBound(sal_False).nContent.Assign( 0, 0 ); + pDoc->GetNodes().Delete( pPaM->GetPoint()->nNode ); + } + } + } + else if( 0 != (pCurrNd = pDoc->GetNodes()[nNodeIdx]->GetTxtNode()) ) + { + // Id we're in insert mode, the empty node is joined with + // the next and the previous one. + if( pCurrNd->CanJoinNext( &pPos->nNode )) + { + SwTxtNode* pNextNd = pPos->nNode.GetNode().GetTxtNode(); + pPos->nContent.Assign( pNextNd, 0 ); + pPaM->SetMark(); pPaM->DeleteMark(); + pNextNd->JoinPrev(); + + // Remove line break that has been inserted by the import, + // but only if one has been inserted! + if( pNextNd->CanJoinPrev(/* &pPos->nNode*/ ) && + *pSttNdIdx != pPos->nNode ) + { +// SwTxtNode* pPrevNd = pPos->nNode.GetNode().GetTxtNode(); +// pPos->nContent.Assign( pPrevNd, 0 ); +// pPaM->SetMark(); pPaM->DeleteMark(); +// pPrevNd->JoinNext(); + pNextNd->JoinPrev(); + } + } + else if( !pCurrNd->GetTxt().Len() ) + { + pPos->nContent.Assign( 0, 0 ); + pPaM->SetMark(); pPaM->DeleteMark(); + pDoc->GetNodes().Delete( pPos->nNode, 1 ); + pPaM->Move( fnMoveBackward ); + } + } + } + } + + /* #108146# Was called too early. Moved from + SwXMLBodyContext_Impl::EndElement */ + + GetTextImport()->RedlineAdjustStartNodeCursor( sal_False ); + + if( (getImportFlags() & IMPORT_CONTENT) != 0 || + ((getImportFlags() & IMPORT_MASTERSTYLES) != 0 && IsStylesOnlyMode()) ) + { + // pDoc might be 0. In this case UpdateTxtCollCondition is looking + // for it itself. + UpdateTxtCollConditions( pDoc ); + } + + GetTextImport()->ResetCursor(); + + delete pSttNdIdx; + pSttNdIdx = 0; + + if( (getImportFlags() == IMPORT_ALL ) ) + { + // Notify math objects. If we are in the package filter this will + // be done by the filter object itself + if( IsInsertMode() ) + pDoc->PrtOLENotify( FALSE ); + else if ( pDoc->IsOLEPrtNotifyPending() ) + pDoc->PrtOLENotify( TRUE ); + } + + // SJ: #i49801# -> now permitting repaints + if ( pDoc ) + { + SdrModel* pDrawModel = pDoc->GetDrawModel(); + if ( pDrawModel ) + pDrawModel->setLock( sal_False ); + } + + // #i90243# + if ( bInititedXForms ) + { + Reference< xforms::XFormsSupplier > xFormsSupp( GetModel(), UNO_QUERY ); + Reference< XNameAccess > xXForms; + if ( xFormsSupp.is() ) + xXForms = xFormsSupp->getXForms().get(); + + if ( xXForms.is() ) + { + try + { + Sequence< beans::PropertyValue > aXFormsSettings; + + ::rtl::OUString sXFormsSettingsName( GetXMLToken( XML_XFORM_MODEL_SETTINGS ) ); + if ( xLateInitSettings.is() && xLateInitSettings->hasByName( sXFormsSettingsName ) ) + { + OSL_VERIFY( xLateInitSettings->getByName( sXFormsSettingsName ) >>= aXFormsSettings ); + applyXFormsSettings( xXForms, aXFormsSettings ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + + // delegate to parent: takes care of error handling + SvXMLImport::endDocument(); +} + + +// Locally derive XMLTextShapeImportHelper, so we can take care of the +// form import This is Writer, but not text specific, so it should go +// here! +class SvTextShapeImportHelper : public XMLTextShapeImportHelper +{ + // hold own reference form import helper, because the SvxImport + // stored in the superclass, from whom we originally got the + // reference, is already destroyed when we want to use it in the + // destructor + UniReference< ::xmloff::OFormLayerXMLImport > rFormImport; + + // hold reference to the one page (if it exists) for calling startPage() + // and endPage. If !xPage.is(), then this document doesn't have a + // XDrawPage. + Reference<drawing::XDrawPage> xPage; + +public: + + SvTextShapeImportHelper(SvXMLImport& rImp); + virtual ~SvTextShapeImportHelper(); +}; + +SvTextShapeImportHelper::SvTextShapeImportHelper(SvXMLImport& rImp) : + XMLTextShapeImportHelper(rImp) +{ + Reference<drawing::XDrawPageSupplier> xSupplier(rImp.GetModel(),UNO_QUERY); + if (xSupplier.is()) + { + if (rImp.GetFormImport().is()) + { + rImp.GetFormImport()->startPage(xSupplier->getDrawPage()); + rFormImport = rImp.GetFormImport(); + } + + xPage = xSupplier->getDrawPage(); + Reference<XShapes> xShapes( xPage, UNO_QUERY ); + XMLShapeImportHelper::startPage( xShapes ); + } +} + +SvTextShapeImportHelper::~SvTextShapeImportHelper() +{ + rFormImport->endPage(); + + if (xPage.is()) + { + Reference<XShapes> xShapes( xPage, UNO_QUERY ); + XMLShapeImportHelper::endPage(xShapes); + } +} + + +XMLShapeImportHelper* SwXMLImport::CreateShapeImport() +{ + return new SvTextShapeImportHelper( *this ); +} + +SvXMLImportContext *SwXMLImport::CreateFontDeclsContext( + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + XMLFontStylesContext *pFSContext = + new XMLFontStylesContext( *this, XML_NAMESPACE_OFFICE, + rLocalName, xAttrList, + gsl_getSystemTextEncoding() ); + SetFontDecls( pFSContext ); + return pFSContext; +} +void SwXMLImport::SetViewSettings(const Sequence < PropertyValue > & aViewProps) +{ + if (IsInsertMode() || IsStylesOnlyMode() || IsBlockMode() || IsOrganizerMode() || !GetModel().is() ) + return; + + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY ); + Reference < XText > xText = xTextDoc->getText(); + Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY); + ASSERT( xTextTunnel.is(), "missing XUnoTunnel for Cursor" ); + if( !xTextTunnel.is() ) + return; + + SwXText *pText = reinterpret_cast< SwXText *>( + sal::static_int_cast< sal_IntPtr >( xTextTunnel->getSomething( SwXText::getUnoTunnelId() ))); + ASSERT( pText, "SwXText missing" ); + if( !pText ) + return; + + SwDoc *pDoc = pText->GetDoc(); + Rectangle aRect; + if( pDoc->GetDocShell() ) + aRect = pDoc->GetDocShell()->GetVisArea( ASPECT_CONTENT ); + //TODO/LATER: why that cast?! + //aRect = ((SfxInPlaceObject *)pDoc->GetDocShell())->GetVisArea(); + + sal_Int32 nCount = aViewProps.getLength(); + const PropertyValue *pValue = aViewProps.getConstArray(); + + sal_Int64 nTmp = 0; + sal_Bool bShowRedlineChanges = sal_False, bBrowseMode = sal_False; + sal_Bool bChangeShowRedline = sal_False, bChangeBrowseMode = sal_False; + + //TODO/LATER: why that cast?! + sal_Bool bTwip = pDoc->GetDocShell()->GetMapUnit ( ) == MAP_TWIP; + //sal_Bool bTwip = pDoc->GetDocShell()->SfxInPlaceObject::GetMapUnit ( ) == MAP_TWIP; + + for (sal_Int32 i = 0; i < nCount ; i++) + { + if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaTop" ) ) ) + { + pValue->Value >>= nTmp; + aRect.setY( static_cast< long >(bTwip ? MM100_TO_TWIP ( nTmp ) : nTmp) ); + } + else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaLeft" ) ) ) + { + pValue->Value >>= nTmp; + aRect.setX( static_cast< long >(bTwip ? MM100_TO_TWIP ( nTmp ) : nTmp) ); + } + else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaWidth" ) ) ) + { + pValue->Value >>= nTmp; + Size aSize( aRect.GetSize() ); + aSize.Width() = static_cast< long >(bTwip ? MM100_TO_TWIP ( nTmp ) : nTmp); + aRect.SetSize( aSize ); + } + else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaHeight" ) ) ) + { + pValue->Value >>= nTmp; + Size aSize( aRect.GetSize() ); + aSize.Height() = static_cast< long >(bTwip ? MM100_TO_TWIP ( nTmp ) : nTmp); + aRect.SetSize( aSize ); + } + else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ShowRedlineChanges" ) ) ) + { + bShowRedlineChanges = *(sal_Bool *)(pValue->Value.getValue()); + bChangeShowRedline = sal_True; + } +// #105372#: Headers and footers are not displayed in BrowseView anymore +// else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ShowHeaderWhileBrowsing" ) ) ) +// else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ShowFooterWhileBrowsing" ) ) ) + else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "InBrowseMode" ) ) ) + { + bBrowseMode = *(sal_Bool *)(pValue->Value.getValue()); + bChangeBrowseMode = sal_True; + } + pValue++; + } + if( pDoc->GetDocShell() ) + pDoc->GetDocShell()->SetVisArea ( aRect ); + + if (bChangeBrowseMode) + pDoc->set(IDocumentSettingAccess::BROWSE_MODE, bBrowseMode ); + + if (bChangeShowRedline) + GetTextImport()->SetShowChanges( bShowRedlineChanges ); +} + +void SwXMLImport::SetConfigurationSettings(const Sequence < PropertyValue > & aConfigProps) +{ + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + Reference< lang::XMultiServiceFactory > xFac( GetModel(), UNO_QUERY ); + if( !xFac.is() ) + return; + + Reference< XPropertySet > xProps( xFac->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.Settings" ) ) ), UNO_QUERY ); + if( !xProps.is() ) + return; + + Reference< XPropertySetInfo > xInfo( xProps->getPropertySetInfo() ); + if( !xInfo.is() ) + return; + + // #111955# + hash_set< String, StringHashRef, StringEqRef > aSet; + aSet.insert(String("ForbiddenCharacters", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("IsKernAsianPunctuation", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("CharacterCompressionType", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("LinkUpdateMode", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("FieldAutoUpdate", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("ChartAutoUpdate", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("AddParaTableSpacing", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("AddParaTableSpacingAtStart", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintAnnotationMode", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintBlackFonts", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintControls", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintDrawings", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintGraphics", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintLeftPages", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintPageBackground", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintProspect", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintReversed", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintRightPages", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintFaxName", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintPaperFromSetup", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintTables", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrintSingleJobs", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("UpdateFromTemplate", RTL_TEXTENCODING_ASCII_US)); + aSet.insert(String("PrinterIndependentLayout", RTL_TEXTENCODING_ASCII_US)); + // --> FME 2005-12-13 #b6354161# + aSet.insert(String("PrintEmptyPages", RTL_TEXTENCODING_ASCII_US)); + // <-- + + sal_Int32 nCount = aConfigProps.getLength(); + const PropertyValue* pValues = aConfigProps.getConstArray(); + + SvtSaveOptions aSaveOpt; + BOOL bIsUserSetting = aSaveOpt.IsLoadUserSettings(), + bSet = bIsUserSetting; + + // for some properties we don't want to use the application + // default if they're missing. So we watch for them in the loop + // below, and set them if not found + bool bPrinterIndependentLayout = false; + bool bUseOldNumbering = false; // #111955# + bool bOutlineLevelYieldsOutlineRule = false; + bool bAddExternalLeading = false; + bool bAddParaSpacingToTableCells = false; + bool bUseFormerLineSpacing = false; + bool bUseFormerObjectPositioning = false; + bool bUseFormerTextWrapping = false; + bool bConsiderWrapOnObjPos = false; + bool bIgnoreFirstLineIndentInNumbering = false; + bool bDoNotJustifyLinesWithManualBreak = false; + bool bDoNotResetParaAttrsForNumFont = false; + bool bLoadReadonly = false; + bool bDoNotCaptureDrawObjsOnPage( false ); + bool bClipAsCharacterAnchoredWriterFlyFrames( false ); + bool bUnixForceZeroExtLeading = false; + bool bUseOldPrinterMetrics = false; + + OUString sRedlineProtectionKey( RTL_CONSTASCII_USTRINGPARAM( "RedlineProtectionKey" ) ); + + while( nCount-- ) + { + if( !bIsUserSetting ) + { + // test over the hash value if the entry is in the table. + String aStr(pValues->Name); + + bSet = aSet.find(aStr) == aSet.end(); + } + + if( bSet ) + { + try + { + if( xInfo->hasPropertyByName( pValues->Name ) ) + { + if( pValues->Name.equals( sRedlineProtectionKey ) ) + { + Sequence<sal_Int8> aKey; + pValues->Value >>= aKey; + GetTextImport()->SetChangesProtectionKey( aKey ); + } + else + { + xProps->setPropertyValue( pValues->Name, + pValues->Value ); + } + } + + // did we find any of the non-default cases? + if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PrinterIndependentLayout")) ) + bPrinterIndependentLayout = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("AddExternalLeading")) ) + bAddExternalLeading = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("AddParaSpacingToTableCells")) ) + bAddParaSpacingToTableCells = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UseFormerLineSpacing")) ) + bUseFormerLineSpacing = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UseFormerObjectPositioning")) ) + bUseFormerObjectPositioning = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UseFormerTextWrapping")) ) + bUseFormerTextWrapping = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UseOldNumbering")) ) + bUseOldNumbering = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("OutlineLevelYieldsNumbering")) ) + bOutlineLevelYieldsOutlineRule = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ConsiderTextWrapOnObjPos")) ) + bConsiderWrapOnObjPos = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IgnoreFirstLineIndentInNumbering")) ) + bIgnoreFirstLineIndentInNumbering = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DoNotJustifyLinesWithManualBreak")) ) + bDoNotJustifyLinesWithManualBreak = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DoNotResetParaAttrsForNumFont")) ) + bDoNotResetParaAttrsForNumFont = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LoadReadonly")) ) + bLoadReadonly = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DoNotCaptureDrawObjsOnPage")) ) + bDoNotCaptureDrawObjsOnPage = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ClipAsCharacterAnchoredWriterFlyFrames")) ) + bClipAsCharacterAnchoredWriterFlyFrames = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UnxForceZeroExtLeading")) ) + bUnixForceZeroExtLeading = true; + else if( pValues->Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UseOldPrinterMetrics")) ) + bUseOldPrinterMetrics = true; + } + catch( Exception& ) + { + DBG_ERROR( "SwXMLImport::SetConfigurationSettings: Exception!" ); + } + } + pValues++; + } + + // finally, treat the non-default cases + // --> OD 2006-04-18 #b6402800# + // introduce boolean, that indicates a document, written by version prior SO8. + const bool bDocumentPriorSO8 = !bConsiderWrapOnObjPos; + // <-- + + if( ! bPrinterIndependentLayout ) + { + Any aAny; + sal_Int16 nTmp = document::PrinterIndependentLayout::DISABLED; + aAny <<= nTmp; + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("PrinterIndependentLayout") ), + aAny ); + } + + if( ! bAddExternalLeading ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("AddExternalLeading")), makeAny( false ) ); + } + + if( ! bUseFormerLineSpacing ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("UseFormerLineSpacing")), makeAny( true ) ); + } + + if( !bUseFormerObjectPositioning ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("UseFormerObjectPositioning")), makeAny( true ) ); + } + + if( !bUseOldNumbering ) // #111955# + { + Any aAny; + sal_Bool bOldNum = true; + aAny.setValue(&bOldNum, ::getBooleanCppuType()); + xProps->setPropertyValue + (OUString( RTL_CONSTASCII_USTRINGPARAM("UseOldNumbering")), + aAny ); + } + + if( !bOutlineLevelYieldsOutlineRule ) + { + Any aAny; + sal_Bool bTmp = true; + aAny.setValue(&bTmp, ::getBooleanCppuType()); + xProps->setPropertyValue + (OUString( RTL_CONSTASCII_USTRINGPARAM + ("OutlineLevelYieldsNumbering")), + aAny ); + } + + if( !bAddParaSpacingToTableCells ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("AddParaSpacingToTableCells")), makeAny( false ) ); + } + + if( !bUseFormerTextWrapping ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("UseFormerTextWrapping")), makeAny( true ) ); + } + + if( !bConsiderWrapOnObjPos ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("ConsiderTextWrapOnObjPos")), makeAny( false ) ); + } + + // FME 2005-05-27 #i47448# + // For SO7pp4, part of the 'new numbering' stuff has been backported from + // SO8. Unfortunately, only part of it and by using the same compatibility option + // like in SO8. Therefore documents generated with SO7pp4, containing + // numbered paragraphs with first line indent differ between SO7pp4 and + // SO8. In order to fix this for SO8pp1, I introduce a new compatiblity + // flag 'bIgnoreFirstLineIndentInNumbering'. This flag has to be set for all + // documents < SO8, but not for SO8. So if the property is not present, the + // flag will be set to 'true'. SO8 documents surely have the + // 'ConsiderWrapOnObjPos' property set (no matter if 'true' or 'false'), + // therefore the correct condition to set this flag is this: + if( !bIgnoreFirstLineIndentInNumbering && bDocumentPriorSO8 ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("IgnoreFirstLineIndentInNumbering")), makeAny( true ) ); + } + + // This flag has to be set for all documents < SO8 + if ( !bDoNotJustifyLinesWithManualBreak && bDocumentPriorSO8 ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DoNotJustifyLinesWithManualBreak")), makeAny( true ) ); + } + // <-- + + // This flag has to be set for all documents < SO8 + if ( !bDoNotResetParaAttrsForNumFont && bDocumentPriorSO8 ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DoNotResetParaAttrsForNumFont")), makeAny( true ) ); + } + + if ( !bLoadReadonly ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("LoadReadonly") ), makeAny( false ) ); + } + + // This flag has to be set for all documents < SO8 + if ( !bDoNotCaptureDrawObjsOnPage && bDocumentPriorSO8 ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DoNotCaptureDrawObjsOnPage") ), makeAny( true ) ); + } + + // This flag has to be set for all documents < SO8 + if ( !bClipAsCharacterAnchoredWriterFlyFrames && bDocumentPriorSO8 ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("ClipAsCharacterAnchoredWriterFlyFrames") ), makeAny( true ) ); + } + + if ( !bUnixForceZeroExtLeading ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("UnxForceZeroExtLeading") ), makeAny( true ) ); + } + + if ( !bUseOldPrinterMetrics ) + { + xProps->setPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("UseOldPrinterMetrics") ), makeAny( true ) ); + } + // <-- + + Reference < XTextDocument > xTextDoc( GetModel(), UNO_QUERY ); + Reference < XText > xText = xTextDoc->getText(); + Reference<XUnoTunnel> xTextTunnel( xText, UNO_QUERY); + ASSERT( xTextTunnel.is(), "missing XUnoTunnel for Cursor" ); + if( xTextTunnel.is() ) + { + SwXText *pText = reinterpret_cast< SwXText *>( + sal::static_int_cast< sal_IntPtr >( xTextTunnel->getSomething( SwXText::getUnoTunnelId() ))); + ASSERT( pText, "SwXText missing" ); + if( pText ) + { + SwDoc *pDoc = pText->GetDoc(); + if( pDoc ) + { + SfxPrinter *pPrinter = pDoc->getPrinter( false ); + if( pPrinter ) + { + // If the printer is known, then the OLE objects will + // already have correct sizes, and we don't have to call + // PrtOLENotify again. Otherwise we have to call it. + // The flag might be set from setting the printer, so it + // it is required to clear it. + pDoc->SetOLEPrtNotifyPending( !pPrinter->IsKnown() ); + + // FME 2007-05-14 #147385# old printer metrics compatibility + if ( pDoc->get(IDocumentSettingAccess::USE_OLD_PRINTER_METRICS ) && + !pDoc->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) ) + { + pPrinter->Compat_OldPrinterMetrics( true ); + pDoc->GetDocShell()->UpdateFontList(); + } + } + } + } + } +} + + +void SwXMLImport::SetDocumentSpecificSettings( + const ::rtl::OUString& _rSettingsGroupName, + const Sequence< PropertyValue>& _rSettings ) +{ + // the only doc-specific settings group we know so far are the XForms settings + if ( !IsXMLToken( _rSettingsGroupName, XML_XFORM_MODEL_SETTINGS ) ) + return; + + // preserve the settings for a later iteration - we are currently reading the settings.xml, + // the content.xml will be read later, by another instance of SwXMLImport + OSL_ENSURE( xLateInitSettings.is(), "SwXMLImport::SetDocumentSpecificSettings: no storage for those settings!" ); + if ( !xLateInitSettings.is() ) + return; + + try + { + if ( xLateInitSettings->hasByName( _rSettingsGroupName ) ) + { + xLateInitSettings->replaceByName( _rSettingsGroupName, makeAny( _rSettings ) ); + OSL_ENSURE( false, "SwXMLImport::SetDocumentSpecificSettings: already have settings for this model!" ); + } + else + xLateInitSettings->insertByName( _rSettingsGroupName, makeAny( _rSettings ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +void SwXMLImport::initialize( + const Sequence<Any>& aArguments ) + throw( uno::Exception, uno::RuntimeException) +{ + // delegate to super class + SvXMLImport::initialize(aArguments); + + // we are only looking for a PropertyValue "PreserveRedlineMode" + sal_Int32 nLength = aArguments.getLength(); + for(sal_Int32 i = 0; i < nLength; i++) + { + beans::PropertyValue aValue; + if ( aArguments[i] >>= aValue ) + { + if (aValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("PreserveRedlineMode"))) + { + OSL_VERIFY( aValue.Value >>= bPreserveRedlineMode ); + } + continue; + } + + beans::NamedValue aNamedValue; + if ( aArguments[i] >>= aNamedValue ) + { + if (aNamedValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("LateInitSettings"))) + { + OSL_VERIFY( aNamedValue.Value >>= xLateInitSettings ); + } + } + } +} + + +// +// UNO component registration helper functions +// + +OUString SAL_CALL SwXMLImport_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisImporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SwXMLImport_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( SwXMLImport_getImplementationName() ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SwXMLImport_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) + throw( uno::Exception ) +{ + // #110680# + // return (cppu::OWeakObject*)new SwXMLImport(IMPORT_ALL); + return (cppu::OWeakObject*)new SwXMLImport( rSMgr, IMPORT_ALL ); +} + +OUString SAL_CALL SwXMLImportStyles_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisStylesImporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SwXMLImportStyles_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( SwXMLImportStyles_getImplementationName() ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SwXMLImportStyles_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) + throw( uno::Exception ) +{ + // #110680# + //return (cppu::OWeakObject*)new SwXMLImport( + // IMPORT_STYLES | IMPORT_MASTERSTYLES | IMPORT_AUTOSTYLES | + // IMPORT_FONTDECLS ); + return (cppu::OWeakObject*)new SwXMLImport( + rSMgr, + IMPORT_STYLES | IMPORT_MASTERSTYLES | IMPORT_AUTOSTYLES | + IMPORT_FONTDECLS ); +} + +OUString SAL_CALL SwXMLImportContent_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisContentImporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SwXMLImportContent_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( SwXMLImportContent_getImplementationName() ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SwXMLImportContent_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) + throw( uno::Exception ) +{ + // #110680# + //return (cppu::OWeakObject*)new SwXMLImport( + // IMPORT_AUTOSTYLES | IMPORT_CONTENT | IMPORT_SCRIPTS | + // IMPORT_FONTDECLS ); + return (cppu::OWeakObject*)new SwXMLImport( + rSMgr, + IMPORT_AUTOSTYLES | IMPORT_CONTENT | IMPORT_SCRIPTS | + IMPORT_FONTDECLS ); +} + +OUString SAL_CALL SwXMLImportMeta_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisMetaImporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SwXMLImportMeta_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( SwXMLImportMeta_getImplementationName() ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SwXMLImportMeta_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) + throw( uno::Exception ) +{ + // #110680# + // return (cppu::OWeakObject*)new SwXMLImport( IMPORT_META ); + return (cppu::OWeakObject*)new SwXMLImport( rSMgr, IMPORT_META ); +} + +OUString SAL_CALL SwXMLImportSettings_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.XMLOasisSettingsImporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SwXMLImportSettings_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( SwXMLImportSettings_getImplementationName() ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SwXMLImportSettings_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) + throw( uno::Exception ) +{ + // #110680# + // return (cppu::OWeakObject*)new SwXMLImport( IMPORT_SETTINGS ); + return (cppu::OWeakObject*)new SwXMLImport( rSMgr, IMPORT_SETTINGS ); +} + + +// XServiceInfo +// override empty method from parent class +OUString SAL_CALL SwXMLImport::getImplementationName() + throw(RuntimeException) +{ + switch( getImportFlags() ) + { + case IMPORT_ALL: + return SwXMLImport_getImplementationName(); + case (IMPORT_STYLES|IMPORT_MASTERSTYLES|IMPORT_AUTOSTYLES|IMPORT_FONTDECLS): + return SwXMLImportStyles_getImplementationName(); + case (IMPORT_AUTOSTYLES|IMPORT_CONTENT|IMPORT_SCRIPTS|IMPORT_FONTDECLS): + return SwXMLImportContent_getImplementationName(); + case IMPORT_META: + return SwXMLImportMeta_getImplementationName(); + case IMPORT_SETTINGS: + return SwXMLImportSettings_getImplementationName(); + default: + // generic name for 'unknown' cases + return OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.Writer.SwXMLImport" ) ); + } +} + +SwDoc* SwImport::GetDocFromXMLImport( SvXMLImport& rImport ) +{ + uno::Reference<lang::XUnoTunnel> xModelTunnel( rImport.GetModel(), uno::UNO_QUERY ); + SwXTextDocument *pTxtDoc = reinterpret_cast< SwXTextDocument *>( + sal::static_int_cast< sal_IntPtr >( xModelTunnel->getSomething(SwXTextDocument::getUnoTunnelId() ))); + ASSERT( pTxtDoc, "Where is my model?" ) + ASSERT( pTxtDoc->GetDocShell(), "Where is my shell?" ) + SwDoc* pDoc = pTxtDoc->GetDocShell()->GetDoc(); + ASSERT( pDoc, "Where is my document?" ) + return pDoc; +} + + +void SwXMLImport::initXForms() +{ + // obtain SwDoc + Reference<XUnoTunnel> xDocTunnel( GetModel(), UNO_QUERY ); + if( ! xDocTunnel.is() ) + return; + SwXTextDocument* pXTextDocument = reinterpret_cast<SwXTextDocument*>( + xDocTunnel->getSomething( SwXTextDocument::getUnoTunnelId() ) ); + if( pXTextDocument == NULL ) + return; + + SwDoc *pDoc = pXTextDocument->GetDocShell()->GetDoc(); + + // init XForms (if not already done) + // (no default model, since we'll load the models) + if( ! pDoc->isXForms() ) + pDoc->initXForms( false ); + + bInititedXForms = sal_True; +} diff --git a/sw/source/filter/xml/xmlimp.hxx b/sw/source/filter/xml/xmlimp.hxx new file mode 100644 index 000000000000..7a6a8d9e26c3 --- /dev/null +++ b/sw/source/filter/xml/xmlimp.hxx @@ -0,0 +1,231 @@ +/************************************************************************ + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLIMP_HXX +#define _XMLIMP_HXX + +#include <sot/storage.hxx> +#include <xmloff/xmlictxt.hxx> +#include "xmlitmap.hxx" +#include <xmloff/xmlimp.hxx> + +class SwDoc; +class SwPaM; +class SvXMLUnitConverter; +class SvXMLTokenMap; +class SvXMLImportItemMapper; +class SfxItemSet; +class SwNodeIndex; +class XMLTextImportHelper; +class SvXMLGraphicHelper; +class SvXMLEmbeddedObjectHelper; + +// define, how many steps ( = paragraphs ) the progress bar should advance +// for styles, autostyles and settings + meta +#define PROGRESS_BAR_STEP 20 + +namespace SwImport { + SwDoc* GetDocFromXMLImport( SvXMLImport& ); +} + +class SwXMLImport: public SvXMLImport +{ + SwNodeIndex *pSttNdIdx; + + SvXMLUnitConverter *pTwipUnitConv; + SvXMLImportItemMapper *pTableItemMapper;// paragraph item import + SvXMLTokenMap *pDocElemTokenMap; + SvXMLTokenMap *pTableElemTokenMap; + SvXMLTokenMap *pTableCellAttrTokenMap; + SvXMLGraphicHelper *pGraphicResolver; + SvXMLEmbeddedObjectHelper *pEmbeddedResolver; + + SvXMLItemMapEntriesRef xTableItemMap; + SvXMLItemMapEntriesRef xTableColItemMap; + SvXMLItemMapEntriesRef xTableRowItemMap; + SvXMLItemMapEntriesRef xTableCellItemMap; + SvStorageRef xPackage; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > + xLateInitSettings; + + sal_uInt16 nStyleFamilyMask;// Mask of styles to load + sal_Bool bLoadDoc : 1; // Load doc or styles only + sal_Bool bInsert : 1; // Insert mode. If styles are + // loaded only sal_False means that + // existing styles will be + // overwritten. + sal_Bool bBlock : 1; // Load text block + sal_Bool bAutoStylesValid : 1; + sal_Bool bShowProgress : 1; + sal_Bool bOrganizerMode : 1; + sal_Bool bInititedXForms : 1; + sal_Bool bPreserveRedlineMode; + + void _InitItemImport(); + void _FinitItemImport(); + void UpdateTxtCollConditions( SwDoc *pDoc ); + + void setTextInsertMode( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > & rInsertPos ); + void setStyleInsertMode( sal_uInt16 nFamilies, + sal_Bool bOverwrite ); + void setBlockMode(); + void setOrganizerMode(); + + +protected: + + // This method is called after the namespace map has been updated, but + // before a context for the current element has been pushed. + virtual SvXMLImportContext *CreateContext( sal_uInt16 nPrefix, + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList ); + + virtual XMLTextImportHelper* CreateTextImport(); + + virtual XMLShapeImportHelper* CreateShapeImport(); + +public: + + // #110680# + SwXMLImport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + sal_uInt16 nImportFlags = IMPORT_ALL); + +#ifdef XML_CORE_API + // #110680# + SwXMLImport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + SwDoc& rDoc, + const SwPaM& rPaM, + sal_Bool bLoadDoc, + sal_Bool bInsertMode, + sal_uInt16 nStyleFamMask, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & rModel, + const ::com::sun::star::uno::Reference< ::com::sun::star::document::XGraphicObjectResolver > &, + SvStorage *pPkg ); +#endif + + ~SwXMLImport() throw(); + + // ::com::sun::star::xml::sax::XDocumentHandler + virtual void SAL_CALL startDocument(void) + throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL endDocument(void) + throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + + // XUnoTunnel + static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId() throw(); + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo (override parent method) + ::rtl::OUString SAL_CALL getImplementationName() + throw( ::com::sun::star::uno::RuntimeException ); + + void InsertStyles( sal_Bool bAuto ); + void FinishStyles(); + + // namespace office + + // NB: in contrast to other CreateFooContexts, this particular one handles + // the root element (i.e. office:document-meta) + SvXMLImportContext *CreateMetaContext( const ::rtl::OUString& rLocalName ); + SvXMLImportContext *CreateScriptContext( const ::rtl::OUString& rLocalName ); + SvXMLImportContext *CreateStylesContext( + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + sal_Bool bAuto ); + SvXMLImportContext *CreateMasterStylesContext( + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList ); + SvXMLImportContext *CreateFontDeclsContext( + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList ); + SvXMLImportContext *CreateBodyContentContext( const ::rtl::OUString& rLocalName ); + sal_uInt16 GetStyleFamilyMask() const { return nStyleFamilyMask; } + sal_Bool IsInsertMode() const { return bInsert; } + sal_Bool IsStylesOnlyMode() const { return !bLoadDoc; } + sal_Bool IsBlockMode() const { return bBlock; } + sal_Bool IsOrganizerMode() const { return bOrganizerMode; } + + inline const SvXMLUnitConverter& GetTwipUnitConverter() const; + inline const SvXMLImportItemMapper& GetTableItemMapper() const; + SvXMLImportContext *CreateTableItemImportContext( sal_uInt16 nPrefix, + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + sal_uInt16 nSubFamily, SfxItemSet& rItemSet ); + + const SvXMLTokenMap& GetDocElemTokenMap(); + const SvXMLTokenMap& GetTableElemTokenMap(); + const SvXMLTokenMap& GetTableCellAttrTokenMap(); + + sal_Bool FindAutomaticStyle( sal_uInt16 nFamily, + const ::rtl::OUString& rName, + const SfxItemSet **ppItemSet=0, + ::rtl::OUString *pParent=0 ) const; + + virtual void SetStatistics( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue> & i_rStats); + virtual void SetViewSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aViewProps); + virtual void SetConfigurationSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aConfigProps); + virtual void SetDocumentSpecificSettings(const ::rtl::OUString& _rSettingsGroupName, + const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& _rSettings); + + SvStorage *GetPackage() { return &xPackage; } + + void SetProgressValue( sal_Int32 nValue ); + + // initialize XForms + virtual void initXForms(); +}; + +inline const SvXMLUnitConverter& SwXMLImport::GetTwipUnitConverter() const +{ + return *pTwipUnitConv; +} + +inline const SvXMLImportItemMapper& SwXMLImport::GetTableItemMapper() const +{ + return *pTableItemMapper; +} + +inline void SwXMLImport::SetProgressValue( sal_Int32 nValue ) +{ + if ( bShowProgress ) + GetProgressBarHelper()->SetValue(nValue); +} + +#endif // _XMLIMP_HXX diff --git a/sw/source/filter/xml/xmlimpit.cxx b/sw/source/filter/xml/xmlimpit.cxx new file mode 100644 index 000000000000..adbaf90e11df --- /dev/null +++ b/sw/source/filter/xml/xmlimpit.cxx @@ -0,0 +1,976 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include "xmlimpit.hxx" +#include <xmloff/xmluconv.hxx> +#include <svl/itempool.hxx> +#include <svl/poolitem.hxx> +#include <svl/itemset.hxx> +#include <xmloff/attrlist.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <editeng/xmlcnitm.hxx> +#include <editeng/memberids.hrc> + + +#include "hintids.hxx" +#include "unomid.h" +#include <svx/unomid.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/shaditem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/brkitem.hxx> +#include <editeng/keepitem.hxx> +#include <editeng/brshitem.hxx> +#include "fmtpdsc.hxx" +#include "fmtornt.hxx" +#include "fmtfsize.hxx" + +#ifndef _FMTLSPLT_HXX +#include "fmtlsplt.hxx" +#endif +#include <xmloff/prhdlfac.hxx> +#include <xmloff/xmltypes.hxx> +#include "xmlithlp.hxx" +#include <com/sun/star/uno/Any.hxx> + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::xmloff::token; +using uno::Any; + +SvXMLImportItemMapper::SvXMLImportItemMapper( + SvXMLItemMapEntriesRef rMapEntries, + USHORT nUnknWhich ) : + mrMapEntries( rMapEntries ), + nUnknownWhich( nUnknWhich ) +{ +} + +SvXMLImportItemMapper::~SvXMLImportItemMapper() +{ +} + +/** fills the given itemset with the attributes in the given list */ +void SvXMLImportItemMapper::importXML( SfxItemSet& rSet, + uno::Reference< xml::sax::XAttributeList > xAttrList, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap ) const +{ + INT16 nAttr = xAttrList->getLength(); + + SvXMLAttrContainerItem *pUnknownItem = 0; + for( INT16 i=0; i < nAttr; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + OUString aLocalName, aPrefix, aNamespace; + USHORT nPrefix = + rNamespaceMap.GetKeyByAttrName( rAttrName, &aPrefix, &aLocalName, + &aNamespace ); + if( XML_NAMESPACE_XMLNS == nPrefix ) + continue; + + const OUString& rValue = xAttrList->getValueByIndex( i ); + + // find a map entry for this attribute + SvXMLItemMapEntry* pEntry = mrMapEntries->getByName( nPrefix, aLocalName ); + + if( pEntry ) + { + // we have a valid map entry here, so lets use it... + if( 0 == (pEntry->nMemberId & (MID_SW_FLAG_NO_ITEM_IMPORT| + MID_SW_FLAG_ELEMENT_ITEM_IMPORT)) ) + { + // first get item from itemset + const SfxPoolItem* pItem = 0; + SfxItemState eState = rSet.GetItemState( pEntry->nWhichId, TRUE, + &pItem ); + + // if its not set, try the pool + if(SFX_ITEM_SET != eState && SFX_WHICH_MAX > pEntry->nWhichId ) + pItem = &rSet.GetPool()->GetDefaultItem(pEntry->nWhichId); + + // do we have an item? + if(eState >= SFX_ITEM_DEFAULT && pItem) + { + SfxPoolItem *pNewItem = pItem->Clone(); + BOOL bPut = FALSE; + + if( 0 == (pEntry->nMemberId&MID_SW_FLAG_SPECIAL_ITEM_IMPORT) ) + { +// bPut = pNewItem->importXML( rValue, +// pEntry->nMemberId & MID_SW_FLAG_MASK, +// rUnitConverter ); + bPut = PutXMLValue( *pNewItem, rValue, + static_cast<sal_uInt16>( pEntry->nMemberId & MID_SW_FLAG_MASK ), + rUnitConverter ); + + } + else + { + bPut = handleSpecialItem( *pEntry, *pNewItem, rSet, + rValue, rUnitConverter, + rNamespaceMap ); + } + + if( bPut ) + rSet.Put( *pNewItem ); + + delete pNewItem; + } + else + { + DBG_ERROR( "Could not get a needed item for xml import!" ); + } + } + else if( 0 != (pEntry->nMemberId & MID_SW_FLAG_NO_ITEM_IMPORT) ) + { + handleNoItem( *pEntry, rSet, rValue, rUnitConverter, + rNamespaceMap ); + } + } + else if( USHRT_MAX != nUnknownWhich ) + { + if( !pUnknownItem ) + { + const SfxPoolItem* pItem = 0; + if( SFX_ITEM_SET == rSet.GetItemState( nUnknownWhich, TRUE, + &pItem ) ) + { + SfxPoolItem *pNew = pItem->Clone(); + pUnknownItem = PTR_CAST( SvXMLAttrContainerItem, pNew ); + DBG_ASSERT( pUnknownItem, + "SvXMLAttrContainerItem expected" ); + if( !pUnknownItem ) + delete pNew; + } + else + { + pUnknownItem = new SvXMLAttrContainerItem( nUnknownWhich ); + } + } + if( pUnknownItem ) + { + if( XML_NAMESPACE_NONE == nPrefix ) + pUnknownItem->AddAttr( aLocalName, rValue ); + else + pUnknownItem->AddAttr( aPrefix, aNamespace, aLocalName, + rValue ); + } + } + } + + if( pUnknownItem ) + { + rSet.Put( *pUnknownItem ); + delete pUnknownItem; + } + + finished( rSet ); +} + +/** this method is called for every item that has the + MID_SW_FLAG_SPECIAL_ITEM_IMPORT flag set */ +BOOL +SvXMLImportItemMapper::handleSpecialItem( const SvXMLItemMapEntry& /*rEntry*/, + SfxPoolItem& /*rItem*/, + SfxItemSet& /*rSet*/, + const OUString& /*rValue*/, + const SvXMLUnitConverter& /*rUnitConverter*/, + const SvXMLNamespaceMap& /*rNamespaceMap*/ ) const +{ + DBG_ERROR( "unsuported special item in xml import" ); + return FALSE; +} + +/** this method is called for every item that has the + MID_SW_FLAG_NO_ITEM_IMPORT flag set */ +BOOL SvXMLImportItemMapper::handleNoItem( const SvXMLItemMapEntry& /*rEntry*/, + SfxItemSet& /*rSet*/, + const OUString& /*rValue*/, + const SvXMLUnitConverter& /*rUnitConverter*/, + const SvXMLNamespaceMap& /*rNamespaceMap*/ ) const +{ + DBG_ERROR( "unsuported no item in xml import" ); + return FALSE; +} + +void SvXMLImportItemMapper::finished( SfxItemSet& ) const +{ + // nothing to do here +} + + + +// put an XML-string value into an item +sal_Bool SvXMLImportItemMapper::PutXMLValue( + SfxPoolItem& rItem, + const ::rtl::OUString& rValue, + sal_uInt16 nMemberId, + const SvXMLUnitConverter& rUnitConverter ) +{ + sal_Bool bOk = sal_False; + + switch (rItem.Which()) + { + case RES_LR_SPACE: + { + SvxLRSpaceItem* pLRSpace = PTR_CAST(SvxLRSpaceItem, &rItem); + DBG_ASSERT( pLRSpace != NULL, "Wrong Which-ID!" ); + + switch( nMemberId ) + { + case MID_L_MARGIN: + case MID_R_MARGIN: + { + sal_Int32 nProp = 100; + sal_Int32 nAbs = 0; + + if( rValue.indexOf( sal_Unicode('%') ) != -1 ) + bOk = rUnitConverter.convertPercent( nProp, rValue ); + else + bOk = rUnitConverter.convertMeasure( nAbs, rValue ); + + if( bOk ) + { + switch( nMemberId ) + { + case MID_L_MARGIN: + pLRSpace->SetTxtLeft( (sal_Int32)nAbs, (sal_uInt16)nProp ); + break; + case MID_R_MARGIN: + pLRSpace->SetRight( (sal_Int32)nAbs, (sal_uInt16)nProp ); + break; + } + } + } + break; + case MID_FIRST_LINE_INDENT: + { + sal_Int32 nProp = 100; + sal_Int32 nAbs = 0; + + if( rValue.indexOf( sal_Unicode('%') ) != -1 ) + bOk = rUnitConverter.convertPercent( nProp, rValue ); + else + bOk = rUnitConverter.convertMeasure( nAbs, rValue, + -0x7fff, 0x7fff ); + + pLRSpace->SetTxtFirstLineOfst( (short)nAbs, (sal_uInt16)nProp ); + } + + case MID_FIRST_AUTO: + { + sal_Bool bAutoFirst; + bOk = rUnitConverter.convertBool( bAutoFirst, rValue ); + if( bOk ) + pLRSpace->SetAutoFirst( bAutoFirst ); + } + break; + + default: + DBG_ERROR( "unknown member id!"); + } + } + break; + + case RES_UL_SPACE: + { + SvxULSpaceItem* pULSpace = PTR_CAST(SvxULSpaceItem, &rItem); + DBG_ASSERT( pULSpace != NULL, "Wrong Which-ID!" ); + + sal_Int32 nProp = 100; + sal_Int32 nAbs = 0; + + if( rValue.indexOf( sal_Unicode('%') ) != -1 ) + bOk = rUnitConverter.convertPercent( nProp, rValue ); + else + bOk = rUnitConverter.convertMeasure( nAbs, rValue ); + + switch( nMemberId ) + { + case MID_UP_MARGIN: + pULSpace->SetUpper( (sal_uInt16)nAbs, (sal_uInt16)nProp ); + break; + case MID_LO_MARGIN: + pULSpace->SetLower( (sal_uInt16)nAbs, (sal_uInt16)nProp ); + break; + default: + DBG_ERROR("unknown MemberId"); + } + } + break; + + case RES_SHADOW: + { + SvxShadowItem* pShadow = PTR_CAST(SvxShadowItem, &rItem); + DBG_ASSERT( pShadow != NULL, "Wrong Which-ID" ); + + sal_Bool bColorFound = sal_False; + sal_Bool bOffsetFound = sal_False; + + SvXMLTokenEnumerator aTokenEnum( rValue ); + + Color aColor( 128,128, 128 ); + pShadow->SetLocation( SVX_SHADOW_BOTTOMRIGHT ); + + OUString aToken; + while( aTokenEnum.getNextToken( aToken ) ) + { + if( IsXMLToken( aToken, XML_NONE ) ) + { + pShadow->SetLocation( SVX_SHADOW_NONE ); + bOk = sal_True; + } + else if( !bColorFound && aToken.compareToAscii( "#", 1 ) == 0 ) + { + bOk = rUnitConverter.convertColor( aColor, aToken ); + if( !bOk ) + return sal_False; + + bColorFound = sal_True; + } + else if( !bOffsetFound ) + { + sal_Int32 nX = 0, nY = 0; + + bOk = rUnitConverter.convertMeasure( nX, aToken ); + if( bOk && aTokenEnum.getNextToken( aToken ) ) + bOk = rUnitConverter.convertMeasure( nY, aToken ); + + if( bOk ) + { + if( nX < 0 ) + { + if( nY < 0 ) + { + pShadow->SetLocation( SVX_SHADOW_TOPLEFT ); + } + else + { + pShadow->SetLocation( SVX_SHADOW_BOTTOMLEFT ); + } + } + else + { + if( nY < 0 ) + { + pShadow->SetLocation( SVX_SHADOW_TOPRIGHT ); + } + else + { + pShadow->SetLocation( SVX_SHADOW_BOTTOMRIGHT ); + } + } + + if( nX < 0 ) nX *= -1; + if( nY < 0 ) nY *= -1; + + pShadow->SetWidth( static_cast< USHORT >( (nX + nY) >> 1 ) ); + } + } + } + + if( bOk && ( bColorFound || bOffsetFound ) ) + { + pShadow->SetColor( aColor ); + } + else + bOk = sal_False; + } + break; + + case RES_BOX: + { + SvxBoxItem* pBox = PTR_CAST(SvxBoxItem, &rItem); + DBG_ASSERT( pBox != NULL, "Wrong WHich-ID" ); + + /** copy SvxBorderLines */ + SvxBorderLine* pTop = pBox->GetTop() == NULL ? + NULL : new SvxBorderLine( *pBox->GetTop() ); + SvxBorderLine* pBottom = pBox->GetBottom() == NULL ? + NULL : new SvxBorderLine( *pBox->GetBottom() ); + SvxBorderLine* pLeft = pBox->GetLeft() == NULL ? + NULL : new SvxBorderLine( *pBox->GetLeft() ); + SvxBorderLine* pRight = pBox->GetRight() == NULL ? + NULL : new SvxBorderLine( *pBox->GetRight() ); + + sal_Int32 nTemp; + + switch( nMemberId ) + { + case ALL_BORDER_PADDING: + case LEFT_BORDER_PADDING: + case RIGHT_BORDER_PADDING: + case TOP_BORDER_PADDING: + case BOTTOM_BORDER_PADDING: + if(!rUnitConverter.convertMeasure( nTemp, rValue, 0, 0xffff )) + return sal_False; + + if( nMemberId == LEFT_BORDER_PADDING || + nMemberId == ALL_BORDER_PADDING ) + pBox->SetDistance( (sal_uInt16)nTemp, BOX_LINE_LEFT ); + if( nMemberId == RIGHT_BORDER_PADDING || + nMemberId == ALL_BORDER_PADDING ) + pBox->SetDistance( (sal_uInt16)nTemp, BOX_LINE_RIGHT ); + if( nMemberId == TOP_BORDER_PADDING || + nMemberId == ALL_BORDER_PADDING ) + pBox->SetDistance( (sal_uInt16)nTemp, BOX_LINE_TOP ); + if( nMemberId == BOTTOM_BORDER_PADDING || + nMemberId == ALL_BORDER_PADDING ) + pBox->SetDistance( (sal_uInt16)nTemp, BOX_LINE_BOTTOM); + break; + + case ALL_BORDER: + case LEFT_BORDER: + case RIGHT_BORDER: + case TOP_BORDER: + case BOTTOM_BORDER: + { + sal_Bool bHasStyle = sal_False; + sal_Bool bHasWidth = sal_False; + sal_Bool bHasColor = sal_False; + + sal_uInt16 nStyle = USHRT_MAX; + sal_uInt16 nWidth = 0; + sal_uInt16 nNamedWidth = USHRT_MAX; + + Color aColor( COL_BLACK ); + + if( !lcl_frmitems_parseXMLBorder( rValue, rUnitConverter, + bHasStyle, nStyle, + bHasWidth, nWidth, nNamedWidth, + bHasColor, aColor ) ) + return sal_False; + + if( TOP_BORDER == nMemberId || ALL_BORDER == nMemberId ) + lcl_frmitems_setXMLBorder( pTop, + bHasStyle, nStyle, + bHasWidth, nWidth, nNamedWidth, + bHasColor, aColor ); + + if( BOTTOM_BORDER == nMemberId || ALL_BORDER == nMemberId ) + lcl_frmitems_setXMLBorder( pBottom, + bHasStyle, nStyle, + bHasWidth, nWidth, nNamedWidth, + bHasColor, aColor ); + + if( LEFT_BORDER == nMemberId || ALL_BORDER == nMemberId ) + lcl_frmitems_setXMLBorder( pLeft, + bHasStyle, nStyle, + bHasWidth, nWidth, nNamedWidth, + bHasColor, aColor ); + + if( RIGHT_BORDER == nMemberId || ALL_BORDER == nMemberId ) + lcl_frmitems_setXMLBorder( pRight, + bHasStyle, nStyle, + bHasWidth, nWidth, nNamedWidth, + bHasColor, aColor ); + } + break; + case ALL_BORDER_LINE_WIDTH: + case LEFT_BORDER_LINE_WIDTH: + case RIGHT_BORDER_LINE_WIDTH: + case TOP_BORDER_LINE_WIDTH: + case BOTTOM_BORDER_LINE_WIDTH: + { + SvXMLTokenEnumerator aTokenEnum( rValue ); + + sal_Int32 nInWidth, nDistance, nOutWidth; + + OUString aToken; + if( !aTokenEnum.getNextToken( aToken ) ) + return sal_False; + + if( !rUnitConverter.convertMeasure( nInWidth, aToken, + DEF_LINE_WIDTH_0, + DEF_LINE_WIDTH_4 ) ) + return sal_False; + + if( !aTokenEnum.getNextToken( aToken ) ) + return sal_False; + + if( !rUnitConverter.convertMeasure( nDistance, aToken, + DEF_LINE_WIDTH_0, + DEF_LINE_WIDTH_4 ) ) + return sal_False; + + if( !aTokenEnum.getNextToken( aToken ) ) + return sal_False; + + if( !rUnitConverter.convertMeasure( nOutWidth, aToken, + DEF_LINE_WIDTH_0, + DEF_LINE_WIDTH_4 ) ) + return sal_False; + + // #i61946: accept line style even it's not part of our "normal" set of line styles + sal_uInt16 nWidth = 0; + + if( TOP_BORDER_LINE_WIDTH == nMemberId || + ALL_BORDER_LINE_WIDTH == nMemberId ) + lcl_frmitems_setXMLBorder( pTop, nWidth, + static_cast< sal_uInt16 >( nOutWidth ), + static_cast< sal_uInt16 >( nInWidth ), + static_cast< sal_uInt16 >( nDistance ) ); + + if( BOTTOM_BORDER_LINE_WIDTH == nMemberId || + ALL_BORDER_LINE_WIDTH == nMemberId ) + lcl_frmitems_setXMLBorder( pBottom, nWidth, + static_cast< sal_uInt16 >( nOutWidth ), + static_cast< sal_uInt16 >( nInWidth ), + static_cast< sal_uInt16 >( nDistance ) ); + + if( LEFT_BORDER_LINE_WIDTH == nMemberId || + ALL_BORDER_LINE_WIDTH == nMemberId ) + lcl_frmitems_setXMLBorder( pLeft, nWidth, + static_cast< sal_uInt16 >( nOutWidth ), + static_cast< sal_uInt16 >( nInWidth ), + static_cast< sal_uInt16 >( nDistance ) ); + + if( RIGHT_BORDER_LINE_WIDTH == nMemberId || + ALL_BORDER_LINE_WIDTH == nMemberId ) + lcl_frmitems_setXMLBorder( pRight, nWidth, + static_cast< sal_uInt16 >( nOutWidth ), + static_cast< sal_uInt16 >( nInWidth ), + static_cast< sal_uInt16 >( nDistance ) ); + } + break; + } + + pBox->SetLine( pTop, BOX_LINE_TOP ); + pBox->SetLine( pBottom, BOX_LINE_BOTTOM ); + pBox->SetLine( pLeft, BOX_LINE_LEFT ); + pBox->SetLine( pRight, BOX_LINE_RIGHT ); + + delete pTop; + delete pBottom; + delete pLeft; + delete pRight; + + bOk = sal_True; + } + break; + + case RES_BREAK: + { + SvxFmtBreakItem* pFmtBreak = PTR_CAST(SvxFmtBreakItem, &rItem); + DBG_ASSERT( pFmtBreak != NULL, "Wrong Which-ID" ); + + sal_uInt16 eEnum; + + if( !rUnitConverter.convertEnum( eEnum, rValue, psXML_BreakType ) ) + return sal_False; + + if( eEnum == 0 ) + { + pFmtBreak->SetValue( SVX_BREAK_NONE ); + bOk = sal_True; + } + else + { + switch( nMemberId ) + { + case MID_BREAK_BEFORE: + pFmtBreak->SetValue( static_cast< USHORT >((eEnum == 1) ? + SVX_BREAK_COLUMN_BEFORE : + SVX_BREAK_PAGE_BEFORE) ); + break; + case MID_BREAK_AFTER: + pFmtBreak->SetValue( static_cast< USHORT >((eEnum == 1) ? + SVX_BREAK_COLUMN_AFTER : + SVX_BREAK_PAGE_AFTER) ); + break; + } + bOk = sal_True; + } + } + break; + + case RES_KEEP: + { + SvxFmtKeepItem* pFmtKeep = PTR_CAST(SvxFmtKeepItem, &rItem); + DBG_ASSERT( pFmtKeep != NULL, "Wrong Which-ID" ); + + if( IsXMLToken( rValue, XML_ALWAYS ) || + IsXMLToken( rValue, XML_TRUE ) ) + { + pFmtKeep->SetValue( sal_True ); + bOk = sal_True; + } + else if( IsXMLToken( rValue, XML_AUTO ) || + IsXMLToken( rValue, XML_FALSE ) ) + { + pFmtKeep->SetValue( sal_False ); + bOk = sal_True; + } + } + break; + + case RES_BACKGROUND: + { + SvxBrushItem* pBrush = PTR_CAST(SvxBrushItem, &rItem); + DBG_ASSERT( pBrush != NULL, "Wrong Which-ID" ); + + Color aTempColor; + switch( nMemberId ) + { + case MID_BACK_COLOR: + if( IsXMLToken( rValue, XML_TRANSPARENT ) ) + { + pBrush->GetColor().SetTransparency(0xff); + bOk = sal_True; + } + else if( rUnitConverter.convertColor( aTempColor, rValue ) ) + { + aTempColor.SetTransparency(0); + pBrush->SetColor( aTempColor ); + bOk = sal_True; + } + break; + + case MID_GRAPHIC_LINK: + { + SvxGraphicPosition eOldGraphicPos = pBrush->GetGraphicPos(); + uno::Any aAny; + aAny <<= rValue; + pBrush->PutValue( aAny, MID_GRAPHIC_URL ); + if( GPOS_NONE == eOldGraphicPos && + GPOS_NONE != pBrush->GetGraphicPos() ) + pBrush->SetGraphicPos( GPOS_TILED ); + bOk = sal_True ; + } + break; + + case MID_GRAPHIC_REPEAT: + { + SvxGraphicPosition eGraphicPos = pBrush->GetGraphicPos(); + sal_uInt16 nPos = GPOS_NONE; + if( rUnitConverter.convertEnum( nPos, rValue, + psXML_BrushRepeat ) ) + { + if( GPOS_MM != nPos || GPOS_NONE == eGraphicPos || + GPOS_AREA == eGraphicPos || GPOS_TILED == eGraphicPos ) + pBrush->SetGraphicPos( (SvxGraphicPosition)nPos ); + bOk = sal_True; + } + } + break; + + case MID_GRAPHIC_POSITION: + { + SvxGraphicPosition ePos = GPOS_NONE, eTmp; + sal_uInt16 nTmp; + SvXMLTokenEnumerator aTokenEnum( rValue ); + OUString aToken; + sal_Bool bHori = sal_False, bVert = sal_False; + bOk = sal_True; + while( bOk && aTokenEnum.getNextToken( aToken ) ) + { + if( bHori && bVert ) + { + bOk = sal_False; + } + else if( -1 != aToken.indexOf( sal_Unicode('%') ) ) + { + sal_Int32 nPrc = 50; + if( rUnitConverter.convertPercent( nPrc, aToken ) ) + { + if( !bHori ) + { + ePos = nPrc < 25 ? GPOS_LT : + (nPrc < 75 ? GPOS_MM : GPOS_RB); + bHori = sal_True; + } + else + { + eTmp = nPrc < 25 ? GPOS_LT: + (nPrc < 75 ? GPOS_LM : GPOS_LB); + lcl_frmitems_MergeXMLVertPos( ePos, eTmp ); + bVert = sal_True; + } + } + else + { + // wrong percentage + bOk = sal_False; + } + } + else if( IsXMLToken( aToken, XML_CENTER ) ) + { + if( bHori ) + lcl_frmitems_MergeXMLVertPos( ePos, GPOS_MM ); + else if ( bVert ) + lcl_frmitems_MergeXMLHoriPos( ePos, GPOS_MM ); + else + ePos = GPOS_MM; + } + else if( rUnitConverter.convertEnum( nTmp, aToken, + psXML_BrushHoriPos ) ) + { + if( bVert ) + lcl_frmitems_MergeXMLHoriPos( + ePos, (SvxGraphicPosition)nTmp ); + else if( !bHori ) + ePos = (SvxGraphicPosition)nTmp; + else + bOk = sal_False; + bHori = sal_True; + } + else if( rUnitConverter.convertEnum( nTmp, aToken, + psXML_BrushVertPos ) ) + { + if( bHori ) + lcl_frmitems_MergeXMLVertPos( + ePos, (SvxGraphicPosition)nTmp ); + else if( !bVert ) + ePos = (SvxGraphicPosition)nTmp; + else + bOk = sal_False; + bVert = sal_True; + } + else + { + bOk = sal_False; + } + } + + bOk &= GPOS_NONE != ePos; + if( bOk ) + pBrush->SetGraphicPos( ePos ); + } + break; + + case MID_GRAPHIC_FILTER: + pBrush->SetGraphicFilter( rValue.getStr() ); + bOk = sal_True; + break; + } + } + break; + + case RES_PAGEDESC: + { + SwFmtPageDesc* pPageDesc = PTR_CAST(SwFmtPageDesc, &rItem); + DBG_ASSERT( pPageDesc != NULL, "Wrong Which-ID" ); + + if( MID_PAGEDESC_PAGENUMOFFSET==nMemberId ) + { + sal_Int32 nVal; + bOk = rUnitConverter.convertNumber( nVal, rValue, 0, USHRT_MAX ); + if( bOk ) + pPageDesc->SetNumOffset( (USHORT)nVal ); + } + } + break; + + case RES_LAYOUT_SPLIT: + case RES_ROW_SPLIT: + { + SfxBoolItem* pSplit = PTR_CAST(SfxBoolItem, &rItem); + DBG_ASSERT( pSplit != NULL, "Wrong Which-ID" ); + + if( IsXMLToken( rValue, XML_AUTO ) || + IsXMLToken( rValue, XML_TRUE ) ) + { + pSplit->SetValue( sal_True ); + bOk = sal_True; + } + else if( IsXMLToken( rValue, XML_ALWAYS ) || + IsXMLToken( rValue, XML_FALSE ) ) + { + pSplit->SetValue( sal_False ); + bOk = sal_True; + } + } + break; + + case RES_HORI_ORIENT: + { + SwFmtHoriOrient* pHoriOrient = PTR_CAST(SwFmtHoriOrient, &rItem); + DBG_ASSERT( pHoriOrient != NULL, "Wrong Which-ID" ); + + sal_uInt16 nValue; + bOk = rUnitConverter.convertEnum( nValue, rValue, + aXMLTableAlignMap ); + if( bOk ) + pHoriOrient->SetHoriOrient( nValue ); + } + break; + + case RES_VERT_ORIENT: + { + SwFmtVertOrient* pVertOrient = PTR_CAST(SwFmtVertOrient, &rItem); + DBG_ASSERT( pVertOrient != NULL, "Wrong Which-ID" ); + + sal_uInt16 nValue; + bOk = rUnitConverter.convertEnum( nValue, rValue, + aXMLTableVAlignMap ); + if( bOk ) + pVertOrient->SetVertOrient( nValue ); + //#i8855# text::VertOrientation::NONE is stored as empty string and should be applied here + else if(!rValue.getLength()) + { + pVertOrient->SetVertOrient( text::VertOrientation::NONE ); + bOk = sal_True; + } + } + break; + + case RES_FRM_SIZE: + { + SwFmtFrmSize* pFrmSize = PTR_CAST(SwFmtFrmSize, &rItem); + DBG_ASSERT( pFrmSize != NULL, "Wrong Which-ID" ); + + sal_Bool bSetHeight = sal_False; + sal_Bool bSetWidth = sal_False; + sal_Bool bSetSizeType = sal_False; + SwFrmSize eSizeType = ATT_VAR_SIZE; + sal_Int32 nMin = MINLAY; + + switch( nMemberId ) + { + case MID_FRMSIZE_REL_WIDTH: + { + sal_Int32 nValue; + bOk = rUnitConverter.convertPercent( nValue, rValue ); + if( bOk ) + { + if( nValue < 1 ) + nValue = 1; + else if( nValue > 100 ) + nValue = 100; + + pFrmSize->SetWidthPercent( (sal_Int8)nValue ); + } + } + break; + case MID_FRMSIZE_WIDTH: + bSetWidth = sal_True; + break; + case MID_FRMSIZE_MIN_HEIGHT: + eSizeType = ATT_MIN_SIZE; + bSetHeight = sal_True; + nMin = 1; + bSetSizeType = sal_True; + break; + case MID_FRMSIZE_FIX_HEIGHT: + eSizeType = ATT_FIX_SIZE; + bSetHeight = sal_True; + nMin = 1; + bSetSizeType = sal_True; + break; + case MID_FRMSIZE_COL_WIDTH: + eSizeType = ATT_FIX_SIZE; + bSetWidth = sal_True; + bSetSizeType = sal_True; + break; + case MID_FRMSIZE_REL_COL_WIDTH: + { + sal_Int32 nPos = rValue.indexOf( (sal_Unicode)'*' ); + if( -1L != nPos ) + { + OUString sNum( rValue.copy( 0L, nPos ) ); + sal_Int32 nValue = rValue.toInt32(); + if( nValue < MINLAY ) + nValue = MINLAY; + else if( nValue > USHRT_MAX ) + nValue = USHRT_MAX; + + pFrmSize->SetWidth( (sal_uInt16)nValue ); + pFrmSize->SetHeightSizeType( ATT_VAR_SIZE ); + bOk = sal_True; + } + } + break; + } + + sal_Int32 nValue; + if( bSetHeight || bSetWidth ) + { + bOk = rUnitConverter.convertMeasure( nValue, rValue, nMin, + USHRT_MAX ); + if( bOk ) + { + if( bSetWidth ) + pFrmSize->SetWidth( (sal_uInt16)nValue ); + if( bSetHeight ) + pFrmSize->SetHeight( (sal_uInt16)nValue ); + if( bSetSizeType ) + pFrmSize->SetHeightSizeType( eSizeType ); + } + } + } + break; + + case RES_FRAMEDIR: + { + const XMLPropertyHandler* pWritingModeHandler = + XMLPropertyHandlerFactory::CreatePropertyHandler( + XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT ); + if( pWritingModeHandler != NULL ) + { + Any aAny; + bOk = pWritingModeHandler->importXML( rValue, aAny, + rUnitConverter ); + if( bOk ) + bOk = rItem.PutValue( aAny ); + } + } + break; + + case RES_COLLAPSING_BORDERS: + { + SfxBoolItem* pBorders = PTR_CAST(SfxBoolItem, &rItem); + DBG_ASSERT( pBorders != NULL, "Wrong Which-ID" ); + + if( IsXMLToken( rValue, XML_COLLAPSING ) ) + { + pBorders->SetValue( sal_True ); + bOk = sal_True; + } + else if( IsXMLToken( rValue, XML_SEPARATING ) ) + { + pBorders->SetValue( sal_False ); + bOk = sal_True; + } + else + bOk = sal_False; + } + break; + + default: + DBG_ERROR("Item not implemented!"); + break; + } + + return bOk; +} + + diff --git a/sw/source/filter/xml/xmlimpit.hxx b/sw/source/filter/xml/xmlimpit.hxx new file mode 100644 index 000000000000..f9f9e746e126 --- /dev/null +++ b/sw/source/filter/xml/xmlimpit.hxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _XMLIMPIT_HXX +#define _XMLIMPIT_HXX + +#include <limits.h> +#include <tools/solar.h> +#include <tools/ref.hxx> + + +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include "xmlitmap.hxx" + +namespace rtl { class OUString; } + +class SvXMLUnitConverter; +class SfxPoolItem; +class SfxItemSet; +class SvXMLNamespaceMap; +struct SvXMLItemMapEntry; + +class SvXMLImportItemMapper +{ +protected: + SvXMLItemMapEntriesRef mrMapEntries; + USHORT nUnknownWhich; + +public: + SvXMLImportItemMapper( SvXMLItemMapEntriesRef rMapEntries , + USHORT nUnknWhich=USHRT_MAX ); + virtual ~SvXMLImportItemMapper(); + + /** fills the given itemset with the attributes in the given list */ + void importXML( SfxItemSet& rSet, + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > xAttrList, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap ) const; + + /** this method is called for every item that has the + MID_SW_FLAG_SPECIAL_ITEM_IMPORT flag set */ + virtual BOOL handleSpecialItem( const SvXMLItemMapEntry& rEntry, + SfxPoolItem& rItem, + SfxItemSet& rSet, + const ::rtl::OUString& rValue, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap ) const; + + /** this method is called for every item that has the + MID_SW_FLAG_NO_ITEM_IMPORT flag set */ + virtual BOOL handleNoItem( const SvXMLItemMapEntry& rEntry, + SfxItemSet& rSet, + const ::rtl::OUString& rValue, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap ) const; + + /** This method is called when all attributes have benn processed. It + * may be used to remove items that are incomplete */ + virtual void finished( SfxItemSet& rSet ) const; + + inline void setMapEntries( SvXMLItemMapEntriesRef rMapEntries ); + inline SvXMLItemMapEntriesRef getMapEntries() const; + + + /** This method is called for every item that should be set based + upon an XML attribute value. */ + static sal_Bool PutXMLValue( + SfxPoolItem& rItem, + const ::rtl::OUString& rValue, + sal_uInt16 nMemberId, + const SvXMLUnitConverter& rUnitConverter ); +}; + +inline void +SvXMLImportItemMapper::setMapEntries( SvXMLItemMapEntriesRef rMapEntries ) +{ + mrMapEntries = rMapEntries; +} + +inline SvXMLItemMapEntriesRef +SvXMLImportItemMapper::getMapEntries() const +{ + return mrMapEntries; +} + + +#endif // _XMLIMPIT_HXX diff --git a/sw/source/filter/xml/xmlitem.cxx b/sw/source/filter/xml/xmlitem.cxx new file mode 100644 index 000000000000..76baffc198c1 --- /dev/null +++ b/sw/source/filter/xml/xmlitem.cxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include <tools/debug.hxx> +#include <xmloff/xmlimp.hxx> +#include "xmlimpit.hxx" +#include "xmlitem.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; + +SvXMLItemSetContext::SvXMLItemSetContext( SvXMLImport& rImp, USHORT nPrfx, + const OUString& rLName, + const uno::Reference< xml::sax::XAttributeList >& xAttrList, + SfxItemSet& rISet, + const SvXMLImportItemMapper& rIMap, + const SvXMLUnitConverter& rUnitConverter ): + SvXMLImportContext( rImp, nPrfx, rLName ), + rItemSet( rISet ), + rIMapper( rIMap ), + rUnitConv( rUnitConverter ) + +{ + rIMapper.importXML( rItemSet, xAttrList, rUnitConv, + GetImport().GetNamespaceMap() ); +} + +SvXMLItemSetContext::~SvXMLItemSetContext() +{ +} + +SvXMLImportContext *SvXMLItemSetContext::CreateChildContext( USHORT nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList >& xAttrList ) +{ + SvXMLItemMapEntriesRef xMapEntries = rIMapper.getMapEntries(); + SvXMLItemMapEntry* pEntry = xMapEntries->getByName( nPrefix, rLocalName ); + + if( pEntry && 0 != (pEntry->nMemberId & MID_SW_FLAG_ELEMENT_ITEM_IMPORT) ) + { + return CreateChildContext( nPrefix, rLocalName, xAttrList, + rItemSet, *pEntry, rUnitConv ); + } + else + { + return new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + } +} + +/** This method is called from this instance implementation of + CreateChildContext if the element matches an entry in the + SvXMLImportItemMapper with the mid flag MID_SW_FLAG_ELEMENT +*/ +SvXMLImportContext *SvXMLItemSetContext::CreateChildContext( USHORT nPrefix, + const rtl::OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList >& /*xAttrList*/, + SfxItemSet& /*rItemSet*/, + const SvXMLItemMapEntry& /*rEntry*/, + const SvXMLUnitConverter& /*rUnitConv*/ ) +{ + return new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); +} + + diff --git a/sw/source/filter/xml/xmlitem.hxx b/sw/source/filter/xml/xmlitem.hxx new file mode 100644 index 000000000000..013afdb804b5 --- /dev/null +++ b/sw/source/filter/xml/xmlitem.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLITEM_HXX +#define _XMLITEM_HXX + +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <tools/solar.h> +#include <limits.h> +#include <xmloff/xmlictxt.hxx> + +namespace rtl { class OUString; } + +class SfxItemSet; +class SvXMLImportItemMapper; +class SvXMLUnitConverter; +struct SvXMLItemMapEntry; + +class SvXMLItemSetContext : public SvXMLImportContext +{ +protected: + SfxItemSet &rItemSet; + const SvXMLImportItemMapper &rIMapper; + const SvXMLUnitConverter &rUnitConv; + +public: + + SvXMLItemSetContext( SvXMLImport& rImport, USHORT nPrfx, + const ::rtl::OUString& rLName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList, + SfxItemSet& rItemSet, + const SvXMLImportItemMapper& rIMappper, + const SvXMLUnitConverter& rUnitConv ); + + virtual ~SvXMLItemSetContext(); + + virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix, + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList ); + + // This method is called from this instance implementation of + // CreateChildContext if the element matches an entry in the + // SvXMLImportItemMapper with the mid flag MID_SW_FLAG_ELEMENT_ITEM_IMPORT + virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix, + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList, + SfxItemSet& rItemSet, + const SvXMLItemMapEntry& rEntry, + const SvXMLUnitConverter& rUnitConv ); + + +}; + + +#endif // _XMLITEM_HXX + diff --git a/sw/source/filter/xml/xmliteme.cxx b/sw/source/filter/xml/xmliteme.cxx new file mode 100644 index 000000000000..5645891c5b3c --- /dev/null +++ b/sw/source/filter/xml/xmliteme.cxx @@ -0,0 +1,256 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <hintids.hxx> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/shl.hxx> +#include <xmloff/xmluconv.hxx> +#include "xmlexpit.hxx" +#include <xmloff/nmspmap.hxx> +#include <xmloff/xmltabe.hxx> +#include "xmlbrshe.hxx" +#include <editeng/tstpitem.hxx> +#include <editeng/brshitem.hxx> +#include <vcl/fldunit.hxx> +#include <swmodule.hxx> +#include <doc.hxx> +#include "fmtornt.hxx" +#include <unomid.h> +#include "frmfmt.hxx" +#include "fmtfsize.hxx" +#include "swrect.hxx" +#include "xmlexp.hxx" +#include <editeng/memberids.hrc> + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::xmloff::token; + +extern SvXMLItemMapEntry aXMLTableItemMap[]; +extern SvXMLItemMapEntry aXMLTableRowItemMap[]; +extern SvXMLItemMapEntry aXMLTableCellItemMap[]; + + +class SwXMLTableItemMapper_Impl: public SvXMLExportItemMapper +{ + SwXMLBrushItemExport aBrushItemExport; + +protected: + + sal_uInt32 nAbsWidth; + + void AddAttribute( sal_uInt16 nPrefix, enum XMLTokenEnum eLName, + const OUString& rValue, + const SvXMLNamespaceMap& rNamespaceMap, + SvXMLAttributeList& rAttrList ) const; + +public: + + SwXMLTableItemMapper_Impl( + SvXMLItemMapEntriesRef rMapEntries, + SwXMLExport& rExp ); + + virtual ~SwXMLTableItemMapper_Impl(); + + virtual void handleSpecialItem( SvXMLAttributeList& rAttrList, + const SvXMLItemMapEntry& rEntry, + const SfxPoolItem& rItem, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap, + const SfxItemSet *pSet = NULL ) const; + + virtual void handleElementItem( + SvXMLExport& rExport, + const SvXMLItemMapEntry& rEntry, + const SfxPoolItem& rItem, + const SvXMLUnitConverter& rUnitConverter, + const SfxItemSet& rSet, + sal_uInt16 nFlags ) const; + + inline void SetAbsWidth( sal_uInt32 nAbs ); +}; + +SwXMLTableItemMapper_Impl::SwXMLTableItemMapper_Impl( + SvXMLItemMapEntriesRef rMapEntries, + SwXMLExport& rExp ) : + SvXMLExportItemMapper( rMapEntries ), + aBrushItemExport( rExp ), + nAbsWidth( USHRT_MAX ) +{ +} + +SwXMLTableItemMapper_Impl::~SwXMLTableItemMapper_Impl() +{ +} + +void SwXMLTableItemMapper_Impl::AddAttribute( sal_uInt16 nPrefix, + enum XMLTokenEnum eLName, + const OUString& rValue, + const SvXMLNamespaceMap& rNamespaceMap, + SvXMLAttributeList& rAttrList ) const +{ + OUString sName( rNamespaceMap.GetQNameByKey( nPrefix, + GetXMLToken(eLName) ) ); + rAttrList.AddAttribute( sName, rValue ); +} + +void SwXMLTableItemMapper_Impl::handleSpecialItem( + SvXMLAttributeList& rAttrList, + const SvXMLItemMapEntry& rEntry, + const SfxPoolItem& rItem, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap, + const SfxItemSet *pSet ) const +{ + switch( rEntry.nWhichId ) + { + case RES_LR_SPACE: + { + const SfxPoolItem *pItem; + if( pSet && + SFX_ITEM_SET == pSet->GetItemState( RES_HORI_ORIENT, sal_True, + &pItem ) ) + { + sal_Int16 eHoriOrient = + ((const SwFmtHoriOrient *)pItem)->GetHoriOrient(); + sal_Bool bExport = sal_False; + sal_uInt16 nMemberId = + static_cast<sal_uInt16>( rEntry.nMemberId & MID_SW_FLAG_MASK ); + switch( nMemberId ) + { + case MID_L_MARGIN: + bExport = text::HoriOrientation::NONE == eHoriOrient || + text::HoriOrientation::LEFT_AND_WIDTH == eHoriOrient; + break; + case MID_R_MARGIN: + bExport = text::HoriOrientation::NONE == eHoriOrient; + break; + } + OUString sValue; + if( bExport && SvXMLExportItemMapper::QueryXMLValue( + rItem, sValue, nMemberId, rUnitConverter ) ) + { + AddAttribute( rEntry.nNameSpace, rEntry.eLocalName, sValue, + rNamespaceMap, rAttrList ); + } + } + } + break; + + case RES_FRM_SIZE: + { + sal_uInt16 nMemberId = + static_cast<sal_uInt16>( rEntry.nMemberId & MID_SW_FLAG_MASK ); + switch( nMemberId ) + { + case MID_FRMSIZE_WIDTH: + if( nAbsWidth ) + { + OUStringBuffer sBuffer; + rUnitConverter.convertMeasure( sBuffer, nAbsWidth ); + AddAttribute( rEntry.nNameSpace, rEntry.eLocalName, + sBuffer.makeStringAndClear(), + rNamespaceMap, rAttrList ); + } + break; + case MID_FRMSIZE_REL_WIDTH: + { + OUString sValue; + if( SvXMLExportItemMapper::QueryXMLValue( + rItem, sValue, nMemberId, rUnitConverter ) ) + { + AddAttribute( rEntry.nNameSpace, rEntry.eLocalName, + sValue, rNamespaceMap, rAttrList ); + } + } + break; + } + } + break; + } +} + +/** this method is called for every item that has the + MID_SW_FLAG_ELEMENT_EXPORT flag set */ +void SwXMLTableItemMapper_Impl::handleElementItem( + SvXMLExport& /*rExport*/, + const SvXMLItemMapEntry& rEntry, + const SfxPoolItem& rItem, + const SvXMLUnitConverter& /*rUnitConverter*/, + const SfxItemSet&, + sal_uInt16 ) const +{ + switch( rEntry.nWhichId ) + { + case RES_BACKGROUND: + { + ((SwXMLTableItemMapper_Impl *)this)->aBrushItemExport.exportXML( + (const SvxBrushItem&)rItem ); + } + break; + } +} + +inline void SwXMLTableItemMapper_Impl::SetAbsWidth( sal_uInt32 nAbs ) +{ + nAbsWidth = nAbs; +} + +// ---------------------------------------------------------------------------- + +void SwXMLExport::_InitItemExport() +{ + // #110680# + pTwipUnitConv = new SvXMLUnitConverter( MAP_TWIP, + GetMM100UnitConverter().getXMLMeasureUnit(), getServiceFactory() ); + + xTableItemMap = new SvXMLItemMapEntries( aXMLTableItemMap ); + xTableRowItemMap = new SvXMLItemMapEntries( aXMLTableRowItemMap ); + xTableCellItemMap = new SvXMLItemMapEntries( aXMLTableCellItemMap ); + + pTableItemMapper = new SwXMLTableItemMapper_Impl( xTableItemMap, *this ); +} + +void SwXMLExport::_FinitItemExport() +{ + delete pTableItemMapper; + delete pTwipUnitConv; +} + +void SwXMLExport::ExportTableFmt( const SwFrmFmt& rFmt, sal_uInt32 nAbsWidth ) +{ + ((SwXMLTableItemMapper_Impl *)pTableItemMapper) + ->SetAbsWidth( nAbsWidth ); + ExportFmt( rFmt, XML_TABLE ); +} diff --git a/sw/source/filter/xml/xmlitemi.cxx b/sw/source/filter/xml/xmlitemi.cxx new file mode 100644 index 000000000000..fa674798eef3 --- /dev/null +++ b/sw/source/filter/xml/xmlitemi.cxx @@ -0,0 +1,272 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + + +#include <hintids.hxx> +#include <rtl/ustring.hxx> +#include <rsc/rscsfx.hxx> +#include "xmlitmap.hxx" +#include "xmlimpit.hxx" +#include "xmlitem.hxx" +#include <xmloff/i18nmap.hxx> +#include <xmloff/xmluconv.hxx> +#ifndef _XMLOFF_FAMILIES_HXX +#include <xmloff/families.hxx> +#endif +#include <svx/unomid.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/tstpitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/langitem.hxx> + +#ifndef _XMLOFF_XMLTABI_HXX +//#include <xmloff/xmltabi.hxx> +#endif +#include "xmlbrshi.hxx" +#include <paratr.hxx> +#include <doc.hxx> +#ifndef _UNOMID_H +#include <unomid.h> +#endif +#include "xmlimp.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +extern SvXMLItemMapEntry aXMLTableItemMap[]; +extern SvXMLItemMapEntry aXMLTableColItemMap[]; +extern SvXMLItemMapEntry aXMLTableRowItemMap[]; +extern SvXMLItemMapEntry aXMLTableCellItemMap[]; + +class SwXMLImportTableItemMapper_Impl: public SvXMLImportItemMapper +{ + +public: + + SwXMLImportTableItemMapper_Impl( SvXMLItemMapEntriesRef rMapEntries ); + virtual ~SwXMLImportTableItemMapper_Impl(); + + virtual sal_Bool handleSpecialItem( const SvXMLItemMapEntry& rEntry, + SfxPoolItem& rItem, + SfxItemSet& rSet, + const OUString& rValue, + const SvXMLUnitConverter& rUnitConverter, + const SvXMLNamespaceMap& rNamespaceMap ) const; + virtual void finished( SfxItemSet& rSet ) const; +}; + +SwXMLImportTableItemMapper_Impl::SwXMLImportTableItemMapper_Impl( + SvXMLItemMapEntriesRef rMapEntries ) : + SvXMLImportItemMapper( rMapEntries, RES_UNKNOWNATR_CONTAINER) +{ +} + +SwXMLImportTableItemMapper_Impl::~SwXMLImportTableItemMapper_Impl() +{ +} + +sal_Bool SwXMLImportTableItemMapper_Impl::handleSpecialItem( + const SvXMLItemMapEntry& rEntry, + SfxPoolItem& rItem, + SfxItemSet& rItemSet, + const OUString& rValue, + const SvXMLUnitConverter& rUnitConv, + const SvXMLNamespaceMap& ) const +{ + sal_Bool bRet = sal_False; + sal_uInt16 nMemberId = static_cast< sal_Int16 >(rEntry.nMemberId & MID_SW_FLAG_MASK); + switch( rItem.Which() ) + { + case RES_FRM_SIZE: + switch( nMemberId ) + { + case MID_FRMSIZE_COL_WIDTH: + // If the item is existing already, a relative value has been set + // already that must be preserved. + if( SFX_ITEM_SET != rItemSet.GetItemState( RES_FRM_SIZE, + sal_False ) ) + bRet = SvXMLImportItemMapper::PutXMLValue( + rItem, rValue, nMemberId, rUnitConv ); + break; + } + } + + return bRet; +} + +void SwXMLImportTableItemMapper_Impl::finished( SfxItemSet& /*rSet*/ ) const +{ +} + +// --------------------------------------------------------------------- + +class SwXMLItemSetContext_Impl : public SvXMLItemSetContext +{ + SvXMLImportContextRef xBackground; + + using SvXMLItemSetContext::CreateChildContext; + +public: + SwXMLItemSetContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SfxItemSet& rItemSet, + const SvXMLImportItemMapper& rIMapper, + const SvXMLUnitConverter& rUnitConv ); + virtual ~SwXMLItemSetContext_Impl(); + + virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix, + const ::rtl::OUString& rLocalName, + const ::uno::Reference< xml::sax::XAttributeList > & xAttrList, + SfxItemSet& rItemSet, + const SvXMLItemMapEntry& rEntry, + const SvXMLUnitConverter& rUnitConv ); +}; + +SwXMLItemSetContext_Impl::SwXMLItemSetContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SfxItemSet& _rItemSet, + const SvXMLImportItemMapper& _rIMapper, + const SvXMLUnitConverter& _rUnitConv ) : + SvXMLItemSetContext( rImport, nPrfx, rLName, xAttrList, + _rItemSet, _rIMapper, _rUnitConv ) +{ +} + +SwXMLItemSetContext_Impl::~SwXMLItemSetContext_Impl() +{ + if( xBackground.Is() ) + { + const SvxBrushItem& rItem = + ((SwXMLBrushItemImportContext*)&xBackground)->GetItem(); + rItemSet.Put( rItem ); + } +} + +SvXMLImportContext *SwXMLItemSetContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SfxItemSet& _rItemSet, + const SvXMLItemMapEntry& rEntry, + const SvXMLUnitConverter& _rUnitConv ) +{ + SvXMLImportContext *pContext = 0; + + switch( rEntry.nWhichId ) + { + case RES_BACKGROUND: + { + const SfxPoolItem *pItem; + if( SFX_ITEM_SET == _rItemSet.GetItemState( RES_BACKGROUND, + sal_False, &pItem ) ) + { + pContext = new SwXMLBrushItemImportContext( + GetImport(), nPrefix, rLocalName, xAttrList, + _rUnitConv, *(const SvxBrushItem *)pItem ); + } + else + { + pContext = new SwXMLBrushItemImportContext( + GetImport(), nPrefix, rLocalName, xAttrList, + _rUnitConv, RES_BACKGROUND ); + } + xBackground = pContext; + } + break; + } + + if( !pContext ) + pContext = SvXMLItemSetContext::CreateChildContext( nPrefix, rLocalName, + xAttrList, _rItemSet, + rEntry, _rUnitConv ); + + return pContext; +} + +// --------------------------------------------------------------------- + +void SwXMLImport::_InitItemImport() +{ + // #110680# + pTwipUnitConv = new SvXMLUnitConverter( MAP_TWIP, MAP_TWIP, getServiceFactory() ); + + xTableItemMap = new SvXMLItemMapEntries( aXMLTableItemMap ); + xTableColItemMap = new SvXMLItemMapEntries( aXMLTableColItemMap ); + xTableRowItemMap = new SvXMLItemMapEntries( aXMLTableRowItemMap ); + xTableCellItemMap = new SvXMLItemMapEntries( aXMLTableCellItemMap ); + + pTableItemMapper = new SwXMLImportTableItemMapper_Impl( xTableItemMap ); +} + +void SwXMLImport::_FinitItemImport() +{ + delete pTableItemMapper; + delete pTwipUnitConv; +} + +SvXMLImportContext *SwXMLImport::CreateTableItemImportContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList, + sal_uInt16 nFamily, + SfxItemSet& rItemSet ) +{ + SvXMLItemMapEntriesRef xItemMap; + + switch( nFamily ) + { + case XML_STYLE_FAMILY_TABLE_TABLE: + xItemMap = xTableItemMap; + break; + case XML_STYLE_FAMILY_TABLE_COLUMN: + xItemMap = xTableColItemMap; + break; + case XML_STYLE_FAMILY_TABLE_ROW: + xItemMap = xTableRowItemMap; + break; + case XML_STYLE_FAMILY_TABLE_CELL: + xItemMap = xTableCellItemMap; + break; + } + + pTableItemMapper->setMapEntries( xItemMap ); + + return new SwXMLItemSetContext_Impl( *this, nPrefix, rLocalName, + xAttrList, rItemSet, + GetTableItemMapper(), + GetTwipUnitConverter() ); +} diff --git a/sw/source/filter/xml/xmlitemm.cxx b/sw/source/filter/xml/xmlitemm.cxx new file mode 100644 index 000000000000..e830601fcd18 --- /dev/null +++ b/sw/source/filter/xml/xmlitemm.cxx @@ -0,0 +1,296 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <editeng/memberids.hrc> +#include <hintids.hxx> +#include <svx/unomid.hxx> +#include <xmloff/xmlnmspe.hxx> +#include "xmlitmap.hxx" +#include <xmloff/xmltoken.hxx> + +#ifndef _UNOMID_H +#include <unomid.h> +#endif + +using namespace ::xmloff::token; + +#define MAP_ENTRY( p, l, w, m ) \ + { XML_NAMESPACE_##p, XML_##l, w, m } +#define M_E_SI( p, l, w, m ) \ + { XML_NAMESPACE_##p, XML_##l, w, MID_SW_FLAG_SPECIAL_ITEM_IMPORT|m } +#define M_E_SE( p, l, w, m ) \ + { XML_NAMESPACE_##p, XML_##l, w, MID_SW_FLAG_SPECIAL_ITEM_EXPORT|m } + +#define M_END { 0, XML_TOKEN_INVALID, 0, 0 } + +SvXMLItemMapEntry aXMLTableItemMap[] = +{ + // RES_FILL_ORDER + // not required + // RES_FRM_SIZE + M_E_SE( STYLE, WIDTH, RES_FRM_SIZE, MID_FRMSIZE_WIDTH ), + M_E_SE( STYLE, REL_WIDTH, RES_FRM_SIZE, MID_FRMSIZE_REL_WIDTH ), + // RES_PAPER_BIN + // not required + // TODO: RES_LR_SPACE + M_E_SE( FO, MARGIN_LEFT, RES_LR_SPACE, MID_L_MARGIN ), + M_E_SE( FO, MARGIN_RIGHT, RES_LR_SPACE, MID_R_MARGIN ), + // RES_UL_SPACE + MAP_ENTRY( FO, MARGIN_TOP, RES_UL_SPACE, MID_UP_MARGIN ), + MAP_ENTRY( FO, MARGIN_BOTTOM, RES_UL_SPACE, MID_LO_MARGIN ), + // RES_PAGEDESC + MAP_ENTRY( STYLE, PAGE_NUMBER, RES_PAGEDESC, MID_PAGEDESC_PAGENUMOFFSET), + // RES_BREAK + MAP_ENTRY( FO, BREAK_BEFORE, RES_BREAK, MID_BREAK_BEFORE ), + MAP_ENTRY( FO, BREAK_AFTER, RES_BREAK, MID_BREAK_AFTER ), + // RES_CNTNT + // not required + // RES_HEADER + // not required + // RES_FOOTER + // not required + // RES_PRINT + // not required + // RES_OPAQUE + // not required + // RES_PROTECT + // not required + // RES_SURROUND + // not required + // RES_VERT_ORIENT + // not required + // RES_HORI_ORIENT + MAP_ENTRY( TABLE, ALIGN, RES_HORI_ORIENT, 0 ), + // RES_ANCHOR + // not required + // RES_BACKGROUND + MAP_ENTRY( FO, BACKGROUND_COLOR, RES_BACKGROUND, MID_BACK_COLOR ), + MAP_ENTRY( STYLE, BACKGROUND_IMAGE, RES_BACKGROUND, MID_SW_FLAG_ELEMENT_ITEM ), + // RES_BOX + // not required + // RES_SHADOW + MAP_ENTRY( STYLE, SHADOW, RES_SHADOW, 0 ), + // RES_FRMMACRO + // not required + // RES_COL + // not required + // RES_KEEP + MAP_ENTRY( FO, KEEP_WITH_NEXT, RES_KEEP, 0 ), + // RES_URL + // not required + // RES_EDIT_IN_READONLY + // not required + // RES_LAYOUT_SPLIT + MAP_ENTRY( STYLE, MAY_BREAK_BETWEEN_ROWS, RES_LAYOUT_SPLIT, 0 ), + // RES_CHAIN + // not required + // RES_LINENUMBER + // not required + // RES_FTN_AT_TXTEND + // not required + // RES_END_AT_TXTEND + // not required + // RES_UNKNOWNATR_CONTAINER + M_E_SE( TEXT, XMLNS, RES_UNKNOWNATR_CONTAINER, 0 ), + + // RES_FRAMEDIR + MAP_ENTRY( STYLE, WRITING_MODE, RES_FRAMEDIR, 0 ), + + // RES_COLLAPSING_BORDERS + MAP_ENTRY( TABLE, BORDER_MODEL, RES_COLLAPSING_BORDERS, 0 ), + + M_END +}; + +SvXMLItemMapEntry aXMLTableColItemMap[] = +{ + M_E_SI( STYLE, COLUMN_WIDTH, RES_FRM_SIZE, MID_FRMSIZE_COL_WIDTH ), + MAP_ENTRY( STYLE, REL_COLUMN_WIDTH, RES_FRM_SIZE, MID_FRMSIZE_REL_COL_WIDTH ), + M_END +}; + +SvXMLItemMapEntry aXMLTableRowItemMap[] = +{ + // RES_FILL_ORDER + // not required + // RES_FRM_SIZE + MAP_ENTRY( STYLE, ROW_HEIGHT, RES_FRM_SIZE, MID_FRMSIZE_FIX_HEIGHT ), + MAP_ENTRY( STYLE, MIN_ROW_HEIGHT, RES_FRM_SIZE, MID_FRMSIZE_MIN_HEIGHT ), + // RES_PAPER_BIN + // not required + // RES_LR_SPACE + // not required + // RES_UL_SPACE + // not required + // RES_PAGEDESC + // not required + // RES_BREAK + // not required + // RES_CNTNT + // not required + // RES_HEADER + // not required + // RES_FOOTER + // not required + // RES_PRINT + // not required + // RES_OPAQUE + // not required + // RES_PROTECT + // not required + // RES_SURROUND + // not required + // RES_VERT_ORIENT + // not required + // RES_HORI_ORIENT + // not required + // RES_ANCHOR + // not required + // RES_BACKGROUND + MAP_ENTRY( FO, BACKGROUND_COLOR, RES_BACKGROUND, MID_BACK_COLOR ), + MAP_ENTRY( STYLE, BACKGROUND_IMAGE, RES_BACKGROUND, MID_SW_FLAG_ELEMENT_ITEM ), + // RES_BOX + // not required + // RES_ANCHOR + // not required + // RES_SHADOW + // not required + // RES_FRMMACRO + // not required + // RES_COL + // not required + // RES_KEEP + // not required + // RES_URL + // not required + // RES_EDIT_IN_READONLY + // not required + // RES_LAYOUT_SPLIT + M_E_SE( STYLE, KEEP_TOGETHER, RES_ROW_SPLIT, 0 ), + M_E_SE( FO, KEEP_TOGETHER, RES_ROW_SPLIT, 0 ), + // RES_CHAIN + // not required + // RES_LINENUMBER + // not required + // RES_FTN_AT_TXTEND + // not required + // RES_END_AT_TXTEND + // not required + // RES_UNKNOWNATR_CONTAINER + M_E_SE( TEXT, XMLNS, RES_UNKNOWNATR_CONTAINER, 0 ), + M_END +}; + +SvXMLItemMapEntry aXMLTableCellItemMap[] = +{ + // RES_FILL_ORDER + // not required + // RES_FRM_SIZE + // not required + // RES_PAPER_BIN + // not required + // RES_LR_SPACE + // not required + // RES_UL_SPACE + // not required + // RES_PAGEDESC + // not required + // RES_BREAK + // not required + // RES_CNTNT + // not required + // RES_HEADER + // not required + // RES_FOOTER + // not required + // RES_PRINT + // not required + // RES_OPAQUE + // not required + // RES_PROTECT + // not required + // RES_SURROUND + // not required + // RES_VERT_ORIENT + MAP_ENTRY( STYLE, VERTICAL_ALIGN, RES_VERT_ORIENT, 0 ), + // RES_HORI_ORIENT + // not required + // RES_ANCHOR + // not required + // RES_BACKGROUND + MAP_ENTRY( FO, BACKGROUND_COLOR, RES_BACKGROUND, MID_BACK_COLOR ), + MAP_ENTRY( STYLE, BACKGROUND_IMAGE, RES_BACKGROUND, MID_SW_FLAG_ELEMENT_ITEM ), + // RES_BOX + MAP_ENTRY( STYLE, BORDER_LINE_WIDTH, RES_BOX, ALL_BORDER_LINE_WIDTH ), + MAP_ENTRY( STYLE, BORDER_LINE_WIDTH_LEFT, RES_BOX, LEFT_BORDER_LINE_WIDTH ), + MAP_ENTRY( STYLE, BORDER_LINE_WIDTH_RIGHT, RES_BOX, RIGHT_BORDER_LINE_WIDTH ), + MAP_ENTRY( STYLE, BORDER_LINE_WIDTH_TOP, RES_BOX, TOP_BORDER_LINE_WIDTH ), + MAP_ENTRY( STYLE, BORDER_LINE_WIDTH_BOTTOM, RES_BOX, BOTTOM_BORDER_LINE_WIDTH ), + MAP_ENTRY( FO, PADDING, RES_BOX, ALL_BORDER_PADDING ), + MAP_ENTRY( FO, PADDING_LEFT, RES_BOX, LEFT_BORDER_PADDING ), + MAP_ENTRY( FO, PADDING_RIGHT, RES_BOX, RIGHT_BORDER_PADDING ), + MAP_ENTRY( FO, PADDING_TOP, RES_BOX, TOP_BORDER_PADDING ), + MAP_ENTRY( FO, PADDING_BOTTOM, RES_BOX, BOTTOM_BORDER_PADDING ), + MAP_ENTRY( FO, BORDER, RES_BOX, ALL_BORDER ), + MAP_ENTRY( FO, BORDER_LEFT, RES_BOX, LEFT_BORDER ), + MAP_ENTRY( FO, BORDER_RIGHT, RES_BOX, RIGHT_BORDER ), + MAP_ENTRY( FO, BORDER_TOP, RES_BOX, TOP_BORDER ), + MAP_ENTRY( FO, BORDER_BOTTOM, RES_BOX, BOTTOM_BORDER ), + // RES_SHADOW + // not required + // RES_FRMMACRO + // not required + // RES_COL + // not required + // RES_KEEP + // not required + // RES_URL + // not required + // RES_EDIT_IN_READONLY + // not required + // RES_LAYOUT_SPLIT + // not required + // RES_CHAIN + // not required + // RES_LINENUMBER + // not required + // RES_FTN_AT_TXTEND + // not required + // RES_END_AT_TXTEND + // not required + // RES_UNKNOWNATR_CONTAINER + M_E_SE( TEXT, XMLNS, RES_UNKNOWNATR_CONTAINER, 0 ), + + // RES_FRAMEDIR + MAP_ENTRY( STYLE, WRITING_MODE, RES_FRAMEDIR, 0 ), + + M_END +}; diff --git a/sw/source/filter/xml/xmlithlp.cxx b/sw/source/filter/xml/xmlithlp.cxx new file mode 100644 index 000000000000..84b320fa0ada --- /dev/null +++ b/sw/source/filter/xml/xmlithlp.cxx @@ -0,0 +1,422 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include "xmlithlp.hxx" +#include "hintids.hxx" +#include "unomid.h" +#include <svx/unomid.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/shaditem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/brkitem.hxx> +#include <editeng/keepitem.hxx> +#include <editeng/brshitem.hxx> +#include "fmtpdsc.hxx" +#include "fmtornt.hxx" +#include "fmtfsize.hxx" + +#ifndef _FMTLSPLT_HXX +#include "fmtlsplt.hxx" +#endif +#include <xmloff/xmluconv.hxx> + +using ::rtl::OUString; +using namespace ::xmloff::token; +using namespace ::com::sun::star; + + +#define SVX_XML_BORDER_STYLE_NONE 0 +#define SVX_XML_BORDER_STYLE_SOLID 1 +#define SVX_XML_BORDER_STYLE_DOUBLE 2 + +#define SVX_XML_BORDER_WIDTH_THIN 0 +#define SVX_XML_BORDER_WIDTH_MIDDLE 1 +#define SVX_XML_BORDER_WIDTH_THICK 2 + + +const struct SvXMLEnumMapEntry psXML_BorderStyles[] = +{ + { XML_NONE, SVX_XML_BORDER_STYLE_NONE }, + { XML_HIDDEN, SVX_XML_BORDER_STYLE_NONE }, + { XML_SOLID, SVX_XML_BORDER_STYLE_SOLID }, + { XML_DOUBLE, SVX_XML_BORDER_STYLE_DOUBLE }, + { XML_DOTTED, SVX_XML_BORDER_STYLE_SOLID }, + { XML_DASHED, SVX_XML_BORDER_STYLE_SOLID }, + { XML_GROOVE, SVX_XML_BORDER_STYLE_SOLID }, + { XML_RIDGE, SVX_XML_BORDER_STYLE_SOLID }, + { XML_INSET, SVX_XML_BORDER_STYLE_SOLID }, + { XML_OUTSET, SVX_XML_BORDER_STYLE_SOLID }, + { XML_TOKEN_INVALID, 0 } +}; + +const struct SvXMLEnumMapEntry psXML_NamedBorderWidths[] = +{ + { XML_THIN, SVX_XML_BORDER_WIDTH_THIN }, + { XML_MIDDLE, SVX_XML_BORDER_WIDTH_MIDDLE }, + { XML_THICK, SVX_XML_BORDER_WIDTH_THICK }, + { XML_TOKEN_INVALID, 0 } +}; +// mapping tables to map external xml input to intarnal box line widths + +// Ein Eintrag besteht aus vier USHORTs. Der erste ist die Gesamtbreite, +// die anderen sind die 3 Einzelbreiten + +#define SBORDER_ENTRY( n ) \ + DEF_LINE_WIDTH_##n, DEF_LINE_WIDTH_##n, 0, 0 + +#define DBORDER_ENTRY( n ) \ + DEF_DOUBLE_LINE##n##_OUT + DEF_DOUBLE_LINE##n##_IN + \ + DEF_DOUBLE_LINE##n##_DIST, \ + DEF_DOUBLE_LINE##n##_OUT, \ + DEF_DOUBLE_LINE##n##_IN, \ + DEF_DOUBLE_LINE##n##_DIST + +#define TDBORDER_ENTRY( n ) \ + DEF_DOUBLE_LINE##n##_OUT, \ + DEF_DOUBLE_LINE##n##_OUT, \ + DEF_DOUBLE_LINE##n##_IN, \ + DEF_DOUBLE_LINE##n##_DIST + + +const sal_uInt16 aSBorderWidths[] = +{ + SBORDER_ENTRY( 0 ), SBORDER_ENTRY( 5 ), SBORDER_ENTRY( 1 ), + SBORDER_ENTRY( 2 ), SBORDER_ENTRY( 3 ), SBORDER_ENTRY( 4 ) +}; + +const sal_uInt16 aDBorderWidths[5*11] = +{ + DBORDER_ENTRY( 0 ), + DBORDER_ENTRY( 7 ), + DBORDER_ENTRY( 1 ), + DBORDER_ENTRY( 8 ), + DBORDER_ENTRY( 4 ), + DBORDER_ENTRY( 9 ), + DBORDER_ENTRY( 3 ), + DBORDER_ENTRY( 10 ), + DBORDER_ENTRY( 2 ), + DBORDER_ENTRY( 6 ), + DBORDER_ENTRY( 5 ) +}; + +sal_Bool lcl_frmitems_parseXMLBorder( const OUString& rValue, + const SvXMLUnitConverter& rUnitConverter, + sal_Bool& rHasStyle, sal_uInt16& rStyle, + sal_Bool& rHasWidth, sal_uInt16& rWidth, + sal_uInt16& rNamedWidth, + sal_Bool& rHasColor, Color& rColor ) +{ + OUString aToken; + SvXMLTokenEnumerator aTokens( rValue ); + + rHasStyle = sal_False; + rHasWidth = sal_False; + rHasColor = sal_False; + + rStyle = USHRT_MAX; + rWidth = 0; + rNamedWidth = USHRT_MAX; + + sal_Int32 nTemp; + while( aTokens.getNextToken( aToken ) && aToken.getLength() != 0 ) + { + if( !rHasWidth && + rUnitConverter.convertEnum( rNamedWidth, aToken, + psXML_NamedBorderWidths ) ) + { + rHasWidth = sal_True; + } + else if( !rHasStyle && + rUnitConverter.convertEnum( rStyle, aToken, + psXML_BorderStyles ) ) + { + rHasStyle = sal_True; + } + else if( !rHasColor && rUnitConverter.convertColor( rColor, aToken ) ) + { + rHasColor = sal_True; + } + else if( !rHasWidth && + rUnitConverter.convertMeasure( nTemp, aToken, 0, USHRT_MAX ) ) + { + rWidth = (sal_uInt16)nTemp; + rHasWidth = sal_True; + } + else + { + // missformed + return sal_False; + } + } + + return rHasStyle || rHasWidth || rHasColor; +} + +void lcl_frmitems_setXMLBorderWidth( SvxBorderLine& rLine, + sal_uInt16 nOutWidth, sal_uInt16 nInWidth, + sal_uInt16 nDistance ) +{ + rLine.SetOutWidth( nOutWidth ); + rLine.SetInWidth( nInWidth ); + rLine.SetDistance( nDistance ); +} + +void lcl_frmitems_setXMLBorderWidth( SvxBorderLine& rLine, + sal_uInt16 nWidth, sal_Bool bDouble ) +{ + const sal_uInt16 *aWidths; + sal_uInt16 nSize; + if( !bDouble ) + { + aWidths = aSBorderWidths; + nSize = sizeof( aSBorderWidths ); + } + else + { + aWidths = aDBorderWidths; + nSize = sizeof( aDBorderWidths ); + } + + sal_uInt16 i = (nSize / sizeof(sal_uInt16)) - 4; + while( i>0 && + nWidth <= ((aWidths[i] + aWidths[i-4]) / 2) ) + { + DBG_ASSERT( aWidths[i] >= aWidths[i-4], "line widths are unordered!" ); + i -= 4; + } + + rLine.SetOutWidth( aWidths[i+1] ); + rLine.SetInWidth( aWidths[i+2] ); + rLine.SetDistance( aWidths[i+3] ); +} + +sal_Bool lcl_frmitems_setXMLBorder( SvxBorderLine*& rpLine, + sal_Bool bHasStyle, sal_uInt16 nStyle, + sal_Bool bHasWidth, sal_uInt16 nWidth, + sal_uInt16 nNamedWidth, + sal_Bool bHasColor, const Color& rColor ) +{ + // first of all, delete an empty line + if( (bHasStyle && SVX_XML_BORDER_STYLE_NONE == nStyle) || + (bHasWidth && USHRT_MAX == nNamedWidth && 0 == nWidth) ) + { + sal_Bool bRet = 0 != rpLine; + if( rpLine ) + { + delete rpLine; + rpLine = 0; + } + + return bRet; + } + + // if there is no line and no style and no with, there will never be a line + if( !rpLine && !(bHasStyle && bHasWidth) ) + return sal_False; + + // We now do know that there will be a line + if( !rpLine ) + rpLine = new SvxBorderLine; + + + if( ( bHasWidth && + (USHRT_MAX != nNamedWidth || (nWidth != rpLine->GetOutWidth() + + rpLine->GetInWidth() + + rpLine->GetDistance()) ) ) || + ( bHasStyle && + ((SVX_XML_BORDER_STYLE_SOLID == nStyle && rpLine->GetDistance()) || + (SVX_XML_BORDER_STYLE_DOUBLE == nStyle && !rpLine->GetDistance())) )) + { + sal_Bool bDouble = (bHasWidth && SVX_XML_BORDER_STYLE_DOUBLE == nStyle ) || + rpLine->GetDistance(); + + // The width has to be changed + if( bHasWidth && USHRT_MAX != nNamedWidth ) + { + const sal_uInt16 *aWidths = bDouble ? aDBorderWidths :aSBorderWidths; + + sal_uInt16 nNWidth = nNamedWidth * 4; + rpLine->SetOutWidth( aWidths[nNWidth+1] ); + rpLine->SetInWidth( aWidths[nNWidth+2] ); + rpLine->SetDistance( aWidths[nNWidth+3] ); + + } + else + { + if( !bHasWidth ) + nWidth = rpLine->GetInWidth() + rpLine->GetDistance() + + rpLine->GetOutWidth(); + + lcl_frmitems_setXMLBorderWidth( *rpLine, nWidth, bDouble ); + } + } + + // set color + if( bHasColor ) + rpLine->SetColor( rColor ); + + return sal_True; +} + +void lcl_frmitems_setXMLBorder( SvxBorderLine*& rpLine, + sal_uInt16 nWidth, sal_uInt16 nOutWidth, + sal_uInt16 nInWidth, sal_uInt16 nDistance ) +{ + if( !rpLine ) + rpLine = new SvxBorderLine; + + if( nWidth > 0 ) + lcl_frmitems_setXMLBorderWidth( *rpLine, nWidth, sal_True ); + else + lcl_frmitems_setXMLBorderWidth( *rpLine, nOutWidth, nInWidth, + nDistance ); +} + +const struct SvXMLEnumMapEntry psXML_BrushRepeat[] = +{ + { XML_BACKGROUND_REPEAT, GPOS_TILED }, + { XML_BACKGROUND_NO_REPEAT, GPOS_MM }, + { XML_BACKGROUND_STRETCH, GPOS_AREA }, + { XML_TOKEN_INVALID, 0 } +}; + +const struct SvXMLEnumMapEntry psXML_BrushHoriPos[] = +{ + { XML_LEFT, GPOS_LM }, + { XML_RIGHT, GPOS_RM }, + { XML_TOKEN_INVALID, 0 } +}; + +const struct SvXMLEnumMapEntry psXML_BrushVertPos[] = +{ + { XML_TOP, GPOS_MT }, + { XML_BOTTOM, GPOS_MB }, + { XML_TOKEN_INVALID, 0 } +}; + +void lcl_frmitems_MergeXMLHoriPos( SvxGraphicPosition& ePos, + SvxGraphicPosition eHori ) +{ + DBG_ASSERT( GPOS_LM==eHori || GPOS_MM==eHori || GPOS_RM==eHori, + "lcl_frmitems_MergeXMLHoriPos: vertical pos must be middle" ); + + switch( ePos ) + { + case GPOS_LT: + case GPOS_MT: + case GPOS_RT: + ePos = GPOS_LM==eHori ? GPOS_LT : (GPOS_MM==eHori ? GPOS_MT : GPOS_RT); + break; + + case GPOS_LM: + case GPOS_MM: + case GPOS_RM: + ePos = eHori; + break; + + case GPOS_LB: + case GPOS_MB: + case GPOS_RB: + ePos = GPOS_LM==eHori ? GPOS_LB : (GPOS_MM==eHori ? GPOS_MB : GPOS_RB); + break; + default: + ; + } +} + +void lcl_frmitems_MergeXMLVertPos( SvxGraphicPosition& ePos, + SvxGraphicPosition eVert ) +{ + DBG_ASSERT( GPOS_MT==eVert || GPOS_MM==eVert || GPOS_MB==eVert, + "lcl_frmitems_MergeXMLVertPos: horizontal pos must be middle" ); + + switch( ePos ) + { + case GPOS_LT: + case GPOS_LM: + case GPOS_LB: + ePos = GPOS_MT==eVert ? GPOS_LT : (GPOS_MM==eVert ? GPOS_LM : GPOS_LB); + ePos = eVert; + break; + + case GPOS_MT: + case GPOS_MM: + case GPOS_MB: + ePos = eVert; + break; + + case GPOS_RT: + case GPOS_RM: + case GPOS_RB: + ePos = GPOS_MT==eVert ? GPOS_RT : (GPOS_MM==eVert ? GPOS_RM : GPOS_RB); + break; + default: + ; + } +} + + +const struct SvXMLEnumMapEntry psXML_BreakType[] = +{ + { XML_AUTO, 0 }, + { XML_COLUMN, 1 }, + { XML_PAGE, 2 }, + { XML_EVEN_PAGE, 2 }, + { XML_ODD_PAGE, 2 }, + { XML_TOKEN_INVALID, 0} +}; + +const struct SvXMLEnumMapEntry aXMLTableAlignMap[] = +{ + { XML_LEFT, text::HoriOrientation::LEFT }, + { XML_LEFT, text::HoriOrientation::LEFT_AND_WIDTH }, + { XML_CENTER, text::HoriOrientation::CENTER }, + { XML_RIGHT, text::HoriOrientation::RIGHT }, + { XML_MARGINS, text::HoriOrientation::FULL }, + { XML_MARGINS, text::HoriOrientation::NONE }, + { XML_TOKEN_INVALID, 0 } +}; + +const struct SvXMLEnumMapEntry aXMLTableVAlignMap[] = +{ + { XML_TOP, text::VertOrientation::TOP }, + { XML_MIDDLE, text::VertOrientation::CENTER }, + { XML_BOTTOM, text::VertOrientation::BOTTOM }, + { XML_TOKEN_INVALID, 0 } +}; + +const struct SvXMLEnumMapEntry aXML_KeepTogetherType[] = +{ + { XML_ALWAYS, 0 }, + { XML_AUTO, 1 }, + { XML_TOKEN_INVALID, 0} +}; + + diff --git a/sw/source/filter/xml/xmlithlp.hxx b/sw/source/filter/xml/xmlithlp.hxx new file mode 100644 index 000000000000..22efde15bc92 --- /dev/null +++ b/sw/source/filter/xml/xmlithlp.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SW_XMLITHLP_HXX +#define _SW_XMLITHLP_HXX + +#include <sal/types.h> +#include <xmloff/xmlement.hxx> +#include "hintids.hxx" // for following include +#include <editeng/brshitem.hxx> // for SvxGraphicsPosition + +class SvxBorderLine; +struct SvXMLEnumMapEntry; +class SvXMLUnitConverter; +class Color; +namespace rtl { class OUString; } + + + +/** Define various helper variables and functions for xmlimpit.cxx and + * xmlexpit.cxx. */ + + +#define SVX_XML_BORDER_STYLE_NONE 0 +#define SVX_XML_BORDER_STYLE_SOLID 1 +#define SVX_XML_BORDER_STYLE_DOUBLE 2 + +#define SVX_XML_BORDER_WIDTH_THIN 0 +#define SVX_XML_BORDER_WIDTH_MIDDLE 1 +#define SVX_XML_BORDER_WIDTH_THICK 2 + + +sal_Bool lcl_frmitems_parseXMLBorder( const ::rtl::OUString& rValue, + const SvXMLUnitConverter& rUnitConverter, + sal_Bool& rHasStyle, sal_uInt16& rStyle, + sal_Bool& rHasWidth, sal_uInt16& rWidth, + sal_uInt16& rNamedWidth, + sal_Bool& rHasColor, Color& rColor ); + +void lcl_frmitems_setXMLBorderWidth( SvxBorderLine& rLine, + sal_uInt16 nOutWidth, sal_uInt16 nInWidth, + sal_uInt16 nDistance ); + +void lcl_frmitems_setXMLBorderWidth( SvxBorderLine& rLine, + sal_uInt16 nWidth, sal_Bool bDouble ); + +sal_Bool lcl_frmitems_setXMLBorder( SvxBorderLine*& rpLine, + sal_Bool bHasStyle, sal_uInt16 nStyle, + sal_Bool bHasWidth, sal_uInt16 nWidth, + sal_uInt16 nNamedWidth, + sal_Bool bHasColor, const Color& rColor ); + +void lcl_frmitems_setXMLBorder( SvxBorderLine*& rpLine, + sal_uInt16 nWidth, sal_uInt16 nOutWidth, + sal_uInt16 nInWidth, sal_uInt16 nDistance ); + +void lcl_frmitems_MergeXMLHoriPos( SvxGraphicPosition& ePos, + SvxGraphicPosition eHori ); + +void lcl_frmitems_MergeXMLVertPos( SvxGraphicPosition& ePos, + SvxGraphicPosition eVert ); + +extern const sal_uInt16 aSBorderWidths[]; +extern const sal_uInt16 aDBorderWidths[5*11]; + +extern const struct SvXMLEnumMapEntry psXML_BorderStyles[]; +extern const struct SvXMLEnumMapEntry psXML_NamedBorderWidths[]; +extern const struct SvXMLEnumMapEntry psXML_BrushRepeat[]; +extern const struct SvXMLEnumMapEntry psXML_BrushHoriPos[]; +extern const struct SvXMLEnumMapEntry psXML_BrushVertPos[]; +extern const struct SvXMLEnumMapEntry psXML_BreakType[]; +extern const struct SvXMLEnumMapEntry aXMLTableAlignMap[]; +extern const struct SvXMLEnumMapEntry aXMLTableVAlignMap[]; +extern const struct SvXMLEnumMapEntry aXML_KeepTogetherType[]; + + +#endif diff --git a/sw/source/filter/xml/xmlitmap.hxx b/sw/source/filter/xml/xmlitmap.hxx new file mode 100644 index 000000000000..e9cc562010da --- /dev/null +++ b/sw/source/filter/xml/xmlitmap.hxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLITMAP_HXX +#define _XMLITMAP_HXX + +#include <sal/types.h> +#include <tools/ref.hxx> +#include <xmloff/xmltoken.hxx> + +namespace rtl { class OUString; } + +#define MID_SW_FLAG_MASK 0x0000ffff + +// this flags are used in the item mapper for import and export + +#define MID_SW_FLAG_SPECIAL_ITEM_IMPORT 0x80000000 +#define MID_SW_FLAG_NO_ITEM_IMPORT 0x40000000 +#define MID_SW_FLAG_SPECIAL_ITEM_EXPORT 0x20000000 +#define MID_SW_FLAG_NO_ITEM_EXPORT 0x10000000 +#define MID_SW_FLAG_SPECIAL_ITEM 0xa0000000 // both import and export +#define MID_SW_FLAG_NO_ITEM 0x50000000 // both import and export +#define MID_SW_FLAG_ELEMENT_ITEM_IMPORT 0x08000000 +#define MID_SW_FLAG_ELEMENT_ITEM_EXPORT 0x04000000 +#define MID_SW_FLAG_ELEMENT_ITEM 0x0c000000 // both import and export + +// --- + +struct SvXMLItemMapEntry +{ + sal_uInt16 nNameSpace; // declares the Namespace in wich this item + // exists + enum ::xmloff::token::XMLTokenEnum eLocalName; + // the local name for the item inside + // the Namespace (as an XMLTokenEnum) + sal_uInt16 nWhichId; // the WichId to identify the item + // in the pool + sal_uInt32 nMemberId; // the memberid specifies wich part + // of the item should be imported or + // exported with this Namespace + // and localName +}; + +// --- + +class SvXMLItemMapEntries_impl; + +/** this class manages an array of SvXMLItemMapEntry. It is + used for optimizing the static array on startup of import + or export */ +class SvXMLItemMapEntries : public SvRefBase +{ +protected: + SvXMLItemMapEntries_impl* mpImpl; + +public: + SvXMLItemMapEntries( SvXMLItemMapEntry* pEntrys ); + virtual ~SvXMLItemMapEntries(); + + SvXMLItemMapEntry* getByName( sal_uInt16 nNameSpace, + const ::rtl::OUString& rString, + SvXMLItemMapEntry* pStartAt = NULL ) const; + SvXMLItemMapEntry* getByIndex( sal_uInt16 nIndex ) const; + + sal_uInt16 getCount() const; +}; + +SV_DECL_REF( SvXMLItemMapEntries ) +SV_IMPL_REF( SvXMLItemMapEntries ) + + +#endif // _XMLITMAP_HXX diff --git a/sw/source/filter/xml/xmlitmpr.cxx b/sw/source/filter/xml/xmlitmpr.cxx new file mode 100644 index 000000000000..6a92fa50efd5 --- /dev/null +++ b/sw/source/filter/xml/xmlitmpr.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include <rtl/ustring.hxx> +#include "xmlitmap.hxx" + +using rtl::OUString; +using ::xmloff::token::IsXMLToken; +using ::xmloff::token::XML_TOKEN_INVALID; + +// TODO: optimize this! + +class SvXMLItemMapEntries_impl +{ +public: + SvXMLItemMapEntry* mpEntries; + sal_uInt16 mnCount; +}; + +SvXMLItemMapEntries::SvXMLItemMapEntries( SvXMLItemMapEntry* pEntries ) +{ + mpImpl = new SvXMLItemMapEntries_impl; + mpImpl->mpEntries = pEntries; + + mpImpl->mnCount = 0; + while( pEntries->eLocalName != XML_TOKEN_INVALID ) + { + pEntries++; + mpImpl->mnCount++; + } +} + +SvXMLItemMapEntries::~SvXMLItemMapEntries() +{ + delete mpImpl; +} + +SvXMLItemMapEntry* SvXMLItemMapEntries::getByName( sal_uInt16 nNameSpace, + const OUString& rString, + SvXMLItemMapEntry* pStartAt /* = NULL */ ) const +{ + SvXMLItemMapEntry* pMap = + (pStartAt && (pStartAt->eLocalName!=XML_TOKEN_INVALID)) ? + &(pStartAt[1]) : mpImpl->mpEntries; + while( pMap && (pMap->eLocalName != XML_TOKEN_INVALID) ) + { + if( pMap->nNameSpace == nNameSpace && + IsXMLToken( rString, pMap->eLocalName ) ) + break; + pMap++; + } + + return (pMap->eLocalName != XML_TOKEN_INVALID) ? pMap : NULL; +} + +SvXMLItemMapEntry* SvXMLItemMapEntries::getByIndex( UINT16 nIndex ) const +{ + return &mpImpl->mpEntries[nIndex]; +} + +UINT16 SvXMLItemMapEntries::getCount() const +{ + return mpImpl->mnCount; +} + diff --git a/sw/source/filter/xml/xmlmeta.cxx b/sw/source/filter/xml/xmlmeta.cxx new file mode 100644 index 000000000000..0d3adfd46c77 --- /dev/null +++ b/sw/source/filter/xml/xmlmeta.cxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <hintids.hxx> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/text/XTextDocument.hpp> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmlmetai.hxx> +#include <xmloff/xmlmetae.hxx> +#include <editeng/langitem.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/nmspmap.hxx> +#include "docstat.hxx" +#include "docsh.hxx" +#include <doc.hxx> +#include "xmlimp.hxx" +#include "xmlexp.hxx" + + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::text; +using namespace ::xmloff::token; + +// --------------------------------------------------------------------- + +SvXMLImportContext *SwXMLImport::CreateMetaContext( + const OUString& rLocalName ) +{ + SvXMLImportContext *pContext = 0; + + if( !(IsStylesOnlyMode() || IsInsertMode()) ) + { + uno::Reference<xml::sax::XDocumentHandler> xDocBuilder( + mxServiceFactory->createInstance(::rtl::OUString::createFromAscii( + "com.sun.star.xml.dom.SAXDocumentBuilder")), + uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + GetModel(), UNO_QUERY_THROW); + pContext = new SvXMLMetaDocumentContext(*this, + XML_NAMESPACE_OFFICE, rLocalName, + xDPS->getDocumentProperties(), xDocBuilder); + } + + if( !pContext ) + pContext = new SvXMLImportContext( *this, + XML_NAMESPACE_OFFICE, rLocalName ); + + return pContext; +} + +// --------------------------------------------------------------------- + +enum SvXMLTokenMapAttrs +{ + XML_TOK_META_STAT_TABLE = 1, + XML_TOK_META_STAT_IMAGE = 2, + XML_TOK_META_STAT_OLE = 4, + XML_TOK_META_STAT_PAGE = 8, + XML_TOK_META_STAT_PARA = 16, + XML_TOK_META_STAT_WORD = 32, + XML_TOK_META_STAT_CHAR = 64, + XML_TOK_META_STAT_END=XML_TOK_UNKNOWN +}; + +/* +static __FAR_DATA SvXMLTokenMapEntry aMetaStatAttrTokenMap[] = +{ + { XML_NAMESPACE_META, XML_TABLE_COUNT, XML_TOK_META_STAT_TABLE }, + { XML_NAMESPACE_META, XML_IMAGE_COUNT, XML_TOK_META_STAT_IMAGE }, + { XML_NAMESPACE_META, XML_OBJECT_COUNT, XML_TOK_META_STAT_OLE }, + { XML_NAMESPACE_META, XML_PARAGRAPH_COUNT, XML_TOK_META_STAT_PARA }, + { XML_NAMESPACE_META, XML_PAGE_COUNT, XML_TOK_META_STAT_PAGE }, + { XML_NAMESPACE_META, XML_WORD_COUNT, XML_TOK_META_STAT_WORD }, + { XML_NAMESPACE_META, XML_CHARACTER_COUNT, XML_TOK_META_STAT_CHAR }, + XML_TOKEN_MAP_END +}; +*/ + +struct statistic { + SvXMLTokenMapAttrs token; + const char* name; + USHORT SwDocStat::* target16; + ULONG SwDocStat::* target32; /* or 64, on LP64 platforms */ +}; + +static const struct statistic s_stats [] = { + { XML_TOK_META_STAT_TABLE, "TableCount", &SwDocStat::nTbl, 0 }, + { XML_TOK_META_STAT_IMAGE, "ImageCount", &SwDocStat::nGrf, 0 }, + { XML_TOK_META_STAT_OLE, "ObjectCount", &SwDocStat::nOLE, 0 }, + { XML_TOK_META_STAT_PAGE, "PageCount", 0, &SwDocStat::nPage }, + { XML_TOK_META_STAT_PARA, "ParagraphCount", 0, &SwDocStat::nPara }, + { XML_TOK_META_STAT_WORD, "WordCount", 0, &SwDocStat::nWord }, + { XML_TOK_META_STAT_CHAR, "CharacterCount", 0, &SwDocStat::nChar }, + { XML_TOK_META_STAT_END, 0, 0, 0 } +}; + +void SwXMLImport::SetStatistics( + const Sequence< beans::NamedValue > & i_rStats) +{ + if( IsStylesOnlyMode() || IsInsertMode() ) + return; + + SvXMLImport::SetStatistics(i_rStats); + + SwDoc *pDoc = SwImport::GetDocFromXMLImport( *this ); + SwDocStat aDocStat( pDoc->GetDocStat() ); + + sal_uInt32 nTokens = 0; + + for (sal_Int32 i = 0; i < i_rStats.getLength(); ++i) { + for (struct statistic const* pStat = s_stats; pStat->name != 0; + ++pStat) { + if (i_rStats[i].Name.equalsAscii(pStat->name)) { + sal_Int32 val = 0; + if (i_rStats[i].Value >>= val) { + if (pStat->target16 != 0) { + aDocStat.*(pStat->target16) + = static_cast<sal_uInt16> (val); + } else { + aDocStat.*(pStat->target32) + = static_cast<sal_uInt32> (val); + } + nTokens |= pStat->token; + } else { + DBG_ERROR("SwXMLImport::SetStatistics: invalid entry"); + } + } + } + } + + if( 127 == nTokens ) + aDocStat.bModified = sal_False; + if( nTokens ) + pDoc->SetDocStat( aDocStat ); + + // set progress bar reference to #paragraphs. If not available, + // use #pages*10, or guesstimate 250 paragraphs. Additionally + // guesstimate PROGRESS_BAR_STEPS each for meta+settings, styles, + // and autostyles. + sal_Int32 nProgressReference = 250; + if( nTokens & XML_TOK_META_STAT_PARA ) + nProgressReference = (sal_Int32)aDocStat.nPara; + else if ( nTokens & XML_TOK_META_STAT_PAGE ) + nProgressReference = 10 * (sal_Int32)aDocStat.nPage; + ProgressBarHelper* pProgress = GetProgressBarHelper(); + pProgress->SetReference( nProgressReference + 3*PROGRESS_BAR_STEP ); + pProgress->SetValue( 0 ); +} + +// --------------------------------------------------------------------- + +void SwXMLExport::_ExportMeta() +{ + SvXMLExport::_ExportMeta(); + + if( !IsBlockMode() ) + { + + if( IsShowProgress() ) + { + ProgressBarHelper *pProgress = GetProgressBarHelper(); + pProgress->SetValue( pProgress->GetValue() + 2 ); + } + } +} + diff --git a/sw/source/filter/xml/xmlscript.cxx b/sw/source/filter/xml/xmlscript.cxx new file mode 100644 index 000000000000..48ba4971f9f5 --- /dev/null +++ b/sw/source/filter/xml/xmlscript.cxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + + +#include <hintids.hxx> +#include <xmloff/xmlnmspe.hxx> + +#ifndef _XMLOFF_XMLMETAI_HXX +#include <xmloff/xmlscripti.hxx> +#endif +#include "xmlimp.hxx" +#include "xmlexp.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; + +// --------------------------------------------------------------------- + +SvXMLImportContext *SwXMLImport::CreateScriptContext( + const OUString& rLocalName ) +{ + SvXMLImportContext *pContext = 0; + + if( !(IsStylesOnlyMode() || IsInsertMode()) ) + { + pContext = new XMLScriptContext( *this, + XML_NAMESPACE_OFFICE, rLocalName, + GetModel() ); + } + + if( !pContext ) + pContext = new SvXMLImportContext( *this, XML_NAMESPACE_OFFICE, + rLocalName ); + + return pContext; +} + diff --git a/sw/source/filter/xml/xmltble.cxx b/sw/source/filter/xml/xmltble.cxx new file mode 100644 index 000000000000..d2be01eba5b1 --- /dev/null +++ b/sw/source/filter/xml/xmltble.cxx @@ -0,0 +1,1250 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <com/sun/star/text/XTextTable.hpp> +#include <com/sun/star/text/XTextSection.hpp> + +#include <hintids.hxx> +#include <rtl/ustrbuf.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/numehelp.hxx> +#include <svl/cntnrsrt.hxx> +#include <svl/zforlist.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/boxitem.hxx> +#include <fmtrowsplt.hxx> +#include <editeng/frmdiritem.hxx> +#include <list> +#include "swtable.hxx" +#include "doc.hxx" +#include "pam.hxx" +#include "frmfmt.hxx" +#include "wrtswtbl.hxx" +#include "fmtfsize.hxx" +#include "fmtornt.hxx" +#include "cellatr.hxx" +#include "ddefld.hxx" +#include "swddetbl.hxx" +#include <ndole.hxx> +#include <xmloff/nmspmap.hxx> +#include <sfx2/linkmgr.hxx> // for cTokenSeperator +#include "unotbl.hxx" +#include "xmltexte.hxx" +#include "xmlexp.hxx" + + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::xmloff::token; +using table::XCell; + + +class SwXMLTableColumn_Impl : public SwWriteTableCol +{ + OUString sStyleName; + sal_uInt32 nRelWidth; + +public: + + + SwXMLTableColumn_Impl( sal_uInt16 nPosition ) : + SwWriteTableCol( nPosition ), + nRelWidth( 0UL ) + {}; + + void SetStyleName( const OUString& rName ) { sStyleName = rName; } + const OUString& GetStyleName() const { return sStyleName; } + + void SetRelWidth( sal_uInt32 nSet ) { nRelWidth = nSet; } + sal_uInt32 GetRelWidth() const { return nRelWidth; } +}; + +sal_Int32 SwXMLTableColumnCmpWidth_Impl( const SwXMLTableColumn_Impl& r1, + const SwXMLTableColumn_Impl& r2 ) +{ + sal_Int32 n = (sal_Int32)r1.GetWidthOpt() - (sal_Int32)r2.GetWidthOpt(); + if( !n ) + n = (sal_Int32)r1.GetRelWidth() - (sal_Int32)r2.GetRelWidth(); + return n; +} + +// --------------------------------------------------------------------- + +typedef SwXMLTableColumn_Impl *SwXMLTableColumnPtr; +SV_DECL_PTRARR_SORT_DEL( SwXMLTableColumns_Impl, SwXMLTableColumnPtr, 5, 5 ) +SV_IMPL_OP_PTRARR_SORT( SwXMLTableColumns_Impl, SwXMLTableColumnPtr ) + +DECLARE_CONTAINER_SORT( SwXMLTableColumnsSortByWidth_Impl, + SwXMLTableColumn_Impl ) +IMPL_CONTAINER_SORT( SwXMLTableColumnsSortByWidth_Impl, SwXMLTableColumn_Impl, + SwXMLTableColumnCmpWidth_Impl ) + +class SwXMLTableLines_Impl +{ + SwXMLTableColumns_Impl aCols; + const SwTableLines *pLines; + sal_uInt32 nWidth; + +public: + + SwXMLTableLines_Impl( const SwTableLines& rLines ); + + ~SwXMLTableLines_Impl() {} + + sal_uInt32 GetWidth() const { return nWidth; } + const SwTableLines *GetLines() const { return pLines; } + + const SwXMLTableColumns_Impl& GetColumns() const { return aCols; } +}; + +SwXMLTableLines_Impl::SwXMLTableLines_Impl( const SwTableLines& rLines ) : + pLines( &rLines ), + nWidth( 0UL ) +{ +#ifdef DBG_UTIL + sal_uInt16 nEndCPos = 0U; +#endif + sal_uInt16 nLines = rLines.Count(); + sal_uInt16 nLine; + for( nLine=0U; nLine<nLines; nLine++ ) + { + const SwTableLine *pLine = rLines[nLine]; + const SwTableBoxes& rBoxes = pLine->GetTabBoxes(); + sal_uInt16 nBoxes = rBoxes.Count(); + + sal_uInt16 nCPos = 0U; + for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ ) + { + const SwTableBox *pBox = rBoxes[nBox]; + + if( nBox < nBoxes-1U || nWidth==0UL ) + { + nCPos = nCPos + (sal_uInt16)SwWriteTable::GetBoxWidth( pBox ); + SwXMLTableColumn_Impl *pCol = + new SwXMLTableColumn_Impl( nCPos ); + + if( !aCols.Insert( pCol ) ) + delete pCol; + + if( nBox==nBoxes-1U ) + { + ASSERT( nLine==0U && nWidth==0UL, + "parent width will be lost" ); + nWidth = nCPos; + } + } + else + { +#ifdef DBG_UTIL + sal_uInt16 nCheckPos = + nCPos + (sal_uInt16)SwWriteTable::GetBoxWidth( pBox ); + if( !nEndCPos ) + { + nEndCPos = nCheckPos; + } + else + { + /* + ASSERT( SwXMLTableColumn_impl(nCheckPos) == + SwXMLTableColumn_Impl(nEndCPos), + "rows have different total widths" ); + */ + } +#endif + nCPos = (sal_uInt16)nWidth; +#ifdef DBG_UTIL + SwXMLTableColumn_Impl aCol( (sal_uInt16)nWidth ); + ASSERT( aCols.Seek_Entry(&aCol), "couldn't find last column" ); + ASSERT( SwXMLTableColumn_Impl(nCheckPos) == + SwXMLTableColumn_Impl(nCPos), + "rows have different total widths" ); +#endif + } + } + } +} + +typedef SwXMLTableLines_Impl *SwXMLTableLinesPtr; +DECLARE_LIST( SwXMLTableLinesCache_Impl, SwXMLTableLinesPtr ) + +// --------------------------------------------------------------------- + +typedef SwFrmFmt *SwFrmFmtPtr; +DECLARE_LIST( SwXMLFrmFmts_Impl, SwFrmFmtPtr ) + +class SwXMLTableFrmFmtsSort_Impl : public SwXMLFrmFmts_Impl +{ +public: + SwXMLTableFrmFmtsSort_Impl ( sal_uInt16 nInit, sal_uInt16 nGrow ) : + SwXMLFrmFmts_Impl( nInit, nGrow ) + {} + + sal_Bool AddRow( SwFrmFmt& rFrmFmt, const OUString& rNamePrefix, sal_uInt32 nLine ); + sal_Bool AddCell( SwFrmFmt& rFrmFmt, const OUString& rNamePrefix, + sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop ); +}; + +sal_Bool SwXMLTableFrmFmtsSort_Impl::AddRow( SwFrmFmt& rFrmFmt, + const OUString& rNamePrefix, + sal_uInt32 nLine ) +{ + const SwFmtFrmSize *pFrmSize = 0; + const SwFmtRowSplit* pRowSplit = 0; + const SvxBrushItem *pBrush = 0; + + const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet(); + const SfxPoolItem *pItem; + if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_False, &pItem ) ) + pFrmSize = (const SwFmtFrmSize *)pItem; + + if( SFX_ITEM_SET == rItemSet.GetItemState( RES_ROW_SPLIT, sal_False, &pItem ) ) + pRowSplit = (const SwFmtRowSplit *)pItem; + + if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) ) + pBrush = (const SvxBrushItem *)pItem; + + // empty styles have not to be exported + if( !pFrmSize && !pBrush && !pRowSplit ) + return sal_False; + + // order is: -/brush, size/-, size/brush + sal_uInt32 nCount2 = Count(); + sal_Bool bInsert = sal_True; + sal_uInt32 i; + for( i = 0; i < nCount2; ++i ) + { + const SwFmtFrmSize *pTestFrmSize = 0; + const SwFmtRowSplit* pTestRowSplit = 0; + const SvxBrushItem *pTestBrush = 0; + const SwFrmFmt *pTestFmt = GetObject(i); + const SfxItemSet& rTestSet = pTestFmt->GetAttrSet(); + if( SFX_ITEM_SET == rTestSet.GetItemState( RES_FRM_SIZE, sal_False, + &pItem ) ) + { + if( !pFrmSize ) + break; + + pTestFrmSize = (const SwFmtFrmSize *)pItem; + } + else + { + if( pFrmSize ) + continue; + } + + if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BACKGROUND, sal_False, + &pItem ) ) + { + if( !pBrush ) + break; + + pTestBrush = (const SvxBrushItem *)pItem; + } + else + { + if( pBrush ) + continue; + } + + if( SFX_ITEM_SET == rTestSet.GetItemState( RES_ROW_SPLIT, sal_False, + &pItem ) ) + { + if( !pRowSplit ) + break; + + pTestRowSplit = (const SwFmtRowSplit *)pItem; + } + else + { + if( pRowSplit ) + continue; + } + + + if( pFrmSize && + ( pFrmSize->GetHeightSizeType() != pTestFrmSize->GetHeightSizeType() || + pFrmSize->GetHeight() != pTestFrmSize->GetHeight() ) ) + continue; + + if( pBrush && (*pBrush != *pTestBrush) ) + continue; + + if( pRowSplit && (!pRowSplit->GetValue() != !pTestRowSplit->GetValue()) ) + continue; + + // found! + const String& rFmtName = pTestFmt->GetName(); + rFrmFmt.SetName( rFmtName ); + bInsert = sal_False; + break; + } + + if( bInsert ) + { + OUStringBuffer sBuffer( rNamePrefix.getLength() + 4UL ); + sBuffer.append( rNamePrefix ); + sBuffer.append( (sal_Unicode)'.' ); + sBuffer.append( (sal_Int32)(nLine+1UL) ); + + rFrmFmt.SetName( sBuffer.makeStringAndClear() ); + Insert( &rFrmFmt, i ); + } + + return bInsert; +} + +void lcl_GetTblBoxColStr( sal_uInt16 nCol, String& rNm ); +void lcl_xmltble_appendBoxPrefix( OUStringBuffer& rBuffer, + const OUString& rNamePrefix, + sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop ) +{ + rBuffer.append( rNamePrefix ); + rBuffer.append( (sal_Unicode)'.' ); + if( bTop ) + { + String sTmp; + lcl_GetTblBoxColStr( (sal_uInt16)nCol, sTmp ); + rBuffer.append( sTmp ); + } + else + { + rBuffer.append( (sal_Int32)(nCol + 1)); + rBuffer.append( (sal_Unicode)'.' ); + } + rBuffer.append( (sal_Int32)(nRow + 1)); +} + +sal_Bool SwXMLTableFrmFmtsSort_Impl::AddCell( SwFrmFmt& rFrmFmt, + const OUString& rNamePrefix, + sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop ) +{ + const SwFmtVertOrient *pVertOrient = 0; + const SvxBrushItem *pBrush = 0; + const SvxBoxItem *pBox = 0; + const SwTblBoxNumFormat *pNumFmt = 0; + const SvxFrameDirectionItem *pFrameDir = 0; + + const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet(); + const SfxPoolItem *pItem; + if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_False, + &pItem ) ) + pVertOrient = (const SwFmtVertOrient *)pItem; + + if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) ) + pBrush = (const SvxBrushItem *)pItem; + + if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BOX, sal_False, &pItem ) ) + pBox = (const SvxBoxItem *)pItem; + + if ( SFX_ITEM_SET == rItemSet.GetItemState( RES_BOXATR_FORMAT, + sal_False, &pItem ) ) + pNumFmt = (const SwTblBoxNumFormat *)pItem; + if ( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRAMEDIR, + sal_False, &pItem ) ) + pFrameDir = (const SvxFrameDirectionItem *)pItem; + + // empty styles have not to be exported + if( !pVertOrient && !pBrush && !pBox && !pNumFmt && !pFrameDir ) + return sal_False; + + // order is: -/-/-/num, + // -/-/box/-, --/-/box/num, + // -/brush/-/-, -/brush/-/num, -/brush/box/-, -/brush/box/num, + // vert/-/-/-, vert/-/-/num, vert/-/box/-, ver/-/box/num, + // vert/brush/-/-, vert/brush/-/num, vert/brush/box/-, + // vert/brush/box/num + sal_uInt32 nCount2 = Count(); + sal_Bool bInsert = sal_True; + sal_uInt32 i; + for( i = 0; i < nCount2; ++i ) + { + const SwFmtVertOrient *pTestVertOrient = 0; + const SvxBrushItem *pTestBrush = 0; + const SvxBoxItem *pTestBox = 0; + const SwTblBoxNumFormat *pTestNumFmt = 0; + const SvxFrameDirectionItem *pTestFrameDir = 0; + const SwFrmFmt *pTestFmt = GetObject(i); + const SfxItemSet& rTestSet = pTestFmt->GetAttrSet(); + if( SFX_ITEM_SET == rTestSet.GetItemState( RES_VERT_ORIENT, sal_False, + &pItem ) ) + { + if( !pVertOrient ) + break; + + pTestVertOrient = (const SwFmtVertOrient *)pItem; + } + else + { + if( pVertOrient ) + continue; + } + + if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BACKGROUND, sal_False, + &pItem ) ) + { + if( !pBrush ) + break; + + pTestBrush = (const SvxBrushItem *)pItem; + } + else + { + if( pBrush ) + continue; + } + + if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BOX, sal_False, &pItem ) ) + { + if( !pBox ) + break; + + pTestBox = (const SvxBoxItem *)pItem; + } + else + { + if( pBox ) + continue; + } + + if ( SFX_ITEM_SET == rTestSet.GetItemState( RES_BOXATR_FORMAT, + sal_False, &pItem ) ) + { + if( !pNumFmt ) + break; + + pTestNumFmt = (const SwTblBoxNumFormat *)pItem; + } + else + { + if( pNumFmt ) + continue; + + } + + if ( SFX_ITEM_SET == rTestSet.GetItemState( RES_FRAMEDIR, + sal_False, &pItem ) ) + { + if( !pFrameDir ) + break; + + pTestFrameDir = (const SvxFrameDirectionItem *)pItem; + } + else + { + if( pFrameDir ) + continue; + + } + + if( pVertOrient && + pVertOrient->GetVertOrient() != pTestVertOrient->GetVertOrient() ) + continue; + + if( pBrush && ( *pBrush != *pTestBrush ) ) + continue; + + if( pBox && ( *pBox != *pTestBox ) ) + continue; + + if( pNumFmt && pNumFmt->GetValue() != pTestNumFmt->GetValue() ) + continue; + + if( pFrameDir && pFrameDir->GetValue() != pTestFrameDir->GetValue() ) + continue; + + // found! + const String& rFmtName = pTestFmt->GetName(); + rFrmFmt.SetName( rFmtName ); + bInsert = sal_False; + break; + } + + if( bInsert ) + { + OUStringBuffer sBuffer( rNamePrefix.getLength() + 8UL ); + lcl_xmltble_appendBoxPrefix( sBuffer, rNamePrefix, nCol, nRow, bTop ); + rFrmFmt.SetName( sBuffer.makeStringAndClear() ); + Insert( &rFrmFmt, i ); + } + + return bInsert; +} +// --------------------------------------------------------------------- + +class SwXMLTableInfo_Impl +{ + const SwTable *pTable; + Reference < XTextSection > xBaseSection; + sal_Bool bBaseSectionValid; + +public: + + inline SwXMLTableInfo_Impl( const SwTable *pTbl ); + + const SwTable *GetTable() const { return pTable; } + const SwFrmFmt *GetTblFmt() const { return pTable->GetFrmFmt(); } + + sal_Bool IsBaseSectionValid() const { return bBaseSectionValid; } + const Reference < XTextSection >& GetBaseSection() const { return xBaseSection; } + inline void SetBaseSection( const Reference < XTextSection >& rBase ); +}; + +inline SwXMLTableInfo_Impl::SwXMLTableInfo_Impl( const SwTable *pTbl ) : + pTable( pTbl ), + bBaseSectionValid( sal_False ) +{ +} + +inline void SwXMLTableInfo_Impl::SetBaseSection( + const Reference < XTextSection >& rBaseSection ) +{ + xBaseSection = rBaseSection; + bBaseSectionValid = sal_True; +} + +// --------------------------------------------------------------------- + + +void SwXMLExport::ExportTableColumnStyle( const SwXMLTableColumn_Impl& rCol ) +{ + // <style:style ...> + CheckAttrList(); + + // style:name="..." + sal_Bool bEncoded = sal_False; + AddAttribute( XML_NAMESPACE_STYLE, XML_NAME, + EncodeStyleName( rCol.GetStyleName(), &bEncoded ) ); + if( bEncoded ) + AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rCol.GetStyleName() ); + + // style:family="table-column" + AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE_COLUMN ); + + { + SvXMLElementExport aElem( *this, XML_NAMESPACE_STYLE, XML_STYLE, sal_True, + sal_True ); + OUStringBuffer sValue; + if( rCol.GetWidthOpt() ) + { + GetTwipUnitConverter().convertMeasure( sValue, rCol.GetWidthOpt() ); + AddAttribute( XML_NAMESPACE_STYLE, XML_COLUMN_WIDTH, + sValue.makeStringAndClear() ); + } + if( rCol.GetRelWidth() ) + { + sValue.append( (sal_Int32)rCol.GetRelWidth() ); + sValue.append( (sal_Unicode)'*' ); + AddAttribute( XML_NAMESPACE_STYLE, XML_REL_COLUMN_WIDTH, + sValue.makeStringAndClear() ); + } + + { + SvXMLElementExport aElemExport( *this, XML_NAMESPACE_STYLE, + XML_TABLE_COLUMN_PROPERTIES, + sal_True, sal_True ); + } + } +} + +void SwXMLExport::ExportTableLinesAutoStyles( const SwTableLines& rLines, + sal_uInt32 nAbsWidth, sal_uInt32 nBaseWidth, + const OUString& rNamePrefix, + SwXMLTableColumnsSortByWidth_Impl& rExpCols, + SwXMLTableFrmFmtsSort_Impl& rExpRows, + SwXMLTableFrmFmtsSort_Impl& rExpCells, + SwXMLTableInfo_Impl& rTblInfo, + sal_Bool bTop ) +{ + // pass 1: calculate columns + SwXMLTableLines_Impl *pLines = + new SwXMLTableLines_Impl( rLines ); + if( !pTableLines ) + pTableLines = new SwXMLTableLinesCache_Impl( 5, 5 ); + pTableLines->Insert( pLines, pTableLines->Count() ); + + OUStringBuffer sBuffer( rNamePrefix.getLength() + 8L ); + + // pass 2: export column styles + { + const SwXMLTableColumns_Impl& rCols = pLines->GetColumns(); + sal_uInt16 nCPos = 0U; + sal_uInt16 nColumns = rCols.Count(); + for( sal_uInt16 nColumn=0U; nColumn<nColumns; nColumn++ ) + { + SwXMLTableColumn_Impl *pColumn = rCols[nColumn]; + + sal_uInt16 nOldCPos = nCPos; + nCPos = pColumn->GetPos(); + + sal_uInt32 nWidth = nCPos - nOldCPos; + + // If a base width is given, the table has either an automatic + // or margin alignment, or an percentage width. In either case, + // relative widths should be exported. + if( nBaseWidth ) + { + pColumn->SetRelWidth( nWidth ); + } + + // If an absolute width is given, the table either has a fixed + // width, or the current width is known from the layout. In the + // later case, a base width is set in addition and must be used + // to "absoultize" the relative column width. + if( nAbsWidth ) + { + sal_uInt32 nColAbsWidth = nWidth; + if( nBaseWidth ) + { + nColAbsWidth *= nAbsWidth; + nColAbsWidth += (nBaseWidth/2UL); + nColAbsWidth /= nBaseWidth; + } + pColumn->SetWidthOpt( (sal_uInt16)nColAbsWidth, sal_False ); + } + + ULONG nExpPos = 0; + if( rExpCols.Seek_Entry( pColumn, &nExpPos ) ) + { + pColumn->SetStyleName( + rExpCols.GetObject(nExpPos)->GetStyleName() ); + } + else + { + sBuffer.append( rNamePrefix ); + sBuffer.append( (sal_Unicode)'.' ); + if( bTop ) + { + String sTmp; + lcl_GetTblBoxColStr( nColumn, sTmp ); + sBuffer.append( sTmp ); + } + else + { + sBuffer.append( (sal_Int32)(nColumn + 1U) ); + } + + pColumn->SetStyleName( sBuffer.makeStringAndClear() ); + ExportTableColumnStyle( *pColumn ); + rExpCols.Insert( pColumn ); + } + } + } + + // pass 3: export line/rows + sal_uInt16 nLines = rLines.Count(); + for( sal_uInt16 nLine=0U; nLine<nLines; nLine++ ) + { + SwTableLine *pLine = rLines[nLine]; + + SwFrmFmt *pFrmFmt = pLine->GetFrmFmt(); + if( rExpRows.AddRow( *pFrmFmt, rNamePrefix, nLine ) ) + ExportFmt( *pFrmFmt, XML_TABLE_ROW ); + + const SwTableBoxes& rBoxes = pLine->GetTabBoxes(); + sal_uInt16 nBoxes = rBoxes.Count(); + + sal_uInt16 nCPos = 0U; + sal_uInt16 nCol = 0U; + for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ ) + { + SwTableBox *pBox = rBoxes[nBox]; + + if( nBox < nBoxes-1U ) + nCPos = nCPos + (sal_uInt16)SwWriteTable::GetBoxWidth( pBox ); + else + nCPos = (sal_uInt16)pLines->GetWidth(); + + + // Und ihren Index + sal_uInt16 nOldCol = nCol; + SwXMLTableColumn_Impl aCol( nCPos ); +#ifdef DBG_UTIL + sal_Bool bFound = +#endif + pLines->GetColumns().Seek_Entry( &aCol, &nCol ); + ASSERT( bFound, "couldn't find column" ); + + const SwStartNode *pBoxSttNd = pBox->GetSttNd(); + if( pBoxSttNd ) + { + SwFrmFmt *pFrmFmt2 = pBox->GetFrmFmt(); + if( rExpCells.AddCell( *pFrmFmt2, rNamePrefix, nOldCol, nLine, + bTop) ) + ExportFmt( *pFrmFmt2, XML_TABLE_CELL ); + + Reference < XCell > xCell = SwXCell::CreateXCell( + (SwFrmFmt *)rTblInfo.GetTblFmt(), + pBox, + (SwTable *)rTblInfo.GetTable() ); + if (xCell.is()) + { + Reference < XText > xText( xCell, UNO_QUERY ); + if( !rTblInfo.IsBaseSectionValid() ) + { + Reference<XPropertySet> xCellPropertySet( xCell, + UNO_QUERY ); + OUString sTextSection( RTL_CONSTASCII_USTRINGPARAM("TextSection") ); + Any aAny = xCellPropertySet->getPropertyValue(sTextSection); + Reference < XTextSection > xTextSection; + aAny >>= xTextSection; + rTblInfo.SetBaseSection( xTextSection ); + } + + const bool bExportContent = (getExportFlags() & EXPORT_CONTENT ) != 0; + if ( !bExportContent ) + { + // AUTOSTYLES - not needed anymore if we are currently exporting content.xml + GetTextParagraphExport()->collectTextAutoStyles( + xText, rTblInfo.GetBaseSection(), IsShowProgress() ); + } + } + else { + DBG_ERROR("here should be a XCell"); + } + } + else + { + lcl_xmltble_appendBoxPrefix( sBuffer, rNamePrefix, nOldCol, + nLine, bTop ); + + ExportTableLinesAutoStyles( pBox->GetTabLines(), + nAbsWidth, nBaseWidth, + sBuffer.makeStringAndClear(), + rExpCols, rExpRows, rExpCells, + rTblInfo ); + } + + nCol++; + } + } +} + +void SwXMLExport::ExportTableAutoStyles( const SwTableNode& rTblNd ) +{ + const SwTable& rTbl = rTblNd.GetTable(); + const SwFrmFmt *pTblFmt = rTbl.GetFrmFmt(); + + if( pTblFmt ) + { + sal_Int16 eTabHoriOri = pTblFmt->GetHoriOrient().GetHoriOrient(); + const SwFmtFrmSize& rFrmSize = pTblFmt->GetFrmSize(); + + sal_uInt32 nAbsWidth = rFrmSize.GetSize().Width(); + sal_uInt32 nBaseWidth = 0UL; + sal_Int8 nPrcWidth = rFrmSize.GetWidthPercent(); + + sal_Bool bFixAbsWidth = nPrcWidth != 0 || /*text::*/HoriOrientation::NONE == eTabHoriOri + || /*text::*/HoriOrientation::FULL == eTabHoriOri; + if( bFixAbsWidth ) + { + nBaseWidth = nAbsWidth; + nAbsWidth = pTblFmt->FindLayoutRect(sal_True).Width(); + if( !nAbsWidth ) + { + // TODO??? + } + } + ExportTableFmt( *pTblFmt, nAbsWidth ); + + OUString sName( pTblFmt->GetName() ); + SwXMLTableColumnsSortByWidth_Impl aExpCols( 10, 10 ); + SwXMLTableFrmFmtsSort_Impl aExpRows( 10, 10 ); + SwXMLTableFrmFmtsSort_Impl aExpCells( 10, 10 ); + SwXMLTableInfo_Impl aTblInfo( &rTbl ); + ExportTableLinesAutoStyles( rTbl.GetTabLines(), nAbsWidth, nBaseWidth, + sName, aExpCols, aExpRows, aExpCells, + aTblInfo, sal_True); + } +} + +// --------------------------------------------------------------------- + +void SwXMLExport::ExportTableBox( const SwTableBox& rBox, + sal_uInt16 nColSpan, + sal_uInt16 nRowSpan, + SwXMLTableInfo_Impl& rTblInfo ) +{ + const SwStartNode *pBoxSttNd = rBox.GetSttNd(); + if( pBoxSttNd ) + { + const SwFrmFmt *pFrmFmt = rBox.GetFrmFmt(); + if( pFrmFmt ) + { + const String& rName = pFrmFmt->GetName(); + if( rName.Len() ) + { + AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(rName) ); + } + } + } + + if( nRowSpan != 1 ) + { + OUStringBuffer sTmp; + sTmp.append( (sal_Int32)nRowSpan ); + AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, + sTmp.makeStringAndClear() ); + } + + if( nColSpan != 1 ) + { + OUStringBuffer sTmp; + sTmp.append( (sal_Int32)nColSpan ); + AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, + sTmp.makeStringAndClear() ); + } + + { + if( pBoxSttNd ) + { + // start node -> normal cell + + // get cell range for table + Reference<XCell> xCell = SwXCell::CreateXCell( (SwFrmFmt *)rTblInfo.GetTblFmt(), + (SwTableBox *)&rBox, + (SwTable *)rTblInfo.GetTable() ); + + if (xCell.is()) + { + Reference<XText> xText( xCell, UNO_QUERY ); + + // get formula (and protection) + OUString sCellFormula = xCell->getFormula(); + + // if this cell has a formula, export it + // (with value and number format) + if (sCellFormula.getLength()>0) + { + OUString sQValue = + GetNamespaceMap().GetQNameByKey( + XML_NAMESPACE_OOOW, sCellFormula, sal_False ); + // formula + AddAttribute(XML_NAMESPACE_TABLE, XML_FORMULA, sQValue ); + } + + // value and format (if NumberFormat != -1) + Reference<XPropertySet> xCellPropertySet(xCell, + UNO_QUERY); + if (xCellPropertySet.is()) + { + sal_Int32 nNumberFormat = 0; + Any aAny = xCellPropertySet->getPropertyValue(sNumberFormat); + aAny >>= nNumberFormat; + + if (NUMBERFORMAT_TEXT == nNumberFormat) + { + // text format + AddAttribute( XML_NAMESPACE_OFFICE, + XML_VALUE_TYPE, XML_STRING ); + } + else if ( (-1 != nNumberFormat) && (xText->getString().getLength() > 0) ) + { + // number format key: + // (export values only if cell contains text; + // cf. #83755#) + XMLNumberFormatAttributesExportHelper:: + SetNumberFormatAttributes( + *this, nNumberFormat, xCell->getValue(), + sal_True ); + } + // else: invalid key; ignore + + // cell protection + aAny = xCellPropertySet->getPropertyValue(sIsProtected); + if (*(sal_Bool*)aAny.getValue()) + { + AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED, + XML_TRUE ); + } + + if( !rTblInfo.IsBaseSectionValid() ) + { + OUString sTextSection( RTL_CONSTASCII_USTRINGPARAM("TextSection") ); + aAny = xCellPropertySet->getPropertyValue(sTextSection); + Reference < XTextSection > xTextSection; + aAny >>= xTextSection; + rTblInfo.SetBaseSection( xTextSection ); + } + } + + // export cell element + SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, + XML_TABLE_CELL, sal_True, sal_True ); + + // export cell content + GetTextParagraphExport()->exportText( xText, + rTblInfo.GetBaseSection(), + IsShowProgress() ); + } + else + { + DBG_ERROR("here should be a XCell"); + ClearAttrList(); + } + } + else + { + // no start node -> merged cells: export subtable in cell + SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, + XML_TABLE_CELL, sal_True, sal_True ); + { + AddAttribute( XML_NAMESPACE_TABLE, XML_IS_SUB_TABLE, + GetXMLToken( XML_TRUE ) ); + + SvXMLElementExport aElemExport( *this, XML_NAMESPACE_TABLE, + XML_TABLE, sal_True, sal_True ); + ExportTableLines( rBox.GetTabLines(), rTblInfo ); + } + } + } +} + +void SwXMLExport::ExportTableLine( const SwTableLine& rLine, + const SwXMLTableLines_Impl& rLines, + SwXMLTableInfo_Impl& rTblInfo ) +{ + if( rLine.hasSoftPageBreak() ) + { + SvXMLElementExport aElem( *this, XML_NAMESPACE_TEXT, + XML_SOFT_PAGE_BREAK, sal_True, sal_True ); + } + const SwFrmFmt *pFrmFmt = rLine.GetFrmFmt(); + if( pFrmFmt ) + { + const String& rName = pFrmFmt->GetName(); + if( rName.Len() ) + { + AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(rName) ); + } + } + + { + SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, + XML_TABLE_ROW, sal_True, sal_True ); + const SwTableBoxes& rBoxes = rLine.GetTabBoxes(); + sal_uInt16 nBoxes = rBoxes.Count(); + + sal_uInt16 nCPos = 0U; + sal_uInt16 nCol = 0U; + for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ ) + { + const SwTableBox *pBox = rBoxes[nBox]; + + // NEW TABLES + const long nRowSpan = pBox->getRowSpan(); + if( nRowSpan < 1 ) + { + SvXMLElementExport aElem2( *this, XML_NAMESPACE_TABLE, + XML_COVERED_TABLE_CELL, sal_True, + sal_False ); + } + + if( nBox < nBoxes-1U ) + nCPos = nCPos + (sal_uInt16)SwWriteTable::GetBoxWidth( pBox ); + else + nCPos = (sal_uInt16)rLines.GetWidth(); + + // Und ihren Index + const sal_uInt16 nOldCol = nCol; + { + SwXMLTableColumn_Impl aCol( nCPos ); +#ifdef DBG_UTIL + const sal_Bool bFound = +#endif + rLines.GetColumns().Seek_Entry( &aCol, &nCol ); + ASSERT( bFound, "couldn't find column" ); + } + + // --> OD 2009-03-19 #i95726# + // Some fault tolerance, if table is somehow corrupted. + if ( nCol < nOldCol ) + { + ASSERT( false, "table and/or table information seems to be corrupted." ); + if ( nBox == nBoxes - 1 ) + { + nCol = rLines.GetColumns().Count() - 1; + } + else + { + nCol = nOldCol; + } + } + // <-- + + sal_uInt16 nColSpan = nCol - nOldCol + 1U; + + if ( nRowSpan >= 1 ) + ExportTableBox( *pBox, nColSpan, static_cast< sal_uInt16 >(nRowSpan), rTblInfo ); + + for( sal_uInt16 i=nOldCol; i<nCol; i++ ) + { + SvXMLElementExport aElemExport( *this, XML_NAMESPACE_TABLE, + XML_COVERED_TABLE_CELL, sal_True, + sal_False ); + } + + nCol++; + } + } +} + +void SwXMLExport::ExportTableLines( const SwTableLines& rLines, + SwXMLTableInfo_Impl& rTblInfo, + USHORT nHeaderRows ) +{ + ASSERT( pTableLines && pTableLines->Count(), + "SwXMLExport::ExportTableLines: table columns infos missing" ); + if( !pTableLines || 0 == pTableLines->Count() ) + return; + + SwXMLTableLines_Impl *pLines = 0; + sal_uInt16 nInfoPos; + for( nInfoPos=0; nInfoPos < pTableLines->Count(); nInfoPos++ ) + { + if( pTableLines->GetObject( nInfoPos )->GetLines() == &rLines ) + { + pLines = pTableLines->GetObject( nInfoPos ); + break; + } + } + ASSERT( pLines, + "SwXMLExport::ExportTableLines: table columns info missing" ); + ASSERT( 0==nInfoPos, + "SwXMLExport::ExportTableLines: table columns infos are unsorted" ); + if( !pLines ) + return; + + pTableLines->Remove( nInfoPos ); + if( 0 == pTableLines->Count() ) + { + delete pTableLines ; + pTableLines = 0; + } + + // pass 2: export columns + const SwXMLTableColumns_Impl& rCols = pLines->GetColumns(); + sal_uInt16 nColumn = 0U; + sal_uInt16 nColumns = rCols.Count(); + sal_uInt16 nColRep = 1U; + SwXMLTableColumn_Impl *pColumn = (nColumns > 0) ? rCols[0U] : 0; + while( pColumn ) + { + nColumn++; + SwXMLTableColumn_Impl *pNextColumn = + (nColumn < nColumns) ? rCols[nColumn] : 0; + if( pNextColumn && + pNextColumn->GetStyleName() == pColumn->GetStyleName() ) + { + nColRep++; + } + else + { + AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, + EncodeStyleName(pColumn->GetStyleName()) ); + + if( nColRep > 1U ) + { + OUStringBuffer sTmp(4); + sTmp.append( (sal_Int32)nColRep ); + AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, + sTmp.makeStringAndClear() ); + } + + { + SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, + XML_TABLE_COLUMN, sal_True, sal_True ); + } + + nColRep = 1U; + } + pColumn = pNextColumn; + } + + // pass 3: export line/rows + sal_uInt16 nLines = rLines.Count(); + // export header rows, if present + if( nHeaderRows > 0 ) + { + SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, + XML_TABLE_HEADER_ROWS, sal_True, sal_True ); + + DBG_ASSERT( nHeaderRows <= nLines, "more headers then lines?" ); + for( sal_uInt16 nLine = 0U; nLine < nHeaderRows; nLine++ ) + ExportTableLine( *(rLines[nLine]), *pLines, rTblInfo ); + } + // export remaining rows + for( sal_uInt16 nLine = nHeaderRows; nLine < nLines; nLine++ ) + { + ExportTableLine( *(rLines[nLine]), *pLines, rTblInfo ); + } + + delete pLines; +} + +sal_Bool lcl_xmltble_ClearName_Line( const SwTableLine*& rpLine, void* ); + +sal_Bool lcl_xmltble_ClearName_Box( const SwTableBox*& rpBox, void* ) +{ + if( !rpBox->GetSttNd() ) + { + ((SwTableBox *)rpBox)->GetTabLines().ForEach( + &lcl_xmltble_ClearName_Line, 0 ); + } + else + { + SwFrmFmt *pFrmFmt = ((SwTableBox *)rpBox)->GetFrmFmt(); + if( pFrmFmt && pFrmFmt->GetName().Len() ) + pFrmFmt->SetName( aEmptyStr ); + } + + return sal_True; +} + +sal_Bool lcl_xmltble_ClearName_Line( const SwTableLine*& rpLine, void* ) +{ + ((SwTableLine *)rpLine)->GetTabBoxes().ForEach( + &lcl_xmltble_ClearName_Box, 0 ); + + return sal_True; +} + +void SwXMLExport::ExportTable( const SwTableNode& rTblNd ) +{ + const SwTable& rTbl = rTblNd.GetTable(); + const SwFrmFmt *pTblFmt = rTbl.GetFrmFmt(); + if( pTblFmt && pTblFmt->GetName().Len() ) + { + AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, pTblFmt->GetName() ); + AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, + EncodeStyleName( pTblFmt->GetName() ) ); + } + + { + SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_TABLE, + sal_True, sal_True ); + + // export DDE source (if this is a DDE table) + if ( rTbl.ISA(SwDDETable) ) + { + // get DDE Field Type (contains the DDE connection) + const SwDDEFieldType* pDDEFldType = + ((SwDDETable&)rTbl).GetDDEFldType(); + + // connection name + AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME, + pDDEFldType->GetName() ); + + // DDE command + const String sCmd = pDDEFldType->GetCmd(); + AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_APPLICATION, + sCmd.GetToken(0, sfx2::cTokenSeperator) ); + AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_ITEM, + sCmd.GetToken(1, sfx2::cTokenSeperator) ); + AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_TOPIC, + sCmd.GetToken(2, sfx2::cTokenSeperator) ); + + // auto update + if (pDDEFldType->GetType() == sfx2::LINKUPDATE_ALWAYS) + { + AddAttribute( XML_NAMESPACE_OFFICE, + XML_AUTOMATIC_UPDATE, XML_TRUE ); + } + + // DDE source element (always empty) + SvXMLElementExport aSource(*this, XML_NAMESPACE_OFFICE, + XML_DDE_SOURCE, sal_True, sal_False); + } + + SwXMLTableInfo_Impl aTblInfo( &rTbl ); + ExportTableLines( rTbl.GetTabLines(), aTblInfo, rTbl.GetRowsToRepeat() ); + + ((SwTable &)rTbl).GetTabLines().ForEach( &lcl_xmltble_ClearName_Line, + 0 ); + } +} + +void SwXMLTextParagraphExport::exportTable( + const Reference < XTextContent > & rTextContent, + sal_Bool bAutoStyles, sal_Bool _bProgress ) +{ + sal_Bool bOldShowProgress = ((SwXMLExport&)GetExport()).IsShowProgress(); + ((SwXMLExport&)GetExport()).SetShowProgress( _bProgress ); + + Reference < XTextTable > xTxtTbl( rTextContent, UNO_QUERY ); + DBG_ASSERT( xTxtTbl.is(), "text table missing" ); + if( xTxtTbl.is() ) + { + const SwXTextTable *pXTable = 0; + Reference<XUnoTunnel> xTableTunnel( rTextContent, UNO_QUERY); + if( xTableTunnel.is() ) + { + pXTable = reinterpret_cast< SwXTextTable * >( + sal::static_int_cast< sal_IntPtr >( xTableTunnel->getSomething( SwXTextTable::getUnoTunnelId() ))); + ASSERT( pXTable, "SwXTextTable missing" ); + } + if( pXTable ) + { + SwFrmFmt *pFmt = pXTable->GetFrmFmt(); + ASSERT( pFmt, "table format missing" ); + const SwTable *pTbl = SwTable::FindTable( pFmt ); + ASSERT( pTbl, "table missing" ); + const SwTableNode *pTblNd = pTbl->GetTableNode(); + ASSERT( pTblNd, "table node missing" ); + if( bAutoStyles ) + { + SwNodeIndex aIdx( *pTblNd ); + // AUTOSTYLES: Optimization: Do not export table autostyle if + // we are currently exporting the content.xml stuff and + // the table is located in header/footer: + // #144704: During the flat XML export (used e.g. by .sdw-export) + // ALL flags are set at the same time. + const bool bExportStyles = ( GetExport().getExportFlags() & EXPORT_STYLES ) != 0; + if ( bExportStyles || !pFmt->GetDoc()->IsInHeaderFooter( aIdx ) ) + ((SwXMLExport&)GetExport()).ExportTableAutoStyles( *pTblNd ); + } + else + { + ((SwXMLExport&)GetExport()).ExportTable( *pTblNd ); + } + } + } + + ((SwXMLExport&)GetExport()).SetShowProgress( bOldShowProgress ); +} + + diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx new file mode 100644 index 000000000000..4b6af56066fc --- /dev/null +++ b/sw/source/filter/xml/xmltbli.cxx @@ -0,0 +1,2951 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include "hintids.hxx" + +#include <limits.h> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/text/XTextTable.hpp> +#include <com/sun/star/table/XCellRange.hpp> +#include <svl/itemset.hxx> +#include <svl/zformat.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmltkmap.hxx> +#include <xmloff/nmspmap.hxx> + +#include <xmloff/families.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/i18nmap.hxx> +#include <editeng/protitem.hxx> +#include "poolfmt.hxx" +#include "fmtfsize.hxx" +#include "fmtornt.hxx" +#include "fmtfordr.hxx" +#include "doc.hxx" +#include "swtable.hxx" +#include "swtblfmt.hxx" +#include "pam.hxx" +#include "unotbl.hxx" +#include "unotextrange.hxx" +#include "unocrsr.hxx" +#include "cellatr.hxx" +#include "swddetbl.hxx" +#include "ddefld.hxx" +#include <sfx2/linkmgr.hxx> // for cTokenSeparator +#include "xmlimp.hxx" +#include "xmltbli.hxx" + +// for locking SolarMutex: svapp + mutex +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include "ndtxt.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::table; +using namespace ::com::sun::star::xml::sax; +using namespace ::xmloff::token; +using ::std::hash_map; + +enum SwXMLTableElemTokens +{ + XML_TOK_TABLE_HEADER_COLS, + XML_TOK_TABLE_COLS, + XML_TOK_TABLE_COL, + XML_TOK_TABLE_HEADER_ROWS, + XML_TOK_TABLE_ROWS, + XML_TOK_TABLE_ROW, + XML_TOK_OFFICE_DDE_SOURCE, + XML_TOK_TABLE_ELEM_END=XML_TOK_UNKNOWN +}; + +enum SwXMLTableCellAttrTokens +{ + XML_TOK_TABLE_XMLID, + XML_TOK_TABLE_STYLE_NAME, + XML_TOK_TABLE_NUM_COLS_SPANNED, + XML_TOK_TABLE_NUM_ROWS_SPANNED, + XML_TOK_TABLE_NUM_COLS_REPEATED, + XML_TOK_TABLE_FORMULA, + XML_TOK_TABLE_VALUE, + XML_TOK_TABLE_TIME_VALUE, + XML_TOK_TABLE_DATE_VALUE, + XML_TOK_TABLE_BOOLEAN_VALUE, + XML_TOK_TABLE_PROTECTED, + XML_TOK_TABLE_STRING_VALUE, + XML_TOK_TABLE_CELL_ATTR_END=XML_TOK_UNKNOWN +}; + +static __FAR_DATA SvXMLTokenMapEntry aTableElemTokenMap[] = +{ + { XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS, + XML_TOK_TABLE_HEADER_COLS }, + { XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, XML_TOK_TABLE_COLS }, + { XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, XML_TOK_TABLE_COL }, + { XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS, + XML_TOK_TABLE_HEADER_ROWS }, + { XML_NAMESPACE_TABLE, XML_TABLE_ROWS, XML_TOK_TABLE_ROWS }, + { XML_NAMESPACE_TABLE, XML_TABLE_ROW, XML_TOK_TABLE_ROW }, + { XML_NAMESPACE_OFFICE, XML_DDE_SOURCE, + XML_TOK_OFFICE_DDE_SOURCE }, + + // There are slight differences between <table:table-columns> and + // <table:table-columns-groups>. However, none of these are + // supported in Writer (they are Calc-only features), so we + // support column groups by simply using the <table:table-columns> + // token for column groups, too. + { XML_NAMESPACE_TABLE, XML_TABLE_COLUMN_GROUP, XML_TOK_TABLE_COLS }, + + XML_TOKEN_MAP_END +}; + +static __FAR_DATA SvXMLTokenMapEntry aTableCellAttrTokenMap[] = +{ + { XML_NAMESPACE_XML, XML_ID, XML_TOK_TABLE_XMLID }, + { XML_NAMESPACE_TABLE, XML_STYLE_NAME, XML_TOK_TABLE_STYLE_NAME }, + { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, XML_TOK_TABLE_NUM_COLS_SPANNED }, + { XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, XML_TOK_TABLE_NUM_ROWS_SPANNED }, + { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, XML_TOK_TABLE_NUM_COLS_REPEATED }, + { XML_NAMESPACE_TABLE, XML_FORMULA, XML_TOK_TABLE_FORMULA }, + { XML_NAMESPACE_OFFICE, XML_VALUE, XML_TOK_TABLE_VALUE }, + { XML_NAMESPACE_OFFICE, XML_TIME_VALUE, XML_TOK_TABLE_TIME_VALUE }, + { XML_NAMESPACE_OFFICE, XML_DATE_VALUE, XML_TOK_TABLE_DATE_VALUE }, + { XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_TOK_TABLE_BOOLEAN_VALUE }, + { XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TOK_TABLE_PROTECTED }, + { XML_NAMESPACE_TABLE, XML_PROTECT, XML_TOK_TABLE_PROTECTED }, // for backwards compatibility with SRC629 (and before) + { XML_NAMESPACE_OFFICE, XML_STRING_VALUE, XML_TOK_TABLE_STRING_VALUE }, + XML_TOKEN_MAP_END +}; + +const SvXMLTokenMap& SwXMLImport::GetTableElemTokenMap() +{ + if( !pTableElemTokenMap ) + pTableElemTokenMap = new SvXMLTokenMap( aTableElemTokenMap ); + + return *pTableElemTokenMap; +} + +const SvXMLTokenMap& SwXMLImport::GetTableCellAttrTokenMap() +{ + if( !pTableCellAttrTokenMap ) + pTableCellAttrTokenMap = new SvXMLTokenMap( aTableCellAttrTokenMap ); + + return *pTableCellAttrTokenMap; +} + +// --------------------------------------------------------------------- + +class SwXMLTableCell_Impl +{ + OUString aStyleName; + + OUString mXmlId; + + OUString sFormula; // cell formula; valid if length > 0 + double dValue; // formula value + + SvXMLImportContextRef xSubTable; + + const SwStartNode *pStartNode; + sal_uInt32 nRowSpan; + sal_uInt32 nColSpan; + + sal_Bool bProtected : 1; + sal_Bool bHasValue; // determines whether dValue attribute is valid + sal_Bool mbCovered; + sal_Bool mbTextValue; + +public: + + SwXMLTableCell_Impl( sal_uInt32 nRSpan=1UL, sal_uInt32 nCSpan=1UL ) : + pStartNode( 0 ), + nRowSpan( nRSpan ), + nColSpan( nCSpan ), + bProtected( sal_False ), + mbCovered( sal_False ) + {} + + inline void Set( const OUString& rStyleName, + sal_uInt32 nRSpan, sal_uInt32 nCSpan, + const SwStartNode *pStNd, SwXMLTableContext *pTable, + sal_Bool bProtect = sal_False, + const OUString* pFormula = NULL, + sal_Bool bHasValue = sal_False, + sal_Bool mbCovered = sal_False, + double dVal = 0.0, + sal_Bool mbTextValue = sal_False, + OUString const& i_rXmlId = OUString()); + + sal_Bool IsUsed() const { return pStartNode!=0 || + xSubTable.Is() || bProtected;} + + sal_uInt32 GetRowSpan() const { return nRowSpan; } + void SetRowSpan( sal_uInt32 nSet ) { nRowSpan = nSet; } + sal_uInt32 GetColSpan() const { return nColSpan; } + const OUString& GetStyleName() const { return aStyleName; } + const OUString& GetFormula() const { return sFormula; } + double GetValue() const { return dValue; } + sal_Bool HasValue() const { return bHasValue; } + sal_Bool IsProtected() const { return bProtected; } + sal_Bool IsCovered() const { return mbCovered; } + sal_Bool HasTextValue() const { return mbTextValue; } + const OUString& GetXmlId() const { return mXmlId; } + + const SwStartNode *GetStartNode() const { return pStartNode; } + inline void SetStartNode( const SwStartNode *pSttNd ); + + inline SwXMLTableContext *GetSubTable() const; + + inline void Dispose(); +}; + +inline void SwXMLTableCell_Impl::Set( const OUString& rStyleName, + sal_uInt32 nRSpan, sal_uInt32 nCSpan, + const SwStartNode *pStNd, + SwXMLTableContext *pTable, + sal_Bool bProtect, + const OUString* pFormula, + sal_Bool bHasVal, + sal_Bool bCov, + double dVal, + sal_Bool bTextVal, + OUString const& i_rXmlId ) +{ + aStyleName = rStyleName; + nRowSpan = nRSpan; + nColSpan = nCSpan; + pStartNode = pStNd; + xSubTable = pTable; + dValue = dVal; + bHasValue = bHasVal; + mbCovered = bCov; + mbTextValue = bTextVal; + bProtected = bProtect; + + if (!mbCovered) // ensure uniqueness + { + mXmlId = i_rXmlId; + } + + // set formula, if valid + if (pFormula != NULL) + { + sFormula = *pFormula; + } +} + +inline void SwXMLTableCell_Impl::SetStartNode( const SwStartNode *pSttNd ) +{ + pStartNode = pSttNd; + xSubTable = 0; +} + +inline SwXMLTableContext *SwXMLTableCell_Impl::GetSubTable() const +{ + return (SwXMLTableContext *)&xSubTable; +} + +inline void SwXMLTableCell_Impl::Dispose() +{ + if( xSubTable.Is() ) + xSubTable = 0; +} + +// --------------------------------------------------------------------- + +typedef SwXMLTableCell_Impl* SwXMLTableCellPtr; +SV_DECL_PTRARR_DEL(SwXMLTableCells_Impl,SwXMLTableCellPtr,5,5) +SV_IMPL_PTRARR(SwXMLTableCells_Impl,SwXMLTableCellPtr) + +class SwXMLTableRow_Impl +{ + OUString aStyleName; + OUString aDfltCellStyleName; + OUString mXmlId; + + SwXMLTableCells_Impl aCells; + + sal_Bool bSplitable; + +public: + + SwXMLTableRow_Impl( const OUString& rStyleName, sal_uInt32 nCells, + const OUString *pDfltCellStyleName = 0, + const OUString& i_rXmlId = OUString() ); + ~SwXMLTableRow_Impl() {} + + inline SwXMLTableCell_Impl *GetCell( sal_uInt32 nCol ) const; + + inline void Set( const OUString& rStyleName, + const OUString& rDfltCellStyleName, + const OUString& i_rXmlId ); + + void Expand( sal_uInt32 nCells, sal_Bool bOneCell ); + + void SetSplitable( sal_Bool bSet ) { bSplitable = bSet; } + sal_Bool IsSplitable() const { return bSplitable; } + + const OUString& GetStyleName() const { return aStyleName; } + const OUString& GetDefaultCellStyleName() const { return aDfltCellStyleName; } + const OUString& GetXmlId() const { return mXmlId; } + + void Dispose(); +}; + +SwXMLTableRow_Impl::SwXMLTableRow_Impl( const OUString& rStyleName, + sal_uInt32 nCells, + const OUString *pDfltCellStyleName, + const OUString& i_rXmlId ) : + aStyleName( rStyleName ), + mXmlId( i_rXmlId ), + bSplitable( sal_False ) +{ + if( pDfltCellStyleName ) + aDfltCellStyleName = *pDfltCellStyleName; + ASSERT( nCells <= USHRT_MAX, + "SwXMLTableRow_Impl::SwXMLTableRow_Impl: too many cells" ); + if( nCells > USHRT_MAX ) + nCells = USHRT_MAX; + + for( sal_uInt16 i=0U; i<nCells; i++ ) + { + aCells.Insert( new SwXMLTableCell_Impl, aCells.Count() ); + } +} + +inline SwXMLTableCell_Impl *SwXMLTableRow_Impl::GetCell( sal_uInt32 nCol ) const +{ + ASSERT( nCol < USHRT_MAX, + "SwXMLTableRow_Impl::GetCell: column number is to big" ); + // --> OD 2009-03-19 #i95726# - some fault tolerance +// return aCells[(sal_uInt16)nCol]; + ASSERT( nCol < aCells.Count(), + "SwXMLTableRow_Impl::GetCell: column number is out of bound" ); + return nCol < aCells.Count() ? aCells[(sal_uInt16)nCol] : 0; + // <-- +} + +void SwXMLTableRow_Impl::Expand( sal_uInt32 nCells, sal_Bool bOneCell ) +{ + ASSERT( nCells <= USHRT_MAX, + "SwXMLTableRow_Impl::Expand: too many cells" ); + if( nCells > USHRT_MAX ) + nCells = USHRT_MAX; + + sal_uInt32 nColSpan = nCells - aCells.Count(); + for( sal_uInt16 i=aCells.Count(); i<nCells; i++ ) + { + aCells.Insert( new SwXMLTableCell_Impl( 1UL, + bOneCell ? nColSpan : 1UL ), + aCells.Count() ); + nColSpan--; + } + + ASSERT( nCells<=aCells.Count(), + "SwXMLTableRow_Impl::Expand: wrong number of cells" ); +} + +inline void SwXMLTableRow_Impl::Set( const OUString& rStyleName, + const OUString& rDfltCellStyleName, + const OUString& i_rXmlId ) +{ + aStyleName = rStyleName; + aDfltCellStyleName = rDfltCellStyleName; + mXmlId = i_rXmlId; +} + +void SwXMLTableRow_Impl::Dispose() +{ + for( sal_uInt16 i=0; i < aCells.Count(); i++ ) + aCells[i]->Dispose(); +} + +// --------------------------------------------------------------------- + +class SwXMLTableCellContext_Impl : public SvXMLImportContext +{ + OUString aStyleName; + OUString sFormula; + OUString sSaveParaDefault; + OUString mXmlId; + + SvXMLImportContextRef xMyTable; + + double fValue; + sal_Bool bHasValue; + sal_Bool bHasTextValue; + sal_Bool bProtect; + + sal_uInt32 nRowSpan; + sal_uInt32 nColSpan; + sal_uInt32 nColRepeat; + + sal_Bool bHasTextContent : 1; + sal_Bool bHasTableContent : 1; + + SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; } + + sal_Bool HasContent() const { return bHasTextContent || bHasTableContent; } + inline void _InsertContent(); + inline void InsertContent(); + inline void InsertContentIfNotThere(); + inline void InsertContent( SwXMLTableContext *pTable ); + +public: + + SwXMLTableCellContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable ); + + virtual ~SwXMLTableCellContext_Impl(); + + virtual SvXMLImportContext *CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ); + virtual void EndElement(); + + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } +}; + +SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + sFormula(), + xMyTable( pTable ), + fValue( 0.0 ), + bHasValue( sal_False ), + bHasTextValue( sal_False ), + bProtect( sal_False ), + nRowSpan( 1UL ), + nColSpan( 1UL ), + nColRepeat( 1UL ), + bHasTextContent( sal_False ), + bHasTableContent( sal_False ) +{ + sSaveParaDefault = GetImport().GetTextImport()->GetCellParaStyleDefault(); + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + + OUString aLocalName; + sal_uInt16 nPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + const OUString& rValue = xAttrList->getValueByIndex( i ); + const SvXMLTokenMap& rTokenMap = + GetSwImport().GetTableCellAttrTokenMap(); + switch( rTokenMap.Get( nPrefix, aLocalName ) ) + { + case XML_TOK_TABLE_XMLID: + mXmlId = rValue; + break; + case XML_TOK_TABLE_STYLE_NAME: + aStyleName = rValue; + GetImport().GetTextImport()->SetCellParaStyleDefault(rValue); + break; + case XML_TOK_TABLE_NUM_COLS_SPANNED: + nColSpan = (sal_uInt32)rValue.toInt32(); + if( nColSpan < 1UL ) + nColSpan = 1UL; + break; + case XML_TOK_TABLE_NUM_ROWS_SPANNED: + nRowSpan = (sal_uInt32)rValue.toInt32(); + if( nRowSpan < 1UL ) + nRowSpan = 1UL; + break; + case XML_TOK_TABLE_NUM_COLS_REPEATED: + nColRepeat = (sal_uInt32)rValue.toInt32(); + if( nColRepeat < 1UL ) + nColRepeat = 1UL; + break; + case XML_TOK_TABLE_FORMULA: + { + OUString sTmp; + sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap(). + _GetKeyByAttrName( rValue, &sTmp, sal_False ); + sFormula = XML_NAMESPACE_OOOW == nPrefix2 ? sTmp : rValue; + } + break; + case XML_TOK_TABLE_VALUE: + { + double fTmp; + if (SvXMLUnitConverter::convertDouble(fTmp, rValue)) + { + fValue = fTmp; + bHasValue = sal_True; + } + } + break; + case XML_TOK_TABLE_TIME_VALUE: + { + double fTmp; + if (SvXMLUnitConverter::convertTime(fTmp, rValue)) + { + fValue = fTmp; + bHasValue = sal_True; + } + } + break; + case XML_TOK_TABLE_DATE_VALUE: + { + double fTmp; + if (GetImport().GetMM100UnitConverter().convertDateTime(fTmp, + rValue)) + { + fValue = fTmp; + bHasValue = sal_True; + } + } + break; + case XML_TOK_TABLE_BOOLEAN_VALUE: + { + sal_Bool bTmp; + if (SvXMLUnitConverter::convertBool(bTmp, rValue)) + { + fValue = (bTmp ? 1.0 : 0.0); + bHasValue = sal_True; + } + } + break; + case XML_TOK_TABLE_PROTECTED: + { + sal_Bool bTmp; + if (SvXMLUnitConverter::convertBool(bTmp, rValue)) + { + bProtect = bTmp; + } + } + break; + case XML_TOK_TABLE_STRING_VALUE: + { + bHasTextValue = sal_True; + } + break; + } + } +} + +SwXMLTableCellContext_Impl::~SwXMLTableCellContext_Impl() +{ +} + +inline void SwXMLTableCellContext_Impl::_InsertContent() +{ + GetTable()->InsertCell( aStyleName, nRowSpan, nColSpan, + GetTable()->InsertTableSection(), + mXmlId, + NULL, bProtect, &sFormula, bHasValue, fValue, bHasTextValue ); +} + +inline void SwXMLTableCellContext_Impl::InsertContent() +{ + ASSERT( !HasContent(), "content already there" ); + bHasTextContent = sal_True; + _InsertContent(); +} + +inline void SwXMLTableCellContext_Impl::InsertContentIfNotThere() +{ + if( !HasContent() ) + InsertContent(); +} + +inline void SwXMLTableCellContext_Impl::InsertContent( + SwXMLTableContext *pTable ) +{ + GetTable()->InsertCell( aStyleName, nRowSpan, nColSpan, 0, mXmlId, pTable, bProtect ); + bHasTableContent = sal_True; +} + +SvXMLImportContext *SwXMLTableCellContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + OUString sXmlId; + sal_Bool bSubTable = sal_False; + if( XML_NAMESPACE_TABLE == nPrefix && + IsXMLToken( rLocalName, XML_TABLE ) ) + { + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + + OUString aLocalName; + sal_uInt16 nPrefix2 = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + if( XML_NAMESPACE_TABLE == nPrefix2 && + IsXMLToken( aLocalName, XML_IS_SUB_TABLE ) && + IsXMLToken( xAttrList->getValueByIndex( i ), XML_TRUE ) ) + { + bSubTable = sal_True; + } + else if ( (XML_NAMESPACE_XML == nPrefix2) && + IsXMLToken( aLocalName, XML_ID ) ) + { + sXmlId = xAttrList->getValueByIndex( i ); + } +//FIXME: RDFa + } + } + + if( bSubTable ) + { + if( !HasContent() ) + { + SwXMLTableContext *pTblContext = + new SwXMLTableContext( GetSwImport(), nPrefix, rLocalName, + xAttrList, GetTable(), sXmlId ); + pContext = pTblContext; + if( GetTable()->IsValid() ) + InsertContent( pTblContext ); + + GetTable()->SetHasSubTables( sal_True ); + } + } + else + { + if( GetTable()->IsValid() ) + InsertContentIfNotThere(); + pContext = GetImport().GetTextImport()->CreateTextChildContext( + GetImport(), nPrefix, rLocalName, xAttrList, + XML_TEXT_TYPE_CELL ); + } + + if( !pContext ) + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + + return pContext; +} + +void SwXMLTableCellContext_Impl::EndElement() +{ + if( GetTable()->IsValid() ) + { + if( bHasTextContent ) + { + GetImport().GetTextImport()->DeleteParagraph(); + if( nColRepeat > 1 && nColSpan == 1 ) + { + // The original text is invalid after deleting the last + // paragraph + Reference < XTextCursor > xSrcTxtCursor = + GetImport().GetTextImport()->GetText()->createTextCursor(); + xSrcTxtCursor->gotoEnd( sal_True ); + + // Until we have an API for copying we have to use the core. + Reference<XUnoTunnel> xSrcCrsrTunnel( xSrcTxtCursor, UNO_QUERY); + ASSERT( xSrcCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pSrcTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xSrcCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pSrcTxtCrsr, "SwXTextCursor missing" ); + SwDoc *pDoc = pSrcTxtCrsr->GetDoc(); + const SwPaM *pSrcPaM = pSrcTxtCrsr->GetPaM(); + + while( nColRepeat > 1 && GetTable()->IsInsertCellPossible() ) + { + _InsertContent(); + + Reference<XUnoTunnel> xDstCrsrTunnel( + GetImport().GetTextImport()->GetCursor(), UNO_QUERY); + ASSERT( xDstCrsrTunnel.is(), + "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pDstTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xDstCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() )) ); + ASSERT( pDstTxtCrsr, "SwXTextCursor missing" ); + SwPaM aSrcPaM( *pSrcPaM->GetPoint(), + *pSrcPaM->GetMark() ); + SwPosition aDstPos( *pDstTxtCrsr->GetPaM()->GetPoint() ); + pDoc->CopyRange( aSrcPaM, aDstPos, false ); + + nColRepeat--; + } + } + } + else if( !bHasTableContent ) + { + InsertContent(); + if( nColRepeat > 1 && nColSpan == 1 ) + { + while( nColRepeat > 1 && GetTable()->IsInsertCellPossible() ) + { + _InsertContent(); + nColRepeat--; + } + } + } + } + GetImport().GetTextImport()->SetCellParaStyleDefault(sSaveParaDefault); +} + +// --------------------------------------------------------------------- + +class SwXMLTableColContext_Impl : public SvXMLImportContext +{ + SvXMLImportContextRef xMyTable; + + SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; } + +public: + + SwXMLTableColContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable ); + + virtual ~SwXMLTableColContext_Impl(); + + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } +}; + +SwXMLTableColContext_Impl::SwXMLTableColContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + xMyTable( pTable ) +{ + sal_uInt32 nColRep = 1UL; + OUString aStyleName, aDfltCellStyleName; + + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + + OUString aLocalName; + sal_uInt16 nPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + const OUString& rValue = xAttrList->getValueByIndex( i ); + if( XML_NAMESPACE_TABLE == nPrefix ) + { + if( IsXMLToken( aLocalName, XML_STYLE_NAME ) ) + aStyleName = rValue; + else if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) ) + nColRep = (sal_uInt32)rValue.toInt32(); + else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) ) + aDfltCellStyleName = rValue; + } + else if ( (XML_NAMESPACE_XML == nPrefix) && + IsXMLToken( aLocalName, XML_ID ) ) + { + (void) rValue; +//FIXME where to put this??? columns do not actually exist in writer... + } + } + + sal_Int32 nWidth = MINLAY; + sal_Bool bRelWidth = sal_True; + if( aStyleName.getLength() ) + { + const SfxPoolItem *pItem; + const SfxItemSet *pAutoItemSet = 0; + if( GetSwImport().FindAutomaticStyle( + XML_STYLE_FAMILY_TABLE_COLUMN, + aStyleName, &pAutoItemSet ) && + pAutoItemSet && + SFX_ITEM_SET == pAutoItemSet->GetItemState( RES_FRM_SIZE, sal_False, + &pItem ) ) + { + const SwFmtFrmSize *pSize = ((const SwFmtFrmSize *)pItem); + nWidth = pSize->GetWidth(); + bRelWidth = ATT_VAR_SIZE == pSize->GetHeightSizeType(); + } + } + + if( nWidth ) + { + while( nColRep-- && GetTable()->IsInsertColPossible() ) + GetTable()->InsertColumn( nWidth, bRelWidth, &aDfltCellStyleName ); + } +} + +SwXMLTableColContext_Impl::~SwXMLTableColContext_Impl() +{ +} + +// --------------------------------------------------------------------- + +class SwXMLTableColsContext_Impl : public SvXMLImportContext +{ + SvXMLImportContextRef xMyTable; + sal_Bool bHeader; + + SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; } + +public: + + SwXMLTableColsContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable, + sal_Bool bHead ); + + virtual ~SwXMLTableColsContext_Impl(); + + virtual SvXMLImportContext *CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ); + + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } +}; + +SwXMLTableColsContext_Impl::SwXMLTableColsContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, + const Reference< xml::sax::XAttributeList > &, + SwXMLTableContext *pTable, sal_Bool bHead ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + xMyTable( pTable ), + bHeader( bHead ) +{ +} + +SwXMLTableColsContext_Impl::~SwXMLTableColsContext_Impl() +{ +} + +SvXMLImportContext *SwXMLTableColsContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + if( XML_NAMESPACE_TABLE == nPrefix && + IsXMLToken( rLocalName, XML_TABLE_COLUMN ) && + GetTable()->IsInsertColPossible() ) + pContext = new SwXMLTableColContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList, + GetTable() ); + + if( !pContext ) + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + + return pContext; +} + +// --------------------------------------------------------------------- + +class SwXMLTableRowContext_Impl : public SvXMLImportContext +{ + SvXMLImportContextRef xMyTable; + + sal_uInt32 nRowRepeat; + + SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; } + +public: + + SwXMLTableRowContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable, sal_Bool bInHead=sal_False ); + + virtual ~SwXMLTableRowContext_Impl(); + + virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ); + + virtual void EndElement(); + + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } +}; + +SwXMLTableRowContext_Impl::SwXMLTableRowContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable, + sal_Bool bInHead ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + xMyTable( pTable ), + nRowRepeat( 1 ) +{ + OUString aStyleName, aDfltCellStyleName; + OUString sXmlId; + + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + + OUString aLocalName; + sal_uInt16 nPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + const OUString& rValue = xAttrList->getValueByIndex( i ); + if( XML_NAMESPACE_TABLE == nPrefix ) + { + if( IsXMLToken( aLocalName, XML_STYLE_NAME ) ) + { + aStyleName = rValue; + } + else if( IsXMLToken( aLocalName, XML_NUMBER_ROWS_REPEATED ) ) + { + nRowRepeat = (sal_uInt32)rValue.toInt32(); + if( nRowRepeat < 1UL ) + nRowRepeat = 1UL; + } + else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) ) + { + aDfltCellStyleName = rValue; + } + } + else if ( (XML_NAMESPACE_XML == nPrefix) && + IsXMLToken( aLocalName, XML_ID ) ) + { + sXmlId = rValue; + } + } + if( GetTable()->IsValid() ) + GetTable()->InsertRow( aStyleName, aDfltCellStyleName, bInHead, + sXmlId ); +} + +void SwXMLTableRowContext_Impl::EndElement() +{ + if( GetTable()->IsValid() ) + { + GetTable()->FinishRow(); + + if( nRowRepeat > 1UL ) + GetTable()->InsertRepRows( nRowRepeat ); + } +} + +SwXMLTableRowContext_Impl::~SwXMLTableRowContext_Impl() +{ +} + +SvXMLImportContext *SwXMLTableRowContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + if( XML_NAMESPACE_TABLE == nPrefix ) + { + if( IsXMLToken( rLocalName, XML_TABLE_CELL ) ) + { + if( !GetTable()->IsValid() || GetTable()->IsInsertCellPossible() ) + pContext = new SwXMLTableCellContext_Impl( GetSwImport(), + nPrefix, + rLocalName, + xAttrList, + GetTable() ); + } + else if( IsXMLToken( rLocalName, XML_COVERED_TABLE_CELL ) ) + pContext = new SvXMLImportContext( GetImport(), nPrefix, + rLocalName ); + } + + if( !pContext ) + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + + return pContext; +} + +// --------------------------------------------------------------------- + +class SwXMLTableRowsContext_Impl : public SvXMLImportContext +{ + SvXMLImportContextRef xMyTable; + + sal_Bool bHeader; + + SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; } + +public: + + SwXMLTableRowsContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable, + sal_Bool bHead ); + + virtual ~SwXMLTableRowsContext_Impl(); + + virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ); + + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } +}; + +SwXMLTableRowsContext_Impl::SwXMLTableRowsContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > &, + SwXMLTableContext *pTable, + sal_Bool bHead ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + xMyTable( pTable ), + bHeader( bHead ) +{ +} + +SwXMLTableRowsContext_Impl::~SwXMLTableRowsContext_Impl() +{ +} + +SvXMLImportContext *SwXMLTableRowsContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + if( XML_NAMESPACE_TABLE == nPrefix && + IsXMLToken( rLocalName, XML_TABLE_ROW ) && + GetTable()->IsInsertRowPossible() ) + pContext = new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList, + GetTable(), + bHeader ); + + if( !pContext ) + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + + return pContext; +} + +// --------------------------------------------------------------------- + +class SwXMLDDETableContext_Impl : public SvXMLImportContext +{ + OUString sConnectionName; + OUString sDDEApplication; + OUString sDDEItem; + OUString sDDETopic; + sal_Bool bIsAutomaticUpdate; + +public: + + TYPEINFO(); + + SwXMLDDETableContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName); + + ~SwXMLDDETableContext_Impl(); + + virtual void StartElement( + const Reference<xml::sax::XAttributeList> & xAttrList); + + OUString& GetConnectionName() { return sConnectionName; } + OUString& GetDDEApplication() { return sDDEApplication; } + OUString& GetDDEItem() { return sDDEItem; } + OUString& GetDDETopic() { return sDDETopic; } + sal_Bool GetIsAutomaticUpdate() { return bIsAutomaticUpdate; } +}; + +TYPEINIT1( SwXMLDDETableContext_Impl, SvXMLImportContext ); + +SwXMLDDETableContext_Impl::SwXMLDDETableContext_Impl( + SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName) : + SvXMLImportContext(rImport, nPrfx, rLName), + sConnectionName(), + sDDEApplication(), + sDDEItem(), + sDDETopic(), + bIsAutomaticUpdate(sal_False) +{ +} + +SwXMLDDETableContext_Impl::~SwXMLDDETableContext_Impl() +{ +} + +void SwXMLDDETableContext_Impl::StartElement( + const Reference<xml::sax::XAttributeList> & xAttrList) +{ + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i = 0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + + OUString aLocalName; + sal_uInt16 nPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + const OUString& rValue = xAttrList->getValueByIndex( i ); + + if (XML_NAMESPACE_OFFICE == nPrefix) + { + if ( IsXMLToken( aLocalName, XML_DDE_APPLICATION ) ) + { + sDDEApplication = rValue; + } + else if ( IsXMLToken( aLocalName, XML_DDE_TOPIC ) ) + { + sDDETopic = rValue; + } + else if ( IsXMLToken( aLocalName, XML_DDE_ITEM ) ) + { + sDDEItem = rValue; + } + else if ( IsXMLToken( aLocalName, XML_NAME ) ) + { + sConnectionName = rValue; + } + else if ( IsXMLToken( aLocalName, XML_AUTOMATIC_UPDATE ) ) + { + sal_Bool bTmp; + if (SvXMLUnitConverter::convertBool(bTmp, rValue)) + { + bIsAutomaticUpdate = bTmp; + } + } + // else: unknown attribute + } + // else: unknown attribute namespace + } +} + +// generate a new name for DDE field type (called by lcl_GetDDEFieldType below) +String lcl_GenerateFldTypeName(OUString sPrefix, SwTableNode* pTableNode) +{ + String sPrefixStr(sPrefix); + + if (sPrefixStr.Len() == 0) + { + sPrefixStr = String('_'); + } +// else if (sPrefixStr.Copy(0, 1).IsAlphaAscii()) +// { +// sPrefixStr.Insert('_', 0); +// } + // else: name is OK. + + // increase count until we find a name that is not yet taken + String sName; + sal_Int32 nCount = 0; + do + { + // this is crazy, but just in case all names are taken: exit gracefully + if (nCount < 0) + return sName; + + nCount++; + sName = sPrefixStr; + sName += String::CreateFromInt32(nCount); + + } + while (NULL != pTableNode->GetDoc()->GetFldType(RES_DDEFLD, sName, false)); + + return sName; +} + +// set table properties +SwDDEFieldType* lcl_GetDDEFieldType(SwXMLDDETableContext_Impl* pContext, + SwTableNode* pTableNode) +{ + // make command string + String sCommand(pContext->GetDDEApplication()); + sCommand += sfx2::cTokenSeperator; + sCommand += String(pContext->GetDDEItem()); + sCommand += sfx2::cTokenSeperator; + sCommand += String(pContext->GetDDETopic()); + + sal_uInt16 nType = static_cast< sal_uInt16 >(pContext->GetIsAutomaticUpdate() ? sfx2::LINKUPDATE_ALWAYS + : sfx2::LINKUPDATE_ONCALL); + + String sName(pContext->GetConnectionName()); + + // field type to be returned + SwDDEFieldType* pType = NULL; + + // valid name? + if (sName.Len() == 0) + { + sName = lcl_GenerateFldTypeName(pContext->GetDDEApplication(), + pTableNode); + } + else + { + // check for existing DDE field type with the same name + SwDDEFieldType* pOldType = (SwDDEFieldType*)pTableNode->GetDoc()->GetFldType(RES_DDEFLD, sName, false); + if (NULL != pOldType) + { + // same values -> return old type + if ( (pOldType->GetCmd() == sCommand) && + (pOldType->GetType() == nType) ) + { + // same name, same values -> return old type! + pType = pOldType; + } + else + { + // same name, different values -> think of new name + sName = lcl_GenerateFldTypeName(pContext->GetDDEApplication(), + pTableNode); + } + } + // no old type -> create new one + } + + // create new field type (unless we already have one) + if (NULL == pType) + { + // create new field type and return + SwDDEFieldType aDDEFieldType(sName, sCommand, nType); + pType = (SwDDEFieldType*)pTableNode-> + GetDoc()->InsertFldType(aDDEFieldType); + } + + DBG_ASSERT(NULL != pType, "We really want a SwDDEFieldType here!"); + return pType; +} + + +// --------------------------------------------------------------------- + +class TableBoxIndex +{ +public: + OUString msName; + sal_Int32 mnWidth; + sal_Bool mbProtected; + + TableBoxIndex( const OUString& rName, sal_Int32 nWidth, + sal_Bool bProtected ) : + msName( rName ), + mnWidth( nWidth ), + mbProtected( bProtected ) + { } + + bool operator== ( const TableBoxIndex& rArg ) const + { + return (rArg.mnWidth == mnWidth) && + (rArg.mbProtected == mbProtected) && + (rArg.msName == msName); + } +}; + +class TableBoxIndexHasher +{ +public: + size_t operator() (const TableBoxIndex& rArg) const + { + return rArg.msName.hashCode() + rArg.mnWidth + rArg.mbProtected; + } +}; + + + + +typedef SwXMLTableRow_Impl* SwXMLTableRowPtr; +SV_DECL_PTRARR_DEL(SwXMLTableRows_Impl,SwXMLTableRowPtr,5,5) +SV_IMPL_PTRARR(SwXMLTableRows_Impl,SwXMLTableRowPtr) + +SwXMLTableCell_Impl *SwXMLTableContext::GetCell( sal_uInt32 nRow, + sal_uInt32 nCol ) const +{ + return (*pRows)[(sal_uInt16)nRow]->GetCell( (sal_uInt16)nCol ); +} + +TYPEINIT1( SwXMLTableContext, XMLTextTableContext ); + +SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > & xAttrList ) : + XMLTextTableContext( rImport, nPrfx, rLName ), + pColumnDefaultCellStyleNames( 0 ), + pRows( new SwXMLTableRows_Impl ), + pTableNode( 0 ), + pBox1( 0 ), + pSttNd1( 0 ), + pBoxFmt( 0 ), + pLineFmt( 0 ), + pSharedBoxFormats(NULL), + pDDESource(NULL), + bFirstSection( sal_True ), + bRelWidth( sal_True ), + bHasSubTables( sal_False ), + nHeaderRows( 0 ), + nCurRow( 0UL ), + nCurCol( 0UL ), + nWidth( 0UL ) +{ + OUString aName; + OUString sXmlId; + + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + + OUString aLocalName; + sal_uInt16 nPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + const OUString& rValue = xAttrList->getValueByIndex( i ); + if( XML_NAMESPACE_TABLE == nPrefix ) + { + if( IsXMLToken( aLocalName, XML_STYLE_NAME ) ) + aStyleName = rValue; + else if( IsXMLToken( aLocalName, XML_NAME ) ) + aName = rValue; + else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) ) + aDfltCellStyleName = rValue; + } + else if ( (XML_NAMESPACE_XML == nPrefix) && + IsXMLToken( aLocalName, XML_ID ) ) + { + sXmlId = rValue; + } + } + + SwDoc *pDoc = SwImport::GetDocFromXMLImport( GetSwImport() ); + + String sTblName; + if( aName.getLength() ) + { + const SwTableFmt *pTblFmt = pDoc->FindTblFmtByName( aName ); + if( !pTblFmt ) + sTblName = aName; + } + if( !sTblName.Len() ) + { + sTblName = pDoc->GetUniqueTblName(); + GetImport().GetTextImport() + ->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_TABLE, aName, sTblName ); + } + + Reference< XTextTable > xTable; + const SwXTextTable *pXTable = 0; + Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(), + UNO_QUERY ); + ASSERT( xFactory.is(), "factory missing" ); + if( xFactory.is() ) + { + OUString sService( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextTable" ) ); + Reference<XInterface> xIfc = xFactory->createInstance( sService ); + ASSERT( xIfc.is(), "Couldn't create a table" ); + + if( xIfc.is() ) + xTable = Reference< XTextTable > ( xIfc, UNO_QUERY ); + } + + if( xTable.is() ) + { + xTable->initialize( 1, 1 ); + + try + { + xTextContent = Reference< XTextContent >( xTable, UNO_QUERY ); + GetImport().GetTextImport()->InsertTextContent( xTextContent ); + } + catch( IllegalArgumentException& ) + { + xTable = 0; + } + } + + if( xTable.is() ) + { +//FIXME + // xml:id for RDF metadata + GetImport().SetXmlId(xTable, sXmlId); + + Reference<XUnoTunnel> xTableTunnel( xTable, UNO_QUERY); + if( xTableTunnel.is() ) + { + pXTable = reinterpret_cast< SwXTextTable * >( + sal::static_int_cast< sal_IntPtr >( xTableTunnel->getSomething( SwXTextTable::getUnoTunnelId() ))); + ASSERT( pXTable, "SwXTextTable missing" ); + } + + Reference < XCellRange > xCellRange( xTable, UNO_QUERY ); + Reference < XCell > xCell = xCellRange->getCellByPosition( 0, 0 ); + Reference < XText> xText( xCell, UNO_QUERY ); + xOldCursor = GetImport().GetTextImport()->GetCursor(); + GetImport().GetTextImport()->SetCursor( xText->createTextCursor() ); + + // take care of open redlines for tables + GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_True); + } + if( pXTable ) + { + SwFrmFmt *pTblFrmFmt = pXTable->GetFrmFmt(); + ASSERT( pTblFrmFmt, "table format missing" ); + SwTable *pTbl = SwTable::FindTable( pTblFrmFmt ); + ASSERT( pTbl, "table missing" ); + pTableNode = pTbl->GetTableNode(); + ASSERT( pTableNode, "table node missing" ); + + pTblFrmFmt->SetName( sTblName ); + + SwTableLine *pLine1 = pTableNode->GetTable().GetTabLines()[0U]; + pBox1 = pLine1->GetTabBoxes()[0U]; + pSttNd1 = pBox1->GetSttNd(); + } +} + +SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName, + const Reference< xml::sax::XAttributeList > &, + SwXMLTableContext *pTable, + OUString const & i_rXmlId ) : + XMLTextTableContext( rImport, nPrfx, rLName ), + mXmlId( i_rXmlId ), + pColumnDefaultCellStyleNames( 0 ), + pRows( new SwXMLTableRows_Impl ), + pTableNode( pTable->pTableNode ), + pBox1( 0 ), + pSttNd1( 0 ), + pBoxFmt( 0 ), + pLineFmt( 0 ), + pSharedBoxFormats(NULL), + xParentTable( pTable ), + pDDESource(NULL), + bFirstSection( sal_False ), + bRelWidth( sal_True ), + bHasSubTables( sal_False ), + nHeaderRows( 0 ), + nCurRow( 0UL ), + nCurCol( 0UL ), + nWidth( 0UL ) +{ +} + +SwXMLTableContext::~SwXMLTableContext() +{ + delete pColumnDefaultCellStyleNames; + delete pSharedBoxFormats; + delete pRows; + + // close redlines on table end nodes + GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_False); +} + +SvXMLImportContext *SwXMLTableContext::CreateChildContext( sal_uInt16 nPrefix, + const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + const SvXMLTokenMap& rTokenMap = GetSwImport().GetTableElemTokenMap(); + sal_Bool bHeader = sal_False; + switch( rTokenMap.Get( nPrefix, rLocalName ) ) + { + case XML_TOK_TABLE_HEADER_COLS: + bHeader = sal_True; + case XML_TOK_TABLE_COLS: + if( IsValid() ) + pContext = new SwXMLTableColsContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList, + this, bHeader ); + break; + case XML_TOK_TABLE_COL: + if( IsValid() && IsInsertColPossible() ) + pContext = new SwXMLTableColContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList, + this ); + break; + case XML_TOK_TABLE_HEADER_ROWS: + bHeader = sal_True; + case XML_TOK_TABLE_ROWS: + pContext = new SwXMLTableRowsContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList, + this, bHeader ); + break; + case XML_TOK_TABLE_ROW: + if( IsInsertRowPossible() ) + pContext = new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix, + rLocalName, xAttrList, + this ); + break; + case XML_TOK_OFFICE_DDE_SOURCE: + // save context for later processing (discard old context, if approp.) + if( IsValid() ) + { + if (pDDESource != NULL) + { + pDDESource->ReleaseRef(); + } + pDDESource = new SwXMLDDETableContext_Impl( GetSwImport(), nPrefix, + rLocalName ); + pDDESource->AddRef(); + pContext = pDDESource; + } + break; + } + + if( !pContext ) + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + + return pContext; +} + +void SwXMLTableContext::InsertColumn( sal_Int32 nWidth2, sal_Bool bRelWidth2, + const OUString *pDfltCellStyleName ) +{ + ASSERT( nCurCol < USHRT_MAX, + "SwXMLTableContext::InsertColumn: no space left" ); + if( nCurCol >= USHRT_MAX ) + return; + + if( nWidth2 < MINLAY ) + nWidth2 = MINLAY; + else if( nWidth2 > USHRT_MAX ) + nWidth2 = USHRT_MAX; + aColumnWidths.Insert( (sal_uInt16)nWidth2, aColumnWidths.Count() ); + aColumnRelWidths.Insert( bRelWidth2, aColumnRelWidths.Count() ); + if( (pDfltCellStyleName && pDfltCellStyleName->getLength() > 0) || + pColumnDefaultCellStyleNames ) + { + if( !pColumnDefaultCellStyleNames ) + { + pColumnDefaultCellStyleNames = new SvStringsDtor; + sal_uInt16 nCount = aColumnRelWidths.Count() - 1; + while( nCount-- ) + pColumnDefaultCellStyleNames->Insert( new String, + pColumnDefaultCellStyleNames->Count() ); + } + + pColumnDefaultCellStyleNames->Insert( + pDfltCellStyleName ? new String( *pDfltCellStyleName ) : new String, + pColumnDefaultCellStyleNames->Count() ); + } +} + +sal_Int32 SwXMLTableContext::GetColumnWidth( sal_uInt32 nCol, + sal_uInt32 nColSpan ) const +{ + sal_uInt32 nLast = nCol+nColSpan; + if( nLast > aColumnWidths.Count() ) + nLast = aColumnWidths.Count(); + + sal_Int32 nWidth2 = 0L; + for( sal_uInt16 i=(sal_uInt16)nCol; i < nLast; i++ ) + nWidth2 += aColumnWidths[i]; + + return nWidth2; +} + +OUString SwXMLTableContext::GetColumnDefaultCellStyleName( sal_uInt32 nCol ) const +{ + OUString sRet; + if( pColumnDefaultCellStyleNames ) + sRet = *(*pColumnDefaultCellStyleNames)[(sal_uInt16)nCol]; + + return sRet; +} + +void SwXMLTableContext::InsertCell( const OUString& rStyleName, + sal_uInt32 nRowSpan, sal_uInt32 nColSpan, + const SwStartNode *pStartNode, + const OUString & i_rXmlId, + SwXMLTableContext *pTable, + sal_Bool bProtect, + const OUString* pFormula, + sal_Bool bHasValue, + double fValue, + sal_Bool bTextValue ) +{ + ASSERT( nCurCol < GetColumnCount(), + "SwXMLTableContext::InsertCell: row is full" ); + ASSERT( nCurRow < USHRT_MAX, + "SwXMLTableContext::InsertCell: table is full" ); + if( nCurCol >= USHRT_MAX || nCurRow > USHRT_MAX ) + return; + + ASSERT( nRowSpan >=1UL, "SwXMLTableContext::InsertCell: row span is 0" ); + if( 0UL == nRowSpan ) + nRowSpan = 1UL; + ASSERT( nColSpan >=1UL, "SwXMLTableContext::InsertCell: col span is 0" ); + if( 0UL == nColSpan ) + nColSpan = 1UL; + + sal_uInt32 i, j; + + // Until it is possible to add columns here, fix the column span. + sal_uInt32 nColsReq = nCurCol + nColSpan; + if( nColsReq > GetColumnCount() ) + { + nColSpan = GetColumnCount() - nCurCol; + nColsReq = GetColumnCount(); + } + + // Check whether there are cells from a previous line already that reach + // into the current row. + if( nCurRow > 0UL && nColSpan > 1UL ) + { + SwXMLTableRow_Impl *pCurRow = (*pRows)[(sal_uInt16)nCurRow]; + sal_uInt32 nLastCol = GetColumnCount() < nColsReq ? GetColumnCount() + : nColsReq; + for( i=nCurCol+1UL; i<nLastCol; i++ ) + { + if( pCurRow->GetCell(i)->IsUsed() ) + { + // If this cell is used, the column span is truncated + nColSpan = i - nCurCol; + nColsReq = i; + break; + } + } + } + + sal_uInt32 nRowsReq = nCurRow + nRowSpan; + if( nRowsReq > USHRT_MAX ) + { + nRowSpan = USHRT_MAX - nCurRow; + nRowsReq = USHRT_MAX; + } + + // Add columns (if # required columns greater than # columns): + // This should never happen, since we require column definitions! + if ( nColsReq > GetColumnCount() ) + { + for( i=GetColumnCount(); i<nColsReq; i++ ) + { + aColumnWidths.Insert( MINLAY, aColumnWidths.Count() ); + aColumnRelWidths.Insert( sal_True, aColumnRelWidths.Count() ); + } + // adjust columns in *all* rows, if columns must be inserted + for( i=0; i<pRows->Count(); i++ ) + (*pRows)[(sal_uInt16)i]->Expand( nColsReq, i<nCurRow ); + } + + // Add rows + if( pRows->Count() < nRowsReq ) + { + OUString aStyleName2; + for( i = pRows->Count(); i < nRowsReq; ++i ) + pRows->Insert( new SwXMLTableRow_Impl(aStyleName2, GetColumnCount()), + pRows->Count() ); + } + + OUString sStyleName( rStyleName ); + if( !sStyleName.getLength() ) + { + sStyleName = ((*pRows)[(sal_uInt16)nCurRow])->GetDefaultCellStyleName(); + if( !sStyleName.getLength() && HasColumnDefaultCellStyleNames() ) + { + sStyleName = GetColumnDefaultCellStyleName( nCurCol ); + if( !sStyleName.getLength() ) + sStyleName = aDfltCellStyleName; + } + } + + // Fill the cells + for( i=nColSpan; i>0UL; i-- ) + { + for( j=nRowSpan; j>0UL; j-- ) + { + const bool bCovered = i != nColSpan || j != nRowSpan; + GetCell( nRowsReq-j, nColsReq-i ) + ->Set( sStyleName, j, i, pStartNode, + pTable, bProtect, pFormula, bHasValue, bCovered, fValue, + bTextValue, i_rXmlId ); + } + } + + // Set current col to the next (free) column + nCurCol = nColsReq; + while( nCurCol<GetColumnCount() && GetCell(nCurRow,nCurCol)->IsUsed() ) + nCurCol++; +} + +void SwXMLTableContext::InsertRow( const OUString& rStyleName, + const OUString& rDfltCellStyleName, + sal_Bool bInHead, + const OUString & i_rXmlId ) +{ + ASSERT( nCurRow < USHRT_MAX, + "SwXMLTableContext::InsertRow: no space left" ); + if( nCurRow >= USHRT_MAX ) + return; + + // Make sure there is at least one column. + if( 0==nCurRow && 0UL == GetColumnCount() ) + InsertColumn( USHRT_MAX, sal_True ); + + if( nCurRow < pRows->Count() ) + { + // The current row has already been inserted because of a row span + // of a previous row. + (*pRows)[(sal_uInt16)nCurRow]->Set( + rStyleName, rDfltCellStyleName, i_rXmlId ); + } + else + { + // add a new row + pRows->Insert( new SwXMLTableRow_Impl( rStyleName, GetColumnCount(), + &rDfltCellStyleName, i_rXmlId ), + pRows->Count() ); + } + + // We start at the first column ... + nCurCol=0UL; + + // ... but this cell may be occupied already. + while( nCurCol<GetColumnCount() && GetCell(nCurRow,nCurCol)->IsUsed() ) + nCurCol++; + + if( bInHead && nHeaderRows == nCurRow ) + nHeaderRows++; +} + +void SwXMLTableContext::InsertRepRows( sal_uInt32 nCount ) +{ + const SwXMLTableRow_Impl *pSrcRow = (*pRows)[(sal_uInt16)nCurRow-1]; + while( nCount > 1 && IsInsertRowPossible() ) + { + InsertRow( pSrcRow->GetStyleName(), pSrcRow->GetDefaultCellStyleName(), + sal_False ); + while( nCurCol < GetColumnCount() ) + { + if( !GetCell(nCurRow,nCurCol)->IsUsed() ) + { + const SwXMLTableCell_Impl *pSrcCell = + GetCell( nCurRow-1, nCurCol ); + InsertCell( pSrcCell->GetStyleName(), 1U, + pSrcCell->GetColSpan(), + InsertTableSection(), + OUString(), + 0, pSrcCell->IsProtected(), + &pSrcCell->GetFormula(), + pSrcCell->HasValue(), pSrcCell->GetValue(), + pSrcCell->HasTextValue() ); + } + } + FinishRow(); + nCount--; + } +} + +void SwXMLTableContext::FinishRow() +{ + // Insert an empty cell at the end of the line if the row is not complete + if( nCurCol < GetColumnCount() ) + { + OUString aStyleName2; + InsertCell( aStyleName2, 1U, GetColumnCount() - nCurCol, + InsertTableSection() ); + } + + // Move to the next row. + nCurRow++; +} + +const SwStartNode *SwXMLTableContext::GetPrevStartNode( sal_uInt32 nRow, + sal_uInt32 nCol ) const +{ + const SwXMLTableCell_Impl *pPrevCell = 0; + if( GetColumnCount() == nCol ) + { + // The last cell is the right one here. + pPrevCell = GetCell( pRows->Count()-1U, GetColumnCount()-1UL ); + } + else if( 0UL == nRow ) + { + // There are no vertically merged cells within the first row, so the + // previous cell is the right one always. + if( nCol > 0UL ) + pPrevCell = GetCell( nRow, nCol-1UL ); + } + else + { + // If there is a previous cell in the current row that is not spanned + // from the previous row, its the right one. + const SwXMLTableRow_Impl *pPrevRow = (*pRows)[(sal_uInt16)nRow-1U]; + sal_uInt32 i = nCol; + while( !pPrevCell && i > 0UL ) + { + i--; + if( 1UL == pPrevRow->GetCell( i )->GetRowSpan() ) + pPrevCell = GetCell( nRow, i ); + } + + // Otherwise, the last cell from the previous row is the right one. + if( !pPrevCell ) + pPrevCell = pPrevRow->GetCell( GetColumnCount()-1UL ); + } + + const SwStartNode *pSttNd = 0; + if( pPrevCell ) + { + if( pPrevCell->GetStartNode() ) + pSttNd = pPrevCell->GetStartNode(); + // --> OD 2009-03-19 #i95726# - Some fault tolerance +// else + else if ( pPrevCell->GetSubTable() ) + // <-- + pSttNd = pPrevCell->GetSubTable()->GetLastStartNode(); + + ASSERT( pSttNd != 0, + "table corrupt" ); + } + + return pSttNd; +} + +void SwXMLTableContext::FixRowSpan( sal_uInt32 nRow, sal_uInt32 nCol, + sal_uInt32 nColSpan ) +{ + sal_uInt32 nLastCol = nCol + nColSpan; + for( sal_uInt16 i = (sal_uInt16)nCol; i < nLastCol; i++ ) + { + sal_uInt32 j = nRow; + sal_uInt32 nRowSpan = 1UL; + SwXMLTableCell_Impl *pCell = GetCell( j, i ); + while( pCell && pCell->GetRowSpan() > 1UL ) + { + pCell->SetRowSpan( nRowSpan++ ); + pCell = j > 0UL ? GetCell( --j, i ) : 0; + } + } +} + +void SwXMLTableContext::ReplaceWithEmptyCell( sal_uInt32 nRow, sal_uInt32 nCol, bool bRows ) +{ + const SwStartNode *pPrevSttNd = GetPrevStartNode( nRow, nCol ); + const SwStartNode *pSttNd = InsertTableSection( pPrevSttNd ); + + const SwXMLTableCell_Impl *pCell = GetCell( nRow, nCol ); + sal_uInt32 nLastRow = bRows ? nRow + pCell->GetRowSpan() : nRow + 1; + sal_uInt32 nLastCol = nCol + pCell->GetColSpan(); + + for( sal_uInt32 i=nRow; i<nLastRow; i++ ) + { + SwXMLTableRow_Impl *pRow = (*pRows)[(sal_uInt16)i]; + for( sal_uInt32 j=nCol; j<nLastCol; j++ ) + pRow->GetCell( j )->SetStartNode( pSttNd ); + } + +} + +SwTableBox *SwXMLTableContext::NewTableBox( const SwStartNode *pStNd, + SwTableLine *pUpper ) +{ + // The topmost table is the only table that maintains the two members + // pBox1 and bFirstSection. + if( xParentTable.Is() ) + return ((SwXMLTableContext *)&xParentTable)->NewTableBox( pStNd, + pUpper ); + + SwTableBox *pBox; + + if( pBox1 && + pBox1->GetSttNd() == pStNd ) + { + // wenn der StartNode dem StartNode der initial angelegten Box + // entspricht nehmen wir diese Box + pBox = pBox1; + pBox->SetUpper( pUpper ); + pBox1 = 0; + } + else + pBox = new SwTableBox( pBoxFmt, *pStNd, pUpper ); + + return pBox; +} + +SwTableBoxFmt* SwXMLTableContext::GetSharedBoxFormat( + SwTableBox* pBox, + const OUString& rStyleName, + sal_Int32 nColumnWidth, + sal_Bool bProtected, + sal_Bool bMayShare, + sal_Bool& bNew, + sal_Bool* pModifyLocked ) +{ + if ( pSharedBoxFormats == NULL ) + pSharedBoxFormats = new map_BoxFmt(); + + SwTableBoxFmt* pBoxFmt2; + + TableBoxIndex aKey( rStyleName, nColumnWidth, bProtected ); + map_BoxFmt::iterator aIter = pSharedBoxFormats->find( aKey ); + if ( aIter == pSharedBoxFormats->end() ) + { + // unknown format so far -> construct a new one + + // get the old format, and reset all attributes + // (but preserve FillOrder) + pBoxFmt2 = (SwTableBoxFmt*)pBox->ClaimFrmFmt(); + SwFmtFillOrder aFillOrder( pBoxFmt2->GetFillOrder() ); + // --> OD 2007-01-25 #i73790# - method renamed + pBoxFmt2->ResetAllFmtAttr(); + // <-- + pBoxFmt2->SetFmtAttr( aFillOrder ); + bNew = sal_True; // it's a new format now + + // share this format, if allowed + if ( bMayShare ) + (*pSharedBoxFormats)[ aKey ] = pBoxFmt2; + } + else + { + // set the shared format + pBoxFmt2 = aIter->second; + pBox->ChgFrmFmt( pBoxFmt2 ); + bNew = sal_False; // copied from an existing format + + // claim it, if we are not allowed to share + if ( !bMayShare ) + pBoxFmt2 = (SwTableBoxFmt*)pBox->ClaimFrmFmt(); + } + + // lock format (if so desired) + if ( pModifyLocked != NULL ) + { + (*pModifyLocked) = pBoxFmt2->IsModifyLocked(); + pBoxFmt2->LockModify(); + } + + return pBoxFmt2; +} + +SwTableBox *SwXMLTableContext::MakeTableBox( SwTableLine *pUpper, + sal_uInt32 nTopRow, + sal_uInt32 nLeftCol, + sal_uInt32 nBottomRow, + sal_uInt32 nRightCol ) +{ +//FIXME: here would be a great place to handle XmlId for cell + SwTableBox *pBox = new SwTableBox( pBoxFmt, 0, pUpper ); + + sal_uInt32 nColSpan = nRightCol - nLeftCol; + sal_Int32 nColWidth = GetColumnWidth( nLeftCol, nColSpan ); + + // TODO: Share formats! + SwFrmFmt *pFrmFmt = pBox->ClaimFrmFmt(); + SwFmtFillOrder aFillOrder( pFrmFmt->GetFillOrder() ); + // --> OD 2007-01-25 #i73790# - method renamed + pFrmFmt->ResetAllFmtAttr(); + // <-- + pFrmFmt->SetFmtAttr( aFillOrder ); + + pFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nColWidth ) ); + + SwTableLines& rLines = pBox->GetTabLines(); + sal_Bool bSplitted = sal_False; + + while( !bSplitted ) + { + sal_uInt32 nStartRow = nTopRow; + sal_uInt32 i; + + for( i = nTopRow; i < nBottomRow; i++ ) + { + // Could the table be splitted behind the current row? + sal_Bool bSplit = sal_True; + SwXMLTableRow_Impl *pRow = (*pRows)[(sal_uInt16)i]; + for( sal_uInt32 j=nLeftCol; j<nRightCol; j++ ) + { + bSplit = ( 1UL == pRow->GetCell(j)->GetRowSpan() ); + if( !bSplit ) + break; + } + if( bSplit && (nStartRow>nTopRow || i+1UL<nBottomRow) ) + { + SwTableLine *pLine = + MakeTableLine( pBox, nStartRow, nLeftCol, i+1UL, + nRightCol ); + + rLines.C40_INSERT( SwTableLine, pLine, rLines.Count() ); + + nStartRow = i+1UL; + bSplitted = sal_True; + } + } + if( !bSplitted ) + { + // No splitting was possible. That for, we have to force it. + // Ruthless! + + nStartRow = nTopRow; + while( nStartRow < nBottomRow ) + { + sal_uInt32 nMaxRowSpan = 0UL; + SwXMLTableRow_Impl *pStartRow = (*pRows)[(sal_uInt16)nStartRow]; + SwXMLTableCell_Impl *pCell; + for( i=nLeftCol; i<nRightCol; i++ ) + if( ( pCell=pStartRow->GetCell(i), + pCell->GetRowSpan() > nMaxRowSpan ) ) + nMaxRowSpan = pCell->GetRowSpan(); + + nStartRow += nMaxRowSpan; + if( nStartRow<nBottomRow ) + { + SwXMLTableRow_Impl *pPrevRow = + (*pRows)[(sal_uInt16)nStartRow-1U]; + i = nLeftCol; + while( i < nRightCol ) + { + if( pPrevRow->GetCell(i)->GetRowSpan() > 1UL ) + { + const SwXMLTableCell_Impl *pCell2 = + GetCell( nStartRow, i ); + const sal_uInt32 nColSpan2 = pCell2->GetColSpan(); + FixRowSpan( nStartRow-1UL, i, nColSpan2 ); + ReplaceWithEmptyCell( nStartRow, i, true ); + i += nColSpan2; + } + else + { + i++; + } + } + } + } + // und jetzt nochmal von vorne ... + } + } + + return pBox; +} + +SwTableBox *SwXMLTableContext::MakeTableBox( + SwTableLine *pUpper, const SwXMLTableCell_Impl *pCell, + sal_uInt32 /*nTopRow*/, sal_uInt32 nLeftCol, sal_uInt32 /*nBottomRow*/, + sal_uInt32 nRightCol ) +{ +//FIXME: here would be a great place to handle XmlId for cell + SwTableBox *pBox; + sal_uInt32 nColSpan = nRightCol - nLeftCol; + sal_Int32 nColWidth = GetColumnWidth( nLeftCol, nColSpan ); + + if( pCell->GetStartNode() ) + { + pBox = NewTableBox( pCell->GetStartNode(), pUpper ); + } + else + { + // und die ist eine Tabelle: dann bauen wir eine neue + // Box und fuegen die Zeilen der Tabelle in die Zeilen + // der Box ein + pBox = new SwTableBox( pBoxFmt, 0, pUpper ); + pCell->GetSubTable()->MakeTable( pBox, nColWidth ); + } + + // Share formats! + OUString sStyleName = pCell->GetStyleName(); + sal_Bool bModifyLocked; + sal_Bool bNew; + SwTableBoxFmt *pBoxFmt2 = GetSharedBoxFormat( + pBox, sStyleName, nColWidth, pCell->IsProtected(), + pCell->GetStartNode() && pCell->GetFormula().getLength() == 0 && + ! pCell->HasValue(), + bNew, &bModifyLocked ); + + // if a new format was created, then we need to set the style + if ( bNew ) + { + // set style + const SfxItemSet *pAutoItemSet = 0; + if( pCell->GetStartNode() && sStyleName && + GetSwImport().FindAutomaticStyle( + XML_STYLE_FAMILY_TABLE_CELL, sStyleName, &pAutoItemSet ) ) + { + if( pAutoItemSet ) + pBoxFmt2->SetFmtAttr( *pAutoItemSet ); + } + } + + if( pCell->GetStartNode() ) + { + + // #104801# try to rescue broken documents with a certain pattern + // if: 1) the cell has a default number format (number 0) + // 2) the call has no formula + // 3) the value is 0.0 + // 4) the text doesn't look anything like 0.0 + // [read: length > 10, or length smaller 10 and no 0 in it] + // then make it a text cell! + bool bSuppressNumericContent = false; + if( pCell->HasValue() && (pCell->GetValue() == 0.0) && + (pCell->GetFormula().getLength() == 0) && + (sStyleName.getLength() != 0) ) + { + // default num format? + const SfxPoolItem* pItem = NULL; + if( pBoxFmt2->GetItemState( RES_BOXATR_FORMAT, FALSE, &pItem ) + == SFX_ITEM_SET ) + { + const SwTblBoxNumFormat* pNumFormat = + static_cast<const SwTblBoxNumFormat*>( pItem ); + if( ( pNumFormat != NULL ) && ( pNumFormat->GetValue() == 0 ) ) + { + // only one text node? + SwNodeIndex aNodeIndex( *(pCell->GetStartNode()), 1 ); + if( ( aNodeIndex.GetNode().EndOfSectionIndex() - + aNodeIndex.GetNode().StartOfSectionIndex() ) == 2 ) + { + SwTxtNode* pTxtNode= aNodeIndex.GetNode().GetTxtNode(); + if( pTxtNode != NULL ) + { + // check text: does it look like some form of 0.0? + const String& rText = pTxtNode->GetTxt(); + if( ( rText.Len() > 10 ) || + ( rText.Search( '0' ) == STRING_NOTFOUND ) ) + { + bSuppressNumericContent = true; + } + } + } + else + bSuppressNumericContent = true; // several nodes + } + } + } + + if( bSuppressNumericContent ) + { + // suppress numeric content? Then reset number format! + pBoxFmt2->ResetFmtAttr( RES_BOXATR_FORMULA ); + pBoxFmt2->ResetFmtAttr( RES_BOXATR_FORMAT ); + pBoxFmt2->ResetFmtAttr( RES_BOXATR_VALUE ); + } + else + { + // the normal case: set formula and value (if available) + + const OUString& rFormula = pCell->GetFormula(); + if (rFormula.getLength() > 0) + { + // formula cell: insert formula if valid + SwTblBoxFormula aFormulaItem( rFormula ); + pBoxFmt2->SetFmtAttr( aFormulaItem ); + } + else if( !pCell->HasValue() && pCell->HasTextValue() ) + { + // Check for another inconsistency: + // No value but a non-textual format, i.e. a number format + // Solution: the number format will be removed, + // the cell gets the default text format. + const SfxPoolItem* pItem = NULL; + if( pBoxFmt->GetItemState( RES_BOXATR_FORMAT, FALSE, &pItem ) + == SFX_ITEM_SET ) + { + const SwDoc* pDoc = pBoxFmt->GetDoc(); + const SvNumberFormatter* pNumberFormatter = pDoc ? + pDoc->GetNumberFormatter() : 0; + const SwTblBoxNumFormat* pNumFormat = + static_cast<const SwTblBoxNumFormat*>( pItem ); + if( pNumFormat != NULL && pNumberFormatter && + !pNumberFormatter->GetEntry( pNumFormat->GetValue() )->IsTextFormat() ) + pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT ); + } + } + // always insert value, even if default + if( pCell->HasValue() ) + { + SwTblBoxValue aValueItem( pCell->GetValue() ); + pBoxFmt2->SetFmtAttr( aValueItem ); + } + } + + // update cell content depend on the default language + pBox->ActualiseValueBox(); + } + + // table cell protection + if( pCell->IsProtected() ) + { + SvxProtectItem aProtectItem( RES_PROTECT ); + aProtectItem.SetCntntProtect( sal_True ); + pBoxFmt2->SetFmtAttr( aProtectItem ); + } + + // restore old modify-lock state + if (! bModifyLocked) + pBoxFmt2->UnlockModify(); + + pBoxFmt2->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nColWidth ) ); + + return pBox; +} + +SwTableLine *SwXMLTableContext::MakeTableLine( SwTableBox *pUpper, + sal_uInt32 nTopRow, + sal_uInt32 nLeftCol, + sal_uInt32 nBottomRow, + sal_uInt32 nRightCol ) +{ +//FIXME: here would be a great place to handle XmlId for row + SwTableLine *pLine; + if( !pUpper && 0UL==nTopRow ) + { + pLine = pTableNode->GetTable().GetTabLines()[0U]; + } + else + { + pLine = new SwTableLine( pLineFmt, 0, pUpper ); + } + + // TODO: Share formats! + SwFrmFmt *pFrmFmt = pLine->ClaimFrmFmt(); + SwFmtFillOrder aFillOrder( pFrmFmt->GetFillOrder() ); + // --> OD 2007-01-25 #i73790# - method renamed + pFrmFmt->ResetAllFmtAttr(); + // <-- + pFrmFmt->SetFmtAttr( aFillOrder ); + + const SfxItemSet *pAutoItemSet = 0; + const OUString& rStyleName = (*pRows)[(sal_uInt16)nTopRow]->GetStyleName(); + if( 1UL == (nBottomRow - nTopRow) && + rStyleName.getLength() && + GetSwImport().FindAutomaticStyle( + XML_STYLE_FAMILY_TABLE_ROW, rStyleName, &pAutoItemSet ) ) + { + if( pAutoItemSet ) + pFrmFmt->SetFmtAttr( *pAutoItemSet ); + } + + SwTableBoxes& rBoxes = pLine->GetTabBoxes(); + + sal_uInt32 nStartCol = nLeftCol; + while( nStartCol < nRightCol ) + { + for( sal_uInt32 nRow=nTopRow; nRow<nBottomRow; nRow++ ) + (*pRows)[(sal_uInt16)nRow]->SetSplitable( sal_True ); + + sal_uInt32 nCol = nStartCol; + sal_uInt32 nSplitCol = nRightCol; + sal_Bool bSplitted = sal_False; + while( !bSplitted ) + { + ASSERT( nCol < nRightCol, "Zu weit gelaufen" ); + + // Kann hinter der aktuellen HTML-Tabellen-Spalte gesplittet + // werden? Wenn ja, koennte der enstehende Bereich auch noch + // in Zeilen zerlegt werden, wenn man die naechste Spalte + // hinzunimmt? + sal_Bool bSplit = sal_True; + sal_Bool bHoriSplitMayContinue = sal_False; + sal_Bool bHoriSplitPossible = sal_False; + + if ( bHasSubTables ) + { + // Convert row spans if the table has subtables: + for( sal_uInt32 nRow=nTopRow; nRow<nBottomRow; nRow++ ) + { + SwXMLTableCell_Impl *pCell = GetCell(nRow,nCol); + // Could the table fragment be splitted horizontally behind + // the current line? + sal_Bool bHoriSplit = (*pRows)[(sal_uInt16)nRow]->IsSplitable() && + nRow+1UL < nBottomRow && + 1UL == pCell->GetRowSpan(); + (*pRows)[(sal_uInt16)nRow]->SetSplitable( bHoriSplit ); + + // Could the table fragment be splitted vertically behind the + // current column (uptp the current line? + bSplit &= ( 1UL == pCell->GetColSpan() ); + if( bSplit ) + { + bHoriSplitPossible |= bHoriSplit; + + // Could the current table fragment be splitted + // horizontally behind the next collumn, too? + bHoriSplit &= (nCol+1UL < nRightCol && + 1UL == GetCell(nRow,nCol+1UL)->GetRowSpan()); + bHoriSplitMayContinue |= bHoriSplit; + } + } + } + else + { + // No subtabels: We use the new table model. + SwXMLTableCell_Impl *pCell = GetCell(nTopRow,nCol); + + // --> OD 2009-03-19 #i95726# - some fault tolerance + if ( pCell == 0 ) + { + ASSERT( false, "table seems to be corrupt." ); + break; + } + // <-- + + // Could the table fragment be splitted vertically behind the + // current column (uptp the current line? + bSplit = 1UL == pCell->GetColSpan(); + } + +#ifdef DBG_UTIL + if( nCol == nRightCol-1UL ) + { + ASSERT( bSplit, "Split-Flag falsch" ); + if ( bHasSubTables ) + { + ASSERT( !bHoriSplitMayContinue, + "HoriSplitMayContinue-Flag falsch" ); + SwXMLTableCell_Impl *pTmpCell = GetCell( nTopRow, nStartCol ); + ASSERT( pTmpCell->GetRowSpan() != (nBottomRow-nTopRow) || + !bHoriSplitPossible, "HoriSplitPossible-Flag falsch" ); + } + } +#endif + + ASSERT( !bHasSubTables || !bHoriSplitMayContinue || bHoriSplitPossible, + "bHoriSplitMayContinue, aber nicht bHoriSplitPossible" ); + + if( bSplit ) + { + SwTableBox* pBox = 0; + SwXMLTableCell_Impl *pCell = GetCell( nTopRow, nStartCol ); + // --> OD 2009-03-19 #i95726# - some fault tolerance + if( ( !bHasSubTables || ( pCell->GetRowSpan() == (nBottomRow-nTopRow) ) ) && + pCell->GetColSpan() == (nCol+1UL-nStartCol) && + ( pCell->GetStartNode() || pCell->GetSubTable() ) ) + // <-- + { + // insert new empty cell for covered cells: + long nBoxRowSpan = 1; + if ( !bHasSubTables ) + { + nBoxRowSpan = pCell->GetRowSpan(); + if ( pCell->IsCovered() ) + { + nBoxRowSpan = -1 * nBoxRowSpan; + ReplaceWithEmptyCell( nTopRow, nStartCol, false ); + } + } + + // The remaining box neither contains lines nor rows (i.e. + // is a content box + nSplitCol = nCol + 1UL; + + pBox = MakeTableBox( pLine, pCell, + nTopRow, nStartCol, + nBottomRow, nSplitCol ); + + if ( 1 != nBoxRowSpan ) + pBox->setRowSpan( nBoxRowSpan ); + + bSplitted = sal_True; + } + else if( bHasSubTables && bHoriSplitPossible && bHoriSplitMayContinue ) + { + // The table fragment could be splitted behind the current + // column, and the remaining fragment could be divided + // into lines. Anyway, it could be that this applies to + // the next column, too. That for, we check the next + // column but rememeber the current one as a good place to + // split. + nSplitCol = nCol + 1UL; + } + else if ( bHasSubTables ) + { + // If the table resulting table fragment could be divided + // into lines if spllitting behind the current column, but + // this doesn't apply for thr next column, we split begind + // the current column. This applies for the last column, + // too. + // If the resulting box cannot be splitted into rows, + // the split at the last split position we remembered. + if( bHoriSplitPossible || nSplitCol > nCol+1 ) + { + ASSERT( !bHoriSplitMayContinue, + "bHoriSplitMayContinue==sal_True" ); + ASSERT( bHoriSplitPossible || nSplitCol == nRightCol, + "bHoriSplitPossible-Flag sollte gesetzt sein" ); + + nSplitCol = nCol + 1UL; + } + + pBox = MakeTableBox( pLine, nTopRow, nStartCol, + nBottomRow, nSplitCol ); + bSplitted = sal_True; + } + + ASSERT( bHasSubTables || pBox, "Colspan trouble" ) + + if( pBox ) + rBoxes.C40_INSERT( SwTableBox, pBox, rBoxes.Count() ); + } + nCol++; + } + nStartCol = nSplitCol; + } + + return pLine; +} + +void SwXMLTableContext::_MakeTable( SwTableBox *pBox ) +{ + // fix column widths + sal_uInt32 i; + sal_uInt32 nCols = GetColumnCount(); + + // If there are empty rows (because of some row span of previous rows) + // the have to be deleted. The previous rows have to be truncated. + + if( pRows->Count() > nCurRow ) + { + SwXMLTableRow_Impl *pPrevRow = (*pRows)[(sal_uInt16)nCurRow-1U]; + SwXMLTableCell_Impl *pCell; + for( i=0UL; i<nCols; i++ ) + { + if( ( pCell=pPrevRow->GetCell(i), pCell->GetRowSpan() > 1UL ) ) + { + FixRowSpan( nCurRow-1UL, i, 1UL ); + } + } + for( i=(sal_uInt32)pRows->Count()-1UL; i>=nCurRow; i-- ) + pRows->DeleteAndDestroy( (sal_uInt16)i ); + } + + if( 0UL == pRows->Count() ) + { + OUString aStyleName2; + InsertCell( aStyleName2, 1U, nCols, InsertTableSection() ); + } + + // TODO: Do we have to keep both values, the realtive and the absolute + // width? + sal_Int32 nAbsWidth = 0L; + sal_Int32 nMinAbsColWidth = 0L; + sal_Int32 nRelWidth = 0L; + sal_Int32 nMinRelColWidth = 0L; + sal_uInt32 nRelCols = 0UL; + for( i=0U; i < nCols; i++ ) + { + sal_Int32 nColWidth = aColumnWidths[(sal_uInt16)i]; + if( aColumnRelWidths[(sal_uInt16)i] ) + { + nRelWidth += nColWidth; + if( 0L == nMinRelColWidth || nColWidth < nMinRelColWidth ) + nMinRelColWidth = nColWidth; + nRelCols++; + } + else + { + nAbsWidth += nColWidth; + if( 0L == nMinAbsColWidth || nColWidth < nMinAbsColWidth ) + nMinAbsColWidth = nColWidth; + } + } + sal_uInt32 nAbsCols = nCols - nRelCols; + + if( bRelWidth ) + { + // If there a columns that have an absolute width, we have to + // calculate a relative one for them. + if( nAbsCols > 0UL ) + { + // All column that have absolute widths get relative widths; + // these widths relate to each over like the original absolute + // widths. The smallest column gets a width that hat the same + // value as the smallest column that has an relative width + // already. + if( 0L == nMinRelColWidth ) + nMinRelColWidth = nMinAbsColWidth; + + for( i=0UL; nAbsCols > 0UL && i < nCols; i++ ) + { + if( !aColumnRelWidths[(sal_uInt16)i] ) + { + sal_Int32 nRelCol = (aColumnWidths[(sal_uInt16)i] * nMinRelColWidth) / + nMinAbsColWidth; + aColumnWidths.Replace( (sal_uInt16)nRelCol, (sal_uInt16)i ); + nRelWidth += nRelCol; + nAbsCols--; + } + } + } + + if( !nWidth ) + { + // This happens only for percentage values for the table itself. + // In this case, the columns get the correct width even if the + // the sum of the relative withs is smaller than the available + // width in TWIP. Therfore, we can use the relative width. + // + nWidth = nRelWidth > USHRT_MAX ? USHRT_MAX : nRelWidth; + } + if( nRelWidth != nWidth && nRelWidth && nCols ) + { + double n = (double)nWidth / (double)nRelWidth; + nRelWidth = 0L; + for( i=0U; i < nCols-1UL; i++ ) + { + sal_Int32 nW = (sal_Int32)(aColumnWidths[(sal_uInt16)i] * n); + aColumnWidths.Replace( (sal_uInt16)nW, (sal_uInt16)i ); + nRelWidth += nW; + } + aColumnWidths.Replace( (sal_uInt16)(nWidth-nRelWidth), + (sal_uInt16)nCols-1U ); + } + } + else + { + // If there are columns that have relative widths, we have to + // calculate a absolute widths for them. + if( nRelCols > 0UL ) + { + // The absolute space that is available for all columns with a + // relative width. + sal_Int32 nAbsForRelWidth = + nWidth > nAbsWidth ? nWidth - nAbsWidth : (sal_Int32)0L; + + // The relative width that has to be distributed in addition to + // equally widthed columns. + sal_Int32 nExtraRel = nRelWidth - (nRelCols * nMinRelColWidth); + + // The absolute space that may be distributed in addition to + // minumum widthed columns. + sal_Int32 nMinAbs = nRelCols * MINLAY; + sal_Int32 nExtraAbs = + nAbsForRelWidth > nMinAbs ? nAbsForRelWidth - nMinAbs : (sal_Int32)0L; + + sal_Bool bMin = sal_False; // Do all columns get the mininum width? + sal_Bool bMinExtra = sal_False; // Do all columns get the minimum width plus + // some extra space? + + if( nAbsForRelWidth <= nMinAbs ) + { + // If there is not enough space left for all columns to + // get the minimum width, they get the minimum width, anyway. + nAbsForRelWidth = nMinAbs; + bMin = sal_True; + } + else if( nAbsForRelWidth <= (nRelWidth * MINLAY) / + nMinRelColWidth ) + { + // If there is enougth space for all columns to get the + // minimum width, but not to get a width that takes the + // relative width into account, each column gets the minimum + // width plus some extra space that is based on the additional + // space that is available. + bMinExtra = sal_True; + } + // Otherwise, if there is enouth space for every column, every + // column gets this space. + + for( i=0UL; nRelCols > 0UL && i < nCols; i++ ) + { + if( aColumnRelWidths[(sal_uInt16)i] ) + { + sal_Int32 nAbsCol; + if( 1UL == nRelCols ) + { + // The last column that has a relative width gets + // all absolute space that is left. + nAbsCol = nAbsForRelWidth; + } + else + { + if( bMin ) + { + nAbsCol = MINLAY; + } + else if( bMinExtra ) + { + sal_Int32 nExtraRelCol = + aColumnWidths[(sal_uInt16)i] - nMinRelColWidth; + nAbsCol = MINLAY + (nExtraRelCol * nExtraAbs) / + nExtraRel; + } + else + { + nAbsCol = (aColumnWidths[(sal_uInt16)i] * nAbsForRelWidth) / + nRelWidth; + } + } + aColumnWidths.Replace( (sal_uInt16)nAbsCol, (sal_uInt16)i ); + nAbsForRelWidth -= nAbsCol; + nAbsWidth += nAbsCol; + nRelCols--; + } + } + } + + if( nCols && nAbsWidth ) + { + if( nAbsWidth < nWidth ) + { + // If the table's width is larger than the absolute column widths, + // every column get some extra width. + sal_Int32 nExtraAbs = nWidth - nAbsWidth; + sal_Int32 nAbsLastCol = + aColumnWidths[(sal_uInt16)nCols-1U] + nExtraAbs; + for( i=0UL; i < nCols-1UL; i++ ) + { + sal_Int32 nAbsCol = aColumnWidths[(sal_uInt16)i]; + sal_Int32 nExtraAbsCol = (nAbsCol * nExtraAbs) / + nAbsWidth; + nAbsCol += nExtraAbsCol; + aColumnWidths.Replace( (sal_uInt16)nAbsCol, (sal_uInt16)i ); + nAbsLastCol -= nExtraAbsCol; + } + aColumnWidths.Replace( (sal_uInt16)nAbsLastCol, (sal_uInt16)nCols-1U ); + } + else if( nAbsWidth > nWidth ) + { + // If the table's width is smaller than the absolute column + // widths, every column gets the minimum width plus some extra + // width. + sal_Int32 nExtraAbs = nWidth - (nCols * MINLAY); + sal_Int32 nAbsLastCol = MINLAY + nExtraAbs; + for( i=0UL; i < nCols-1UL; i++ ) + { + sal_Int32 nAbsCol = aColumnWidths[(sal_uInt16)i]; + sal_Int32 nExtraAbsCol = (nAbsCol * nExtraAbs) / + nAbsWidth; + nAbsCol = MINLAY + nExtraAbsCol; + aColumnWidths.Replace( (sal_uInt16)nAbsCol, (sal_uInt16)i ); + nAbsLastCol -= nExtraAbsCol; + } + aColumnWidths.Replace( (sal_uInt16)nAbsLastCol, (sal_uInt16)nCols-1U ); + } + } + } + + SwTableLines& rLines = + pBox ? pBox->GetTabLines() + : pTableNode->GetTable().GetTabLines(); + + sal_uInt32 nStartRow = 0UL; + sal_uInt32 nRows = pRows->Count(); + for( i=0UL; i<nRows; i++ ) + { + // Could we split the table behind the current line? + sal_Bool bSplit = sal_True; + if ( bHasSubTables ) + { + SwXMLTableRow_Impl *pRow = (*pRows)[(sal_uInt16)i]; + for( sal_uInt32 j=0UL; j<nCols; j++ ) + { + bSplit = ( 1UL == pRow->GetCell(j)->GetRowSpan() ); + if( !bSplit ) + break; + } + } + + if( bSplit ) + { + SwTableLine *pLine = + MakeTableLine( pBox, nStartRow, 0UL, i+1UL, nCols ); + if( pBox || nStartRow>0UL ) + rLines.C40_INSERT( SwTableLine, pLine, rLines.Count() ); + nStartRow = i+1UL; + } + } +} + +void SwXMLTableContext::MakeTable() +{ + // this method will modify the document directly -> lock SolarMutex + // This will call all other MakeTable*(..) methods, so + // those don't need to be locked separately. + vos::OGuard aGuard(Application::GetSolarMutex()); + + // #i97274# handle invalid tables + if (!pRows || !pRows->Count() || !GetColumnCount()) + { + ASSERT(false, "invalid table: no cells; deleting..."); + pTableNode->GetDoc()->DeleteSection( pTableNode ); + pTableNode = 0; + pBox1 = 0; + pSttNd1 = 0; + return; + } + + SwXMLImport& rSwImport = GetSwImport(); + + SwFrmFmt *pFrmFmt = pTableNode->GetTable().GetFrmFmt(); + + sal_Int16 eHoriOrient = text::HoriOrientation::FULL; + sal_Bool bSetHoriOrient = sal_False; + + sal_uInt16 nPrcWidth = 0U; + + pTableNode->GetTable().SetRowsToRepeat( nHeaderRows ); + pTableNode->GetTable().SetTableModel( !bHasSubTables ); + + const SfxItemSet *pAutoItemSet = 0; + if( aStyleName.getLength() && + rSwImport.FindAutomaticStyle( + XML_STYLE_FAMILY_TABLE_TABLE, aStyleName, &pAutoItemSet ) && + pAutoItemSet ) + { + const SfxPoolItem *pItem; + const SvxLRSpaceItem *pLRSpace = 0; + if( SFX_ITEM_SET == pAutoItemSet->GetItemState( RES_LR_SPACE, sal_False, + &pItem ) ) + pLRSpace = (const SvxLRSpaceItem *)pItem; + + if( SFX_ITEM_SET == pAutoItemSet->GetItemState( RES_HORI_ORIENT, sal_False, + &pItem ) ) + { + eHoriOrient = ((const SwFmtHoriOrient *)pItem)->GetHoriOrient(); + switch( eHoriOrient ) + { + case text::HoriOrientation::FULL: + if( pLRSpace ) + { + eHoriOrient = text::HoriOrientation::NONE; + bSetHoriOrient = sal_True; + } + break; + case text::HoriOrientation::LEFT: + if( pLRSpace ) + { + eHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH; + bSetHoriOrient = sal_True; + } + break; + default: + ; + } + } + else + { + bSetHoriOrient = sal_True; + } + + const SwFmtFrmSize *pSize = 0; + if( SFX_ITEM_SET == pAutoItemSet->GetItemState( RES_FRM_SIZE, sal_False, + &pItem ) ) + pSize = (const SwFmtFrmSize *)pItem; + + switch( eHoriOrient ) + { + case text::HoriOrientation::FULL: + case text::HoriOrientation::NONE: + // #78246#: For text::HoriOrientation::NONE we would prefere to use the sum + // of the relative column widths as reference width. + // Unfortunately this works only if this sum interpreted as + // twip value is larger than the space that is avaialable. + // We don't know that space, so we have to use USHRT_MAX, too. + // Even if a size is speczified, it will be ignored! + nWidth = USHRT_MAX; + break; + default: + if( pSize ) + { + if( pSize->GetWidthPercent() ) + { + // The width will be set in _MakeTable + nPrcWidth = pSize->GetWidthPercent(); + } + else + { + nWidth = pSize->GetWidth(); + if( nWidth < (sal_Int32)GetColumnCount() * MINLAY ) + { + nWidth = GetColumnCount() * MINLAY; + } + else if( nWidth > USHRT_MAX ) + { + nWidth = USHRT_MAX; + } + bRelWidth = sal_False; + } + } + else + { + eHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH == eHoriOrient + ? text::HoriOrientation::NONE : text::HoriOrientation::FULL; + bSetHoriOrient = sal_True; + nWidth = USHRT_MAX; + } + break; + } + + pFrmFmt->SetFmtAttr( *pAutoItemSet ); + } + else + { + bSetHoriOrient = sal_True; + nWidth = USHRT_MAX; + } + + SwTableLine *pLine1 = pTableNode->GetTable().GetTabLines()[0U]; + DBG_ASSERT( pBox1 == pLine1->GetTabBoxes()[0U], + "Why is box 1 change?" ); + pBox1->pSttNd = pSttNd1; + pLine1->GetTabBoxes().Remove(0U); + + pLineFmt = (SwTableLineFmt*)pLine1->GetFrmFmt(); + pBoxFmt = (SwTableBoxFmt*)pBox1->GetFrmFmt(); + + _MakeTable( 0 ); + + if( bSetHoriOrient ) + pFrmFmt->SetFmtAttr( SwFmtHoriOrient( 0, eHoriOrient ) ); + + // This must be after the call to _MakeTable, because nWidth might be + // changed there. + pFrmFmt->LockModify(); + SwFmtFrmSize aSize( ATT_VAR_SIZE, nWidth ); + aSize.SetWidthPercent( (sal_Int8)nPrcWidth ); + pFrmFmt->SetFmtAttr( aSize ); + pFrmFmt->UnlockModify(); + + + for( sal_uInt16 i=0; i<pRows->Count(); i++ ) + (*pRows)[i]->Dispose(); + + // now that table is complete, change into DDE table (if appropriate) + if (NULL != pDDESource) + { + // change existing table into DDE table: + // 1) Get DDE field type (get data from dde-source context), + SwDDEFieldType* pFldType = lcl_GetDDEFieldType( pDDESource, + pTableNode ); + + // 2) release the DDE source context, + pDDESource->ReleaseRef(); + + // 3) create new DDE table, and + SwDDETable* pDDETable = new SwDDETable( pTableNode->GetTable(), + pFldType, FALSE ); + + // 4) set new (DDE)table at node. + pTableNode->SetNewTable(pDDETable, FALSE); + } + + // ??? this is always false: root frame is only created in ViewShell::Init + if( pTableNode->GetDoc()->GetRootFrm() ) + { + pTableNode->DelFrms(); + SwNodeIndex aIdx( *pTableNode->EndOfSectionNode(), 1 ); + pTableNode->MakeFrms( &aIdx ); + } +} + +void SwXMLTableContext::MakeTable( SwTableBox *pBox, sal_Int32 nW ) +{ +//FIXME: here would be a great place to handle XmlId for subtable + pLineFmt = GetParentTable()->pLineFmt; + pBoxFmt = GetParentTable()->pBoxFmt; + nWidth = nW; + bRelWidth = GetParentTable()->bRelWidth; + + _MakeTable( pBox ); +} + +const SwStartNode *SwXMLTableContext::InsertTableSection( + const SwStartNode *pPrevSttNd ) +{ + // The topmost table is the only table that maintains the two members + // pBox1 and bFirstSection. + if( xParentTable.Is() ) + return ((SwXMLTableContext *)&xParentTable)->InsertTableSection( pPrevSttNd ); + + const SwStartNode *pStNd; + Reference<XUnoTunnel> xCrsrTunnel( GetImport().GetTextImport()->GetCursor(), + UNO_QUERY); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + + if( bFirstSection ) + { + // The Cursor already is in the first section + pStNd = pTxtCrsr->GetPaM()->GetNode()->FindTableBoxStartNode(); + bFirstSection = sal_False; + OUString sStyleName( RTL_CONSTASCII_USTRINGPARAM("Standard") ); + GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(), + GetImport().GetTextImport()->GetCursor(), sStyleName, sal_True ); + } + else + { + SwDoc* pDoc = SwImport::GetDocFromXMLImport( GetSwImport() ); + const SwEndNode *pEndNd = pPrevSttNd ? pPrevSttNd->EndOfSectionNode() + : pTableNode->EndOfSectionNode(); + // --> OD 2007-07-02 #i78921# - make code robust +#if OSL_DEBUG_LEVEL > 1 + ASSERT( pDoc, "<SwXMLTableContext::InsertTableSection(..)> - no <pDoc> at <SwXTextCursor> instance - <SwXTextCurosr> doesn't seem to be registered at a <SwUnoCrsr> instance." ); +#endif + if ( !pDoc ) + { + pDoc = const_cast<SwDoc*>(pEndNd->GetDoc()); + } + // <-- + sal_uInt32 nOffset = pPrevSttNd ? 1UL : 0UL; + SwNodeIndex aIdx( *pEndNd, nOffset ); + SwTxtFmtColl *pColl = + pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ); + pStNd = pDoc->GetNodes().MakeTextSection( aIdx, SwTableBoxStartNode, + pColl ); + // --> FLR 2005-08-30 #125369# + // Consider the case that a table is defined without a row. + if( !pPrevSttNd && pBox1 != NULL ) + // <-- + { + pBox1->pSttNd = pStNd; + SwCntntNode *pCNd = pDoc->GetNodes()[ pStNd->GetIndex() + 1 ] + ->GetCntntNode(); + SwPosition aPos( *pCNd ); + aPos.nContent.Assign( pCNd, 0U ); + + const uno::Reference< text::XTextRange > xTextRange = + SwXTextRange::CreateXTextRange( *pDoc, aPos, 0 ); + Reference < XText > xText = xTextRange->getText(); + Reference < XTextCursor > xTextCursor = + xText->createTextCursorByRange( xTextRange ); + GetImport().GetTextImport()->SetCursor( xTextCursor ); + } + } + + return pStNd; +} + +void SwXMLTableContext::EndElement() +{ + if( IsValid() && !xParentTable.Is() ) + { + MakeTable(); + GetImport().GetTextImport()->SetCursor( xOldCursor ); + } +} + +Reference < XTextContent > SwXMLTableContext::GetXTextContent() const +{ + return xTextContent; +} diff --git a/sw/source/filter/xml/xmltbli.hxx b/sw/source/filter/xml/xmltbli.hxx new file mode 100644 index 000000000000..89c3996bc566 --- /dev/null +++ b/sw/source/filter/xml/xmltbli.hxx @@ -0,0 +1,225 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLTBLI_HXX +#define _XMLTBLI_HXX + +#include <xmloff/XMLTextTableContext.hxx> + +// STL include +#include <hash_map> + +#if !defined(_SVSTDARR_USHORTS_DECL) || !defined(_SVSTDARR_BOOLS_DECL) || !defined(_SVSTDARR_STRINGSDTOR_DECL) +#define _SVSTDARR_USHORTS +#define _SVSTDARR_BOOLS +#define _SVSTDARR_STRINGSDTOR +#include <svl/svstdarr.hxx> +#endif + +class SwXMLImport; +class SwTableNode; +class SwTableBox; +class SwTableLine; +class SwStartNode; +class SwTableBoxFmt; +class SwTableLineFmt; +class SwXMLTableCell_Impl; +class SwXMLTableRows_Impl; +class SwXMLDDETableContext_Impl; +class TableBoxIndexHasher; +class TableBoxIndex; + +namespace com { namespace sun { namespace star { + namespace text { class XTextContent; } + namespace text { class XTextCursor; } +} } } + + + +class SwXMLTableContext : public XMLTextTableContext +{ + ::rtl::OUString aStyleName; + ::rtl::OUString aDfltCellStyleName; + /// NB: this contains the xml:id only if this table is a subtable! + ::rtl::OUString mXmlId; + + SvUShorts aColumnWidths; + SvBools aColumnRelWidths; + SvStringsDtor *pColumnDefaultCellStyleNames; + + ::com::sun::star::uno::Reference < + ::com::sun::star::text::XTextCursor > xOldCursor; + ::com::sun::star::uno::Reference < + ::com::sun::star::text::XTextContent > xTextContent; + + SwXMLTableRows_Impl *pRows; + + SwTableNode *pTableNode; + SwTableBox *pBox1; + const SwStartNode *pSttNd1; + + SwTableBoxFmt *pBoxFmt; + SwTableLineFmt *pLineFmt; + + // hash map of shared format, indexed by the (XML) style name, + // the column width, and protection flag + typedef std::hash_map<TableBoxIndex,SwTableBoxFmt*, + TableBoxIndexHasher> map_BoxFmt; + map_BoxFmt* pSharedBoxFormats; + + SvXMLImportContextRef xParentTable; // if table is a sub table + + SwXMLDDETableContext_Impl *pDDESource; + + sal_Bool bFirstSection : 1; + sal_Bool bRelWidth : 1; + sal_Bool bHasSubTables : 1; + + USHORT nHeaderRows; + sal_uInt32 nCurRow; + sal_uInt32 nCurCol; + sal_Int32 nWidth; + + SwTableBox *NewTableBox( const SwStartNode *pStNd, + SwTableLine *pUpper ); + SwTableBox *MakeTableBox( SwTableLine *pUpper, + const SwXMLTableCell_Impl *pStartNode, + sal_uInt32 nTopRow, sal_uInt32 nLeftCol, + sal_uInt32 nBottomRow, sal_uInt32 nRightCol ); + SwTableBox *MakeTableBox( SwTableLine *pUpper, + sal_uInt32 nTopRow, sal_uInt32 nLeftCol, + sal_uInt32 nBottomRow, sal_uInt32 nRightCol ); + SwTableLine *MakeTableLine( SwTableBox *pUpper, + sal_uInt32 nTopRow, sal_uInt32 nLeftCol, + sal_uInt32 nBottomRow, sal_uInt32 nRightCol ); + + void _MakeTable( SwTableBox *pBox=0 ); + void MakeTable( SwTableBox *pBox, sal_Int32 nWidth ); + void MakeTable(); + + inline SwXMLTableContext *GetParentTable() const; + + const SwStartNode *GetPrevStartNode( sal_uInt32 nRow, + sal_uInt32 nCol ) const; + inline const SwStartNode *GetLastStartNode() const; + void FixRowSpan( sal_uInt32 nRow, sal_uInt32 nCol, sal_uInt32 nColSpan ); + void ReplaceWithEmptyCell( sal_uInt32 nRow, sal_uInt32 nCol, bool bRows ); + + /** sets the appropriate SwTblBoxFmt at pBox. */ + SwTableBoxFmt* GetSharedBoxFormat( + SwTableBox* pBox, /// the table box + const ::rtl::OUString& rStyleName, /// XML style name + sal_Int32 nColumnWidth, /// width of column + sal_Bool bProtected, /// is cell protected? + sal_Bool bMayShare, /// may the format be shared (no value, formula...) + sal_Bool& bNew, /// true, if the format it not from the cache + sal_Bool* pModifyLocked ); /// if set, call pBox->LockModify() and return old lock status + +public: + + TYPEINFO(); + + SwXMLTableContext( SwXMLImport& rImport, sal_uInt16 nPrfx, + const ::rtl::OUString& rLName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList ); + SwXMLTableContext( SwXMLImport& rImport, sal_uInt16 nPrfx, + const ::rtl::OUString& rLName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + SwXMLTableContext *pTable, + const ::rtl::OUString& i_rXmlId ); + + virtual ~SwXMLTableContext(); + + virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList ); + + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } + + void InsertColumn( sal_Int32 nWidth, sal_Bool bRelWidth, + const ::rtl::OUString *pDfltCellStyleName = 0 ); + sal_Int32 GetColumnWidth( sal_uInt32 nCol, sal_uInt32 nColSpan=1UL ) const; + ::rtl::OUString GetColumnDefaultCellStyleName( sal_uInt32 nCol ) const; + inline sal_uInt32 GetColumnCount() const; + inline sal_Bool HasColumnDefaultCellStyleNames() const; + + sal_Bool IsInsertCellPossible() const { return nCurCol < GetColumnCount(); } + sal_Bool IsInsertColPossible() const { return nCurCol < USHRT_MAX; } + sal_Bool IsInsertRowPossible() const { return nCurRow < USHRT_MAX; } + sal_Bool IsValid() const { return pTableNode != 0; } + + void InsertCell( const ::rtl::OUString& rStyleName, + sal_uInt32 nRowSpan=1U, sal_uInt32 nColSpan=1U, + const SwStartNode *pStNd=0, + const ::rtl::OUString & i_rXmlId = ::rtl::OUString(), + SwXMLTableContext *pTable=0, + sal_Bool bIsProtected = sal_False, + const ::rtl::OUString *pFormula=0, + sal_Bool bHasValue = sal_False, + double fValue = 0.0, + sal_Bool bTextValue = sal_False ); + void InsertRow( const ::rtl::OUString& rStyleName, + const ::rtl::OUString& rDfltCellStyleName, + sal_Bool bInHead, + const ::rtl::OUString & i_rXmlId = ::rtl::OUString() ); + void FinishRow(); + void InsertRepRows( sal_uInt32 nCount ); + SwXMLTableCell_Impl *GetCell( sal_uInt32 nRow, sal_uInt32 nCol ) const; + const SwStartNode *InsertTableSection( const SwStartNode *pPrevSttNd=0 ); + + virtual void EndElement(); + + virtual ::com::sun::star::uno::Reference < + ::com::sun::star::text::XTextContent > GetXTextContent() const; + + void SetHasSubTables( sal_Bool bNew ) { bHasSubTables = bNew; } +}; + +inline SwXMLTableContext *SwXMLTableContext::GetParentTable() const +{ + return (SwXMLTableContext *)&xParentTable; +} + +inline sal_uInt32 SwXMLTableContext::GetColumnCount() const +{ + return aColumnWidths.Count(); +} + +inline const SwStartNode *SwXMLTableContext::GetLastStartNode() const +{ + return GetPrevStartNode( 0UL, GetColumnCount() ); +} + +inline sal_Bool SwXMLTableContext::HasColumnDefaultCellStyleNames() const +{ + return pColumnDefaultCellStyleNames != 0; +} + +#endif diff --git a/sw/source/filter/xml/xmltext.cxx b/sw/source/filter/xml/xmltext.cxx new file mode 100644 index 000000000000..f9cf0f6cdc7c --- /dev/null +++ b/sw/source/filter/xml/xmltext.cxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <xmloff/xmlnmspe.hxx> +#include "xmlimp.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; + +// --------------------------------------------------------------------- + + +class SwXMLBodyContentContext_Impl : public SvXMLImportContext +{ + SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); } + +public: + + SwXMLBodyContentContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName ); + virtual ~SwXMLBodyContentContext_Impl(); + + virtual SvXMLImportContext *CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ); + + // The body element's text:global attribute can be ignored, because + // we must have the correct object shell already. + virtual void EndElement(); +}; + +SwXMLBodyContentContext_Impl::SwXMLBodyContentContext_Impl( SwXMLImport& rImport, + sal_uInt16 nPrfx, + const OUString& rLName ) : + SvXMLImportContext( rImport, nPrfx, rLName ) +{ +} + +SwXMLBodyContentContext_Impl::~SwXMLBodyContentContext_Impl() +{ +} + +SvXMLImportContext *SwXMLBodyContentContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, const OUString& rLocalName, + const Reference< xml::sax::XAttributeList > & xAttrList ) +{ + SvXMLImportContext *pContext = 0; + + pContext = GetSwImport().GetTextImport()->CreateTextChildContext( + GetImport(), nPrefix, rLocalName, xAttrList, + XML_TEXT_TYPE_BODY ); + if( !pContext ) + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + + return pContext; +} + +void SwXMLBodyContentContext_Impl::EndElement() +{ + /* #108146# Code moved to SwXMLOmport::endDocument */ + GetImport().GetTextImport()->SetOutlineStyles( sal_False ); +} + +SvXMLImportContext *SwXMLImport::CreateBodyContentContext( + const OUString& rLocalName ) +{ + SvXMLImportContext *pContext = 0; + + if( !IsStylesOnlyMode() ) + pContext = new SwXMLBodyContentContext_Impl( *this, XML_NAMESPACE_OFFICE, + rLocalName ); + else + pContext = new SvXMLImportContext( *this, XML_NAMESPACE_OFFICE, + rLocalName ); + + return pContext; +} diff --git a/sw/source/filter/xml/xmltexte.cxx b/sw/source/filter/xml/xmltexte.cxx new file mode 100644 index 000000000000..2e22743fd1ee --- /dev/null +++ b/sw/source/filter/xml/xmltexte.cxx @@ -0,0 +1,767 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <sot/clsids.hxx> +#include <com/sun/star/embed/XEmbedObjectCreator.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/embed/XLinkageSupport.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/XClassifiedObject.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp> +#include <xmloff/families.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/txtprmap.hxx> + +#include <svx/svdobj.hxx> +#include <doc.hxx> +#include <ndole.hxx> +#include <fmtcntnt.hxx> +#include <unostyle.hxx> +#include <unoframe.hxx> +#include <ndgrf.hxx> +#include "xmlexp.hxx" +#include "xmltexte.hxx" +#include <tools/urlobj.hxx> +#include <SwAppletImpl.hxx> + +#define _SVSTDARR_ULONGS +#include <svl/svstdarr.hxx> +#include "svl/urihelper.hxx" +#include <sfx2/frmdescr.hxx> +#include <SwStyleNameMapper.hxx> + + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::io; +using namespace ::xmloff::token; + +enum SvEmbeddedObjectTypes +{ + SV_EMBEDDED_OWN, + SV_EMBEDDED_OUTPLACE, + SV_EMBEDDED_APPLET, + SV_EMBEDDED_PLUGIN, + SV_EMBEDDED_FRAME +}; + +const sal_Char sObjectReplacements[] = "ObjectReplacements/"; + +// --------------------------------------------------------------------- + +SwNoTxtNode *SwXMLTextParagraphExport::GetNoTxtNode( + const Reference < XPropertySet >& rPropSet ) const +{ + Reference<XUnoTunnel> xCrsrTunnel( rPropSet, UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for embedded" ); + SwXFrame *pFrame = reinterpret_cast< SwXFrame * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( SwXFrame::getUnoTunnelId() ))); + ASSERT( pFrame, "SwXFrame missing" ); + SwFrmFmt *pFrmFmt = pFrame->GetFrmFmt(); + const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); + const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx(); + return pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetNoTxtNode(); +} + +void SwXMLTextParagraphExport::exportStyleContent( + const Reference< XStyle > & rStyle ) +{ + + const SwXStyle* pStyle = 0; + Reference<XUnoTunnel> xStyleTunnel( rStyle, UNO_QUERY); + if( xStyleTunnel.is() ) + { + pStyle = reinterpret_cast< SwXStyle * >( + sal::static_int_cast< sal_IntPtr >( xStyleTunnel->getSomething( SwXStyle::getUnoTunnelId() ))); + } + if( pStyle && SFX_STYLE_FAMILY_PARA == pStyle->GetFamily() ) + { + const SwDoc *pDoc = pStyle->GetDoc(); + const SwTxtFmtColl *pColl = + pDoc->FindTxtFmtCollByName( pStyle->GetStyleName() ); + ASSERT( pColl, "There is the text collection?" ); + if( pColl && RES_CONDTXTFMTCOLL == pColl->Which() ) + { + const SwFmtCollConditions& rConditions = + ((const SwConditionTxtFmtColl *)pColl)->GetCondColls(); + for( sal_uInt16 i=0; i < rConditions.Count(); i++ ) + { + const SwCollCondition& rCond = *rConditions[i]; + + enum XMLTokenEnum eFunc = XML_TOKEN_INVALID; + OUStringBuffer sBuffer( 20 ); + switch( rCond.GetCondition() ) + { + case PARA_IN_LIST: + eFunc = XML_LIST_LEVEL; + sBuffer.append( (sal_Int32)(rCond.GetSubCondition()+1) ); + break; + case PARA_IN_OUTLINE: + eFunc = XML_OUTLINE_LEVEL; + sBuffer.append( (sal_Int32)(rCond.GetSubCondition()+1) ); + break; + case PARA_IN_FRAME: + eFunc = XML_TEXT_BOX; + break; + case PARA_IN_TABLEHEAD: + eFunc = XML_TABLE_HEADER; + break; + case PARA_IN_TABLEBODY: + eFunc = XML_TABLE; + break; + case PARA_IN_SECTION: + eFunc = XML_SECTION; + break; + case PARA_IN_FOOTENOTE: + eFunc = XML_FOOTNOTE; + break; + case PARA_IN_FOOTER: + eFunc = XML_FOOTER; + break; + case PARA_IN_HEADER: + eFunc = XML_HEADER; + break; + case PARA_IN_ENDNOTE: + eFunc = XML_ENDNOTE; + break; + } + OUString sVal( sBuffer.makeStringAndClear() ); + + DBG_ASSERT( eFunc != XML_TOKEN_INVALID, + "SwXMLExport::ExportFmt: unknown condition" ); + if( eFunc != XML_TOKEN_INVALID ) + { + sBuffer.append( GetXMLToken(eFunc) ); + sBuffer.append( (sal_Unicode)'(' ); + sBuffer.append( (sal_Unicode)')' ); + if( sVal.getLength() ) + { + sBuffer.append( (sal_Unicode)'=' ); + sBuffer.append( sVal ); + } + + GetExport().AddAttribute( XML_NAMESPACE_STYLE, + XML_CONDITION, + sBuffer.makeStringAndClear() ); + String aString; + SwStyleNameMapper::FillProgName( + rCond.GetTxtFmtColl()->GetName(), + aString, + nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, + sal_True); + aString = GetExport().EncodeStyleName( aString ); + GetExport().AddAttribute( XML_NAMESPACE_STYLE, + XML_APPLY_STYLE_NAME, aString ); + SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE, + XML_MAP, sal_True, sal_True ); + } + } + } + } +} + +SwXMLTextParagraphExport::SwXMLTextParagraphExport( + SwXMLExport& rExp, + SvXMLAutoStylePoolP& _rAutoStylePool ) : + XMLTextParagraphExport( rExp, _rAutoStylePool ), + sTextTable( RTL_CONSTASCII_USTRINGPARAM( "TextTable" ) ), + sEmbeddedObjectProtocol( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.EmbeddedObject:" ) ), + sGraphicObjectProtocol( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) ), + aAppletClassId( SO3_APPLET_CLASSID ), + aPluginClassId( SO3_PLUGIN_CLASSID ), + aIFrameClassId( SO3_IFRAME_CLASSID ), + aOutplaceClassId( SO3_OUT_CLASSID ) +{ +} + +SwXMLTextParagraphExport::~SwXMLTextParagraphExport() +{ +} + +void SwXMLTextParagraphExport::setTextEmbeddedGraphicURL( + const Reference < XPropertySet >& rPropSet, + OUString& rURL) const +{ + if( !rURL.getLength() ) + return; + + SwGrfNode *pGrfNd = GetNoTxtNode( rPropSet )->GetGrfNode(); + if( !pGrfNd->IsGrfLink() ) + { + String aNewURL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.Package:") ); + aNewURL += String(rURL); + pGrfNd->SetNewStreamName( aNewURL ); + + // #i15411# save-as will swap all graphics in; we need to swap + // them out again, to prevent excessive memory use + pGrfNd->SwapOut(); + } +} +/* +static void lcl_addParam ( SvXMLExport &rExport, const SvCommand &rCommand ) +{ + rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, rCommand.GetCommand() ); + rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, rCommand.GetArgument() ); + SvXMLElementExport aElem( rExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True ); +}*/ + +static void lcl_addURL ( SvXMLExport &rExport, const String &rURL, + sal_Bool bToRel = sal_True ) +{ + String sRelURL; + + if( bToRel && (rURL.Len() > 0) ) + sRelURL = URIHelper::simpleNormalizedMakeRelative(rExport.GetOrigFileName(), + rURL); + else + sRelURL = rURL; + + if (sRelURL.Len()) + { + rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, sRelURL ); + rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE ); + rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED ); + rExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD ); + } +} + +void lcl_addAspect( + const svt::EmbeddedObjectRef& rObj, + const XMLPropertyState **pStates, + const UniReference < XMLPropertySetMapper >& rMapper ) +{ + { + sal_Int64 nAspect = rObj.GetViewAspect(); + + if ( nAspect ) + { + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_OLE_DRAW_ASPECT ), uno::makeAny( nAspect ) ); + pStates++; + } + } +} + +void lcl_addOutplaceProperties( + const svt::EmbeddedObjectRef& rObj, + const XMLPropertyState **pStates, + const UniReference < XMLPropertySetMapper >& rMapper ) +{ + { + MapMode aMode( MAP_100TH_MM ); // the API expects this map mode for the embedded objects + Size aSize = rObj.GetSize( &aMode ); // get the size in the requested map mode + + if( aSize.Width() && aSize.Height() ) + { + Any aAny; + //aAny <<= (sal_Int32)rVisArea.Left(); + aAny <<= 0L; + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_LEFT ), aAny ); + pStates++; + + //aAny <<= (sal_Int32)rVisArea.Top(); + aAny <<= 0L; + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_TOP ), aAny ); + pStates++; + + //aAny <<= (sal_Int32)rVisArea.GetWidth(); + aAny <<= (sal_Int32)aSize.Width(); + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_WIDTH ), aAny ); + pStates++; + + //aAny <<= (sal_Int32)rVisArea.GetHeight(); + aAny <<= (sal_Int32)aSize.Height(); + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_OLE_VIS_AREA_HEIGHT ), aAny ); + pStates++; + } + } +} + +void lcl_addFrameProperties( + const uno::Reference < embed::XEmbeddedObject >& xObj, + const XMLPropertyState **pStates, + const UniReference < XMLPropertySetMapper >& rMapper ) +{ + if ( !::svt::EmbeddedObjectRef::TryRunningState( xObj ) ) + return; + + uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); + if ( !xSet.is() ) + return; + + ::rtl::OUString aURL; + Any aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameURL") ); + aAny >>= aURL; + + ::rtl::OUString aName; + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameName") ); + aAny >>= aName; + + sal_Bool bIsAutoScroll = sal_False, bIsScrollingMode; + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameIsAutoScroll") ); + aAny >>= bIsAutoScroll; + if ( !bIsAutoScroll ) + { + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameIsScrollingMode") ); + aAny >>= bIsScrollingMode; + } + + sal_Bool bIsBorderSet, bIsAutoBorder = sal_False; + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameIsAutoBorder") ); + aAny >>= bIsAutoBorder; + if ( !bIsAutoBorder ) + { + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameIsBorder") ); + aAny >>= bIsBorderSet; + } + + sal_Int32 nWidth, nHeight; + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameMarginWidth") ); + aAny >>= nWidth; + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameMarginHeight") ); + aAny >>= nHeight; + + if( !bIsAutoScroll ) + { + Any aAny2( &bIsScrollingMode, ::getBooleanCppuType() ); + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_FRAME_DISPLAY_SCROLLBAR ), aAny2 ); + pStates++; + } + if( !bIsAutoBorder ) + { + Any aAny2( &bIsBorderSet, ::getBooleanCppuType() ); + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_FRAME_DISPLAY_BORDER ), aAny2 ); + pStates++; + } + if( SIZE_NOT_SET != nWidth ) + { + Any aAny2; + aAny <<= nWidth; + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_FRAME_MARGIN_HORI ), aAny2 ); + pStates++; + } + if( SIZE_NOT_SET != nHeight ) + { + Any aAny2; + aAny <<= nHeight; + *pStates = new XMLPropertyState( rMapper->FindEntryIndex( CTF_FRAME_MARGIN_VERT ), aAny2 ); + pStates++; + } +} + +void SwXMLTextParagraphExport::_collectTextEmbeddedAutoStyles( + const Reference < XPropertySet > & rPropSet ) +{ + SwOLENode *pOLENd = GetNoTxtNode( rPropSet )->GetOLENode(); + svt::EmbeddedObjectRef& rObjRef = pOLENd->GetOLEObj().GetObject(); + if( !rObjRef.is() ) + return; + + const XMLPropertyState *aStates[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + SvGlobalName aClassId( rObjRef->getClassID() ); + + if( aIFrameClassId == aClassId ) + { + lcl_addFrameProperties( rObjRef.GetObject(), aStates, + GetAutoFramePropMapper()->getPropertySetMapper() ); + } + else if ( !SotExchange::IsInternal( aClassId ) ) + { + lcl_addOutplaceProperties( rObjRef, aStates, + GetAutoFramePropMapper()->getPropertySetMapper() ); + } + + lcl_addAspect( rObjRef, aStates, + GetAutoFramePropMapper()->getPropertySetMapper() ); + + Add( XML_STYLE_FAMILY_TEXT_FRAME, rPropSet, aStates ); + + const XMLPropertyState **pStates = aStates; + while( *pStates ) + { + delete *pStates; + pStates++; + } +} + +void SwXMLTextParagraphExport::_exportTextEmbedded( + const Reference < XPropertySet > & rPropSet, + const Reference < XPropertySetInfo > & rPropSetInfo ) +{ + SwOLENode *pOLENd = GetNoTxtNode( rPropSet )->GetOLENode(); + SwOLEObj& rOLEObj = pOLENd->GetOLEObj(); + svt::EmbeddedObjectRef& rObjRef = rOLEObj.GetObject(); + if( !rObjRef.is() ) + return; + + SvGlobalName aClassId( rObjRef->getClassID() ); + + SvEmbeddedObjectTypes nType = SV_EMBEDDED_OWN; + if( aPluginClassId == aClassId ) + { + nType = SV_EMBEDDED_PLUGIN; + } + else if( aAppletClassId == aClassId ) + { + nType = SV_EMBEDDED_APPLET; + } + else if( aIFrameClassId == aClassId ) + { + nType = SV_EMBEDDED_FRAME; + } + else if ( !SotExchange::IsInternal( aClassId ) ) + { + nType = SV_EMBEDDED_OUTPLACE; + } + + enum XMLTokenEnum eElementName = XML__UNKNOWN_; + SvXMLExport &rXMLExport = GetExport(); + + // First the stuff common to each of Applet/Plugin/Floating Frame + OUString sStyle; + Any aAny; + if( rPropSetInfo->hasPropertyByName( sFrameStyleName ) ) + { + aAny = rPropSet->getPropertyValue( sFrameStyleName ); + aAny >>= sStyle; + } + + const XMLPropertyState *aStates[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + switch( nType ) + { + case SV_EMBEDDED_FRAME: + lcl_addFrameProperties( rObjRef.GetObject(), aStates, + GetAutoFramePropMapper()->getPropertySetMapper() ); + break; + case SV_EMBEDDED_OUTPLACE: + lcl_addOutplaceProperties( rObjRef, aStates, + GetAutoFramePropMapper()->getPropertySetMapper() ); + break; + default: + ; + } + + lcl_addAspect( rObjRef, aStates, + GetAutoFramePropMapper()->getPropertySetMapper() ); + + OUString sAutoStyle( sStyle ); + sAutoStyle = Find( XML_STYLE_FAMILY_TEXT_FRAME, rPropSet, sStyle, + aStates ); + const XMLPropertyState **pStates = aStates; + while( *pStates ) + { + delete *pStates; + pStates++; + } + + if( sAutoStyle.getLength() ) + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME, sAutoStyle ); + addTextFrameAttributes( rPropSet, sal_False ); + + SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, + XML_FRAME, sal_False, sal_True ); + + switch (nType) + { + case SV_EMBEDDED_OUTPLACE: + case SV_EMBEDDED_OWN: + if( (rXMLExport.getExportFlags() & EXPORT_EMBEDDED) == 0 ) + { + OUString sURL; + + sal_Bool bIsOwnLink = sal_False; + if( SV_EMBEDDED_OWN == nType ) + { + try + { + uno::Reference< embed::XLinkageSupport > xLinkage( rObjRef.GetObject(), uno::UNO_QUERY ); + bIsOwnLink = xLinkage.is() && xLinkage->isLink(); + if ( bIsOwnLink ) + sURL = xLinkage->getLinkURL(); + } + catch( uno::Exception ) + { + // TODO/LATER: error handling + DBG_ERROR( "Link detection or retrieving of the URL of OOo link is failed!\n" ); + } + } + + if ( !bIsOwnLink ) + { + sURL = OUString( sEmbeddedObjectProtocol ); + sURL += rOLEObj.GetCurrentPersistName(); + } + + sURL = GetExport().AddEmbeddedObject( sURL ); + lcl_addURL( rXMLExport, sURL, sal_False ); + } + if( SV_EMBEDDED_OWN == nType && pOLENd->GetChartTblName().Len() ) + { + OUString sRange( pOLENd->GetChartTblName() ); + OUStringBuffer aBuffer( sRange.getLength() + 2 ); + for( sal_Int32 i=0; i < sRange.getLength(); i++ ) + { + sal_Unicode c = sRange[i]; + switch( c ) + { + case ' ': + case '.': + case '\'': + case '\\': + if( !aBuffer.getLength() ) + { + aBuffer.append( (sal_Unicode)'\'' ); + aBuffer.append( sRange.copy( 0, i ) ); + } + if( '\'' == c || '\\' == c ) + aBuffer.append( (sal_Unicode)'\\' ); + // no break! + default: + if( aBuffer.getLength() ) + aBuffer.append( c ); + } + } + if( aBuffer.getLength() ) + { + aBuffer.append( (sal_Unicode)'\'' ); + sRange = aBuffer.makeStringAndClear(); + } + + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES, + sRange ); + } + eElementName = SV_EMBEDDED_OUTPLACE==nType ? XML_OBJECT_OLE + : XML_OBJECT; + break; + case SV_EMBEDDED_APPLET: + { + // It's an applet! + if( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) ) + { + uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY ); + ::rtl::OUString aStr; + Any aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("AppletCodeBase") ); + aAny2 >>= aStr; + if (aStr.getLength() ) + lcl_addURL(rXMLExport, aStr); + + aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("AppletName") ); + aAny2 >>= aStr; + if (aStr.getLength()) + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_APPLET_NAME, aStr ); + + aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("AppletCode") ); + aAny2 >>= aStr; + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CODE, aStr ); + + sal_Bool bScript = sal_False; + aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("AppletIsScript") ); + aAny2 >>= bScript; + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MAY_SCRIPT, bScript ? XML_TRUE : XML_FALSE ); + + uno::Sequence < beans::PropertyValue > aProps; + aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("AppletCommands") ); + aAny2 >>= aProps; + + sal_Int32 i = aProps.getLength(); + while ( i > 0 ) + { + beans::PropertyValue& aProp = aProps[--i]; + USHORT nType2 = SwApplet_Impl::GetOptionType( aProp.Name, TRUE ); + if ( nType2 == SWHTML_OPTTYPE_TAG) + { + ::rtl::OUString aStr2; + aProp.Value >>= aStr2; + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, aProp.Name, aStr2); + } + } + + eElementName = XML_APPLET; + } + } + break; + case SV_EMBEDDED_PLUGIN: + { + // It's a plugin! + if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) ) + { + uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY ); + ::rtl::OUString aStr; + Any aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("PluginURL") ); + aAny2 >>= aStr; + lcl_addURL( rXMLExport, aStr ); + + aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("PluginMimeType") ); + aAny2 >>= aStr; + if (aStr.getLength()) + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, aStr ); + eElementName = XML_PLUGIN; + } + } + break; + case SV_EMBEDDED_FRAME: + { + // It's a floating frame! + if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) ) + { + uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY ); + ::rtl::OUString aStr; + Any aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameURL") ); + aAny2 >>= aStr; + + lcl_addURL( rXMLExport, aStr ); + + aAny2 = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("FrameName") ); + aAny2 >>= aStr; + + if (aStr.getLength()) + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_FRAME_NAME, aStr ); + eElementName = XML_FLOATING_FRAME; + } + } + break; + default: + ASSERT( !this, "unknown object type! Base class should have been called!" ); + } + + { + SvXMLElementExport aElementExport( rXMLExport, XML_NAMESPACE_DRAW, eElementName, + sal_False, sal_True ); + switch( nType ) + { + case SV_EMBEDDED_OWN: + if( (rXMLExport.getExportFlags() & EXPORT_EMBEDDED) != 0 ) + { + Reference < XEmbeddedObjectSupplier > xEOS( rPropSet, UNO_QUERY ); + ASSERT( xEOS.is(), "no embedded object supplier for own object" ); + Reference < XComponent > xComp = xEOS->getEmbeddedObject(); + rXMLExport.ExportEmbeddedOwnObject( xComp ); + } + break; + case SV_EMBEDDED_OUTPLACE: + if( (rXMLExport.getExportFlags() & EXPORT_EMBEDDED) != 0 ) + { + OUString sURL( sEmbeddedObjectProtocol ); + sURL += rOLEObj.GetCurrentPersistName(); + + if ( ( rXMLExport.getExportFlags() & EXPORT_OASIS ) == 0 ) + sURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "?oasis=false" ) ); + + rXMLExport.AddEmbeddedObjectAsBase64( sURL ); + } + break; + case SV_EMBEDDED_APPLET: + { + if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) ) + { + uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY ); + uno::Sequence < beans::PropertyValue > aProps; + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("AppletCommands") ); + aAny >>= aProps; + + sal_Int32 i = aProps.getLength(); + while ( i > 0 ) + { + beans::PropertyValue& aProp = aProps[--i]; + USHORT nType2 = SwApplet_Impl::GetOptionType( aProp.Name, TRUE ); + if (SWHTML_OPTTYPE_PARAM == nType2 || SWHTML_OPTTYPE_SIZE == nType2 ) + { + ::rtl::OUString aStr; + aProp.Value >>= aStr; + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aProp.Name ); + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aStr ); + SvXMLElementExport aElementExport2( rXMLExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True ); + } + } + } + } + break; + case SV_EMBEDDED_PLUGIN: + { + if ( svt::EmbeddedObjectRef::TryRunningState( rObjRef.GetObject() ) ) + { + uno::Reference < beans::XPropertySet > xSet( rObjRef->getComponent(), uno::UNO_QUERY ); + uno::Sequence < beans::PropertyValue > aProps; + aAny = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("PluginCommands") ); + aAny >>= aProps; + + sal_Int32 i = aProps.getLength(); + while ( i > 0 ) + { + beans::PropertyValue& aProp = aProps[--i]; + USHORT nType2 = SwApplet_Impl::GetOptionType( aProp.Name, FALSE ); + if ( nType2 == SWHTML_OPTTYPE_TAG) + { + ::rtl::OUString aStr; + aProp.Value >>= aStr; + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aProp.Name ); + rXMLExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aStr ); + SvXMLElementExport aElementExport2( rXMLExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True ); + } + } + } + } + break; + default: + break; + } + } + if( SV_EMBEDDED_OUTPLACE==nType || SV_EMBEDDED_OWN==nType ) + { + OUString sURL( sGraphicObjectProtocol ); + sURL += rOLEObj.GetCurrentPersistName(); + if( (rXMLExport.getExportFlags() & EXPORT_EMBEDDED) == 0 ) + { + sURL = GetExport().AddEmbeddedObject( sURL ); + lcl_addURL( rXMLExport, sURL, sal_False ); + } + + SvXMLElementExport aElementExport( GetExport(), XML_NAMESPACE_DRAW, + XML_IMAGE, sal_False, sal_True ); + + if( (rXMLExport.getExportFlags() & EXPORT_EMBEDDED) != 0 ) + GetExport().AddEmbeddedObjectAsBase64( sURL ); + } + + // Lastly the stuff common to each of Applet/Plugin/Floating Frame + exportEvents( rPropSet ); + // --> OD 2009-07-22 #i73249# + exportTitleAndDescription( rPropSet, rPropSetInfo ); + // <-- + exportContour( rPropSet, rPropSetInfo ); +} diff --git a/sw/source/filter/xml/xmltexte.hxx b/sw/source/filter/xml/xmltexte.hxx new file mode 100644 index 000000000000..ea0fd20356e9 --- /dev/null +++ b/sw/source/filter/xml/xmltexte.hxx @@ -0,0 +1,88 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XMLTEXTE_HXX +#define _XMLTEXTE_HXX + +#include <xmloff/txtparae.hxx> +#include <tools/globname.hxx> + +class SwXMLExport; +class SvXMLAutoStylePoolP; +class SwNoTxtNode; + +namespace com { namespace sun { namespace star { namespace style { + class XStyle; } } } } + +class SwXMLTextParagraphExport : public XMLTextParagraphExport +{ + const ::rtl::OUString sTextTable; + const ::rtl::OUString sEmbeddedObjectProtocol; + const ::rtl::OUString sGraphicObjectProtocol; + + const SvGlobalName aAppletClassId; + const SvGlobalName aPluginClassId; + const SvGlobalName aIFrameClassId; + const SvGlobalName aOutplaceClassId; + + SwNoTxtNode *GetNoTxtNode( + const ::com::sun::star::uno::Reference < + ::com::sun::star::beans::XPropertySet >& rPropSet ) const; + +protected: + virtual void exportStyleContent( + const ::com::sun::star::uno::Reference< + ::com::sun::star::style::XStyle > & rStyle ); + + virtual void _collectTextEmbeddedAutoStyles( + const ::com::sun::star::uno::Reference < + ::com::sun::star::beans::XPropertySet > & rPropSet ); + virtual void _exportTextEmbedded( + const ::com::sun::star::uno::Reference < + ::com::sun::star::beans::XPropertySet > & rPropSet, + const ::com::sun::star::uno::Reference < + ::com::sun::star::beans::XPropertySetInfo > & rPropSetInfo ); + + virtual void exportTable( + const ::com::sun::star::uno::Reference < + ::com::sun::star::text::XTextContent > & rTextContent, + sal_Bool bAutoStyles, sal_Bool bProgress ); + +public: + SwXMLTextParagraphExport( + SwXMLExport& rExp, + SvXMLAutoStylePoolP& rAutoStylePool ); + ~SwXMLTextParagraphExport(); + + virtual void setTextEmbeddedGraphicURL( + const ::com::sun::star::uno::Reference < + ::com::sun::star::beans::XPropertySet >& rPropSet, + ::rtl::OUString& rStreamName ) const; +}; + + +#endif // _XMLTEXTE_HXX diff --git a/sw/source/filter/xml/xmltexti.cxx b/sw/source/filter/xml/xmltexti.cxx new file mode 100644 index 000000000000..d5f298b5292c --- /dev/null +++ b/sw/source/filter/xml/xmltexti.cxx @@ -0,0 +1,1062 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <comphelper/storagehelper.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/XEmbedObjectCreator.hpp> +#include <com/sun/star/embed/XLinkCreator.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/embed/XVisualObject.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <rtl/ustrbuf.hxx> +#include <sot/clsids.hxx> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <xmloff/prstylei.hxx> +#include <xmloff/maptype.hxx> +#include <xmloff/xmlprmap.hxx> +#include <xmloff/txtprmap.hxx> +#include <xmloff/i18nmap.hxx> +#include "unocrsr.hxx" +#include "TextCursorHelper.hxx" +#include "unoframe.hxx" +#include "doc.hxx" +#include "unocoll.hxx" +#include <fmtfsize.hxx> +#include <fmtanchr.hxx> +#include <fmtcntnt.hxx> +#include "xmlimp.hxx" +#include "xmltbli.hxx" +#include "xmltexti.hxx" +#include "XMLRedlineImportHelper.hxx" +#include <xmloff/XMLFilterServiceNames.h> +#include <SwAppletImpl.hxx> +#include <ndole.hxx> +#include <docsh.hxx> +#include <sfx2/docfile.hxx> + +// for locking SolarMutex: svapp + mutex +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +#include <toolkit/helper/vclunohelper.hxx> +#include <svtools/embedhlp.hxx> +#include <svl/urihelper.hxx> + + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; +using namespace xml::sax; + + +struct XMLServiceMapEntry_Impl +{ + const sal_Char *sFilterService; + sal_Int32 nFilterServiceLen; + + sal_uInt32 n1; + sal_uInt16 n2, n3; + sal_uInt8 n4, n5, n6, n7, n8, n9, n10, n11; +}; + +#define SERVICE_MAP_ENTRY( app, s ) \ + { XML_IMPORT_FILTER_##app, sizeof(XML_IMPORT_FILTER_##app)-1, \ + SO3_##s##_CLASSID } + +const XMLServiceMapEntry_Impl aServiceMap[] = +{ + SERVICE_MAP_ENTRY( WRITER, SW ), + SERVICE_MAP_ENTRY( CALC, SC ), + SERVICE_MAP_ENTRY( DRAW, SDRAW ), + SERVICE_MAP_ENTRY( IMPRESS, SIMPRESS ), + SERVICE_MAP_ENTRY( CHART, SCH ), + SERVICE_MAP_ENTRY( MATH, SM ), + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; +static void lcl_putHeightAndWidth ( SfxItemSet &rItemSet, + sal_Int32 nHeight, sal_Int32 nWidth, + long *pTwipHeight=0, long *pTwipWidth=0 ) +{ + if( nWidth > 0 && nHeight > 0 ) + { + nWidth = MM100_TO_TWIP( nWidth ); + if( nWidth < MINFLY ) + nWidth = MINFLY; + nHeight = MM100_TO_TWIP( nHeight ); + if( nHeight < MINFLY ) + nHeight = MINFLY; + rItemSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, nWidth, nHeight ) ); + } + + SwFmtAnchor aAnchor( FLY_AT_CHAR ); + rItemSet.Put( aAnchor ); + + if( pTwipWidth ) + *pTwipWidth = nWidth; + if( pTwipHeight ) + *pTwipHeight = nHeight; +} + +static void lcl_setObjectVisualArea( const uno::Reference< embed::XEmbeddedObject >& xObj, + sal_Int64 nAspect, + const Size& aVisSize, + const MapUnit& aUnit ) +{ + if( xObj.is() && nAspect != embed::Aspects::MSOLE_ICON ) + { + // convert the visual area to the objects units + MapUnit aObjUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) ); + Size aObjVisSize = OutputDevice::LogicToLogic( aVisSize, aUnit, aObjUnit ); + awt::Size aSz; + aSz.Width = aObjVisSize.Width(); + aSz.Height = aObjVisSize.Height(); + + try + { + xObj->setVisualAreaSize( nAspect, aSz ); + } + catch( uno::Exception& ) + { + OSL_ASSERT( "Couldn't set visual area of the object!\n" ); + } + } +} + +SwXMLTextImportHelper::SwXMLTextImportHelper( + const uno::Reference < XModel>& rModel, + SvXMLImport& rImport, + const uno::Reference<XPropertySet> & rInfoSet, + sal_Bool bInsertM, sal_Bool bStylesOnlyM, sal_Bool _bProgress, + sal_Bool bBlockM, sal_Bool bOrganizerM, + sal_Bool /*bPreserveRedlineMode*/ ) : + XMLTextImportHelper( rModel, rImport, bInsertM, bStylesOnlyM, _bProgress, + bBlockM, bOrganizerM ), + pRedlineHelper( NULL ) +{ + uno::Reference<XPropertySet> xDocPropSet( rModel, UNO_QUERY ); + pRedlineHelper = new XMLRedlineImportHelper( + bInsertM || bBlockM, xDocPropSet, rInfoSet ); +} + +SwXMLTextImportHelper::~SwXMLTextImportHelper() +{ + // #90463# the redline helper destructor sets properties on the document + // and may through an exception while doing so... catch this + try + { + delete pRedlineHelper; + } + catch ( const RuntimeException& ) + { + // ignore + } +} + +SvXMLImportContext *SwXMLTextImportHelper::CreateTableChildContext( + SvXMLImport& rImport, + sal_uInt16 nPrefix, const OUString& rLocalName, + const uno::Reference< XAttributeList > & xAttrList ) +{ + return new SwXMLTableContext( + (SwXMLImport&)rImport, nPrefix, rLocalName, xAttrList ); +} + +sal_Bool SwXMLTextImportHelper::IsInHeaderFooter() const +{ + uno::Reference<XUnoTunnel> xCrsrTunnel( + ((SwXMLTextImportHelper *)this)->GetCursor(), UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + SwDoc *pDoc = pTxtCrsr->GetDoc(); + + return pDoc && pDoc->IsInHeaderFooter( pTxtCrsr->GetPaM()->GetPoint()->nNode ); +} + +SwOLENode *lcl_GetOLENode( const SwFrmFmt *pFrmFmt ) +{ + SwOLENode *pOLENd = 0; + if( pFrmFmt ) + { + const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); + const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx(); + pOLENd = pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetOLENode(); + } + ASSERT( pOLENd, "Where is the OLE node" ); + return pOLENd; +} + +uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertOLEObject( + SvXMLImport& rImport, + const OUString& rHRef, + const OUString& rStyleName, + const OUString& rTblName, + sal_Int32 nWidth, sal_Int32 nHeight ) +{ + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + uno::Reference < XPropertySet > xPropSet; + + sal_Int32 nPos = rHRef.indexOf( ':' ); + if( -1 == nPos ) + return xPropSet; + + OUString aObjName( rHRef.copy( nPos+1) ); + + if( !aObjName.getLength() ) + return xPropSet; + + uno::Reference<XUnoTunnel> xCrsrTunnel( GetCursor(), UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + SwDoc *pDoc = SwImport::GetDocFromXMLImport( rImport ); + + SfxItemSet aItemSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, + RES_FRMATR_END ); + Size aTwipSize( 0, 0 ); + Rectangle aVisArea( 0, 0, nWidth, nHeight ); + lcl_putHeightAndWidth( aItemSet, nHeight, nWidth, + &aTwipSize.Height(), &aTwipSize.Width() ); + + SwFrmFmt *pFrmFmt = 0; + SwOLENode *pOLENd = 0; + if( rHRef.copy( 0, nPos ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.ServiceName") ) ) + { + sal_Bool bInsert = sal_False; + SvGlobalName aClassName; + const XMLServiceMapEntry_Impl *pEntry = aServiceMap; + while( pEntry->sFilterService ) + { + if( aObjName.equalsAsciiL( pEntry->sFilterService, + pEntry->nFilterServiceLen ) ) + { + aClassName = SvGlobalName( pEntry->n1, pEntry->n2, + pEntry->n3, pEntry->n4, + pEntry->n5, pEntry->n6, + pEntry->n7, pEntry->n8, + pEntry->n9, pEntry->n10, + pEntry->n11 ); + bInsert = sal_True; + break; + } + pEntry++; + } + + if( bInsert ) + { + uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage(); + try + { + // create object with desired ClassId + sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; + ::rtl::OUString aName = ::rtl::OUString::createFromAscii( "DummyName" ); + uno::Sequence < sal_Int8 > aClass( aClassName.GetByteSequence() ); + uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY ); + uno::Reference < embed::XEmbeddedObject > xObj = + uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitNew( + aClass, ::rtl::OUString(), xStorage, aName, + uno::Sequence < beans::PropertyValue >() ), uno::UNO_QUERY ); + if ( xObj.is() ) + { + //TODO/LATER: is it enough to only set the VisAreaSize? + lcl_setObjectVisualArea( xObj, nAspect, aTwipSize, MAP_TWIP ); + } + + pFrmFmt = pDoc->Insert( *pTxtCrsr->GetPaM(), + ::svt::EmbeddedObjectRef( xObj, embed::Aspects::MSOLE_CONTENT ), + &aItemSet, + NULL, + NULL ); + pOLENd = lcl_GetOLENode( pFrmFmt ); + if( pOLENd ) + aObjName = pOLENd->GetOLEObj().GetCurrentPersistName(); + } + catch ( uno::Exception& ) + { + } + } + } + else + { + // check whether an object with this name already exists in the document + String aName; + SwClientIter aIter( *(SwModify*)pDoc->GetDfltGrfFmtColl() ); + for( SwCntntNode* pNd = (SwCntntNode*)aIter.First( TYPE( SwCntntNode ) ); + pNd; pNd = (SwCntntNode*)aIter.Next() ) + { + SwOLENode* pExistingOLENd = pNd->GetOLENode(); + if( pExistingOLENd ) + { + ::rtl::OUString aExistingName = pExistingOLENd->GetOLEObj().GetCurrentPersistName(); + if ( aExistingName.equals( aObjName ) ) + { + OSL_ENSURE( sal_False, "The document contains duplicate object references, means it is partially broken, please let developers know how this document was generated!\n" ); + + ::rtl::OUString aTmpName = pDoc->GetPersist()->GetEmbeddedObjectContainer().CreateUniqueObjectName(); + try + { + pDoc->GetPersist()->GetStorage()->copyElementTo( aObjName, + pDoc->GetPersist()->GetStorage(), + aTmpName ); + aName = aTmpName; + } + catch ( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Couldn't create a copy of the object!\n" ); + } + + break; + } + } + } + + if ( !aName.Len() ) + aName = aObjName; + + // the correct aspect will be set later + // TODO/LATER: Actually it should be set here + if( pTxtCrsr ) + { + pFrmFmt = pDoc->InsertOLE( *pTxtCrsr->GetPaM(), aName, embed::Aspects::MSOLE_CONTENT, &aItemSet, NULL, NULL ); + pOLENd = lcl_GetOLENode( pFrmFmt ); + } + aObjName = aName; + } + + if( !pFrmFmt ) + return xPropSet; + + if( IsInsertMode() ) + { + if( !pOLENd ) + pOLENd = lcl_GetOLENode( pFrmFmt ); + if( pOLENd ) + pOLENd->SetOLESizeInvalid( sal_True ); + } + + SwXFrame *pXFrame = SwXFrames::GetObject( *pFrmFmt, FLYCNTTYPE_OLE ); + xPropSet = pXFrame; + if( pDoc->GetDrawModel() ) + SwXFrame::GetOrCreateSdrObject( + static_cast<SwFlyFrmFmt*>( pXFrame->GetFrmFmt() ) ); // req for z-order + if( rTblName.getLength() ) + { + const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); + const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx(); + SwOLENode *pOLENode = pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetOLENode(); + ASSERT( pOLENode, "Where is the OLE node" ); + + OUStringBuffer aBuffer( rTblName.getLength() ); + sal_Bool bQuoted = sal_False; + sal_Bool bEscape = sal_False; + sal_Bool bError = sal_False; + for( sal_Int32 i=0; i < rTblName.getLength(); i++ ) + { + sal_Bool bEndOfNameFound = sal_False; + sal_Unicode c = rTblName[i]; + switch( c ) + { + case '\'': + if( bEscape ) + { + aBuffer.append( c ); + bEscape = sal_False; + } + else if( bQuoted ) + { + bEndOfNameFound = sal_True; + } + else if( 0 == i ) + { + bQuoted = sal_True; + } + else + { + bError = sal_True; + } + break; + case '\\': + if( bEscape ) + { + aBuffer.append( c ); + bEscape = sal_False; + } + else + { + bEscape = sal_True; + } + break; + case ' ': + case '.': + if( !bQuoted ) + { + bEndOfNameFound = sal_True; + } + else + { + aBuffer.append( c ); + bEscape = sal_False; + } + break; + default: + { + aBuffer.append( c ); + bEscape = sal_False; + } + break; + } + if( bError || bEndOfNameFound ) + break; + } + if( !bError ) + { + OUString sTblName( aBuffer.makeStringAndClear() ); + pOLENode->SetChartTblName( GetRenameMap().Get( XML_TEXT_RENAME_TYPE_TABLE, sTblName ) ); + } + } + + sal_Int64 nDrawAspect = 0; + const XMLPropStyleContext *pStyle = 0; + sal_Bool bHasSizeProps = sal_False; + if( rStyleName.getLength() ) + { + pStyle = FindAutoFrameStyle( rStyleName ); + if( pStyle ) + { + UniReference < SvXMLImportPropertyMapper > xImpPrMap = + pStyle->GetStyles() + ->GetImportPropertyMapper(pStyle->GetFamily()); + ASSERT( xImpPrMap.is(), "Where is the import prop mapper?" ); + if( xImpPrMap.is() ) + { + UniReference<XMLPropertySetMapper> rPropMapper = + xImpPrMap->getPropertySetMapper(); + + sal_Int32 nCount = pStyle->GetProperties().size(); + for( sal_Int32 i=0; i < nCount; i++ ) + { + const XMLPropertyState& rProp = pStyle->GetProperties()[i]; + sal_Int32 nIdx = rProp.mnIndex; + if( -1 == nIdx ) + continue; + + switch( rPropMapper->GetEntryContextId(nIdx) ) + { + case CTF_OLE_VIS_AREA_LEFT: + { + sal_Int32 nVal = 0; + rProp.maValue >>= nVal; + aVisArea.setX( nVal ); + } + break; + case CTF_OLE_VIS_AREA_TOP: + { + sal_Int32 nVal = 0; + rProp.maValue >>= nVal; + aVisArea.setY( nVal ); + } + break; + case CTF_OLE_VIS_AREA_WIDTH: + { + sal_Int32 nVal = 0; + rProp.maValue >>= nVal; + aVisArea.setWidth( nVal ); + bHasSizeProps = sal_True; + } + break; + case CTF_OLE_VIS_AREA_HEIGHT: + { + sal_Int32 nVal = 0; + rProp.maValue >>= nVal; + aVisArea.setHeight( nVal ); + bHasSizeProps = sal_True; + } + break; + case CTF_OLE_DRAW_ASPECT: + { + rProp.maValue >>= nDrawAspect; + + if ( !nDrawAspect ) + nDrawAspect = embed::Aspects::MSOLE_CONTENT; + + if ( pOLENd ) + pOLENd->GetOLEObj().GetObject().SetViewAspect( nDrawAspect ); + } + break; + } + } + } + } + } + + if ( bHasSizeProps ) + { + uno::Reference < embed::XEmbeddedObject > xObj = + pDoc->GetPersist()->GetEmbeddedObjectContainer().GetEmbeddedObject( aObjName ); + if( xObj.is() ) + lcl_setObjectVisualArea( xObj, ( nDrawAspect ? nDrawAspect : embed::Aspects::MSOLE_CONTENT ), + aVisArea.GetSize(), MAP_100TH_MM ); + } + + return xPropSet; +} + +uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertOOoLink( + SvXMLImport& rImport, + const OUString& rHRef, + const OUString& /*rStyleName*/, + const OUString& /*rTblName*/, + sal_Int32 nWidth, sal_Int32 nHeight ) +{ + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + uno::Reference < XPropertySet > xPropSet; + + uno::Reference<XUnoTunnel> xCrsrTunnel( GetCursor(), UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + SwDoc *pDoc = SwImport::GetDocFromXMLImport( rImport ); + + SfxItemSet aItemSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, + RES_FRMATR_END ); + Size aTwipSize( 0, 0 ); + Rectangle aVisArea( 0, 0, nWidth, nHeight ); + lcl_putHeightAndWidth( aItemSet, nHeight, nWidth, + &aTwipSize.Height(), &aTwipSize.Width() ); + + // We'll need a (valid) URL. If we don't have do not insert the link and return early. + // Copy URL into URL oject on the way. + INetURLObject aURLObj; + bool bValidURL = rHRef.getLength() != 0 && + aURLObj.SetURL( URIHelper::SmartRel2Abs( + INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ) ); + if( !bValidURL ) + return xPropSet; + + uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage(); + try + { + // create object with desired ClassId + ::rtl::OUString aName = ::rtl::OUString::createFromAscii( "DummyName" ); + uno::Reference < embed::XLinkCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.OOoEmbeddedObjectFactory")) ), + uno::UNO_QUERY_THROW ); + + uno::Sequence< beans::PropertyValue > aMediaDescriptor( 1 ); + aMediaDescriptor[0].Name = ::rtl::OUString::createFromAscii( "URL" ); + aMediaDescriptor[0].Value <<= ::rtl::OUString( aURLObj.GetMainURL( INetURLObject::NO_DECODE ) ); + if ( pDoc && pDoc->GetDocShell() && pDoc->GetDocShell()->GetMedium() ) + { + uno::Reference< task::XInteractionHandler > xInteraction = + pDoc->GetDocShell()->GetMedium()->GetInteractionHandler(); + if ( xInteraction.is() ) + { + aMediaDescriptor.realloc( 2 ); + aMediaDescriptor[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InteractionHandler" ) ); + aMediaDescriptor[1].Value <<= xInteraction; + } + } + + uno::Reference < embed::XEmbeddedObject > xObj( + xFactory->createInstanceLink( + xStorage, aName, aMediaDescriptor, uno::Sequence< beans::PropertyValue >() ), + uno::UNO_QUERY_THROW ); + + { + SwFrmFmt *pFrmFmt = pDoc->Insert( *pTxtCrsr->GetPaM(), + ::svt::EmbeddedObjectRef( xObj, embed::Aspects::MSOLE_CONTENT ), + &aItemSet, + NULL, + NULL ); + + // TODO/LATER: in future may need a way to set replacement image url to the link ( may be even to the object ), needs oasis cws??? + + SwXFrame *pXFrame = SwXFrames::GetObject( *pFrmFmt, FLYCNTTYPE_OLE ); + xPropSet = pXFrame; + if( pDoc->GetDrawModel() ) + SwXFrame::GetOrCreateSdrObject( + static_cast<SwFlyFrmFmt*>( pXFrame->GetFrmFmt() ) ); // req for z-order + } + } + catch ( uno::Exception& ) + { + } + + // TODO/LATER: should the rStyleName and rTblName be handled as for usual embedded object? + + return xPropSet; +} + +uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertApplet( + const OUString &rName, + const OUString &rCode, + sal_Bool bMayScript, + const OUString& rHRef, + sal_Int32 nWidth, sal_Int32 nHeight ) +{ + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + uno::Reference < XPropertySet > xPropSet; + uno::Reference<XUnoTunnel> xCrsrTunnel( GetCursor(), UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + SwDoc *pDoc = pTxtCrsr->GetDoc(); + + SfxItemSet aItemSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, + RES_FRMATR_END ); + lcl_putHeightAndWidth( aItemSet, nHeight, nWidth); + + SwApplet_Impl aAppletImpl ( aItemSet ); + + String sCodeBase; + if( rHRef.getLength() ) + sCodeBase = GetXMLImport().GetAbsoluteReference( rHRef ); + + aAppletImpl.CreateApplet ( rCode, rName, bMayScript, sCodeBase, GetXMLImport().GetDocumentBase() ); + + // set the size of the applet + lcl_setObjectVisualArea( aAppletImpl.GetApplet(), + embed::Aspects::MSOLE_CONTENT, + Size( nWidth, nHeight ), + MAP_100TH_MM ); + + SwFrmFmt *pFrmFmt = pDoc->Insert( *pTxtCrsr->GetPaM(), + ::svt::EmbeddedObjectRef( aAppletImpl.GetApplet(), embed::Aspects::MSOLE_CONTENT ), + &aAppletImpl.GetItemSet(), + NULL, + NULL); + SwXFrame *pXFrame = SwXFrames::GetObject( *pFrmFmt, FLYCNTTYPE_OLE ); + xPropSet = pXFrame; + if( pDoc->GetDrawModel() ) + SwXFrame::GetOrCreateSdrObject( + static_cast<SwFlyFrmFmt*>( pXFrame->GetFrmFmt() ) ); // req for z-order + + return xPropSet; +} + +uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertPlugin( + const OUString &rMimeType, + const OUString& rHRef, + sal_Int32 nWidth, sal_Int32 nHeight ) +{ + uno::Reference < XPropertySet > xPropSet; + uno::Reference<XUnoTunnel> xCrsrTunnel( GetCursor(), UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + SwDoc *pDoc = pTxtCrsr->GetDoc(); + + SfxItemSet aItemSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, + RES_FRMATR_END ); + lcl_putHeightAndWidth( aItemSet, nHeight, nWidth); + + // We'll need a (valid) URL, or we need a MIME type. If we don't have + // either, do not insert plugin and return early. Copy URL into URL oject + // on the way. + INetURLObject aURLObj; + + bool bValidURL = rHRef.getLength() != 0 && + aURLObj.SetURL( URIHelper::SmartRel2Abs( INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ) ); + bool bValidMimeType = rMimeType.getLength() != 0; + if( !bValidURL && !bValidMimeType ) + return xPropSet; + + uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage(); + try + { + // create object with desired ClassId + ::rtl::OUString aName = ::rtl::OUString::createFromAscii( "DummyName" ); + uno::Sequence < sal_Int8 > aClass( SvGlobalName( SO3_PLUGIN_CLASSID ).GetByteSequence() ); + uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY ); + uno::Reference < embed::XEmbeddedObject > xObj = + uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitNew( + aClass, ::rtl::OUString(), xStorage, aName, + uno::Sequence < beans::PropertyValue >() ), uno::UNO_QUERY ); + + // set size to the object + lcl_setObjectVisualArea( xObj, + embed::Aspects::MSOLE_CONTENT, + Size( nWidth, nHeight ), + MAP_100TH_MM ); + + if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) ) + { + uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); + if ( xSet.is() ) + { + if( bValidURL ) + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("PluginURL"), + makeAny( ::rtl::OUString( aURLObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) ); + if( bValidMimeType ) + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("PluginMimeType"), + makeAny( ::rtl::OUString( rMimeType ) ) ); + } + + SwFrmFmt *pFrmFmt = pDoc->Insert( *pTxtCrsr->GetPaM(), + ::svt::EmbeddedObjectRef( xObj, embed::Aspects::MSOLE_CONTENT ), + &aItemSet, + NULL, + NULL); + SwXFrame *pXFrame = SwXFrames::GetObject( *pFrmFmt, FLYCNTTYPE_OLE ); + xPropSet = pXFrame; + if( pDoc->GetDrawModel() ) + SwXFrame::GetOrCreateSdrObject( + static_cast<SwFlyFrmFmt*>( pXFrame->GetFrmFmt() ) ); // req for z-order + } + } + catch ( uno::Exception& ) + { + } + + return xPropSet; +} +uno::Reference< XPropertySet > SwXMLTextImportHelper::createAndInsertFloatingFrame( + const OUString& rName, + const OUString& rHRef, + const OUString& rStyleName, + sal_Int32 nWidth, sal_Int32 nHeight ) +{ + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + uno::Reference < XPropertySet > xPropSet; + uno::Reference<XUnoTunnel> xCrsrTunnel( GetCursor(), UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" ); + OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ))); + ASSERT( pTxtCrsr, "SwXTextCursor missing" ); + SwDoc *pDoc = pTxtCrsr->GetDoc(); + + SfxItemSet aItemSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, + RES_FRMATR_END ); + lcl_putHeightAndWidth( aItemSet, nHeight, nWidth); + + ScrollingMode eScrollMode = ScrollingAuto; + sal_Bool bHasBorder = sal_False; + sal_Bool bIsBorderSet = sal_False; + Size aMargin( SIZE_NOT_SET, SIZE_NOT_SET ); + const XMLPropStyleContext *pStyle = 0; + if( rStyleName.getLength() ) + { + pStyle = FindAutoFrameStyle( rStyleName ); + if( pStyle ) + { + UniReference < SvXMLImportPropertyMapper > xImpPrMap = + pStyle->GetStyles() + ->GetImportPropertyMapper(pStyle->GetFamily()); + ASSERT( xImpPrMap.is(), "Where is the import prop mapper?" ); + if( xImpPrMap.is() ) + { + UniReference<XMLPropertySetMapper> rPropMapper = + xImpPrMap->getPropertySetMapper(); + + sal_Int32 nCount = pStyle->GetProperties().size(); + for( sal_Int32 i=0; i < nCount; i++ ) + { + const XMLPropertyState& rProp = pStyle->GetProperties()[i]; + sal_Int32 nIdx = rProp.mnIndex; + if( -1 == nIdx ) + continue; + + switch( rPropMapper->GetEntryContextId(nIdx) ) + { + case CTF_FRAME_DISPLAY_SCROLLBAR: + { + sal_Bool bYes = *(sal_Bool *)rProp.maValue.getValue(); + eScrollMode = bYes ? ScrollingYes : ScrollingNo; + } + break; + case CTF_FRAME_DISPLAY_BORDER: + { + bHasBorder = *(sal_Bool *)rProp.maValue.getValue(); + bIsBorderSet = sal_True; + } + break; + case CTF_FRAME_MARGIN_HORI: + { + sal_Int32 nVal = SIZE_NOT_SET; + rProp.maValue >>= nVal; + aMargin.Width() = nVal; + } + break; + case CTF_FRAME_MARGIN_VERT: + { + sal_Int32 nVal = SIZE_NOT_SET; + rProp.maValue >>= nVal; + aMargin.Height() = nVal; + } + break; + } + } + } + } + } + + uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage(); + try + { + // create object with desired ClassId + ::rtl::OUString aName = ::rtl::OUString::createFromAscii( "DummyName" ); + uno::Sequence < sal_Int8 > aClass( SvGlobalName( SO3_IFRAME_CLASSID ).GetByteSequence() ); + uno::Reference < embed::XEmbedObjectCreator > xFactory( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.EmbeddedObjectCreator")) ), uno::UNO_QUERY ); + uno::Reference < embed::XEmbeddedObject > xObj = + uno::Reference < embed::XEmbeddedObject >( xFactory->createInstanceInitNew( + aClass, ::rtl::OUString(), xStorage, aName, + uno::Sequence < beans::PropertyValue >() ), uno::UNO_QUERY ); + + // set size to the object + lcl_setObjectVisualArea( xObj, + embed::Aspects::MSOLE_CONTENT, + Size( nWidth, nHeight ), + MAP_100TH_MM ); + + if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) ) + { + uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); + if ( xSet.is() ) + { + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("FrameURL"), + makeAny( ::rtl::OUString( URIHelper::SmartRel2Abs( + INetURLObject( GetXMLImport().GetBaseURL() ), rHRef ) ) ) ); + + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("FrameName"), + makeAny( ::rtl::OUString( rName ) ) ); + + if ( eScrollMode == ScrollingAuto ) + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("FrameIsAutoScroll"), + makeAny( sal_True ) ); + else + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("FrameIsScrollingMode"), + makeAny( (sal_Bool) (eScrollMode == ScrollingYes) ) ); + + if ( bIsBorderSet ) + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("FrameIsBorder"), + makeAny( bHasBorder ) ); + else + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("FrameIsAutoBorder"), + makeAny( sal_True ) ); + + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("FrameMarginWidth"), + makeAny( sal_Int32( aMargin.Width() ) ) ); + + xSet->setPropertyValue( ::rtl::OUString::createFromAscii("FrameMarginHeight"), + makeAny( sal_Int32( aMargin.Height() ) ) ); + } + + SwFrmFmt *pFrmFmt = pDoc->Insert( *pTxtCrsr->GetPaM(), + ::svt::EmbeddedObjectRef( xObj, embed::Aspects::MSOLE_CONTENT ), + &aItemSet, + NULL, + NULL); + SwXFrame *pXFrame = SwXFrames::GetObject( *pFrmFmt, FLYCNTTYPE_OLE ); + xPropSet = pXFrame; + if( pDoc->GetDrawModel() ) + SwXFrame::GetOrCreateSdrObject( + static_cast<SwFlyFrmFmt*>( pXFrame->GetFrmFmt() ) ); // req for z-order + } + } + catch ( uno::Exception& ) + { + } + + return xPropSet; +} + +void SwXMLTextImportHelper::endAppletOrPlugin( + const uno::Reference < XPropertySet > &rPropSet, + ::std::map < const ::rtl::OUString, ::rtl::OUString, ::comphelper::UStringLess > &rParamMap) +{ + // this method will modify the document directly -> lock SolarMutex + vos::OGuard aGuard(Application::GetSolarMutex()); + + uno::Reference<XUnoTunnel> xCrsrTunnel( rPropSet, UNO_QUERY ); + ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for embedded" ); + SwXFrame *pFrame = reinterpret_cast< SwXFrame * >( + sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( SwXFrame::getUnoTunnelId() ))); + ASSERT( pFrame, "SwXFrame missing" ); + SwFrmFmt *pFrmFmt = pFrame->GetFrmFmt(); + const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); + const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx(); + SwOLENode *pOLENd = pNdIdx->GetNodes()[pNdIdx->GetIndex() + 1]->GetNoTxtNode()->GetOLENode(); + SwOLEObj& rOLEObj = pOLENd->GetOLEObj(); + + uno::Reference < embed::XEmbeddedObject > xEmbObj( rOLEObj.GetOleRef() ); + if ( svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) ) + { + uno::Reference < beans::XPropertySet > xSet( xEmbObj->getComponent(), uno::UNO_QUERY ); + if ( xSet.is() ) + { + const sal_Int32 nCount = rParamMap.size(); + uno::Sequence< beans::PropertyValue > aCommandSequence( nCount ); + + ::std::map < const ::rtl::OUString, ::rtl::OUString, ::comphelper::UStringLess > ::iterator aIter = rParamMap.begin(); + ::std::map < const ::rtl::OUString, ::rtl::OUString, ::comphelper::UStringLess > ::iterator aEnd = rParamMap.end(); + sal_Int32 nIndex=0; + while (aIter != aEnd ) + { + aCommandSequence[nIndex].Name = (*aIter).first; + aCommandSequence[nIndex].Handle = -1; + aCommandSequence[nIndex].Value = makeAny( OUString((*aIter).second) ); + aCommandSequence[nIndex].State = beans::PropertyState_DIRECT_VALUE; + aIter++, nIndex++; + } + + // unfortunately the names of the properties are depending on the object + ::rtl::OUString aParaName = ::rtl::OUString::createFromAscii("AppletCommands"); + try + { + xSet->setPropertyValue( aParaName, makeAny( aCommandSequence ) ); + } + catch ( uno::Exception& ) + { + aParaName = ::rtl::OUString::createFromAscii("PluginCommands"); + try + { + xSet->setPropertyValue( aParaName, makeAny( aCommandSequence ) ); + } + catch ( uno::Exception& ) + { + } + } + } + } +} + +XMLTextImportHelper* SwXMLImport::CreateTextImport() +{ + return new SwXMLTextImportHelper( GetModel(), *this, getImportInfo(), + IsInsertMode(), + IsStylesOnlyMode(), bShowProgress, + IsBlockMode(), IsOrganizerMode(), + bPreserveRedlineMode ); +} + + +// redlining helper methods +// (override to provide the real implementation) + +void SwXMLTextImportHelper::RedlineAdd( + const OUString& rType, + const OUString& rId, + const OUString& rAuthor, + const OUString& rComment, + const util::DateTime& rDateTime, + sal_Bool bMergeLastPara) +{ + // create redline helper on demand + DBG_ASSERT(NULL != pRedlineHelper, "helper should have been created in constructor"); + if (NULL != pRedlineHelper) + pRedlineHelper->Add(rType, rId, rAuthor, rComment, rDateTime, + bMergeLastPara); +} + +uno::Reference<XTextCursor> SwXMLTextImportHelper::RedlineCreateText( + uno::Reference<XTextCursor> & rOldCursor, + const OUString& rId) +{ + uno::Reference<XTextCursor> xRet; + + if (NULL != pRedlineHelper) + { + xRet = pRedlineHelper->CreateRedlineTextSection(rOldCursor, rId); + } + + return xRet; +} + +void SwXMLTextImportHelper::RedlineSetCursor( + const OUString& rId, + sal_Bool bStart, + sal_Bool bIsOutsideOfParagraph) +{ + if (NULL != pRedlineHelper) { + uno::Reference<XTextRange> xTextRange( GetCursor()->getStart() ); + pRedlineHelper->SetCursor(rId, bStart, xTextRange, + bIsOutsideOfParagraph); + } + // else: ignore redline (wasn't added before, else we'd have a helper) +} + +void SwXMLTextImportHelper::RedlineAdjustStartNodeCursor( + sal_Bool bStart) +{ + OUString rId = GetOpenRedlineId(); + if ((NULL != pRedlineHelper) && (rId.getLength() > 0)) + { + uno::Reference<XTextRange> xTextRange( GetCursor()->getStart() ); + pRedlineHelper->AdjustStartNodeCursor(rId, bStart, xTextRange ); + ResetOpenRedlineId(); + } + // else: ignore redline (wasn't added before, or no open redline ID +} + +void SwXMLTextImportHelper::SetShowChanges( sal_Bool bShowChanges ) +{ + if ( NULL != pRedlineHelper ) + pRedlineHelper->SetShowChanges( bShowChanges ); +} + +void SwXMLTextImportHelper::SetRecordChanges( sal_Bool bRecordChanges ) +{ + if ( NULL != pRedlineHelper ) + pRedlineHelper->SetRecordChanges( bRecordChanges ); +} + +void SwXMLTextImportHelper::SetChangesProtectionKey( + const Sequence<sal_Int8> & rKey ) +{ + if ( NULL != pRedlineHelper ) + pRedlineHelper->SetProtectionKey( rKey ); +} + + + diff --git a/sw/source/filter/xml/xmltexti.hxx b/sw/source/filter/xml/xmltexti.hxx new file mode 100644 index 000000000000..bdd68b082eb5 --- /dev/null +++ b/sw/source/filter/xml/xmltexti.hxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _XMLTEXTI_HXX +#define _XMLTEXTI_HXX + +#ifndef _XMLOFF_TXTIMP_HXX +#include <xmloff/txtimp.hxx> +#endif +#include <xmloff/functional.hxx> + +class XMLRedlineImportHelper; +class SvXMLImport; + +class SwXMLTextImportHelper : public XMLTextImportHelper +{ + XMLRedlineImportHelper *pRedlineHelper; + +protected: + virtual SvXMLImportContext *CreateTableChildContext( + SvXMLImport& rImport, + sal_uInt16 nPrefix, const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList ); + +public: + SwXMLTextImportHelper( + const ::com::sun::star::uno::Reference < + ::com::sun::star::frame::XModel>& rModel, + SvXMLImport& rImport, + const ::com::sun::star::uno::Reference < + ::com::sun::star::beans::XPropertySet>& rInfoSet, + sal_Bool bInsertM, sal_Bool bStylesOnlyM, sal_Bool bProgress, + sal_Bool bBlockM, sal_Bool bOrganizerM, + sal_Bool bPreserveRedlineMode ); + ~SwXMLTextImportHelper(); + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> + createAndInsertOLEObject( SvXMLImport& rImport, + const ::rtl::OUString& rHRef, + const ::rtl::OUString& rStyleName, + const ::rtl::OUString& rTblName, + sal_Int32 nWidth, sal_Int32 nHeight ); + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> + createAndInsertOOoLink( SvXMLImport& rImport, + const ::rtl::OUString& rHRef, + const ::rtl::OUString& rStyleName, + const ::rtl::OUString& rTblName, + sal_Int32 nWidth, sal_Int32 nHeight ); + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> + createAndInsertApplet( + const ::rtl::OUString &rName, + const ::rtl::OUString &rCode, + sal_Bool bMayScript, + const ::rtl::OUString& rHRef, + sal_Int32 nWidth, sal_Int32 nHeight ); + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> + createAndInsertPlugin( + const ::rtl::OUString &rMimeType, + const ::rtl::OUString& rHRef, + sal_Int32 nWidth, sal_Int32 nHeight ); + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet> + createAndInsertFloatingFrame( + const ::rtl::OUString &rName, + const ::rtl::OUString &rHRef, + const ::rtl::OUString &rStyleName, + sal_Int32 nWidth, sal_Int32 nHeight ); + + virtual void endAppletOrPlugin( + const ::com::sun::star::uno::Reference < ::com::sun::star::beans::XPropertySet > &rPropSet, + ::std::map < const ::rtl::OUString, ::rtl::OUString, ::comphelper::UStringLess> &rParamMap); + + virtual sal_Bool IsInHeaderFooter() const; + + // redlining helper methods + // (here is the real implementation) + virtual void RedlineAdd( + const ::rtl::OUString& rType, /// redline type (insert, del,... ) + const ::rtl::OUString& rId, /// use to identify this redline + const ::rtl::OUString& rAuthor, /// name of the author + const ::rtl::OUString& rComment, /// redline comment + const ::com::sun::star::util::DateTime& rDateTime, /// date+time + sal_Bool bMergeLastPara); /// merge last paragraph + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextCursor> RedlineCreateText( + ::com::sun::star::uno::Reference< /// needed to get the document + ::com::sun::star::text::XTextCursor> & rOldCursor, + const ::rtl::OUString& rId); /// ID used to RedlineAdd() call + virtual void RedlineSetCursor( + const ::rtl::OUString& rId, /// ID used to RedlineAdd() call + sal_Bool bStart, /// start or end Cursor + sal_Bool bIsOutsideOfParagraph); + virtual void RedlineAdjustStartNodeCursor( + sal_Bool bStart); + virtual void SetShowChanges( sal_Bool bShowChanges ); + virtual void SetRecordChanges( sal_Bool bRecordChanges ); + virtual void SetChangesProtectionKey( + const ::com::sun::star::uno::Sequence<sal_Int8> & rKey ); +}; + +#endif // _XMLTEXTI_HXX + |