summaryrefslogtreecommitdiff
path: root/sw/source/filter/writer
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/writer')
-rw-r--r--sw/source/filter/writer/makefile.mk54
-rw-r--r--sw/source/filter/writer/writer.cxx629
-rw-r--r--sw/source/filter/writer/wrt_fn.cxx132
-rw-r--r--sw/source/filter/writer/wrtswtbl.cxx926
4 files changed, 1741 insertions, 0 deletions
diff --git a/sw/source/filter/writer/makefile.mk b/sw/source/filter/writer/makefile.mk
new file mode 100644
index 000000000000..d08caa9eb441
--- /dev/null
+++ b/sw/source/filter/writer/makefile.mk
@@ -0,0 +1,54 @@
+#*************************************************************************
+#
+# 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=writer
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : $(PRJ)$/inc$/swpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/inc$/sw.mk
+
+# --- Files --------------------------------------------------------
+
+CXXFILES = \
+ writer.cxx \
+ wrt_fn.cxx \
+ wrtswtbl.cxx
+
+SLOFILES = \
+ $(SLO)$/writer.obj \
+ $(SLO)$/wrt_fn.obj \
+ $(SLO)$/wrtswtbl.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sw/source/filter/writer/writer.cxx b/sw/source/filter/writer/writer.cxx
new file mode 100644
index 000000000000..a2cce0c8e7da
--- /dev/null
+++ b/sw/source/filter/writer/writer.cxx
@@ -0,0 +1,629 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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>
+
+#define _SVSTDARR_STRINGSSORTDTOR
+#include <svl/svstdarr.hxx>
+
+#include <sot/storage.hxx>
+#include <sfx2/docfile.hxx>
+#include <svl/urihelper.hxx>
+#include <svtools/filter.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/eeitem.hxx>
+#include <shellio.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <IMark.hxx>
+#include <numrule.hxx>
+#include <swerror.h>
+#include <boost/bind.hpp>
+
+using namespace ::com::sun::star;
+
+
+// Stringbuffer fuer die umgewandelten Zahlen
+static sal_Char aNToABuf[] = "0000000000000000000000000";
+#define NTOABUFLEN (sizeof(aNToABuf))
+
+DECLARE_TABLE( SwBookmarkNodeTable, SvPtrarr* )
+
+struct Writer_Impl
+{
+ SvStream * m_pStream;
+
+ SvStringsSortDtor *pSrcArr, *pDestArr;
+ SvPtrarr* pFontRemoveLst, *pBkmkArr;
+ SwBookmarkNodeTable* pBkmkNodePos;
+
+ Writer_Impl();
+ ~Writer_Impl();
+
+ void RemoveFontList( SwDoc& rDoc );
+ void InsertBkmk( const ::sw::mark::IMark& rBkmk );
+};
+
+Writer_Impl::Writer_Impl()
+ : m_pStream(0)
+ , pSrcArr( 0 ), pDestArr( 0 ), pFontRemoveLst( 0 ), pBkmkNodePos( 0 )
+{
+}
+
+Writer_Impl::~Writer_Impl()
+{
+ delete pSrcArr;
+ delete pDestArr;
+ delete pFontRemoveLst;
+
+ if( pBkmkNodePos )
+ {
+ for( SvPtrarr* p = pBkmkNodePos->First(); p; p = pBkmkNodePos->Next() )
+ delete p;
+ delete pBkmkNodePos;
+ }
+}
+
+void Writer_Impl::RemoveFontList( SwDoc& rDoc )
+{
+ OSL_ENSURE( pFontRemoveLst, "wo ist die FontListe?" );
+ for( USHORT i = pFontRemoveLst->Count(); i; )
+ {
+ SvxFontItem* pItem = (SvxFontItem*)(*pFontRemoveLst)[ --i ];
+ rDoc.GetAttrPool().Remove( *pItem );
+ }
+}
+
+void Writer_Impl::InsertBkmk(const ::sw::mark::IMark& rBkmk)
+{
+ if( !pBkmkNodePos )
+ pBkmkNodePos = new SwBookmarkNodeTable;
+
+ ULONG nNd = rBkmk.GetMarkPos().nNode.GetIndex();
+ SvPtrarr* pArr = pBkmkNodePos->Get( nNd );
+ if( !pArr )
+ {
+ pArr = new SvPtrarr( 1, 4 );
+ pBkmkNodePos->Insert( nNd, pArr );
+ }
+
+ void* p = (void*)&rBkmk;
+ pArr->Insert( p, pArr->Count() );
+
+ if(rBkmk.IsExpanded() && rBkmk.GetOtherMarkPos().nNode != nNd)
+ {
+ nNd = rBkmk.GetOtherMarkPos().nNode.GetIndex();
+ pArr = pBkmkNodePos->Get( nNd );
+ if( !pArr )
+ {
+ pArr = new SvPtrarr( 1, 4 );
+ pBkmkNodePos->Insert( nNd, pArr );
+ }
+ pArr->Insert( p, pArr->Count() );
+ }
+}
+
+/*
+ * Dieses Modul ist die Zentrale-Sammelstelle fuer alle Write-Filter
+ * und ist eine DLL !
+ *
+ * Damit der Writer mit den unterschiedlichen Writern arbeiten kann,
+ * muessen fuer diese die Ausgabe-Funktionen der Inhalts tragenden
+ * Objecte auf die verschiedenen Ausgabe-Funktionen gemappt werden.
+ *
+ * Dazu kann fuer jedes Object ueber den Which-Wert in einen Tabelle ge-
+ * griffen werden, um seine Ausgabe-Funktion zu erfragen.
+ * Diese Funktionen stehen in den entsprechenden Writer-DLL's.
+ */
+
+Writer::Writer()
+ : m_pImpl(new Writer_Impl)
+ , pOrigPam(0), pOrigFileName(0), pDoc(0), pCurPam(0)
+{
+ bWriteAll = bShowProgress = bUCS2_WithStartChar = true;
+ bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR =
+ bWriteClipboardDoc = bWriteOnlyFirstTable = bBlock =
+ bOrganizerMode = false;
+ bExportPargraphNumbering = sal_True;
+}
+
+Writer::~Writer()
+{
+}
+
+/*
+ * Document Interface Access
+ */
+IDocumentSettingAccess* Writer::getIDocumentSettingAccess() { return pDoc; }
+const IDocumentSettingAccess* Writer::getIDocumentSettingAccess() const { return pDoc; }
+IDocumentStylePoolAccess* Writer::getIDocumentStylePoolAccess() { return pDoc; }
+const IDocumentStylePoolAccess* Writer::getIDocumentStylePoolAccess() const { return pDoc; }
+
+void Writer::ResetWriter()
+{
+ if (m_pImpl->pFontRemoveLst)
+ {
+ m_pImpl->RemoveFontList( *pDoc );
+ }
+ m_pImpl.reset(new Writer_Impl);
+
+ if( pCurPam )
+ {
+ while( pCurPam->GetNext() != pCurPam )
+ delete pCurPam->GetNext();
+ delete pCurPam;
+ }
+ pCurPam = 0;
+ pOrigFileName = 0;
+ pDoc = 0;
+
+ bShowProgress = bUCS2_WithStartChar = TRUE;
+ bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR =
+ bWriteClipboardDoc = bWriteOnlyFirstTable = bBlock =
+ bOrganizerMode = FALSE;
+}
+
+BOOL Writer::CopyNextPam( SwPaM ** ppPam )
+{
+ if( (*ppPam)->GetNext() == pOrigPam )
+ {
+ *ppPam = pOrigPam; // wieder auf den Anfangs-Pam setzen
+ return FALSE; // Ende vom Ring
+ }
+
+ // ansonsten kopiere den die Werte aus dem naechsten Pam
+ *ppPam = ((SwPaM*)(*ppPam)->GetNext() );
+
+ *pCurPam->GetPoint() = *(*ppPam)->Start();
+ *pCurPam->GetMark() = *(*ppPam)->End();
+
+ return TRUE;
+}
+
+// suche die naechste Bookmark-Position aus der Bookmark-Tabelle
+
+sal_Int32 Writer::FindPos_Bkmk(const SwPosition& rPos) const
+{
+ const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ const IDocumentMarkAccess::const_iterator_t ppBkmk = ::std::lower_bound(
+ pMarkAccess->getMarksBegin(),
+ pMarkAccess->getMarksEnd(),
+ rPos,
+ ::boost::bind(&::sw::mark::IMark::StartsBefore, _1, _2)); // find the first Mark that does not start before
+ if(ppBkmk != pMarkAccess->getMarksEnd())
+ return ppBkmk - pMarkAccess->getMarksBegin();
+ return -1;
+}
+
+
+SwPaM* Writer::NewSwPaM( SwDoc & rDoc, ULONG nStartIdx, ULONG nEndIdx,
+ BOOL bNodesArray )
+{
+ SwNodes* pNds = bNodesArray ? &rDoc.GetNodes() : (SwNodes*)rDoc.GetUndoNds();
+
+ SwNodeIndex aStt( *pNds, nStartIdx );
+ SwCntntNode* pCNode = aStt.GetNode().GetCntntNode();
+ if( !pCNode && 0 == ( pCNode = pNds->GoNext( &aStt )) )
+ {
+ OSL_ENSURE( false, "An StartPos kein ContentNode mehr" );
+ }
+
+ SwPaM* pNew = new SwPaM( aStt );
+ pNew->SetMark();
+ aStt = nEndIdx;
+ if( 0 == (pCNode = aStt.GetNode().GetCntntNode()) &&
+ 0 == (pCNode = pNds->GoPrevious( &aStt )) )
+ {
+ OSL_ENSURE( false, "An StartPos kein ContentNode mehr" );
+ }
+ pCNode->MakeEndIndex( &pNew->GetPoint()->nContent );
+ pNew->GetPoint()->nNode = aStt;
+ return pNew;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// Stream-spezifisches
+SvStream& Writer::Strm()
+{
+ OSL_ENSURE( m_pImpl->m_pStream, "Oh-oh. Writer with no Stream!" );
+ return *m_pImpl->m_pStream;
+}
+
+void Writer::SetStream(SvStream *const pStream)
+{ m_pImpl->m_pStream = pStream; }
+
+
+SvStream& Writer::OutHex( SvStream& rStrm, ULONG nHex, BYTE nLen )
+{ // in einen Stream aus
+ // Pointer an das Bufferende setzen
+ sal_Char* pStr = aNToABuf + (NTOABUFLEN-1);
+ for( BYTE n = 0; n < nLen; ++n )
+ {
+ *(--pStr) = (sal_Char)(nHex & 0xf ) + 48;
+ if( *pStr > '9' )
+ *pStr += 39;
+ nHex >>= 4;
+ }
+ return rStrm << pStr;
+}
+
+SvStream& Writer::OutLong( SvStream& rStrm, long nVal )
+{
+ // Pointer an das Bufferende setzen
+ sal_Char* pStr = aNToABuf + (NTOABUFLEN-1);
+
+ int bNeg = nVal < 0;
+ if( bNeg )
+ nVal = -nVal;
+
+ do {
+ *(--pStr) = (sal_Char)(nVal % 10 ) + 48;
+ nVal /= 10;
+ } while( nVal );
+
+ // Ist Zahl negativ, dann noch -
+ if( bNeg )
+ *(--pStr) = '-';
+
+ return rStrm << pStr;
+}
+
+SvStream& Writer::OutULong( SvStream& rStrm, ULONG nVal )
+{
+ // Pointer an das Bufferende setzen
+ sal_Char* pStr = aNToABuf + (NTOABUFLEN-1);
+
+ do {
+ *(--pStr) = (sal_Char)(nVal % 10 ) + 48;
+ nVal /= 10;
+ } while ( nVal );
+ return rStrm << pStr;
+}
+
+
+ULONG Writer::Write( SwPaM& rPaM, SvStream& rStrm, const String* pFName )
+{
+ if ( IsStgWriter() )
+ {
+ SotStorageRef aRef = new SotStorage( rStrm );
+ ULONG nResult = Write( rPaM, *aRef, pFName );
+ if ( nResult == ERRCODE_NONE )
+ aRef->Commit();
+ return nResult;
+ }
+
+ pDoc = rPaM.GetDoc();
+ pOrigFileName = pFName;
+ m_pImpl->m_pStream = &rStrm;
+
+ // PaM kopieren, damit er veraendert werden kann
+ pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
+ // zum Vergleich auf den akt. Pam sichern
+ pOrigPam = &rPaM;
+
+ ULONG nRet = WriteStream();
+
+ ResetWriter();
+
+ return nRet;
+}
+
+ULONG Writer::Write( SwPaM& rPam, SfxMedium& rMed, const String* pFileName )
+{
+ // This method must be overloaded in SwXMLWriter a storage from medium will be used there.
+ // The microsoft format can write to storage but the storage will be based on the stream.
+ return Write( rPam, *rMed.GetOutStream(), pFileName );
+}
+
+ULONG Writer::Write( SwPaM& /*rPam*/, SvStorage&, const String* )
+{
+ OSL_ENSURE( !this, "Schreiben in Storages auf einem Stream?" );
+ return ERR_SWG_WRITE_ERROR;
+}
+
+ULONG Writer::Write( SwPaM&, const uno::Reference < embed::XStorage >&, const String*, SfxMedium* )
+{
+ OSL_ENSURE( !this, "Schreiben in Storages auf einem Stream?" );
+ return ERR_SWG_WRITE_ERROR;
+}
+
+BOOL Writer::CopyLocalFileToINet( String& rFileNm )
+{
+ if( !pOrigFileName ) // can be happen, by example if we
+ return FALSE; // write into the clipboard
+
+ BOOL bRet = FALSE;
+ INetURLObject aFileUrl( rFileNm ), aTargetUrl( *pOrigFileName );
+
+// JP 01.11.00: what is the correct question for the portal??
+// if( aFileUrl.GetProtocol() == aFileUrl.GetProtocol() )
+// return bRet;
+// this is our old without the Mail-Export
+ if( ! ( INET_PROT_FILE == aFileUrl.GetProtocol() &&
+ INET_PROT_FILE != aTargetUrl.GetProtocol() &&
+ INET_PROT_FTP <= aTargetUrl.GetProtocol() &&
+ INET_PROT_NEWS >= aTargetUrl.GetProtocol() ) )
+ return bRet;
+
+ if (m_pImpl->pSrcArr)
+ {
+ // wurde die Datei schon verschoben
+ USHORT nPos;
+ if (m_pImpl->pSrcArr->Seek_Entry( &rFileNm, &nPos ))
+ {
+ rFileNm = *(*m_pImpl->pDestArr)[ nPos ];
+ return TRUE;
+ }
+ }
+ else
+ {
+ m_pImpl->pSrcArr = new SvStringsSortDtor( 4, 4 );
+ m_pImpl->pDestArr = new SvStringsSortDtor( 4, 4 );
+ }
+
+ String *pSrc = new String( rFileNm );
+ String *pDest = new String( aTargetUrl.GetPartBeforeLastName() );
+ *pDest += String(aFileUrl.GetName());
+
+ SfxMedium aSrcFile( *pSrc, STREAM_READ, FALSE );
+ SfxMedium aDstFile( *pDest, STREAM_WRITE | STREAM_SHARE_DENYNONE, FALSE );
+
+ *aDstFile.GetOutStream() << *aSrcFile.GetInStream();
+
+ aSrcFile.Close();
+ aDstFile.Commit();
+
+ bRet = 0 == aDstFile.GetError();
+
+ if( bRet )
+ {
+ m_pImpl->pSrcArr->Insert( pSrc );
+ m_pImpl->pDestArr->Insert( pDest );
+ rFileNm = *pDest;
+ }
+ else
+ {
+ delete pSrc;
+ delete pDest;
+ }
+
+ return bRet;
+}
+
+void Writer::PutNumFmtFontsInAttrPool()
+{
+ // dann gibt es noch in den NumRules ein paar Fonts
+ // Diese in den Pool putten. Haben sie danach einen RefCount > 1
+ // kann es wieder entfernt werden - ist schon im Pool
+ SfxItemPool& rPool = pDoc->GetAttrPool();
+ const SwNumRuleTbl& rListTbl = pDoc->GetNumRuleTbl();
+ const SwNumRule* pRule;
+ const SwNumFmt* pFmt;
+ // --> OD 2006-06-27 #b644095#
+// const Font *pFont, *pDefFont = &SwNumRule::GetDefBulletFont();
+ const Font* pFont;
+ const Font* pDefFont = &numfunc::GetDefBulletFont();
+ // <--
+ BOOL bCheck = FALSE;
+
+ for( USHORT nGet = rListTbl.Count(); nGet; )
+ if( pDoc->IsUsed( *(pRule = rListTbl[ --nGet ] )))
+ for( BYTE nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
+ if( SVX_NUM_CHAR_SPECIAL == (pFmt = &pRule->Get( nLvl ))->GetNumberingType() ||
+ SVX_NUM_BITMAP == pFmt->GetNumberingType() )
+ {
+ if( 0 == ( pFont = pFmt->GetBulletFont() ) )
+ pFont = pDefFont;
+
+ if( bCheck )
+ {
+ if( *pFont == *pDefFont )
+ continue;
+ }
+ else if( *pFont == *pDefFont )
+ bCheck = TRUE;
+
+ _AddFontItem( rPool, SvxFontItem( pFont->GetFamily(),
+ pFont->GetName(), pFont->GetStyleName(),
+ pFont->GetPitch(), pFont->GetCharSet(), RES_CHRATR_FONT ));
+ }
+}
+
+void Writer::PutEditEngFontsInAttrPool( BOOL bIncl_CJK_CTL )
+{
+ SfxItemPool& rPool = pDoc->GetAttrPool();
+ if( rPool.GetSecondaryPool() )
+ {
+ _AddFontItems( rPool, EE_CHAR_FONTINFO );
+ if( bIncl_CJK_CTL )
+ {
+ _AddFontItems( rPool, EE_CHAR_FONTINFO_CJK );
+ _AddFontItems( rPool, EE_CHAR_FONTINFO_CTL );
+ }
+ }
+}
+
+void Writer::PutCJKandCTLFontsInAttrPool()
+{
+ SfxItemPool& rPool = pDoc->GetAttrPool();
+ _AddFontItems( rPool, RES_CHRATR_CJK_FONT );
+ _AddFontItems( rPool, RES_CHRATR_CTL_FONT );
+}
+
+
+void Writer::_AddFontItems( SfxItemPool& rPool, USHORT nW )
+{
+ const SvxFontItem* pFont = (const SvxFontItem*)&rPool.GetDefaultItem( nW );
+ _AddFontItem( rPool, *pFont );
+
+ if( 0 != ( pFont = (const SvxFontItem*)rPool.GetPoolDefaultItem( nW )) )
+ _AddFontItem( rPool, *pFont );
+
+ USHORT nMaxItem = rPool.GetItemCount( nW );
+ for( USHORT nGet = 0; nGet < nMaxItem; ++nGet )
+ if( 0 != (pFont = (const SvxFontItem*)rPool.GetItem( nW, nGet )) )
+ _AddFontItem( rPool, *pFont );
+}
+
+void Writer::_AddFontItem( SfxItemPool& rPool, const SvxFontItem& rFont )
+{
+ const SvxFontItem* pItem;
+ if( RES_CHRATR_FONT != rFont.Which() )
+ {
+ SvxFontItem aFont( rFont );
+ aFont.SetWhich( RES_CHRATR_FONT );
+ pItem = (SvxFontItem*)&rPool.Put( aFont );
+ }
+ else
+ pItem = (SvxFontItem*)&rPool.Put( rFont );
+
+ if( 1 < pItem->GetRefCount() )
+ rPool.Remove( *pItem );
+ else
+ {
+ if (!m_pImpl->pFontRemoveLst)
+ {
+ m_pImpl->pFontRemoveLst = new SvPtrarr( 0, 10 );
+ }
+
+ void* p = (void*)pItem;
+ m_pImpl->pFontRemoveLst->Insert( p, m_pImpl->pFontRemoveLst->Count() );
+ }
+}
+
+// build a bookmark table, which is sort by the node position. The
+// OtherPos of the bookmarks also inserted.
+void Writer::CreateBookmarkTbl()
+{
+ const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ for(IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->getBookmarksBegin();
+ ppBkmk != pMarkAccess->getBookmarksEnd();
+ ++ppBkmk)
+ {
+ m_pImpl->InsertBkmk(**ppBkmk);
+ }
+}
+
+
+// search alle Bookmarks in the range and return it in the Array
+USHORT Writer::GetBookmarks(const SwCntntNode& rNd, xub_StrLen nStt,
+ xub_StrLen nEnd, SvPtrarr& rArr)
+{
+ OSL_ENSURE( !rArr.Count(), "es sind noch Eintraege vorhanden" );
+
+ ULONG nNd = rNd.GetIndex();
+ SvPtrarr* pArr = (m_pImpl->pBkmkNodePos) ?
+ m_pImpl->pBkmkNodePos->Get( nNd ) : 0;
+ if( pArr )
+ {
+ // there exist some bookmarks, search now all which is in the range
+ if( !nStt && nEnd == rNd.Len() )
+ // all
+ rArr.Insert( pArr, 0 );
+ else
+ {
+ USHORT n;
+ xub_StrLen nCntnt;
+ for( n = 0; n < pArr->Count(); ++n )
+ {
+ void* p = (*pArr)[ n ];
+ const ::sw::mark::IMark& rBkmk = *(::sw::mark::IMark *)p;
+ if( rBkmk.GetMarkPos().nNode == nNd &&
+ (nCntnt = rBkmk.GetMarkPos().nContent.GetIndex() ) >= nStt &&
+ nCntnt < nEnd )
+ {
+ rArr.Insert( p, rArr.Count() );
+ }
+ else if( rBkmk.IsExpanded() && nNd ==
+ rBkmk.GetOtherMarkPos().nNode.GetIndex() && (nCntnt =
+ rBkmk.GetOtherMarkPos().nContent.GetIndex() ) >= nStt &&
+ nCntnt < nEnd )
+ {
+ rArr.Insert( p, rArr.Count() );
+ }
+ }
+ }
+ }
+ return rArr.Count();
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+// Storage-spezifisches
+
+ULONG StgWriter::WriteStream()
+{
+ OSL_ENSURE( !this, "Schreiben in Streams auf einem Storage?" );
+ return ERR_SWG_WRITE_ERROR;
+}
+
+ULONG StgWriter::Write( SwPaM& rPaM, SvStorage& rStg, const String* pFName )
+{
+ SetStream(0);
+ pStg = &rStg;
+ pDoc = rPaM.GetDoc();
+ pOrigFileName = pFName;
+
+ // PaM kopieren, damit er veraendert werden kann
+ pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
+ // zum Vergleich auf den akt. Pam sichern
+ pOrigPam = &rPaM;
+
+ ULONG nRet = WriteStorage();
+
+ pStg = NULL;
+ ResetWriter();
+
+ return nRet;
+}
+
+ULONG StgWriter::Write( SwPaM& rPaM, const uno::Reference < embed::XStorage >& rStg, const String* pFName, SfxMedium* pMedium )
+{
+ SetStream(0);
+ pStg = 0;
+ xStg = rStg;
+ pDoc = rPaM.GetDoc();
+ pOrigFileName = pFName;
+
+ // PaM kopieren, damit er veraendert werden kann
+ pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
+ // zum Vergleich auf den akt. Pam sichern
+ pOrigPam = &rPaM;
+
+ ULONG nRet = pMedium ? WriteMedium( *pMedium ) : WriteStorage();
+
+ pStg = NULL;
+ ResetWriter();
+
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/writer/wrt_fn.cxx b/sw/source/filter/writer/wrt_fn.cxx
new file mode 100644
index 000000000000..dc2f9c20f553
--- /dev/null
+++ b/sw/source/filter/writer/wrt_fn.cxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <svl/itemiter.hxx>
+#include <svl/whiter.hxx>
+
+
+#include "shellio.hxx"
+#include "wrt_fn.hxx"
+#include "node.hxx"
+#include "format.hxx"
+
+
+
+Writer& Out( const SwAttrFnTab pTab, const SfxPoolItem& rHt, Writer & rWrt )
+{
+ USHORT nId = rHt.Which();
+ OSL_ENSURE( nId < POOLATTR_END && nId >= POOLATTR_BEGIN, "SwAttrFnTab::Out()" );
+ FnAttrOut pOut;
+ if( 0 != ( pOut = pTab[ nId - RES_CHRATR_BEGIN] ))
+ (*pOut)( rWrt, rHt );
+ return rWrt;
+
+}
+
+Writer& Out_SfxItemSet( const SwAttrFnTab pTab, Writer& rWrt,
+ const SfxItemSet& rSet, BOOL bDeep,
+ BOOL bTstForDefault )
+{
+ // erst die eigenen Attribute ausgeben
+ const SfxItemPool& rPool = *rSet.GetPool();
+ const SfxItemSet* pSet = &rSet;
+ if( !pSet->Count() ) // Optimierung - leere Sets
+ {
+ if( !bDeep )
+ return rWrt;
+ while( 0 != ( pSet = pSet->GetParent() ) && !pSet->Count() )
+ ;
+ if( !pSet )
+ return rWrt;
+ }
+ const SfxPoolItem* pItem;
+ FnAttrOut pOut;
+ if( !bDeep || !pSet->GetParent() )
+ {
+ OSL_ENSURE( rSet.Count(), "Wurde doch schon behandelt oder?" );
+ SfxItemIter aIter( *pSet );
+ pItem = aIter.GetCurItem();
+ do {
+ if( 0 != ( pOut = pTab[ pItem->Which() - RES_CHRATR_BEGIN] ))
+ (*pOut)( rWrt, *pItem );
+ } while( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
+ }
+ else
+ {
+ SfxWhichIter aIter( *pSet );
+ USHORT nWhich = aIter.FirstWhich();
+ while( nWhich )
+ {
+ if( SFX_ITEM_SET == pSet->GetItemState( nWhich, bDeep, &pItem ) &&
+ ( !bTstForDefault || (
+ *pItem != rPool.GetDefaultItem( nWhich )
+ || ( pSet->GetParent() &&
+ *pItem != pSet->GetParent()->Get( nWhich ))
+ )) && 0 != ( pOut = pTab[ nWhich - RES_CHRATR_BEGIN] ))
+ (*pOut)( rWrt, *pItem );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ return rWrt;
+}
+
+
+
+Writer& Out( const SwNodeFnTab pTab, SwNode& rNode, Writer & rWrt )
+{
+ // es muss ein CntntNode sein !!
+ SwCntntNode * pCNd = rNode.GetCntntNode();
+ if( !pCNd )
+ return rWrt;
+
+ USHORT nId = RES_TXTNODE;
+ switch (pCNd->GetNodeType())
+ {
+ case ND_TEXTNODE:
+ nId = RES_TXTNODE;
+ break;
+ case ND_GRFNODE:
+ nId = RES_GRFNODE;
+ break;
+ case ND_OLENODE:
+ nId = RES_OLENODE;
+ break;
+ default:
+ OSL_ENSURE(false, "was fuer ein Node ist es denn nun?");
+ break;
+ }
+ FnNodeOut pOut;
+ if( 0 != ( pOut = pTab[ nId - RES_NODE_BEGIN ] ))
+ (*pOut)( rWrt, *pCNd );
+ return rWrt;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/writer/wrtswtbl.cxx b/sw/source/filter/writer/wrtswtbl.cxx
new file mode 100644
index 000000000000..58e3cbde1b3c
--- /dev/null
+++ b/sw/source/filter/writer/wrtswtbl.cxx
@@ -0,0 +1,926 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <editeng/boxitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <tools/fract.hxx>
+#include <wrtswtbl.hxx>
+#include <swtable.hxx>
+#include <frmfmt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <frmatr.hxx>
+#include <htmltbl.hxx>
+
+using namespace ::com::sun::star;
+
+SV_IMPL_PTRARR( SwWriteTableCells, SwWriteTableCellPtr )
+SV_IMPL_OP_PTRARR_SORT( SwWriteTableRows, SwWriteTableRowPtr )
+SV_IMPL_OP_PTRARR_SORT( SwWriteTableCols, SwWriteTableColPtr )
+
+//-----------------------------------------------------------------------
+
+sal_Int16 SwWriteTableCell::GetVertOri() const
+{
+ sal_Int16 eCellVertOri = text::VertOrientation::TOP;
+ if( pBox->GetSttNd() )
+ {
+ const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, FALSE, &pItem ) )
+ {
+ sal_Int16 eBoxVertOri =
+ ((const SwFmtVertOrient *)pItem)->GetVertOrient();
+ if( text::VertOrientation::CENTER==eBoxVertOri || text::VertOrientation::BOTTOM==eBoxVertOri)
+ eCellVertOri = eBoxVertOri;
+ }
+ }
+
+ return eCellVertOri;
+}
+
+//-----------------------------------------------------------------------
+
+SwWriteTableRow::SwWriteTableRow( long nPosition, BOOL bUseLayoutHeights )
+ : pBackground(0), nPos(nPosition), mbUseLayoutHeights(bUseLayoutHeights),
+ nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX), bTopBorder(true),
+ bBottomBorder(true)
+{
+}
+
+SwWriteTableCell *SwWriteTableRow::AddCell( const SwTableBox *pBox,
+ USHORT nRow, USHORT nCol,
+ USHORT nRowSpan, USHORT nColSpan,
+ long nHeight,
+ const SvxBrushItem *pBackgroundBrush )
+{
+ SwWriteTableCell *pCell =
+ new SwWriteTableCell( pBox, nRow, nCol, nRowSpan, nColSpan,
+ nHeight, pBackgroundBrush );
+ aCells.Insert( pCell, aCells.Count() );
+
+ return pCell;
+}
+
+//-----------------------------------------------------------------------
+
+SwWriteTableCol::SwWriteTableCol(USHORT nPosition)
+ : nPos(nPosition), nWidthOpt(0), bRelWidthOpt(false), bOutWidth(true),
+ bLeftBorder(true), bRightBorder(true)
+{
+}
+
+//-----------------------------------------------------------------------
+
+long SwWriteTable::GetBoxWidth( const SwTableBox *pBox )
+{
+ const SwFrmFmt *pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& aFrmSize=
+ (const SwFmtFrmSize&)pFmt->GetFmtAttr( RES_FRM_SIZE );
+
+ return aFrmSize.GetSize().Width();
+}
+
+long SwWriteTable::GetLineHeight( const SwTableLine *pLine )
+{
+#if OSL_DEBUG_LEVEL > 1
+ BOOL bOldGetLineHeightCalled = bGetLineHeightCalled;
+ bGetLineHeightCalled = TRUE;
+#endif
+
+ long nHeight = 0;
+ if( bUseLayoutHeights )
+ {
+ // Erstmal versuchen wir die Hoehe ueber das Layout zu bekommen
+ bool bLayoutAvailable = false;
+ nHeight = pLine->GetTableLineHeight(bLayoutAvailable);
+ if( nHeight > 0 )
+ return nHeight;
+
+ // Wenn kein Layout gefunden wurde, gehen wir von festen Hoehen aus.
+ // --> FME 2007-3-26 #i60390# in some cases we still want to continue
+ // to use the layout heights even if one of the rows has a height of 0
+ // ('hidden' rows)
+ // <--
+ bUseLayoutHeights = bLayoutAvailable; /*FALSE;*/
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bLayoutAvailable || !bOldGetLineHeightCalled, "Layout ungueltig?" );
+#endif
+ }
+
+ const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ USHORT nBoxes = rBoxes.Count();
+
+ for( USHORT nBox=0; nBox<nBoxes; nBox++ )
+ {
+ const SwTableBox* pBox = rBoxes[nBox];
+ if( pBox->GetSttNd() )
+ {
+ if( nHeight < ROW_DFLT_HEIGHT )
+ nHeight = ROW_DFLT_HEIGHT;
+ }
+ else
+ {
+ long nTmp = 0;
+ const SwTableLines &rLines = pBox->GetTabLines();
+ for( USHORT nLine=0; nLine<rLines.Count(); nLine++ )
+ {
+ nTmp += GetLineHeight( rLines[nLine] );
+ }
+ if( nHeight < nTmp )
+ nHeight = nTmp;
+ }
+ }
+
+ return nHeight;
+}
+
+long SwWriteTable::GetLineHeight( const SwTableBox *pBox ) const
+{
+ const SwTableLine *pLine = pBox->GetUpper();
+
+ if( !pLine )
+ return 0;
+
+ const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
+ const SfxPoolItem* pItem;
+ const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
+
+ long nHeight = 0;
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, TRUE, &pItem ))
+ nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
+
+ return nHeight;
+}
+
+const SvxBrushItem *SwWriteTable::GetLineBrush( const SwTableBox *pBox,
+ SwWriteTableRow *pRow )
+{
+ const SwTableLine *pLine = pBox->GetUpper();
+
+ while( pLine )
+ {
+ const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
+ const SfxPoolItem* pItem;
+ const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
+
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, FALSE,
+ &pItem ) )
+ {
+ if( !pLine->GetUpper() )
+ {
+ if( !pRow->GetBackground() )
+ pRow->SetBackground( (const SvxBrushItem *)pItem );
+ pItem = 0;
+ }
+
+ return (const SvxBrushItem *)pItem;
+ }
+
+ pBox = pLine->GetUpper();
+ pLine = pBox ? pBox->GetUpper() : 0;
+ }
+
+ return 0;
+}
+
+
+void SwWriteTable::MergeBorders( const SvxBorderLine* pBorderLine,
+ BOOL bTable )
+{
+ if( (UINT32)-1 == nBorderColor )
+ {
+ Color aGrayColor( COL_GRAY );
+ if( !pBorderLine->GetColor().IsRGBEqual( aGrayColor ) )
+ nBorderColor = pBorderLine->GetColor().GetColor();
+ }
+
+ if( !bCollectBorderWidth )
+ return;
+
+ USHORT nOutWidth = pBorderLine->GetOutWidth();
+ if( bTable )
+ {
+ if( nOutWidth && (!nBorder || nOutWidth < nBorder) )
+ nBorder = nOutWidth;
+ }
+ else
+ {
+ if( nOutWidth && (!nInnerBorder || nOutWidth < nInnerBorder) )
+ nInnerBorder = nOutWidth;
+ }
+
+ USHORT nDist = pBorderLine->GetInWidth() ? pBorderLine->GetDistance()
+ : 0;
+ if( nDist && (!nCellSpacing || nDist < nCellSpacing) )
+ nCellSpacing = nDist;
+}
+
+
+USHORT SwWriteTable::MergeBoxBorders( const SwTableBox *pBox,
+ USHORT nRow, USHORT nCol,
+ USHORT nRowSpan, USHORT nColSpan,
+ USHORT& rTopBorder,
+ USHORT &rBottomBorder )
+{
+ USHORT nBorderMask = 0;
+
+ const SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
+ const SvxBoxItem& rBoxItem = (const SvxBoxItem&)pFrmFmt->GetFmtAttr( RES_BOX );
+
+ if( rBoxItem.GetTop() )
+ {
+ nBorderMask |= 1;
+ MergeBorders( rBoxItem.GetTop(), nRow==0 );
+ rTopBorder = rBoxItem.GetTop()->GetOutWidth();
+ }
+
+ if( rBoxItem.GetLeft() )
+ {
+ nBorderMask |= 4;
+ MergeBorders( rBoxItem.GetLeft(), nCol==0 );
+ }
+
+ if( rBoxItem.GetBottom() )
+ {
+ nBorderMask |= 2;
+ MergeBorders( rBoxItem.GetBottom(), nRow+nRowSpan==aRows.Count() );
+ rBottomBorder = rBoxItem.GetBottom()->GetOutWidth();
+ }
+
+ if( rBoxItem.GetRight() )
+ {
+ nBorderMask |= 8;
+ MergeBorders( rBoxItem.GetRight(), nCol+nColSpan==aCols.Count() );
+ }
+
+ // If any distance is set, the smallest one is used. This holds for
+ // the four distance of a box as well as for the distances of different
+ // boxes.
+ if( bCollectBorderWidth )
+ {
+ USHORT nDist = rBoxItem.GetDistance( BOX_LINE_TOP );
+ if( nDist && (!nCellPadding || nDist < nCellPadding) )
+ nCellPadding = nDist;
+ nDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
+ if( nDist && (!nCellPadding || nDist < nCellPadding) )
+ nCellPadding = nDist;
+ nDist = rBoxItem.GetDistance( BOX_LINE_LEFT );
+ if( nDist && (!nCellPadding || nDist < nCellPadding) )
+ nCellPadding = nDist;
+ nDist = rBoxItem.GetDistance( BOX_LINE_RIGHT );
+ if( nDist && (!nCellPadding || nDist < nCellPadding) )
+ nCellPadding = nDist;
+ }
+
+ return nBorderMask;
+}
+
+
+USHORT SwWriteTable::GetRawWidth( USHORT nCol, USHORT nColSpan ) const
+{
+ USHORT nWidth = aCols[nCol+nColSpan-1]->GetPos();
+ if( nCol > 0 )
+ nWidth = nWidth - aCols[nCol-1]->GetPos();
+
+ return nWidth;
+}
+
+USHORT SwWriteTable::GetLeftSpace( USHORT nCol ) const
+{
+ USHORT nSpace = nCellPadding + nCellSpacing;
+
+ // In der ersten Spalte auch noch die Liniendicke abziehen
+ if( nCol==0 )
+ {
+ nSpace = nSpace + nLeftSub;
+
+ const SwWriteTableCol *pCol = aCols[nCol];
+ if( pCol->HasLeftBorder() )
+ nSpace = nSpace + nBorder;
+ }
+
+ return nSpace;
+}
+
+USHORT SwWriteTable::GetRightSpace( USHORT nCol, USHORT nColSpan ) const
+{
+ USHORT nSpace = nCellPadding;
+
+ // In der letzten Spalte noch einmal zusaetzlich CELLSPACING und
+ // und die Liniendicke abziehen
+ if( nCol+nColSpan==aCols.Count() )
+ {
+ nSpace += (nCellSpacing + nRightSub);
+
+ const SwWriteTableCol *pCol = aCols[nCol+nColSpan-1];
+ if( pCol->HasRightBorder() )
+ nSpace = nSpace + nBorder;
+ }
+
+ return nSpace;
+}
+
+USHORT SwWriteTable::GetAbsWidth( USHORT nCol, USHORT nColSpan ) const
+{
+ long nWidth = GetRawWidth( nCol, nColSpan );
+ if( nBaseWidth != nTabWidth )
+ {
+ nWidth *= nTabWidth;
+ nWidth /= nBaseWidth;
+ }
+
+ nWidth -= GetLeftSpace( nCol ) + GetRightSpace( nCol, nColSpan );
+
+ OSL_ENSURE( nWidth > 0, "Spaltenbreite <= 0. OK?" );
+ return nWidth > 0 ? (USHORT)nWidth : 0;
+}
+
+USHORT SwWriteTable::GetRelWidth( USHORT nCol, USHORT nColSpan ) const
+{
+ long nWidth = GetRawWidth( nCol, nColSpan );
+
+ return (USHORT)(long)Fraction( nWidth*256 + GetBaseWidth()/2,
+ GetBaseWidth() );
+}
+
+USHORT SwWriteTable::GetPrcWidth( USHORT nCol, USHORT nColSpan ) const
+{
+ long nWidth = GetRawWidth( nCol, nColSpan );
+
+ // sieht komisch aus, ist aber nichts anderes als
+ // [(100 * nWidth) + .5] ohne Rundungsfehler
+ return (USHORT)(long)Fraction( nWidth*100 + GetBaseWidth()/2,
+ GetBaseWidth() );
+}
+
+long SwWriteTable::GetAbsHeight( long nRawHeight, USHORT nRow,
+ USHORT nRowSpan ) const
+{
+ nRawHeight -= (2*nCellPadding + nCellSpacing);
+
+ // In der ersten Zeile noch einmal zusaetzlich CELLSPACING und
+ // und die Liniendicke abziehen
+ const SwWriteTableRow *pRow = 0;
+ if( nRow==0 )
+ {
+ nRawHeight -= nCellSpacing;
+ pRow = aRows[nRow];
+ if( pRow->HasTopBorder() )
+ nRawHeight -= nBorder;
+ }
+
+ // In der letzten Zeile noch die Liniendicke abziehen
+ if( nRow+nRowSpan==aRows.Count() )
+ {
+ if( !pRow || nRowSpan > 1 )
+ pRow = aRows[nRow+nRowSpan-1];
+ if( pRow->HasBottomBorder() )
+ nRawHeight -= nBorder;
+ }
+
+ OSL_ENSURE( nRawHeight > 0, "Zeilenheohe <= 0. OK?" );
+ return nRawHeight > 0 ? nRawHeight : 0;
+}
+
+BOOL SwWriteTable::ShouldExpandSub(const SwTableBox *pBox, BOOL /*bExpandedBefore*/,
+ USHORT nDepth) const
+{
+ return !pBox->GetSttNd() && nDepth > 0;
+}
+
+void SwWriteTable::CollectTableRowsCols( long nStartRPos,
+ USHORT nStartCPos,
+ long nParentLineHeight,
+ USHORT nParentLineWidth,
+ const SwTableLines& rLines,
+ USHORT nDepth )
+{
+ BOOL bSubExpanded = FALSE;
+ USHORT nLines = rLines.Count();
+
+#if OSL_DEBUG_LEVEL > 1
+ USHORT nEndCPos = 0;
+#endif
+
+ long nRPos = nStartRPos;
+ for( USHORT nLine = 0; nLine < nLines; nLine++ )
+ {
+ /*const*/ SwTableLine *pLine = rLines[nLine];
+
+ long nOldRPos = nRPos;
+
+ if( nLine < nLines-1 || nParentLineHeight==0 )
+ {
+ long nLineHeight = GetLineHeight( pLine );
+ nRPos += nLineHeight;
+ if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
+ {
+ /* If you have corrupt line height information, e.g. breaking rows in complex table
+ layout, you may run into this robust code.
+ It's not allowed that subrows leaves their parentrow. If this would happen the line
+ height of subrow is reduced to a part of the remaining height */
+ OSL_ENSURE( FALSE, "Corrupt line height I" );
+ nRPos -= nLineHeight;
+ nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
+ nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
+ nRPos += nLineHeight;
+ }
+ SwWriteTableRow *pRow = new SwWriteTableRow( nRPos, bUseLayoutHeights);
+ USHORT nRow;
+ if( aRows.Seek_Entry( pRow, &nRow ) )
+ delete pRow;
+ else
+ aRows.Insert( pRow );
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ long nCheckPos = nRPos + GetLineHeight( pLine );
+#endif
+ nRPos = nStartRPos + nParentLineHeight;
+#if OSL_DEBUG_LEVEL > 1
+ SwWriteTableRow aRow( nStartRPos + nParentLineHeight, bUseLayoutHeights );
+ OSL_ENSURE( aRows.Seek_Entry(&aRow),
+ "Parent-Zeile nicht gefunden" );
+ SwWriteTableRow aRowCheckPos(nCheckPos,bUseLayoutHeights);
+ SwWriteTableRow aRowRPos(nRPos,bUseLayoutHeights);
+ OSL_ENSURE( !bUseLayoutHeights ||
+ aRowCheckPos == aRowRPos,
+ "Hoehe der Zeilen stimmt nicht mit Parent ueberein" );
+#endif
+ }
+
+ // Fuer alle Boxen der Zeile ggf. eine Spalte einfuegen
+ const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ USHORT nBoxes = rBoxes.Count();
+
+ USHORT nCPos = nStartCPos;
+ for( USHORT nBox=0; nBox<nBoxes; nBox++ )
+ {
+ const SwTableBox *pBox = rBoxes[nBox];
+
+ USHORT nOldCPos = nCPos;
+
+ if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
+ {
+ nCPos = nCPos + (USHORT)GetBoxWidth( pBox );
+ SwWriteTableCol *pCol = new SwWriteTableCol( nCPos );
+
+ USHORT nCol;
+ if( aCols.Seek_Entry( pCol, &nCol ) )
+ delete pCol;
+ else
+ aCols.Insert( pCol );
+
+ if( nBox==nBoxes-1 )
+ {
+ OSL_ENSURE( nLine==0 && nParentLineWidth==0,
+ "Jetzt wird die Parent-Breite plattgemacht!" );
+ nParentLineWidth = nCPos-nStartCPos;
+ }
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ USHORT nCheckPos = nCPos + (USHORT)GetBoxWidth( pBox );
+ if( !nEndCPos )
+ {
+ nEndCPos = nCheckPos;
+ }
+ else
+ {
+ OSL_ENSURE( SwWriteTableCol(nCheckPos) ==
+ SwWriteTableCol(nEndCPos),
+ "Zelle enthaelt unterschiedlich breite Zeilen" );
+ }
+#endif
+ nCPos = nStartCPos + nParentLineWidth;
+#if OSL_DEBUG_LEVEL > 1
+ SwWriteTableCol aCol( nStartCPos + nParentLineWidth );
+ OSL_ENSURE( aCols.Seek_Entry(&aCol),
+ "Parent-Zelle nicht gefunden" );
+ OSL_ENSURE( SwWriteTableCol(nCheckPos) ==
+ SwWriteTableCol(nCPos),
+ "Breite der Zellen stimmt nicht mit Parent ueberein" );
+#endif
+ }
+
+ if( ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
+ {
+ CollectTableRowsCols( nOldRPos, nOldCPos,
+ nRPos - nOldRPos,
+ nCPos - nOldCPos,
+ pBox->GetTabLines(),
+ nDepth-1 );
+ bSubExpanded = TRUE;
+ }
+ }
+ }
+}
+
+
+void SwWriteTable::FillTableRowsCols( long nStartRPos, USHORT nStartRow,
+ USHORT nStartCPos, USHORT nStartCol,
+ long nParentLineHeight,
+ USHORT nParentLineWidth,
+ const SwTableLines& rLines,
+ const SvxBrushItem* pParentBrush,
+ USHORT nDepth,
+ sal_uInt16 nNumOfHeaderRows )
+{
+ USHORT nLines = rLines.Count();
+ BOOL bSubExpanded = FALSE;
+
+ // Festlegen der Umrandung
+ long nRPos = nStartRPos;
+ USHORT nRow = nStartRow;
+
+ for( USHORT nLine = 0; nLine < nLines; nLine++ )
+ {
+ const SwTableLine *pLine = rLines[nLine];
+
+ // Position der letzten ueberdeckten Zeile ermitteln
+ long nOldRPos = nRPos;
+ if( nLine < nLines-1 || nParentLineHeight==0 )
+ {
+ long nLineHeight = GetLineHeight( pLine );
+ nRPos += nLineHeight;
+ if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
+ {
+ /* See comment in CollectTableRowCols */
+ OSL_ENSURE( FALSE, "Corrupt line height II" );
+ nRPos -= nLineHeight;
+ nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
+ nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
+ nRPos += nLineHeight;
+ }
+ }
+ else
+ nRPos = nStartRPos + nParentLineHeight;
+
+ // Und ihren Index
+ USHORT nOldRow = nRow;
+ SwWriteTableRow aRow( nRPos,bUseLayoutHeights );
+#if OSL_DEBUG_LEVEL > 1
+ BOOL bFound =
+#endif
+ aRows.Seek_Entry( &aRow, &nRow );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bFound, "Wo ist die Zeile geblieben?" );
+#endif
+
+ OSL_ENSURE( nOldRow <= nRow, "Don't look back!" );
+ if( nOldRow > nRow )
+ {
+ nOldRow = nRow;
+ if( nOldRow )
+ --nOldRow;
+ }
+
+
+ SwWriteTableRow *pRow = aRows[nOldRow];
+ SwWriteTableRow *pEndRow = aRows[nRow];
+// if( nLine==0 && nParentLineHeight==0 )
+ if( nLine+1==nNumOfHeaderRows && nParentLineHeight==0 )
+ nHeadEndRow = nRow;
+
+ const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+
+ const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
+ const SfxPoolItem* pItem;
+ const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
+
+ long nHeight = 0;
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, TRUE, &pItem ))
+ nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
+
+
+ const SvxBrushItem *pBrushItem, *pLineBrush = pParentBrush;
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, FALSE,
+ &pItem ) )
+ {
+ pLineBrush = (const SvxBrushItem *)pItem;
+
+ // Wenn die Zeile die gesamte Tabelle umspannt, koennen
+ // Wir den Hintergrund an der Zeile ausgeben. Sonst muessen
+ // wir in an den Zelle ausgeben.
+ BOOL bOutAtRow = !nParentLineWidth;
+ if( !bOutAtRow && nStartCPos==0 )
+ {
+ USHORT nEndCol;
+ SwWriteTableCol aCol( nParentLineWidth );
+ bOutAtRow = aCols.Seek_Entry(&aCol,&nEndCol) &&
+ nEndCol == aCols.Count()-1;
+ }
+ if( bOutAtRow )
+ {
+ pRow->SetBackground( pLineBrush );
+ pBrushItem = 0;
+ }
+ else
+ pBrushItem = pLineBrush;
+ }
+ else
+ {
+ pRow->SetBackground( pLineBrush );
+ pBrushItem = 0;
+ }
+
+ USHORT nBoxes = rBoxes.Count();
+ USHORT nCPos = nStartCPos;
+ USHORT nCol = nStartCol;
+
+ for( USHORT nBox=0; nBox<nBoxes; nBox++ )
+ {
+ const SwTableBox *pBox = rBoxes[nBox];
+
+ // Position der letzten ueberdeckten Spalte ermitteln
+ USHORT nOldCPos = nCPos;
+ if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
+ {
+ nCPos = nCPos + (USHORT)GetBoxWidth( pBox );
+ if( nBox==nBoxes-1 )
+ nParentLineWidth = nCPos - nStartCPos;
+ }
+ else
+ nCPos = nStartCPos + nParentLineWidth;
+
+ // Und ihren Index
+ USHORT nOldCol = nCol;
+ SwWriteTableCol aCol( nCPos );
+#if OSL_DEBUG_LEVEL > 1
+ BOOL bFound2 =
+#endif
+ aCols.Seek_Entry( &aCol, &nCol );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bFound2, "Wo ist die Spalte geblieben?" );
+#endif
+
+ if( !ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
+ {
+ USHORT nRowSpan = nRow - nOldRow + 1;
+
+ // The new table model may have true row span attributes
+ const long nAttrRowSpan = pBox->getRowSpan();
+ if ( 1 < nAttrRowSpan )
+ nRowSpan = (USHORT)nAttrRowSpan;
+ else if ( nAttrRowSpan < 1 )
+ nRowSpan = 0;
+
+ USHORT nColSpan = nCol - nOldCol + 1;
+ pRow->AddCell( pBox, nOldRow, nOldCol,
+ nRowSpan, nColSpan, nHeight,
+ pBrushItem );
+ nHeight = 0; // Die Hoehe braucht nur einmal geschieben werden
+
+ if( pBox->GetSttNd() )
+ {
+ USHORT nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
+ USHORT nBorderMask = MergeBoxBorders(pBox, nOldRow, nOldCol,
+ nRowSpan, nColSpan, nTopBorder, nBottomBorder);
+
+ // #i30094# add a sanity check here to ensure that
+ // we don't access an invalid aCols[] as &nCol
+ // above can be changed.
+ if (!(nBorderMask & 4) && nOldCol < aCols.Count())
+ {
+ SwWriteTableCol *pCol = aCols[nOldCol];
+ OSL_ENSURE(pCol, "No TableCol found, panic!");
+ if (pCol)
+ pCol->bLeftBorder = FALSE;
+ }
+
+ if (!(nBorderMask & 8))
+ {
+ SwWriteTableCol *pCol = aCols[nCol];
+ OSL_ENSURE(pCol, "No TableCol found, panic!");
+ if (pCol)
+ pCol->bRightBorder = FALSE;
+ }
+
+ if (!(nBorderMask & 1))
+ pRow->bTopBorder = FALSE;
+ else if (!pRow->nTopBorder || nTopBorder < pRow->nTopBorder)
+ pRow->nTopBorder = nTopBorder;
+
+ if (!(nBorderMask & 2))
+ pEndRow->bBottomBorder = FALSE;
+ else if (
+ !pEndRow->nBottomBorder ||
+ nBottomBorder < pEndRow->nBottomBorder
+ )
+ {
+ pEndRow->nBottomBorder = nBottomBorder;
+ }
+ }
+// MIB: 13.12.2000: Why should a cell that contains a subtable
+// not have borders? Moreover, switching them, off switches off
+// the fill border lines between the columns and rows. (#74222#)
+// else
+// {
+// aCols[nOldCol]->bLeftBorder = FALSE;
+// aCols[nCol]->bRightBorder = FALSE;
+// pRow->bTopBorder = FALSE;
+// pEndRow->bBottomBorder = FALSE;
+// }
+ }
+ else
+ {
+ FillTableRowsCols( nOldRPos, nOldRow, nOldCPos, nOldCol,
+ nRPos-nOldRPos, nCPos-nOldCPos,
+ pBox->GetTabLines(),
+ pLineBrush, nDepth-1,
+ nNumOfHeaderRows );
+ bSubExpanded = TRUE;
+ }
+
+ nCol++; // Die naechste Zelle faengt in der nachten Spalte an
+ }
+
+ nRow++;
+ }
+}
+
+SwWriteTable::SwWriteTable(const SwTableLines& rLines, long nWidth,
+ USHORT nBWidth, BOOL bRel, USHORT nMaxDepth, USHORT nLSub, USHORT nRSub, sal_uInt32 nNumOfRowsToRepeat)
+ : nBorderColor((UINT32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
+ nInnerBorder(0), nBaseWidth(nBWidth), nHeadEndRow(USHRT_MAX),
+ nLeftSub(nLSub), nRightSub(nRSub), nTabWidth(nWidth), bRelWidths(bRel),
+ bUseLayoutHeights(true),
+#if OSL_DEBUG_LEVEL > 1
+ bGetLineHeightCalled(false),
+#endif
+ bColsOption(false), bColTags(true), bLayoutExport(false),
+ bCollectBorderWidth(true)
+{
+ USHORT nParentWidth = nBaseWidth + nLeftSub + nRightSub;
+
+ // Erstmal die Tabellen-Struktur festlegen. Hinter der Tabelle ist in
+ // jedem Fall eine Spalte zu Ende
+ SwWriteTableCol *pCol = new SwWriteTableCol( nParentWidth );
+ aCols.Insert( pCol );
+ CollectTableRowsCols( 0, 0, 0, nParentWidth, rLines, nMaxDepth - 1 );
+
+ // Und jetzt mit leben fuellen
+ FillTableRowsCols( 0, 0, 0, 0, 0, nParentWidth, rLines, 0, nMaxDepth - 1, static_cast< sal_uInt16 >(nNumOfRowsToRepeat) );
+
+ // Einige Twip-Werte an Pixel-Grenzen anpassen
+ if( !nBorder )
+ nBorder = nInnerBorder;
+}
+
+SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo )
+ : nBorderColor((UINT32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
+ nInnerBorder(0), nBaseWidth(pLayoutInfo->GetWidthOption()), nHeadEndRow(0),
+ nLeftSub(0), nRightSub(0), nTabWidth(pLayoutInfo->GetWidthOption()),
+ bRelWidths(pLayoutInfo->HasPrcWidthOption()), bUseLayoutHeights(false),
+#if OSL_DEBUG_LEVEL > 1
+ bGetLineHeightCalled(false),
+#endif
+ bColsOption(pLayoutInfo->HasColsOption()),
+ bColTags(pLayoutInfo->HasColTags()), bLayoutExport(true),
+ bCollectBorderWidth(pLayoutInfo->HaveBordersChanged())
+{
+ if( !bCollectBorderWidth )
+ {
+ nBorder = pLayoutInfo->GetBorder();
+ nCellPadding = pLayoutInfo->GetCellPadding();
+ nCellSpacing = pLayoutInfo->GetCellSpacing();
+ }
+
+ USHORT nRow, nCol;
+ USHORT nCols = pLayoutInfo->GetColCount();
+ USHORT nRows = pLayoutInfo->GetRowCount();
+
+ // Erstmal die Tabellen-Struktur festlegen.
+ for( nCol=0; nCol<nCols; nCol++ )
+ {
+ SwWriteTableCol *pCol =
+ new SwWriteTableCol( (nCol+1)*COL_DFLT_WIDTH );
+
+ if( bColTags )
+ {
+ const SwHTMLTableLayoutColumn *pLayoutCol =
+ pLayoutInfo->GetColumn( nCol );
+ pCol->SetWidthOpt( pLayoutCol->GetWidthOption(),
+ pLayoutCol->IsRelWidthOption() );
+ }
+
+ aCols.Insert( pCol );
+ }
+
+ for( nRow=0; nRow<nRows; nRow++ )
+ {
+ SwWriteTableRow *pRow =
+ new SwWriteTableRow( (nRow+1)*ROW_DFLT_HEIGHT, bUseLayoutHeights );
+ pRow->nTopBorder = 0;
+ pRow->nBottomBorder = 0;
+ aRows.Insert( pRow );
+ }
+
+ // Und jetzt mit leben fuellen
+ for( nRow=0; nRow<nRows; nRow++ )
+ {
+ SwWriteTableRow *pRow = aRows[nRow];
+
+ BOOL bHeightExported = FALSE;
+ for( nCol=0; nCol<nCols; nCol++ )
+ {
+ const SwHTMLTableLayoutCell *pLayoutCell =
+ pLayoutInfo->GetCell( nRow, nCol );
+
+ const SwHTMLTableLayoutCnts *pLayoutCnts =
+ pLayoutCell->GetContents();
+
+ // Beginnt die Zelle eigentlich eine Zeile weiter oben oder
+ // weiter vorne?
+ if( ( nRow>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow-1,nCol)
+ ->GetContents() ) ||
+ ( nCol>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow,nCol-1)
+ ->GetContents() ) )
+ {
+ continue;
+ }
+
+ USHORT nRowSpan = pLayoutCell->GetRowSpan();
+ USHORT nColSpan = pLayoutCell->GetColSpan();
+ const SwTableBox *pBox = pLayoutCnts->GetTableBox();
+ OSL_ENSURE( pBox,
+ "Tabelle in Tabelle kann nicht ueber Layout exportiert werden" );
+
+ long nHeight = bHeightExported ? 0 : GetLineHeight( pBox );
+ const SvxBrushItem *pBrushItem = GetLineBrush( pBox, pRow );
+
+ SwWriteTableCell *pCell =
+ pRow->AddCell( pBox, nRow, nCol, nRowSpan, nColSpan,
+ nHeight, pBrushItem );
+ pCell->SetWidthOpt( pLayoutCell->GetWidthOption(),
+ pLayoutCell->IsPrcWidthOption() );
+
+ USHORT nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
+ USHORT nBorderMask =
+ MergeBoxBorders( pBox, nRow, nCol, nRowSpan, nColSpan,
+ nTopBorder, nBottomBorder );
+
+ SwWriteTableCol *pCol = aCols[nCol];
+ if( !(nBorderMask & 4) )
+ pCol->bLeftBorder = FALSE;
+
+ pCol = aCols[nCol+nColSpan-1];
+ if( !(nBorderMask & 8) )
+ pCol->bRightBorder = FALSE;
+
+ if( !(nBorderMask & 1) )
+ pRow->bTopBorder = FALSE;
+
+ SwWriteTableRow *pEndRow = aRows[nRow+nRowSpan-1];
+ if( !(nBorderMask & 2) )
+ pEndRow->bBottomBorder = FALSE;
+
+ // Die Hoehe braucht nur einmal geschieben werden
+ if( nHeight )
+ bHeightExported = TRUE;
+ }
+ }
+
+ // Einige Twip-Werte an Pixel-Grenzen anpassen
+ if( bCollectBorderWidth && !nBorder )
+ nBorder = nInnerBorder;
+}
+
+SwWriteTable::~SwWriteTable()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */