diff options
Diffstat (limited to 'sw/source/filter/writer')
-rw-r--r-- | sw/source/filter/writer/makefile.mk | 94 | ||||
-rw-r--r-- | sw/source/filter/writer/writer.cxx | 780 | ||||
-rw-r--r-- | sw/source/filter/writer/wrt_fn.cxx | 230 | ||||
-rw-r--r-- | sw/source/filter/writer/wrtswtbl.cxx | 959 |
4 files changed, 2063 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..bea300064a8e --- /dev/null +++ b/sw/source/filter/writer/makefile.mk @@ -0,0 +1,94 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 17:14:57 $ +# +# The Contents of this file are made available subject to the terms of +# either of the following licenses +# +# - GNU Lesser General Public License Version 2.1 +# - Sun Industry Standards Source License Version 1.1 +# +# Sun Microsystems Inc., October, 2000 +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2000 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library 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 for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# +# Sun Industry Standards Source License Version 1.1 +# ================================================= +# The contents of this file are subject to the Sun Industry Standards +# Source License Version 1.1 (the "License"); You may not use this file +# except in compliance with the License. You may obtain a copy of the +# License at http://www.openoffice.org/license.html. +# +# Software provided under this License is provided on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +# See the License for the specific provisions governing your rights and +# obligations concerning the Software. +# +# The Initial Developer of the Original Code is: Sun Microsystems, Inc. +# +# Copyright: 2000 by Sun Microsystems, Inc. +# +# All Rights Reserved. +# +# Contributor(s): _______________________________________ +# +# +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=sw +TARGET=writer + +PROJECTPCH=filt_pch +PROJECTPCHSOURCE=..\filt_1st\filt_pch + +# --- Settings ----------------------------------------------------- + +.INCLUDE : $(PRJ)$/inc$/swpre.mk +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/inc$/sw.mk + +# --- Files -------------------------------------------------------- + +CXXFILES = \ + writer.cxx \ + wrt_fn.cxx \ + wrtswtbl.cxx \ + wrttxatr.cxx \ + +SLOFILES = \ + $(SLO)$/writer.obj \ + $(SLO)$/wrt_fn.obj \ + $(SLO)$/wrtswtbl.obj \ + $(SLO)$/wrttxatr.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..677df928acee --- /dev/null +++ b/sw/source/filter/writer/writer.cxx @@ -0,0 +1,780 @@ +/************************************************************************* + * + * $RCSfile: writer.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:14:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifdef PRECOMPILED +#include "filt_pch.hxx" +#endif + +#pragma hdrstop + +#ifndef _HINTIDS_HXX +#include <hintids.hxx> +#endif + +#define _SVSTDARR_STRINGSSORTDTOR +#include <svtools/svstdarr.hxx> + +#ifndef _STREAM_HXX //autogen +#include <tools/stream.hxx> +#endif +#ifndef _SFXDOCFILE_HXX //autogen +#include <sfx2/docfile.hxx> +#endif +#ifndef SVTOOLS_URIHELPER_HXX +#include <svtools/urihelper.hxx> +#endif +#ifndef _FILTER_HXX //autogen +#include <svtools/filter.hxx> +#endif +#ifndef _SVX_IMPGRF_HXX //autogen +#include <svx/impgrf.hxx> +#endif +#ifndef _SVX_FONTITEM_HXX //autogen +#include <svx/fontitem.hxx> +#endif +#ifndef _EEITEM_HXX +#include <svx/eeitem.hxx> +#endif + + +#ifndef _TOOLS_TEMPFILE_HXX +#include <tools/tempfile.hxx> +#endif +#ifndef _SHELLIO_HXX +#include <shellio.hxx> +#endif +#ifndef _PAM_HXX +#include <pam.hxx> +#endif +#ifndef _DOC_HXX +#include <doc.hxx> +#endif +#ifndef _DOCARY_HXX +#include <docary.hxx> +#endif +#ifndef _NODE_HXX +#include <node.hxx> +#endif +#ifndef _FORMAT_HXX +#include <format.hxx> +#endif +#ifndef _BOOKMRK_HXX +#include <bookmrk.hxx> // fuer SwBookmark ... +#endif +#ifndef _NUMRULE_HXX //autogen +#include <numrule.hxx> +#endif + +#ifndef _SWSWERROR_H +#include <swerror.h> +#endif + +// Stringbuffer fuer die umgewandelten Zahlen +static sal_Char aNToABuf[] = "0000000000000000000000000"; +#define NTOABUFLEN (sizeof(aNToABuf)) + +DECLARE_TABLE( SwBookmarkNodeTable, SvPtrarr* ) + +struct Writer_Impl +{ + SvStringsSortDtor *pSrcArr, *pDestArr; + SvPtrarr* pFontRemoveLst, *pBkmkArr; + SwBookmarkNodeTable* pBkmkNodePos; + + Writer_Impl( const SwDoc& rDoc ); + ~Writer_Impl(); + + void RemoveFontList( SwDoc& rDoc ); + void InsertBkmk( const SwBookmark& rBkmk ); +}; + +Writer_Impl::Writer_Impl( const SwDoc& rDoc ) + : 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 ) +{ + ASSERT( 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 SwBookmark& rBkmk ) +{ + if( !pBkmkNodePos ) + pBkmkNodePos = new SwBookmarkNodeTable; + + ULONG nNd = rBkmk.GetPos().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.GetOtherPos() && rBkmk.GetOtherPos()->nNode != nNd ) + { + nNd = rBkmk.GetOtherPos()->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() + : pImpl( 0 ), pStrm( 0 ), pOrigPam( 0 ), pOrigFileName( 0 ), + pCurPam(0), pDoc( 0 ) +{ + bWriteAll = bShowProgress = bUCS2_WithStartChar = TRUE; + bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR = + bWriteClipboardDoc = bWriteOnlyFirstTable = FALSE; +} + +Writer::~Writer() +{ +} + +void Writer::ResetWriter() +{ + if( pImpl && pImpl->pFontRemoveLst ) + pImpl->RemoveFontList( *pDoc ); + delete pImpl, pImpl = 0; + + if( pCurPam ) + { + while( pCurPam->GetNext() != pCurPam ) + delete pCurPam->GetNext(); + delete pCurPam; + } + pCurPam = 0; + pOrigFileName = 0; + pDoc = 0; + pStrm = 0; + + bShowProgress = bUCS2_WithStartChar = TRUE; + bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR = + bWriteClipboardDoc = bWriteOnlyFirstTable = 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 + +USHORT Writer::FindPos_Bkmk( const SwPosition& rPos ) const +{ + USHORT nRet = USHRT_MAX; + const SwBookmarks& rBkmks = pDoc->GetBookmarks(); + + if( rBkmks.Count() ) + { + SwBookmark aBkmk( rPos ); + USHORT nPos; + if( rBkmks.Seek_Entry( &aBkmk, &nPos )) + { + // suche abwaerts nach weiteren Bookmarks auf der Cursor-Position + while( 0 < nPos && + rBkmks[ nPos-1 ]->IsEqualPos( aBkmk )) + --nPos; + } + else if( nPos < rBkmks.Count() ) + nRet = nPos; + } + return nRet; +} + + +SwPaM* Writer::NewSwPaM( SwDoc & rDoc, ULONG nStartIdx, ULONG nEndIdx, + BOOL bNodesArray ) const +{ + SwNodes* pNds = bNodesArray ? &rDoc.GetNodes() : (SwNodes*)rDoc.GetUndoNds(); + + SwNodeIndex aStt( *pNds, nStartIdx ); + SwCntntNode* pCNode = aStt.GetNode().GetCntntNode(); + if( !pCNode && 0 == ( pCNode = pNds->GoNext( &aStt )) ) + ASSERT( !this, "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 )) ) + ASSERT( !this, "An StartPos kein ContentNode mehr" ); + pCNode->MakeEndIndex( &pNew->GetPoint()->nContent ); + pNew->GetPoint()->nNode = aStt; + return pNew; +} + +///////////////////////////////////////////////////////////////////////////// + +// Stream-spezifisches +#ifndef PRODUCT +SvStream& Writer::Strm() +{ + ASSERT( pStrm, "Oh-oh. Dies ist ein Storage-Writer. Gleich knallts!" ); + return *pStrm; +} +#endif + + +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 ) +{ + pStrm = &rStrm; + pDoc = rPaM.GetDoc(); + pOrigFileName = pFName; + pImpl = new Writer_Impl( *pDoc ); + + // 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 ) +{ + return IsStgWriter() + ? Write( rPam, *rMed.GetStorage(), pFileName ) + : Write( rPam, *rMed.GetOutStream(), pFileName ); +} + +ULONG Writer::Write( SwPaM& rPam, SvStorage&, const String* ) +{ + ASSERT( !this, "Schreiben in Storages auf einem Stream?" ); + return ERR_SWG_WRITE_ERROR; +} + + +BOOL Writer::CopyLocalFileToINet( String& rFileNm, BOOL bCIdTarget ) +{ + BOOL bRet = FALSE; + INetURLObject aFileUrl( rFileNm ), aTargetUrl( *pOrigFileName ); + if( ( INET_PROT_FILE == aFileUrl.GetProtocol() || + (bCIdTarget && INET_PROT_CID == aFileUrl.GetProtocol()) ) && + ( (bCIdTarget && INET_PROT_FILE == aTargetUrl.GetProtocol()) || + (!bCIdTarget && INET_PROT_FILE != aTargetUrl.GetProtocol() && + INET_PROT_FTP <= aTargetUrl.GetProtocol() && + INET_PROT_NEWS >= aTargetUrl.GetProtocol()) ) ) + { + if( pImpl->pSrcArr ) + { + // wurde die Datei schon verschoben + USHORT nPos; + if( pImpl->pSrcArr->Seek_Entry( &rFileNm, &nPos )) + { + rFileNm = *(*pImpl->pDestArr)[ nPos ]; + return TRUE; + } + } + else + { + pImpl->pSrcArr = new SvStringsSortDtor( 4, 4 ); + pImpl->pDestArr = new SvStringsSortDtor( 4, 4 ); + } + + String* pSrc = new String( rFileNm ); + + String* pDest = 0; + + if( INET_PROT_FILE == aFileUrl.GetProtocol() ) + { + SvFileStream aTmp( aFileUrl.PathToFileName(), STREAM_READ ); + + pDest = new String( aTargetUrl.GetPartBeforeLastName() ); + *pDest += aFileUrl.GetName(); + + if( INET_PROT_FILE == aTargetUrl.GetProtocol() ) + { + ASSERT( bCIdTarget, + "CopyLocalFile: file->file: CId-Flag nicht gesetzt" ); + INetURLObject aCpyURL( *pDest ); + SvFileStream aCpy( aCpyURL.PathToFileName(), STREAM_WRITE ); + aCpy << aTmp; + + aCpy.Close(); + bRet = SVSTREAM_OK == aCpy.GetError(); + } + else + { + ASSERT( !bCIdTarget, + "CopyLocalFile: file->net: CId-Flag gesetzt" ); + SfxMedium aMedium( *pDest, STREAM_WRITE | STREAM_SHARE_DENYNONE, + FALSE, FALSE ); + + SvFileStream aCpy( aMedium.GetPhysicalName(), STREAM_WRITE ); + aCpy << aTmp; + aCpy.Close(); + + aMedium.Close(); + aMedium.Commit(); + + bRet = 0 == aMedium.GetError(); + } + } + else + { + ASSERT( INET_PROT_CID == aFileUrl.GetProtocol(), + "CopyLocalFile: cid->file: Source-URL nicht cid" ); + ASSERT( INET_PROT_FILE == aTargetUrl.GetProtocol(), + "CopyLocalFile: cid->file: Target-URL nicht file" ); + ASSERT( bCIdTarget, + "CopyLocalFile: cid->file: CId-Flag nicht gesetzt" ); + + SfxMedium aMedium( *pSrc, STREAM_READ | STREAM_SHARE_DENYNONE, + FALSE, TRUE ); + if( aMedium.GetInStream() ) + { + // Eine CID-URL wird in eine Datei kopiert, wenn eine + // Mail beantworted wird. Die Datei muss dann die richtige + // Extension bekommen. Da Netscape-CIDs keine Extensions + // enthalten muessen wir sie ueber den Grafik-Typ + // bestimmen und koennen sie nicht uas der URL extrahieren. + GraphicDescriptor aDesc( *aMedium.GetInStream() ); + GraphicFilter *pGrfFilter = GetGrfFilter(); + + if ( aDesc.Detect( FALSE ) ) + { + String aExt( pGrfFilter->GetImportFormatShortName( + aDesc.GetImportFormatNumber( aDesc.GetFileFormat(), + pGrfFilter->GetConfig() ) ) ); + + INetURLObject aAbsObj(URIHelper::SmartRelToAbs(aTargetUrl.GetMainURL())); + aAbsObj.removeSegment(); + String sPath(aAbsObj.GetMainURL()); + TempFile aTempFile(aTargetUrl.GetBase(), &aExt, &sPath); + + SvFileStream aCpy( aTempFile.GetName(), STREAM_WRITE ); + aCpy << *aMedium.GetInStream(); + aCpy.Close(); + + bRet = SVSTREAM_OK == aCpy.GetError(); + if( bRet ) + pDest = new String( aTempFile.GetName() ); + } + } + } + + if( bRet ) + { + pImpl->pSrcArr->Insert( pSrc ); + 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; + const Font *pFont, *pDefFont = &SwNumRule::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 ))->eType || + SVX_NUM_BITMAP == pFmt->eType ) + { + 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() )); + } +} + +void Writer::PutEditEngFontsInAttrPool() +{ + SfxItemPool& rPool = pDoc->GetAttrPool(); + if( rPool.GetSecondaryPool() ) + { + USHORT nW = EE_CHAR_FONTINFO; + 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->GetRef() ) + rPool.Remove( *pItem ); + else + { + if( !pImpl->pFontRemoveLst ) + pImpl->pFontRemoveLst = new SvPtrarr( 0, 10 ); + + void* p = (void*)pItem; + pImpl->pFontRemoveLst->Insert( p, 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 SwBookmarks& rBkmks = pDoc->GetBookmarks(); + for( USHORT n = rBkmks.Count(); n; ) + { + const SwBookmark& rBkmk = *rBkmks[ --n ]; + if( rBkmk.IsBookMark() ) + pImpl->InsertBkmk( rBkmk ); + } +} + + +// 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 ) +{ + ASSERT( !rArr.Count(), "es sind noch Eintraege vorhanden" ); + + ULONG nNd = rNd.GetIndex(); + SvPtrarr* pArr = pImpl->pBkmkNodePos ? 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 SwBookmark& rBkmk = *(SwBookmark*)p; + if( rBkmk.GetPos().nNode == nNd && + (nCntnt = rBkmk.GetPos().nContent.GetIndex() ) >= nStt && + nCntnt < nEnd ) + { + rArr.Insert( p, rArr.Count() ); + } + else if( rBkmk.GetOtherPos() && nNd == + rBkmk.GetOtherPos()->nNode.GetIndex() && (nCntnt = + rBkmk.GetOtherPos()->nContent.GetIndex() ) >= nStt && + nCntnt < nEnd ) + { + rArr.Insert( p, rArr.Count() ); + } + } + } + } + return rArr.Count(); +} + +//////////////////////////////////////////////////////////////////////////// + +// Storage-spezifisches + +ULONG StgWriter::WriteStream() +{ + ASSERT( !this, "Schreiben in Streams auf einem Storage?" ); + return ERR_SWG_WRITE_ERROR; +} + +ULONG StgWriter::Write( SwPaM& rPaM, SvStorage& rStg, const String* pFName ) +{ + pStrm = 0; + pStg = &rStg; + pDoc = rPaM.GetDoc(); + pOrigFileName = pFName; + pImpl = new Writer_Impl( *pDoc ); + + // 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; +} + +/************************************************************************* + + Source Code Control System - Header + + $Header: /zpool/svn/migration/cvs_rep_09_09_08/code/sw/source/filter/writer/writer.cxx,v 1.1.1.1 2000-09-18 17:14:57 hr Exp $ + + Source Code Control System - Update + + $Log: not supported by cvs2svn $ + Revision 1.103 2000/09/18 16:04:55 willem.vandorp + OpenOffice header added. + + Revision 1.102 2000/08/04 16:25:50 jp + read/write unicode ascii files + + Revision 1.101 2000/06/26 13:01:26 os + INetURLObject::SmartRelToAbs removed + + Revision 1.100 2000/06/13 09:43:46 os + using UCB + + Revision 1.99 2000/05/08 16:51:53 jp + Changes for Unicode + + Revision 1.98 1999/10/13 10:38:29 jp + PutEditEngFontsInAtrPool - check if the editenginepool exist + + Revision 1.97 1999/10/12 20:04:37 jp + Writer: put EditEngine fonts into the writer pool + + Revision 1.96 1999/08/12 10:19:56 MIB + Don\'t delete impl if it hasn\'t been set (for XML filter) + + + Rev 1.95 12 Aug 1999 12:19:56 MIB + Don't delete impl if it hasn't been set (for XML filter) + + Rev 1.94 30 Jun 1999 18:53:20 JP + dtor for impl class + + Rev 1.93 24 Jun 1999 22:51:34 JP + new: Writer with internal Impl-structur, build Bookmark table sortet by nodes + + Rev 1.92 23 Jun 1999 19:13:40 JP + interface of Writer::FindPos_Bkmk has changed + + Rev 1.91 16 Jun 1999 19:52:14 JP + Change interface of base class Writer + + Rev 1.90 28 Jan 1999 14:21:28 JP + GraphicFilter-SS hat sich geaendert - Task #59174# + + Rev 1.89 30 Oct 1998 18:30:02 JP + Task #58596#: neues Flag an der Writerklasse -> schreibe nur die 1. Tabelle + + Rev 1.88 27 Jun 1998 16:02:08 JP + Writer mit neuen Flags; fuer den ASCII-Writer, etwas aufgeraeumt + + Rev 1.87 23 Apr 1998 19:07:44 MIB + fix #49729#: Stream beim kopieren von Grafiken ins INet schliessen + + Rev 1.86 22 Jan 1998 20:02:56 JP + CTOR des SwPaM umgestellt + + Rev 1.85 26 Nov 1997 14:29:14 MA + headerfiles + + Rev 1.84 03 Nov 1997 14:12:48 MA + precomp entfernt + + Rev 1.83 13 Oct 1997 16:06:34 JP + pNext vom Ring wurde privat; zugriff ueber GetNext() + + Rev 1.82 09 Oct 1997 14:26:24 JP + Umstellung NodeIndex/-Array/BigPtrArray + + Rev 1.81 03 Sep 1997 11:59:44 JP + zusaetzliches include von docary + +*************************************************************************/ + diff --git a/sw/source/filter/writer/wrt_fn.cxx b/sw/source/filter/writer/wrt_fn.cxx new file mode 100644 index 000000000000..98784a8a3eb9 --- /dev/null +++ b/sw/source/filter/writer/wrt_fn.cxx @@ -0,0 +1,230 @@ +/************************************************************************* + * + * $RCSfile: wrt_fn.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:14:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifdef PRECOMPILED +#include "filt_pch.hxx" +#endif + +#pragma hdrstop + +#ifndef _SFXITEMITER_HXX //autogen +#include <svtools/itemiter.hxx> +#endif +#ifndef _SFX_WHITER_HXX //autogen +#include <svtools/whiter.hxx> +#endif + + +#include "shellio.hxx" +#include "wrt_fn.hxx" +#include "pam.hxx" +#include "node.hxx" +#include "format.hxx" + + + +Writer& Out( const SwAttrFnTab pTab, const SfxPoolItem& rHt, Writer & rWrt ) +{ + USHORT nId = rHt.Which(); + ASSERT( 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() ) + { + ASSERT( 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 ); + register 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; + 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: + ASSERT( FALSE, "was fuer ein Node ist es denn nun?" ); + } + FnNodeOut pOut; + if( 0 != ( pOut = pTab[ nId - RES_NODE_BEGIN ] )) + (*pOut)( rWrt, *pCNd ); + return rWrt; +} + + +/************************************************************************* + + Source Code Control System - Header + + $Header: /zpool/svn/migration/cvs_rep_09_09_08/code/sw/source/filter/writer/wrt_fn.cxx,v 1.1.1.1 2000-09-18 17:14:57 hr Exp $ + + Source Code Control System - Update + + $Log: not supported by cvs2svn $ + Revision 1.32 2000/09/18 16:04:55 willem.vandorp + OpenOffice header added. + + Revision 1.31 1999/07/06 12:55:38 JP + Out_SfxItemSet: test to default items optional + + + Rev 1.30 06 Jul 1999 14:55:38 JP + Out_SfxItemSet: test to default items optional + + Rev 1.29 26 Nov 1997 14:29:14 MA + headerfiles + + Rev 1.28 03 Nov 1997 14:12:48 MA + precomp entfernt + + Rev 1.27 22 Jan 1997 12:01:18 JP + neu: Tabellen Box Attribute + + Rev 1.26 16 Oct 1996 16:58:54 JP + unbenutzte Methoden entfernt + + Rev 1.25 01 Jul 1996 16:03:14 MA + includes + + Rev 1.24 22 Mar 1996 14:52:12 SWG + include hinzugefuegt + + Rev 1.23 24 Nov 1995 17:24:42 OM + PCH->PRECOMPILED + + Rev 1.22 25 Oct 1994 15:57:12 MA + PreHdr. + + Rev 1.21 04 Oct 1994 16:34:06 JP + Out_SfxItemSet: optimiert + + Rev 1.20 28 Sep 1994 12:37:34 JP + neue Methode: Out_SfxItemSet + + Rev 1.19 25 Aug 1994 18:09:12 JP + Umstellung Attribute (von SwHint -> SfxPoolItem) + + Rev 1.18 15 Feb 1994 15:31:30 MI + handsegmentierung + + Rev 1.17 28 Jan 1994 11:34:06 MI + TCOV() entfernt, SW_... nach SEG_... umbenannt + + Rev 1.16 13 Jan 1994 08:31:32 MI + Segmentierung per #define ermoeglicht + +*************************************************************************/ + + diff --git a/sw/source/filter/writer/wrtswtbl.cxx b/sw/source/filter/writer/wrtswtbl.cxx new file mode 100644 index 000000000000..308c191c48e4 --- /dev/null +++ b/sw/source/filter/writer/wrtswtbl.cxx @@ -0,0 +1,959 @@ +/************************************************************************* + * + * $RCSfile: wrtswtbl.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:14:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifdef PCH +#include "filt_pch.hxx" +#endif + +#pragma hdrstop + +#ifndef _HINTIDS_HXX +#include <hintids.hxx> +#endif + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _SVX_BOXITEM_HXX //autogen +#include <svx/boxitem.hxx> +#endif +#ifndef _SVX_BRSHITEM_HXX //autogen +#include <svx/brshitem.hxx> +#endif +#ifndef _FRACT_HXX +#include <tools/fract.hxx> +#endif + +#ifndef _WRTSWTBL_HXX +#include <wrtswtbl.hxx> +#endif +#ifndef _SWTABLE_HXX +#include <swtable.hxx> +#endif +#ifndef _FRMFMT_HXX +#include <frmfmt.hxx> +#endif +#ifndef _FMTFSIZE_HXX +#include <fmtfsize.hxx> +#endif +#ifndef _FMTORNT_HXX +#include <fmtornt.hxx> +#endif +#ifndef _FRMATR_HXX +#include <frmatr.hxx> +#endif +#ifndef _HTMLTBL_HXX +#include <htmltbl.hxx> +#endif + + +SV_IMPL_PTRARR( SwWriteTableCells, SwWriteTableCellPtr ) +SV_IMPL_OP_PTRARR_SORT( SwWriteTableRows, SwWriteTableRowPtr ) +SV_IMPL_OP_PTRARR_SORT( SwWriteTableCols, SwWriteTableColPtr ) + +//----------------------------------------------------------------------- + +SwVertOrient SwWriteTableCell::GetVertOri() const +{ + SwVertOrient eCellVertOri = VERT_TOP; + if( pBox->GetSttNd() ) + { + const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet(); + const SfxPoolItem *pItem; + if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, FALSE, &pItem ) ) + { + SwVertOrient eBoxVertOri = + ((const SwFmtVertOrient *)pItem)->GetVertOrient(); + if( VERT_CENTER==eBoxVertOri || VERT_BOTTOM==eBoxVertOri) + eCellVertOri = eBoxVertOri; + } + } + + return eCellVertOri; +} + +//----------------------------------------------------------------------- + +SwWriteTableRow::SwWriteTableRow( long nPosition ) + : nPos(nPosition), pBackground( 0 ), + bTopBorder(TRUE), bBottomBorder(TRUE), + nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX) +{ +} + + +SwWriteTableCell *SwWriteTableRow::AddCell( const SwTableBox *pBox, + USHORT nRow, USHORT nCol, + USHORT nRowSpan, USHORT nColSpan, + long nHeight, + const SvxBrushItem *pBackground ) +{ + SwWriteTableCell *pCell = + new SwWriteTableCell( pBox, nRow, nCol, nRowSpan, nColSpan, + nHeight, pBackground ); + aCells.Insert( pCell, aCells.Count() ); + + return pCell; +} + +//----------------------------------------------------------------------- + +SwWriteTableCol::SwWriteTableCol( USHORT nPosition ) + : nPos(nPosition), + bLeftBorder(TRUE), bRightBorder(TRUE), + nWidthOpt( 0 ), bRelWidthOpt( FALSE ), + bOutWidth( TRUE ) +{ +} + +//----------------------------------------------------------------------- + +long SwWriteTable::GetBoxWidth( const SwTableBox *pBox ) +{ + const SwFrmFmt *pFmt = pBox->GetFrmFmt(); + const SwFmtFrmSize& aFrmSize= + (const SwFmtFrmSize&)pFmt->GetAttr( RES_FRM_SIZE ); + + return aFrmSize.GetSize().Width(); +} + +long SwWriteTable::GetLineHeight( const SwTableLine *pLine ) +{ +#ifndef PRODUCT + BOOL bOldGetLineHeightCalled = bGetLineHeightCalled; + bGetLineHeightCalled = TRUE; +#endif + + long nHeight = 0; + if( bUseLayoutHeights ) + { + // Erstmal versuchen wir die Hoehe ueber das Layout zu bekommen + long nHeight = pLine->GetLineRect( FALSE ).Height(); + if( nHeight > 0 ) + return nHeight; + + // Wenn kein Layout gefunden wurde, gehen wir von festen Hoehen aus. + bUseLayoutHeights = FALSE; + +#ifndef PRODUCT + ASSERT( !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(); + + const SvxBrushItem *pBrushItem = 0; + 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->GetAttr( RES_BOX ); + + USHORT nWidth = 0; + + 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 -= 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 += nLeftSub; + + const SwWriteTableCol *pCol = aCols[nCol]; + if( pCol->HasLeftBorder() ) + 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 += 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 ); + + ASSERT( 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; + } + + ASSERT( 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(); + +#ifndef PRODUCT + 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 ) + { + nRPos += GetLineHeight( pLine ); + SwWriteTableRow *pRow = new SwWriteTableRow( nRPos ); + + USHORT nRow; + if( aRows.Seek_Entry( pRow, &nRow ) ) + delete pRow; + else + aRows.Insert( pRow ); + } + else + { + long nCheckPos = nRPos + GetLineHeight( pLine ); + nRPos = nStartRPos + nParentLineHeight; +#ifndef PRODUCT + SwWriteTableRow aRow( nStartRPos + nParentLineHeight ); + ASSERT( aRows.Seek_Entry(&aRow), + "Parent-Zeile nicht gefunden" ); + ASSERT( !bUseLayoutHeights || + SwWriteTableRow(nCheckPos) == SwWriteTableRow(nRPos), + "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 += (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 ) + { + ASSERT( nLine==0 && nParentLineWidth==0, + "Jetzt wird die Parent-Breite plattgemacht!" ); + nParentLineWidth = nCPos-nStartCPos; + } + } + else + { +#ifndef PRODUCT + USHORT nCheckPos = nCPos + (USHORT)GetBoxWidth( pBox ); + if( !nEndCPos ) + { + nEndCPos = nCheckPos; + } + else + { + ASSERT( SwWriteTableCol(nCheckPos) == + SwWriteTableCol(nEndCPos), + "Zelle enthaelt unterschiedlich breite Zeilen" ); + } +#endif + nCPos = nStartCPos + nParentLineWidth; +#ifndef PRODUCT + SwWriteTableCol aCol( nStartCPos + nParentLineWidth ); + ASSERT( aCols.Seek_Entry(&aCol), + "Parent-Zelle nicht gefunden" ); + ASSERT( 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 ) +{ + 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 ) + nRPos += GetLineHeight( pLine ); + else + nRPos = nStartRPos + nParentLineHeight; + + // Und ihren Index + USHORT nOldRow = nRow; + SwWriteTableRow aRow( nRPos ); + BOOL bFound = aRows.Seek_Entry( &aRow, &nRow ); + ASSERT( bFound, "Wo ist die Zeile geblieben?" ); + + SwWriteTableRow *pRow = aRows[nOldRow]; + SwWriteTableRow *pEndRow = aRows[nRow]; + if( nLine==0 && 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 += (USHORT)GetBoxWidth( pBox ); + if( nBox==nBoxes-1 ) + nParentLineWidth = nCPos - nStartCPos; + } + else + nCPos = nStartCPos + nParentLineWidth; + + // Und ihren Index + USHORT nOldCol = nCol; + SwWriteTableCol aCol( nCPos ); + BOOL bFound = aCols.Seek_Entry( &aCol, &nCol ); + ASSERT( bFound, "Wo ist die Spalte geblieben?" ); + + if( !ShouldExpandSub( pBox, bSubExpanded, nDepth ) ) + { + USHORT nRowSpan = nRow - nOldRow + 1; + 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() ) + { + // Wegen OS/2 schon hier, sonst gibt es einen + // Optimierungs-Fehler!!!! + SwWriteTableCol *pCol = aCols[nOldCol]; + + USHORT nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX; + USHORT nBorderMask = MergeBoxBorders( pBox, nOldRow, nOldCol, + nRowSpan, nColSpan, + nTopBorder, + nBottomBorder ); + + if( !(nBorderMask & 4) ) + pCol->bLeftBorder = FALSE; + + pCol = aCols[nCol]; + if( !(nBorderMask & 8) ) + 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; + } + 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 ); + 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 ) + : nBorderColor( (UINT32)-1 ), + nBorder( 0 ), + nInnerBorder( 0 ), + nCellPadding( 0 ), + nCellSpacing( 0 ), + nTabWidth( nWidth ), + nBaseWidth( nBWidth ), + nLeftSub( nLSub ), nRightSub( nRSub ), + bRelWidths( bRel ), + bUseLayoutHeights( TRUE ), +#ifndef PRODUCT + bGetLineHeightCalled( FALSE ), +#endif + nHeadEndRow( USHRT_MAX ), + 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 ); + + // Einige Twip-Werte an Pixel-Grenzen anpassen + if( !nBorder ) + nBorder = nInnerBorder; +} + + + +SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo ) + : nBorderColor( (UINT32)-1 ), + nBorder( 0 ), + nInnerBorder( 0 ), + nCellPadding( 0 ), + nCellSpacing( 0 ), + nTabWidth( pLayoutInfo->GetWidthOption() ), + nBaseWidth( pLayoutInfo->GetWidthOption() ), + nLeftSub( 0 ), nRightSub( 0 ), + bRelWidths( pLayoutInfo->HasPrcWidthOption() ), + bUseLayoutHeights( FALSE ), +#ifndef PRODUCT + bGetLineHeightCalled( FALSE ), +#endif + nHeadEndRow( 0 ), + 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 ); + 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(); + ASSERT( 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; +} + + + +/************************************************************************* + + Source Code Control System - Header + + $Header: /zpool/svn/migration/cvs_rep_09_09_08/code/sw/source/filter/writer/wrtswtbl.cxx,v 1.1.1.1 2000-09-18 17:14:57 hr Exp $ + + Source Code Control System - Update + + $Log: not supported by cvs2svn $ + Revision 1.3 2000/09/18 16:04:55 willem.vandorp + OpenOffice header added. + + Revision 1.2 2000/03/03 15:22:02 os + StarView remainders removed + + Revision 1.1 1999/10/29 17:38:03 jp + class for build a '2D-Table' from a SwTable + + +*************************************************************************/ + |