summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/wrtww8.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/wrtww8.cxx')
-rw-r--r--sw/source/filter/ww8/wrtww8.cxx3754
1 files changed, 3754 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
new file mode 100644
index 000000000000..6bf7ecbb8cdf
--- /dev/null
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -0,0 +1,3754 @@
+/*************************************************************************
+ *
+ * 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"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+
+#include <iostream>
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <unotools/ucbstreamhelper.hxx>
+
+#include <algorithm>
+
+#include <hintids.hxx>
+#include <string.h> // memcpy()
+#include <osl/endian.h>
+#include <docsh.hxx>
+
+#define _SVSTDARR_BOOLS
+#include <svl/svstdarr.hxx>
+
+#include <unotools/fltrcfg.hxx>
+#include <vcl/salbtype.hxx>
+#include <sot/storage.hxx>
+#include <svl/zformat.hxx>
+#include <sfx2/docinf.hxx>
+#include <editeng/tstpitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/langitem.hxx>
+#include <filter/msfilter/msoleexp.hxx>
+#include <filter/msfilter/msocximex.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <swtypes.hxx>
+#include <swrect.hxx>
+#include <txatbase.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtrowsplt.hxx>
+#include <frmatr.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <shellio.hxx>
+#include <docstat.hxx>
+#include <pagedesc.hxx>
+#include <IMark.hxx>
+#include <swtable.hxx>
+#include <wrtww8.hxx>
+#include <ww8par.hxx>
+#include <fltini.hxx>
+#include <swmodule.hxx>
+#include <section.hxx>
+#include <swfltopt.hxx>
+#include <fmtinfmt.hxx>
+#include <txtinet.hxx>
+#include <fmturl.hxx>
+#include <fesh.hxx>
+#include <svtools/imap.hxx>
+#include <svtools/imapobj.hxx>
+#include <tools/urlobj.hxx>
+#include <mdiexp.hxx> // Progress
+#include <statstr.hrc> // ResId fuer Statusleiste
+#include <fmtline.hxx>
+#include <fmtfsize.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/stlunosequence.hxx>
+#include <writerfilter/doctok/sprmids.hxx>
+
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "ww8attributeoutput.hxx"
+
+#include <IDocumentMarkAccess.hxx>
+#include <xmloff/odffields.hxx>
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
+#include "dbgoutsw.hxx"
+
+#include <sfx2/docfile.hxx>
+#include <svl/stritem.hxx>
+#include <unotools/tempfile.hxx>
+#include <filter/msfilter/mscodec.hxx>
+#include <filter/msfilter/svxmsbas.hxx>
+#include <osl/time.h>
+#include <rtl/random.h>
+#include "WW8Sttbf.hxx"
+#include "WW8FibData.hxx"
+
+using namespace sw::util;
+using namespace sw::types;
+
+/** FKP - Formatted disK Page
+*/
+class WW8_WrFkp
+{
+ BYTE* pFkp; // gesamter Fkp ( zuerst nur FCs und Sprms )
+ BYTE* pOfs; // Pointer auf Offset-Bereich, spaeter nach pFkp kopiert
+ ePLCFT ePlc;
+ short nStartGrp; // ab hier grpprls
+ short nOldStartGrp;
+ BYTE nItemSize;
+ BYTE nIMax; // Anzahl der Eintrags-Paare
+ BYTE nOldVarLen;
+ BYTE nMark;
+ bool bCombined; // true : Einfuegen verboten
+
+ BYTE SearchSameSprm( USHORT nVarLen, const BYTE* pSprms );
+public:
+ WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8);
+ ~WW8_WrFkp();
+ bool Append( WW8_FC nEndFc, USHORT nVarLen = 0, const BYTE* pSprms = 0 );
+ bool Combine();
+ void Write( SvStream& rStrm, SwWW8WrGrf& rGrf );
+
+ bool IsEqualPos(WW8_FC nEndFc) const
+ { return !bCombined && nIMax && nEndFc == ((INT32*)pFkp)[nIMax]; }
+ void MergeToNew( short& rVarLen, BYTE *& pNewSprms );
+ bool IsEmptySprm() const
+ { return !bCombined && nIMax && !nOldVarLen; }
+ void SetNewEnd( WW8_FC nEnd )
+ { ((INT32*)pFkp)[nIMax] = nEnd; }
+
+#ifdef __WW8_NEEDS_COPY
+ WW8_FC GetStartFc() const;
+ WW8_FC GetEndFc() const;
+#else
+ WW8_FC GetStartFc() const { return ((INT32*)pFkp)[0]; };
+ WW8_FC GetEndFc() const { return ((INT32*)pFkp)[nIMax]; };
+#endif // defined __WW8_NEEDS_COPY
+
+ BYTE *CopyLastSprms(BYTE &rLen, bool bVer8);
+};
+
+
+// -------------------------------------------------------------------------
+// class WW8_WrPc sammelt alle Piece-Eintraege fuer ein Piece
+// -------------------------------------------------------------------------
+
+class WW8_WrPc
+{
+ WW8_CP nStartCp; // Start ZeichenPosition vom Text
+ WW8_FC nStartFc; // Start File Position vom Text
+ USHORT nStatus; // Absatzende im Piece ?
+
+public:
+ WW8_WrPc(WW8_FC nSFc, WW8_CP nSCp )
+ : nStartCp( nSCp ), nStartFc( nSFc ), nStatus( 0x0040 )
+ {}
+
+ void SetStatus() { nStatus = 0x0050; }
+ USHORT GetStatus() const { return nStatus; }
+ WW8_CP GetStartCp() const { return nStartCp; }
+ WW8_FC GetStartFc() const { return nStartFc; }
+};
+
+class WW8_WrtBookmarks
+{
+private:
+ SvULongs aSttCps, aEndCps; // Array of Start- and End CPs
+ SvBools aFieldMarks; // If the bookmark is in a field result
+ std::vector<String> maSwBkmkNms; // Array of Sw - Bookmarknames
+ typedef std::vector<String>::iterator myIter;
+
+ USHORT GetPos( const String& rNm );
+
+ //No copying
+ WW8_WrtBookmarks(const WW8_WrtBookmarks&);
+ WW8_WrtBookmarks& operator=(const WW8_WrtBookmarks&);
+public:
+ WW8_WrtBookmarks();
+ ~WW8_WrtBookmarks();
+
+ void Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark* pBkmk=NULL );
+ void Write( WW8Export& rWrt );
+ void MoveFieldMarks(ULONG nFrom,ULONG nTo);
+
+// String GetWWBkmkName( const String& rName ) const;
+};
+
+#define ANZ_DEFAULT_STYLES 16
+
+// die Namen der StorageStreams
+#define sMainStream CREATE_CONST_ASC("WordDocument")
+#define sCompObj CREATE_CONST_ASC("\1CompObj")
+
+
+SV_IMPL_VARARR( WW8Bytes, BYTE )
+SV_IMPL_PTRARR( WW8_WrFkpPtrs, WW8_FkpPtr )
+
+typedef WW8_WrPc* WW8_WrPcPtr;
+SV_DECL_PTRARR_DEL( WW8_WrPcPtrs, WW8_WrPcPtr, 4, 4 )
+SV_IMPL_PTRARR( WW8_WrPcPtrs, WW8_WrPcPtr )
+
+static void WriteDop( WW8Export& rWrt )
+{
+ WW8Dop& rDop = *rWrt.pDop;
+
+ // i#78951#, store the value of unknown compatability options
+ rDop.SetCompatabilityOptions( rWrt.pDoc->Getn32DummyCompatabilityOptions1());
+ rDop.SetCompatabilityOptions2( rWrt.pDoc->Getn32DummyCompatabilityOptions2());
+
+ rDop.fNoLeading = !rWrt.pDoc->get(IDocumentSettingAccess::ADD_EXT_LEADING);
+ rDop.fUsePrinterMetrics = !rWrt.pDoc->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE);
+
+ // default TabStop schreiben
+ const SvxTabStopItem& rTabStop =
+ DefaultItemGet<SvxTabStopItem>(*rWrt.pDoc, RES_PARATR_TABSTOP);
+ rDop.dxaTab = (USHORT)rTabStop[0].GetTabPos();
+
+
+ // Werte aus der DocStatistik (werden aufjedenfall fuer die
+ // DocStat-Felder benoetigt!)
+ rDop.fWCFtnEdn = true; // because they are included in StarWriter
+
+ const SwDocStat& rDStat = rWrt.pDoc->GetDocStat();
+ rDop.cWords = rDStat.nWord;
+ rDop.cCh = rDStat.nChar;
+ rDop.cPg = static_cast< INT16 >(rDStat.nPage);
+ rDop.cParas = rDStat.nPara;
+ rDop.cLines = rDStat.nPara;
+
+ SwDocShell *pDocShell(rWrt.pDoc->GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ uno::Reference<document::XDocumentProperties> xDocProps;
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ xDocProps = xDPS->getDocumentProperties();
+ DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
+ }
+
+ if (!xDocProps.is()) {
+ rDop.dttmCreated = rDop.dttmRevised = rDop.dttmLastPrint = 0x45FBAC69;
+ } else {
+ ::util::DateTime uDT = xDocProps->getCreationDate();
+ Date aD(uDT.Day, uDT.Month, uDT.Year);
+ Time aT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ rDop.dttmCreated = sw::ms::DateTime2DTTM(DateTime(aD,aT));
+ uDT = xDocProps->getModificationDate();
+ Date aD2(uDT.Day, uDT.Month, uDT.Year);
+ Time aT2(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ rDop.dttmRevised = sw::ms::DateTime2DTTM(DateTime(aD2,aT2));
+ uDT = xDocProps->getPrintDate();
+ Date aD3(uDT.Day, uDT.Month, uDT.Year);
+ Time aT3(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ rDop.dttmLastPrint = sw::ms::DateTime2DTTM(DateTime(aD3,aT3));
+ }
+
+ rDop.fProtEnabled = rWrt.pSepx ? rWrt.pSepx->DocumentIsProtected() : 0;
+
+// auch damit werden die DocStat-Felder in Kopf-/Fusszeilen nicht korrekt
+// berechnet.
+// ( we do not have this fields! )
+
+ // und noch fuer die Header und Footers
+ rDop.cWordsFtnEnd = rDStat.nWord;
+ rDop.cChFtnEdn = rDStat.nChar;
+ rDop.cPgFtnEdn = (INT16)rDStat.nPage;
+ rDop.cParasFtnEdn = rDStat.nPara;
+ rDop.cLinesFtnEdn = rDStat.nPara;
+
+ rDop.fDontUseHTMLAutoSpacing = (rWrt.pDoc->get(IDocumentSettingAccess::PARA_SPACE_MAX) != 0);
+
+ rDop.fExpShRtn = !rWrt.pDoc->get(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK); // #i56856#
+
+ rDop.Write( *rWrt.pTableStrm, *rWrt.pFib );
+}
+
+const sal_Unicode *WW8DopTypography::GetJapanNotBeginLevel1()
+{
+ static const sal_Unicode aJapanNotBeginLevel1[nMaxFollowing] =
+ //Japanese Level 1
+ {
+ 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
+ 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
+ 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
+ 0x300f, 0x3011, 0x3015, 0x309b, 0x309c, 0x309d, 0x309e, 0x30fb,
+ 0x30fd, 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a,
+ 0xff1b, 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65,
+ 0xff9e, 0xff9f, 0xffe0
+ };
+ return &aJapanNotBeginLevel1[0];
+}
+
+const sal_Unicode *WW8DopTypography::GetJapanNotEndLevel1()
+{
+ static const sal_Unicode aJapanNotEndLevel1[nMaxLeading] =
+ //Japanese Level 1
+ {
+ 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
+ 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
+ 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
+ };
+ return &aJapanNotEndLevel1[0];
+}
+
+int lcl_CmpBeginEndChars( const rtl::OUString& rSWStr,
+ const sal_Unicode* pMSStr, int nMSStrByteLen )
+{
+ nMSStrByteLen /= sizeof( sal_Unicode );
+ if( nMSStrByteLen > rSWStr.getLength() )
+ nMSStrByteLen = rSWStr.getLength()+1;
+ nMSStrByteLen *= sizeof( sal_Unicode );
+
+ return memcmp( rSWStr.getStr(), pMSStr, nMSStrByteLen );
+}
+
+/*
+Converts the OOo Asian Typography into a best fit match for Microsoft
+Asian typography. This structure is actually dumped to disk within the
+Dop Writer. Assumption is that rTypo is cleared to 0 on entry
+*/
+void WW8Export::ExportDopTypography(WW8DopTypography &rTypo)
+{
+ static const sal_Unicode aLangNotBegin[4][WW8DopTypography::nMaxFollowing]=
+ {
+ //Japanese Level 1
+ {
+ 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
+ 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
+ 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
+ 0x300f, 0x3011, 0x3015, 0x3041, 0x3043, 0x3045, 0x3047, 0x3049,
+ 0x3063, 0x3083, 0x3085, 0x3087, 0x308e, 0x309b, 0x309c, 0x309d,
+ 0x309e, 0x30a1, 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30c3, 0x30e3,
+ 0x30e5, 0x30e7, 0x30ee, 0x30f5, 0x30f6, 0x30fb, 0x30fc, 0x30fd,
+ 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b,
+ 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65, 0xff67,
+ 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
+ 0xff70, 0xff9e, 0xff9f, 0xffe0
+ },
+ //Simplified Chinese
+ {
+ 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
+ 0x007d, 0x00a8, 0x00b7, 0x02c7, 0x02c9, 0x2015, 0x2016, 0x2019,
+ 0x201d, 0x2026, 0x2236, 0x3001, 0x3002, 0x3003, 0x3005, 0x3009,
+ 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x3017, 0xff01, 0xff02,
+ 0xff07, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
+ 0xff40, 0xff5c, 0xff5d, 0xff5e, 0xffe0
+ },
+ //Korean
+ {
+ 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
+ 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2032, 0x2033,
+ 0x2103, 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0xff01,
+ 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
+ 0xff5d, 0xffe0
+ },
+ //Traditional Chinese
+ {
+ 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
+ 0x007d, 0x00a2, 0x00b7, 0x2013, 0x2014, 0x2019, 0x201d, 0x2022,
+ 0x2025, 0x2026, 0x2027, 0x2032, 0x2574, 0x3001, 0x3002, 0x3009,
+ 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x301e, 0xfe30, 0xfe31,
+ 0xfe33, 0xfe34, 0xfe36, 0xfe38, 0xfe3a, 0xfe3c, 0xfe3e, 0xfe40,
+ 0xfe42, 0xfe44, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55,
+ 0xfe56, 0xfe57, 0xfe5a, 0xfe5c, 0xfe5e, 0xff01, 0xff09, 0xff0c,
+ 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff5c, 0xff5d, 0xff64
+ },
+ };
+
+ static const sal_Unicode aLangNotEnd[4][WW8DopTypography::nMaxLeading] =
+ {
+ //Japanese Level 1
+ {
+ 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
+ 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
+ 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
+ },
+ //Simplified Chinese
+ {
+ 0x0028, 0x005b, 0x007b, 0x00b7, 0x2018, 0x201c, 0x3008, 0x300a,
+ 0x300c, 0x300e, 0x3010, 0x3014, 0x3016, 0xff08, 0xff0e, 0xff3b,
+ 0xff5b, 0xffe1, 0xffe5
+ },
+ //Korean
+ {
+ 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c,
+ 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04, 0xff08,
+ 0xff3b, 0xff5b, 0xffe6
+ },
+ //Traditional Chinese
+ {
+ 0x0028, 0x005b, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c, 0x2035,
+ 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0x301d, 0xfe35,
+ 0xfe37, 0xfe39, 0xfe3b, 0xfe3d, 0xfe3f, 0xfe41, 0xfe43, 0xfe59,
+ 0xfe5b, 0xfe5d, 0xff08, 0xff5b
+ },
+ };
+
+ const i18n::ForbiddenCharacters *pForbidden = 0;
+ const i18n::ForbiddenCharacters *pUseMe = 0;
+ BYTE nUseReserved=0;
+ int nNoNeeded=0;
+ /*
+ Now we have some minor difficult issues, to wit...
+ a. MicroSoft Office can only store one set of begin and end characters in
+ a given document, not one per language.
+ b. StarOffice has only a concept of one set of begin and end characters for
+ a given language, i.e. not the two levels of kinsoku in japanese
+
+ What is unknown as yet is if our default begin and end chars for
+ japanese, chinese tradition, chinese simplified and korean are different
+ in Word and Writer. I already suspect that they are different between
+ different version of word itself.
+
+ So what have come up with is to simply see if any of the four languages
+ in OOo have been changed away from OUR defaults, and if one has then
+ export that. If more than one has in the future we may hack in something
+ which examines our document properties to see which language is used the
+ most and choose that, for now we choose the first and throw an ASSERT.
+ */
+
+ /*Our default Japanese Level is 2, this is a special MS hack to set this*/
+ rTypo.reserved2 = 1;
+
+ for (rTypo.reserved1=8;rTypo.reserved1>0;rTypo.reserved1-=2)
+ {
+ if (0 != (pForbidden = pDoc->getForbiddenCharacters(rTypo.GetConvertedLang(),
+ false)))
+ {
+ int nIdx = (rTypo.reserved1-2)/2;
+ if( lcl_CmpBeginEndChars( pForbidden->endLine,
+ aLangNotEnd[ nIdx ], sizeof(aLangNotEnd[ nIdx ]) ) ||
+ lcl_CmpBeginEndChars( pForbidden->beginLine,
+ aLangNotBegin[ nIdx ], sizeof(aLangNotBegin[ nIdx ]) ) )
+ {
+ //One exception for Japanese, if it matches a level 1 we
+ //can use one extra flag for that, rather than use a custom
+ if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
+ {
+ if (
+ !lcl_CmpBeginEndChars
+ (
+ pForbidden->endLine,
+ rTypo.GetJapanNotEndLevel1(),
+ rTypo.nMaxLeading * sizeof(sal_Unicode)
+ )
+ &&
+ !lcl_CmpBeginEndChars
+ (
+ pForbidden->beginLine,
+ rTypo.GetJapanNotBeginLevel1(),
+ rTypo.nMaxFollowing * sizeof(sal_Unicode)
+ )
+ )
+ {
+ rTypo.reserved2 = 0;
+ continue;
+ }
+ }
+
+ if (!pUseMe)
+ {
+ pUseMe = pForbidden;
+ nUseReserved = rTypo.reserved1;
+ rTypo.iLevelOfKinsoku = 2;
+ }
+ nNoNeeded++;
+ }
+ }
+ }
+
+ ASSERT( nNoNeeded<=1, "Example of unexportable forbidden chars" );
+ rTypo.reserved1=nUseReserved;
+ if (rTypo.iLevelOfKinsoku)
+ {
+ rTypo.cchFollowingPunct = msword_cast<sal_Int16>
+ (pUseMe->beginLine.getLength());
+ if (rTypo.cchFollowingPunct > WW8DopTypography::nMaxFollowing - 1)
+ rTypo.cchFollowingPunct = WW8DopTypography::nMaxFollowing - 1;
+
+ rTypo.cchLeadingPunct = msword_cast<sal_Int16>
+ (pUseMe->endLine.getLength());
+ if (rTypo.cchLeadingPunct > WW8DopTypography::nMaxLeading - 1)
+ rTypo.cchLeadingPunct = WW8DopTypography::nMaxLeading -1;
+
+ memcpy(rTypo.rgxchFPunct,pUseMe->beginLine.getStr(),
+ (rTypo.cchFollowingPunct+1)*2);
+
+ memcpy(rTypo.rgxchLPunct,pUseMe->endLine.getStr(),
+ (rTypo.cchLeadingPunct+1)*2);
+ }
+
+ const IDocumentSettingAccess* pIDocumentSettingAccess = GetWriter().getIDocumentSettingAccess();
+
+ rTypo.fKerningPunct = pIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION);
+ rTypo.iJustification = pDoc->getCharacterCompressionType();
+}
+
+// HasItem ist fuer die Zusammenfassung der Doppel-Attribute
+// Underline / WordLineMode und Box / Shadow.
+// Es kann nur etwas gefunden werden, wenn diese Methode innerhalb
+// der aufgerufenen Methoden WW8_SwAttrIter::OutAttr() und
+// WW8Export::OutputItemSet() benutzt wird.
+const SfxPoolItem* MSWordExportBase::HasItem( USHORT nWhich ) const
+{
+ const SfxPoolItem* pItem=0;
+ if (pISet)
+ {
+ // if write a EditEngine text, then the WhichIds are greater as
+ // ourer own Ids. So the Id have to translate from our into the
+ // EditEngine Range
+ nWhich = sw::hack::GetSetWhichFromSwDocWhich(*pISet, *pDoc, nWhich);
+ if (nWhich && SFX_ITEM_SET != pISet->GetItemState(nWhich, true, &pItem))
+ pItem = 0;
+ }
+ else if( pChpIter )
+ pItem = pChpIter->HasTextItem( nWhich );
+ else
+ {
+ ASSERT( !this, "Wo ist mein ItemSet / pChpIter ?" );
+ pItem = 0;
+ }
+ return pItem;
+}
+
+const SfxPoolItem& MSWordExportBase::GetItem(USHORT nWhich) const
+{
+ const SfxPoolItem* pItem;
+ if (pISet)
+ {
+ // if write a EditEngine text, then the WhichIds are greater as
+ // ourer own Ids. So the Id have to translate from our into the
+ // EditEngine Range
+ nWhich = sw::hack::GetSetWhichFromSwDocWhich(*pISet, *pDoc, nWhich);
+ ASSERT(nWhich != 0, "All broken, Impossible");
+ pItem = &pISet->Get(nWhich, true);
+ }
+ else if( pChpIter )
+ pItem = &pChpIter->GetItem( nWhich );
+ else
+ {
+ ASSERT( !this, "Wo ist mein ItemSet / pChpIter ?" );
+ pItem = 0;
+ }
+ return *pItem;
+}
+
+//------------------------------------------------------------------------------
+
+WW8_WrPlc1::WW8_WrPlc1( USHORT nStructSz )
+ : aPos( 16, 16 ), nStructSiz( nStructSz )
+{
+ nDataLen = 16 * nStructSz;
+ pData = new BYTE[ nDataLen ];
+}
+
+WW8_WrPlc1::~WW8_WrPlc1()
+{
+ delete[] pData;
+}
+
+WW8_CP WW8_WrPlc1::Prev() const
+{
+ USHORT nLen = aPos.Count();
+ ASSERT(nLen,"Prev called on empty list");
+ return nLen ? aPos[nLen-1] : 0;
+}
+
+void WW8_WrPlc1::Append( WW8_CP nCp, const void* pNewData )
+{
+ ULONG nInsPos = aPos.Count() * nStructSiz;
+ aPos.Insert( nCp, aPos.Count() );
+ if( nDataLen < nInsPos + nStructSiz )
+ {
+ BYTE* pNew = new BYTE[ 2 * nDataLen ];
+ memmove( pNew, pData, nDataLen );
+ delete[] pData;
+ pData = pNew;
+ nDataLen *= 2;
+ }
+ memcpy( pData + nInsPos, pNewData, nStructSiz );
+}
+
+void WW8_WrPlc1::Finish( ULONG nLastCp, ULONG nSttCp )
+{
+ if( aPos.Count() )
+ {
+ aPos.Insert( nLastCp, aPos.Count() );
+ if( nSttCp )
+ for( USHORT n = 0; n < aPos.Count(); ++n )
+ aPos[ n ] -= nSttCp;
+ }
+}
+
+
+void WW8_WrPlc1::Write( SvStream& rStrm )
+{
+ USHORT i;
+ for( i = 0; i < aPos.Count(); ++i )
+ SwWW8Writer::WriteLong( rStrm, aPos[i] );
+ if( i )
+ rStrm.Write( pData, (i-1) * nStructSiz );
+}
+
+//------------------------------------------------------------------------------
+// Klasse WW8_WrPlcFld fuer Felder
+//------------------------------------------------------------------------------
+
+
+bool WW8_WrPlcFld::Write( WW8Export& rWrt )
+{
+ if( WW8_WrPlc1::Count() <= 1 )
+ return false;
+
+ WW8_FC *pfc;
+ sal_Int32 *plc;
+ switch (nTxtTyp)
+ {
+ case TXT_MAINTEXT:
+ pfc = &rWrt.pFib->fcPlcffldMom;
+ plc = &rWrt.pFib->lcbPlcffldMom;
+ break;
+ case TXT_HDFT:
+ pfc = &rWrt.pFib->fcPlcffldHdr;
+ plc = &rWrt.pFib->lcbPlcffldHdr;
+ break;
+
+ case TXT_FTN:
+ pfc = &rWrt.pFib->fcPlcffldFtn;
+ plc = &rWrt.pFib->lcbPlcffldFtn;
+ break;
+
+ case TXT_EDN:
+ pfc = &rWrt.pFib->fcPlcffldEdn;
+ plc = &rWrt.pFib->lcbPlcffldEdn;
+ break;
+
+ case TXT_ATN:
+ pfc = &rWrt.pFib->fcPlcffldAtn;
+ plc = &rWrt.pFib->lcbPlcffldAtn;
+ break;
+
+ case TXT_TXTBOX:
+ pfc = &rWrt.pFib->fcPlcffldTxbx;
+ plc = &rWrt.pFib->lcbPlcffldTxbx;
+ break;
+
+ case TXT_HFTXTBOX:
+ pfc = &rWrt.pFib->fcPlcffldHdrTxbx;
+ plc = &rWrt.pFib->lcbPlcffldHdrTxbx;
+ break;
+
+ default:
+ pfc = plc = 0;
+ break;
+ }
+
+ if( pfc && plc )
+ {
+ ULONG nFcStart = rWrt.pTableStrm->Tell();
+ WW8_WrPlc1::Write( *rWrt.pTableStrm );
+ *pfc = nFcStart;
+ *plc = rWrt.pTableStrm->Tell() - nFcStart;
+ }
+ return true;
+}
+
+bool WW8_WrMagicTable::Write( WW8Export& rWrt )
+{
+ if( WW8_WrPlc1::Count() <= 1 )
+ return false;
+ ULONG nFcStart = rWrt.pTableStrm->Tell();
+ WW8_WrPlc1::Write( *rWrt.pTableStrm );
+ rWrt.pFib->fcPlcfTch = nFcStart;
+ rWrt.pFib->lcbPlcfTch = rWrt.pTableStrm->Tell() - nFcStart;
+ return true;
+}
+
+void WW8_WrMagicTable::Append( WW8_CP nCp, ULONG nData)
+{
+ SVBT32 nLittle;
+ /*
+ Tell the undocumented table hack that everything between here and the last
+ table position is nontable text, don't do it if the previous position is
+ the same as this one, as that would be a region of 0 length
+ */
+ if ((!Count()) || (Prev() != nCp))
+ {
+ UInt32ToSVBT32(nData,nLittle);
+ WW8_WrPlc1::Append(nCp, nLittle);
+ }
+}
+
+//--------------------------------------------------------------------------
+
+void SwWW8Writer::FillCount( SvStream& rStrm, ULONG nCount )
+{
+ static const UINT32 aNulls[16] =
+ {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 64 Byte
+ };
+
+ while (nCount > 64)
+ {
+ rStrm.Write( aNulls, 64 ); // in 64-Byte-Schritten
+ nCount -= 64;
+ }
+ rStrm.Write( aNulls, nCount ); // Rest ( 0 .. 64 Bytes ) schreiben
+}
+
+ULONG SwWW8Writer::FillUntil( SvStream& rStrm, ULONG nEndPos )
+{
+ ULONG nCurPos = rStrm.Tell();
+ if( !nEndPos ) // nEndPos == 0 -> next Page
+ nEndPos = (nCurPos + 0x1ff) & ~0x1ffUL;
+
+ if( nEndPos > nCurPos )
+ SwWW8Writer::FillCount( rStrm, nEndPos - nCurPos );
+#ifdef DBG_UTIL
+ else
+ ASSERT( nEndPos == nCurPos, "Falsches FillUntil()" );
+#endif
+ return rStrm.Tell();
+}
+
+
+//--------------------------------------------------------------------------
+/* */
+
+WW8_WrPlcPn::WW8_WrPlcPn( WW8Export& rWr, ePLCFT ePl, WW8_FC nStartFc )
+ : rWrt(rWr), nFkpStartPage(0), ePlc(ePl), nMark(0)
+{
+ WW8_FkpPtr pF = new WW8_WrFkp( ePlc, nStartFc, rWrt.bWrtWW8 );
+ aFkps.Insert( pF, aFkps.Count() );
+}
+
+WW8_WrPlcPn::~WW8_WrPlcPn()
+{
+ aFkps.DeleteAndDestroy( 0, aFkps.Count() );
+}
+
+BYTE *WW8_WrPlcPn::CopyLastSprms(BYTE &rLen)
+{
+ WW8_FkpPtr pF = aFkps.GetObject(aFkps.Count() - 1);
+ return pF->CopyLastSprms(rLen, rWrt.bWrtWW8);
+}
+
+void WW8_WrPlcPn::AppendFkpEntry(WW8_FC nEndFc,short nVarLen,const BYTE* pSprms)
+{
+ WW8_FkpPtr pF = aFkps.GetObject( aFkps.Count() - 1 );
+
+ // big sprm? build the sprmPHugePapx
+ BYTE* pNewSprms = (BYTE*)pSprms;
+ BYTE aHugePapx[ 8 ];
+ if( rWrt.bWrtWW8 && PAP == ePlc && 488 < nVarLen )
+ {
+ BYTE* p = aHugePapx;
+ *p++ = *pSprms++; // set style Id
+ *p++ = *pSprms++;
+ nVarLen -= 2;
+
+ long nDataPos = rWrt.pDataStrm->Tell();
+ SwWW8Writer::WriteShort( *rWrt.pDataStrm, nVarLen );
+ rWrt.pDataStrm->Write( pSprms, nVarLen );
+
+ Set_UInt16( p, 0x6646 ); // set SprmCode
+ Set_UInt32( p, nDataPos ); // set startpos (FC) in the datastream
+ nVarLen = static_cast< short >(p - aHugePapx);
+ pSprms = pNewSprms = aHugePapx;
+ }
+ // if append at the same FC-EndPos and there are sprms, then get the old
+ // sprms and erase it; they will append now with the new sprms
+ else if( nVarLen && pF->IsEqualPos( nEndFc ))
+ pF->MergeToNew( nVarLen, pNewSprms );
+ // has the prev EndFC an empty sprm and the current is empty too, then
+ // expand only the old EndFc to the new EndFc
+ else if( !nVarLen && pF->IsEmptySprm() )
+ {
+ pF->SetNewEnd( nEndFc );
+ return ;
+ }
+
+ bool bOk = pF->Append(nEndFc, nVarLen, pNewSprms);
+ if( !bOk )
+ {
+ pF->Combine();
+ pF = new WW8_WrFkp( ePlc, pF->GetEndFc(), rWrt.bWrtWW8 );// Anfang neuer Fkp
+ // == Ende alter Fkp
+ aFkps.Insert( pF, aFkps.Count() );
+ if( !pF->Append( nEndFc, nVarLen, pNewSprms ) )
+ {
+ ASSERT( !this, "Sprm liess sich nicht einfuegen" );
+ }
+ }
+ if( pNewSprms != pSprms ) //Merge to new has created a new block
+ delete[] pNewSprms;
+}
+
+void WW8_WrPlcPn::WriteFkps()
+{
+ nFkpStartPage = (USHORT) ( SwWW8Writer::FillUntil( rWrt.Strm() ) >> 9 );
+
+ for( USHORT i = 0; i < aFkps.Count(); i++ )
+ aFkps.GetObject( i )->Write( rWrt.Strm(), *rWrt.pGrf );
+
+ if( CHP == ePlc )
+ {
+ rWrt.pFib->pnChpFirst = nFkpStartPage;
+ rWrt.pFib->cpnBteChp = aFkps.Count();
+ }
+ else
+ {
+ rWrt.pFib->pnPapFirst = nFkpStartPage;
+ rWrt.pFib->cpnBtePap = aFkps.Count();
+ }
+}
+
+void WW8_WrPlcPn::WritePlc()
+{
+ ULONG nFcStart = rWrt.pTableStrm->Tell();
+ USHORT i;
+
+ for( i = 0; i < aFkps.Count(); i++ )
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm,
+ aFkps.GetObject( i )->GetStartFc() );
+
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm,
+ aFkps.GetObject( i - 1 )->GetEndFc() );
+
+ // fuer jedes FKP die Page ausgeben
+ if( rWrt.bWrtWW8) // fuer WW97 Long-Ausgabe
+ for ( i = 0; i < aFkps.Count(); i++)
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, i + nFkpStartPage );
+ else // fuer WW95 Short-Ausgabe
+ for ( i = 0; i < aFkps.Count(); i++)
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, i + nFkpStartPage );
+
+ if( CHP == ePlc )
+ {
+ rWrt.pFib->fcPlcfbteChpx = nFcStart;
+ rWrt.pFib->lcbPlcfbteChpx = rWrt.pTableStrm->Tell() - nFcStart;
+ }
+ else
+ {
+ rWrt.pFib->fcPlcfbtePapx = nFcStart;
+ rWrt.pFib->lcbPlcfbtePapx = rWrt.pTableStrm->Tell() - nFcStart;
+ }
+}
+
+//--------------------------------------------------------------------------
+/* */
+
+WW8_WrFkp::WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8)
+ : ePlc(ePl), nStartGrp(511), nOldStartGrp(511),
+ nItemSize( ( CHP == ePl ) ? 1 : ( bWrtWW8 ? 13 : 7 )),
+ nIMax(0), nOldVarLen(0), nMark(0), bCombined(false)
+{
+ pFkp = (BYTE*)new INT32[128]; // 512 Byte
+ pOfs = (BYTE*)new INT32[128]; // 512 Byte
+ memset( pFkp, 0, 4 * 128 );
+ memset( pOfs, 0, 4 * 128 );
+ ( (INT32*)pFkp )[0] = nStartFc; // 0. FC-Eintrag auf nStartFc
+}
+
+WW8_WrFkp::~WW8_WrFkp()
+{
+ delete[] (INT32 *)pFkp;
+ delete[] (INT32 *)pOfs;
+}
+
+BYTE WW8_WrFkp::SearchSameSprm( USHORT nVarLen, const BYTE* pSprms )
+{
+ if( 3 < nVarLen )
+ {
+ // if the sprms contained picture-references then never equal!
+ for( BYTE n = static_cast< BYTE >(nVarLen - 1); 3 < n; --n )
+ if( pSprms[ n ] == GRF_MAGIC_3 &&
+ pSprms[ n-1 ] == GRF_MAGIC_2 &&
+ pSprms[ n-2 ] == GRF_MAGIC_1 )
+ return 0;
+ }
+
+ short i;
+ for( i = 0; i < nIMax; i++ )
+ {
+ BYTE nStart = pOfs[i * nItemSize];
+ if( nStart )
+ { // Hat Sprms
+ const BYTE* p = pFkp + ( (USHORT)nStart << 1 );
+ if( ( CHP == ePlc
+ ? (*p++ == nVarLen)
+ : (((USHORT)*p++ << 1 ) == (( nVarLen+1) & 0xfffe)) )
+ && !memcmp( p, pSprms, nVarLen ) )
+ return nStart; // gefunden
+ }
+ }
+ return 0; // nicht gefunden
+}
+
+BYTE *WW8_WrFkp::CopyLastSprms(BYTE &rLen, bool bVer8)
+{
+ rLen=0;
+ BYTE *pStart=0,*pRet=0;
+
+ if (!bCombined)
+ pStart = pOfs;
+ else
+ pStart = pFkp + ( nIMax + 1 ) * 4;
+
+ BYTE nStart = *(pStart + (nIMax-1) * nItemSize);
+
+ const BYTE* p = pFkp + ( (USHORT)nStart << 1 );
+
+ if (!*p && bVer8)
+ p++;
+
+ if (*p)
+ {
+ rLen = *p++;
+ if (PAP == ePlc)
+ rLen *= 2;
+ pRet = new BYTE[rLen];
+ memcpy(pRet,p,rLen);
+ }
+ return pRet;
+}
+
+bool WW8_WrFkp::Append( WW8_FC nEndFc, USHORT nVarLen, const BYTE* pSprms )
+{
+ ASSERT( !nVarLen || pSprms, "Item-Pointer fehlt" );
+ ASSERT( nVarLen < ( ( ePlc == PAP ) ? 497U : 502U ), "Sprms zu lang !" );
+
+ if( bCombined )
+ {
+ ASSERT( !this, "Fkp::Append: Fkp is already combined" );
+ return false;
+ }
+ INT32 n = ((INT32*)pFkp)[nIMax]; // letzter Eintrag
+ if( nEndFc <= n )
+ {
+ ASSERT( nEndFc >= n, "+Fkp: FC rueckwaerts" );
+ ASSERT( !nVarLen || !pSprms || nEndFc != n,
+ "+Fkp: selber FC mehrfach benutzt" );
+ // selber FC ohne Sprm wird ohne zu mosern ignoriert.
+
+ return true; // ignorieren, keinen neuen Fkp anlegen
+ }
+
+ BYTE nOldP = ( nVarLen ) ? SearchSameSprm( nVarLen, pSprms ) : 0;
+ // Kombinieren gleicher Eintraege
+ short nOffset=0, nPos = nStartGrp;
+ if (nVarLen && !nOldP)
+ {
+ nPos = PAP == ePlc
+ ? ( 13 == nItemSize // HACK: PAP und bWrtWW8 !!
+ ? (nStartGrp & 0xFFFE ) - nVarLen - 1
+ : (nStartGrp - (((nVarLen + 1) & 0xFFFE)+1)) & 0xFFFE )
+ : ((nStartGrp - nVarLen - 1) & 0xFFFE);
+ if( nPos < 0 )
+ return false; // Passt absolut nicht
+ nOffset = nPos; // Offset merken (kann auch ungerade sein!)
+ nPos &= 0xFFFE; // Pos fuer Sprms ( gerade Pos )
+ }
+
+ if( (USHORT)nPos <= ( nIMax + 2U ) * 4U + ( nIMax + 1U ) * nItemSize )
+ // Passt hinter CPs und Offsets ?
+ return false; // Nein
+
+ ((INT32*)pFkp)[nIMax + 1] = nEndFc; // FC eintragen
+
+ nOldVarLen = (BYTE)nVarLen;
+ if( nVarLen && !nOldP )
+ { // echt eintragen
+ nOldStartGrp = nStartGrp;
+
+ nStartGrp = nPos;
+ pOfs[nIMax * nItemSize] = (BYTE)( nStartGrp >> 1 );
+ // ( DatenAnfg >> 1 ) eintragen
+ BYTE nCnt = static_cast< BYTE >(CHP == ePlc
+ ? ( nVarLen < 256 ) ? (BYTE) nVarLen : 255
+ : ( ( nVarLen + 1 ) >> 1 ));
+
+ pFkp[ nOffset ] = nCnt; // DatenLaenge eintragen
+ memcpy( pFkp + nOffset + 1, pSprms, nVarLen ); // Sprms speichern
+ }
+ else
+ {
+ // nicht echt eintragen ( keine Sprms oder Wiederholung )
+ // DatenAnfg 0 ( keine Daten ) oder Wiederholung
+ pOfs[nIMax * nItemSize] = nOldP;
+ }
+ nIMax++;
+ return true;
+}
+
+bool WW8_WrFkp::Combine()
+{
+ if( bCombined )
+ return false;
+ if( nIMax )
+ memcpy( pFkp + ( nIMax + 1 ) * 4, pOfs, nIMax * nItemSize );
+ DELETEZ( pOfs );
+ ((BYTE*)pFkp)[511] = nIMax;
+ bCombined = true;
+
+#if defined OSL_BIGENDIAN // Hier werden nur die FCs gedreht, die
+ USHORT i; // Sprms muessen an anderer Stelle gedreht
+ // werden
+ UINT32* p;
+ for( i = 0, p = (UINT32*)pFkp; i <= nIMax; i++, p++ )
+ *p = SWAPLONG( *p );
+#endif // ifdef OSL_BIGENDIAN
+
+ return true;
+}
+
+void WW8_WrFkp::Write( SvStream& rStrm, SwWW8WrGrf& rGrf )
+{
+ Combine(); // Falls noch nicht Combined
+
+ BYTE* p; // Suche Magic fuer nPicLocFc
+ BYTE* pEnd = pFkp + nStartGrp;
+ for( p = pFkp + 511 - 4; p >= pEnd; p-- )
+ {
+ if( *p != GRF_MAGIC_1 ) // Suche nach Signatur 0x12 0x34 0x56 0xXX
+ continue;
+ if( *(p+1) != GRF_MAGIC_2 )
+ continue;
+ if( *(p+2) != GRF_MAGIC_3 )
+ continue;
+
+ SVBT32 nPos; // Signatur gefunden
+ UInt32ToSVBT32( rGrf.GetFPos(), nPos ); // FilePos der Grafik
+ memcpy( p, nPos, 4 ); // Patche FilePos ueber Signatur
+ }
+ rStrm.Write( pFkp, 512 );
+}
+
+void WW8_WrFkp::MergeToNew( short& rVarLen, BYTE *& rpNewSprms )
+{
+ BYTE nStart = pOfs[ (nIMax-1) * nItemSize ];
+ if( nStart )
+ { // Hat Sprms
+ BYTE* p = pFkp + ( (USHORT)nStart << 1 );
+
+ // old and new equal? Then copy only one into the new sprms
+ if( nOldVarLen == rVarLen && !memcmp( p+1, rpNewSprms, nOldVarLen ))
+ {
+ BYTE* pNew = new BYTE[ nOldVarLen ];
+ memcpy( pNew, p+1, nOldVarLen );
+ rpNewSprms = pNew;
+ }
+ else
+ {
+ BYTE* pNew = new BYTE[ nOldVarLen + rVarLen ];
+ memcpy( pNew, p+1, nOldVarLen );
+ memcpy( pNew + nOldVarLen, rpNewSprms, rVarLen );
+
+ rpNewSprms = pNew;
+ rVarLen = rVarLen + nOldVarLen;
+ }
+ --nIMax;
+ // if this sprms dont used from others, remove it
+ bool bFnd = false;
+ for (USHORT n = 0; n < nIMax; ++n)
+ {
+ if (nStart == pOfs[n * nItemSize])
+ {
+ bFnd = true;
+ break;
+ }
+ }
+ if (!bFnd)
+ {
+ nStartGrp = nOldStartGrp;
+ memset( p, 0, nOldVarLen+1 );
+ }
+ }
+}
+
+#ifdef __WW8_NEEDS_COPY
+
+WW8_FC WW8_WrFkp::GetStartFc() const
+{
+// wenn bCombined, dann ist das Array ab pFkp schon Bytemaessig auf LittleEndian
+// umgedreht, d.h. zum Herausholen der Anfangs- und Endpositionen muss
+// zurueckgedreht werden.
+ if( bCombined )
+ return SVBT32ToUInt32( pFkp ); // 0. Element
+ return ((INT32*)pFkp)[0];
+}
+
+WW8_FC WW8_WrFkp::GetEndFc() const
+{
+ if( bCombined )
+ return SVBT32ToUInt32( &(pFkp[nIMax*4]) ); // nIMax-tes SVBT32-Element
+ return ((INT32*)pFkp)[nIMax];
+}
+
+#endif // defined __WW8_NEEDS_COPY
+
+
+
+//--------------------------------------------------------------------------
+// Methoden fuer Piece-Table-Verwaltung
+//--------------------------------------------------------------------------
+
+WW8_WrPct::WW8_WrPct(WW8_FC nfcMin, bool bSaveUniCode)
+ : pPcts(new WW8_WrPcPtrs), nOldFc(nfcMin), bIsUni(bSaveUniCode)
+{
+ AppendPc( nOldFc, bIsUni );
+}
+
+WW8_WrPct::~WW8_WrPct()
+{
+ delete pPcts;
+}
+
+// Piece fuellen und neues Piece erzeugen
+void WW8_WrPct::AppendPc(WW8_FC nStartFc, bool bIsUnicode)
+{
+ WW8_CP nStartCp = nStartFc - nOldFc; // Textbeginn abziehen
+ if ( !nStartCp )
+ {
+ if ( 0 != pPcts->Count() )
+ {
+ ASSERT( 1 == pPcts->Count(), "Leeres Piece !!");
+ pPcts->DeleteAndDestroy( pPcts->Count() - 1 , 1);
+ }
+ }
+
+ nOldFc = nStartFc; // StartFc als alten merken
+
+ if( bIsUni )
+ nStartCp >>= 1; // Bei Unicode Anzahl der Zeichen / 2
+
+
+ if ( !bIsUnicode )
+ {
+ nStartFc <<= 1; // Adresse * 2
+ nStartFc |= 0x40000000; // Vorletztes Bit setzen fuer !Unicode
+ }
+
+ if( pPcts->Count() )
+ nStartCp += pPcts->GetObject( pPcts->Count()- 1 )->GetStartCp();
+
+ WW8_WrPcPtr pPc = new WW8_WrPc( nStartFc, nStartCp );
+ pPcts->Insert( pPc, pPcts->Count() );
+
+ bIsUni = bIsUnicode;
+}
+
+
+void WW8_WrPct::WritePc( WW8Export& rWrt )
+{
+ ULONG nPctStart;
+ ULONG nOldPos, nEndPos;
+ USHORT i;
+
+ nPctStart = rWrt.pTableStrm->Tell(); // Beginn Piece-Table
+ *rWrt.pTableStrm << ( char )0x02; // Statusbyte PCT
+ nOldPos = nPctStart + 1; // Position merken
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); // Laenge folgt
+ for( i = 0; i < pPcts->Count(); ++i ) // Bereiche
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm,
+ pPcts->GetObject( i )->GetStartCp() );
+
+
+ // die letzte Pos noch errechnen
+ ULONG nStartCp = rWrt.pFib->fcMac - nOldFc;
+ if( bIsUni )
+ nStartCp >>= 1; // Bei Unicode Anzahl der Zeichen / 2
+ nStartCp += pPcts->GetObject( i-1 )->GetStartCp();
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, nStartCp );
+
+ // Pieceverweise
+ for ( i = 0; i < pPcts->Count(); ++i )
+ {
+ WW8_WrPcPtr pPc = pPcts->GetObject( i );
+
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, pPc->GetStatus());
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, pPc->GetStartFc());
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0); // PRM=0
+ }
+
+ // Eintraege im FIB
+ rWrt.pFib->fcClx = nPctStart;
+ nEndPos = rWrt.pTableStrm->Tell();
+ rWrt.pFib->lcbClx = nEndPos - nPctStart;
+
+ // und noch die Laenge eintragen
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, nOldPos,
+ nEndPos - nPctStart-5 );
+
+}
+
+void WW8_WrPct::SetParaBreak()
+{
+ ASSERT( pPcts->Count(),"SetParaBreak : aPcts.Count = 0" );
+ pPcts->GetObject( pPcts->Count() - 1)->SetStatus();
+}
+
+WW8_CP WW8_WrPct::Fc2Cp( ULONG nFc ) const
+{
+ ASSERT( nFc >= (ULONG)nOldFc, "FilePos liegt vorm letzten Piece" );
+ ASSERT( pPcts->Count(), "Fc2Cp noch kein Piece vorhanden" );
+
+ nFc -= nOldFc;
+ if( bIsUni )
+ nFc /= 2;
+ return nFc + pPcts->GetObject( pPcts->Count() - 1 )->GetStartCp();
+}
+
+//--------------------------------------------------------------------------
+/* */
+
+WW8_WrtBookmarks::WW8_WrtBookmarks()
+ : aSttCps( 0, 16 ), aEndCps( 0, 16 )
+{
+}
+
+WW8_WrtBookmarks::~WW8_WrtBookmarks()
+{
+}
+
+void WW8_WrtBookmarks::Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark* )
+{
+ USHORT nPos = GetPos( rNm );
+ if( USHRT_MAX == nPos )
+ {
+ // new -> insert as start position
+ nPos = aSttCps.Count();
+ myIter aIter = maSwBkmkNms.end();
+ // sort by startposition
+ // theory: write continuous -> then the new position is at end
+ while( nPos && aSttCps[ nPos - 1 ] > ULONG( nStartCp ))
+ {
+ --nPos;
+ --aIter;
+ }
+
+ aSttCps.Insert(nStartCp, nPos);
+ aEndCps.Insert(nStartCp, nPos);
+ aFieldMarks.Insert(BOOL(false), nPos);
+ maSwBkmkNms.insert(aIter, rNm);
+ }
+ else
+ {
+ // old -> its the end position
+ ASSERT( aEndCps[ nPos ] == aSttCps[ nPos ], "end position is valid" );
+
+ //If this bookmark was around a field in writer, then we want to move
+ //it to the field result in word. The end is therefore one cp
+ //backwards from the 0x15 end mark that was inserted.
+ if (aFieldMarks[nPos])
+ --nStartCp;
+
+ aEndCps.Replace( nStartCp, nPos );
+ }
+}
+
+
+void WW8_WrtBookmarks::Write( WW8Export& rWrt )
+{
+ USHORT nCount = aSttCps.Count(), i;
+ if( nCount )
+ {
+ SvULongs aEndSortTab( 255 < nCount ? 255 : nCount, 4 );
+ // sort then endpositions
+ for( i = 0; i < nCount; ++i )
+ {
+ ULONG nCP = aEndCps[ i ];
+ USHORT nPos = i;
+ while( nPos && aEndSortTab[ nPos - 1 ] > nCP )
+ --nPos;
+ aEndSortTab.Insert( nCP, nPos );
+ }
+
+ // we have some bookmarks found in the document -> write them
+ // first the Bookmark Name Stringtable
+ rWrt.WriteAsStringTable(maSwBkmkNms, rWrt.pFib->fcSttbfbkmk,
+ rWrt.pFib->lcbSttbfbkmk);
+
+ // second the Bookmark start positions as pcf of longs
+ SvStream& rStrm = rWrt.bWrtWW8 ? *rWrt.pTableStrm : rWrt.Strm();
+ rWrt.pFib->fcPlcfbkf = rStrm.Tell();
+ for( i = 0; i < nCount; ++i )
+ SwWW8Writer::WriteLong( rStrm, aSttCps[ i ] );
+ SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
+ for( i = 0; i < nCount; ++i )
+ {
+ ULONG nEndCP = aEndCps[ i ];
+ USHORT nPos = i;
+ if( aEndSortTab[ nPos ] > nEndCP )
+ {
+ while( aEndSortTab[ --nPos ] != nEndCP )
+ ;
+ }
+ else if( aEndSortTab[ nPos ] < nEndCP )
+ while( aEndSortTab[ ++nPos ] != nEndCP )
+ ;
+
+ SwWW8Writer::WriteLong( rStrm, nPos );
+ }
+ rWrt.pFib->lcbPlcfbkf = rStrm.Tell() - rWrt.pFib->fcPlcfbkf;
+
+ // third the Bookmark end positions
+ rWrt.pFib->fcPlcfbkl = rStrm.Tell();
+ for( i = 0; i < nCount; ++i )
+ SwWW8Writer::WriteLong( rStrm, aEndSortTab[ i ] );
+ SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
+ rWrt.pFib->lcbPlcfbkl = rStrm.Tell() - rWrt.pFib->fcPlcfbkl;
+ }
+}
+
+USHORT WW8_WrtBookmarks::GetPos( const String& rNm )
+{
+ USHORT nRet = USHRT_MAX, n;
+ for (n = 0; n < aSttCps.Count(); ++n)
+ if (rNm == maSwBkmkNms[n])
+ {
+ nRet = n;
+ break;
+ }
+ return nRet;
+}
+
+void WW8_WrtBookmarks::MoveFieldMarks(ULONG nFrom, ULONG nTo)
+{
+ for (USHORT nI=0;nI<aSttCps.Count();++nI)
+ {
+ if (aSttCps[nI] == nFrom)
+ {
+ aSttCps[nI] = nTo;
+ if (aEndCps[nI] == nFrom)
+ {
+ aFieldMarks[nI] = true;
+ aEndCps[nI] = nTo;
+ }
+ }
+ }
+}
+
+void WW8Export::AppendBookmarks( const SwTxtNode& rNd,
+ xub_StrLen nAktPos, xub_StrLen nLen )
+{
+ SvPtrarr aArr( 8, 8 );
+ USHORT nCntnt;
+ xub_StrLen nAktEnd = nAktPos + nLen;
+ if( GetWriter().GetBookmarks( rNd, nAktPos, nAktEnd, aArr ))
+ {
+ ULONG nNd = rNd.GetIndex(), nSttCP = Fc2Cp( Strm().Tell() );
+ for( USHORT n = 0; n < aArr.Count(); ++n )
+ {
+ ::sw::mark::IMark& rBkmk = *(::sw::mark::IMark*)aArr[ n ];
+ if(dynamic_cast< ::sw::mark::IFieldmark *>(&rBkmk))
+ continue;
+
+ const SwPosition* pPos = &rBkmk.GetMarkPos();
+ const SwPosition* pOPos = 0;
+ if(rBkmk.IsExpanded())
+ pOPos = &rBkmk.GetOtherMarkPos();
+ if( pOPos && pOPos->nNode == pPos->nNode &&
+ pOPos->nContent < pPos->nContent )
+ {
+ pPos = pOPos;
+ pOPos = &rBkmk.GetMarkPos();
+ }
+
+ if( !pOPos || ( nNd == pPos->nNode.GetIndex() &&
+ ( nCntnt = pPos->nContent.GetIndex() ) >= nAktPos &&
+ nCntnt < nAktEnd ) )
+ {
+ ULONG nCp = nSttCP + pPos->nContent.GetIndex() - nAktPos;
+ pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
+ }
+ if( pOPos && nNd == pOPos->nNode.GetIndex() &&
+ ( nCntnt = pOPos->nContent.GetIndex() ) >= nAktPos &&
+ nCntnt < nAktEnd )
+ {
+ ULONG nCp = nSttCP + pOPos->nContent.GetIndex() - nAktPos;
+ pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
+ }
+ }
+ }
+}
+
+void WW8Export::MoveFieldMarks(ULONG nFrom, ULONG nTo)
+{
+ pBkmks->MoveFieldMarks(nFrom, nTo);
+}
+
+void WW8Export::AppendBookmark( const rtl::OUString& rName, bool bSkip )
+{
+ ULONG nSttCP = Fc2Cp( Strm().Tell() ) + ( bSkip? 1: 0 );
+ pBkmks->Append( nSttCP, rName );
+}
+
+void MSWordExportBase::AppendWordBookmark( const String& rName )
+{
+ AppendBookmark( BookmarkToWord( rName ) );
+}
+
+
+//--------------------------------------------------------------------------
+/* */
+
+void WW8_WrtRedlineAuthor::Write( Writer& rWrt )
+{
+ WW8Export & rWW8Wrt = *(((SwWW8Writer&)rWrt).m_pExport);
+ rWW8Wrt.WriteAsStringTable(maAuthors, rWW8Wrt.pFib->fcSttbfRMark,
+ rWW8Wrt.pFib->lcbSttbfRMark, rWW8Wrt.bWrtWW8 ? 0 : 2);
+}
+
+USHORT WW8Export::AddRedlineAuthor( USHORT nId )
+{
+ if( !pRedlAuthors )
+ {
+ pRedlAuthors = new WW8_WrtRedlineAuthor;
+ pRedlAuthors->AddName(CREATE_CONST_ASC("Unknown"));
+ }
+ return pRedlAuthors->AddName( SW_MOD()->GetRedlineAuthor( nId ) );
+}
+
+//--------------------------------------------------------------------------
+/* */
+
+void WW8Export::WriteAsStringTable(const std::vector<String>& rStrings,
+ INT32& rfcSttbf, INT32& rlcbSttbf, USHORT nExtraLen)
+{
+ USHORT n, nCount = static_cast< USHORT >(rStrings.size());
+ if( nCount )
+ {
+ // we have some Redlines found in the document -> the
+ // Author Name Stringtable
+ SvStream& rStrm = bWrtWW8 ? *pTableStrm : Strm();
+ rfcSttbf = rStrm.Tell();
+ if( bWrtWW8 )
+ {
+ SwWW8Writer::WriteShort( rStrm, -1 );
+ SwWW8Writer::WriteLong( rStrm, nCount );
+ for( n = 0; n < nCount; ++n )
+ {
+ const String& rNm = rStrings[n];
+ SwWW8Writer::WriteShort( rStrm, rNm.Len() );
+ SwWW8Writer::WriteString16(rStrm, rNm, false);
+ if( nExtraLen )
+ SwWW8Writer::FillCount(rStrm, nExtraLen);
+ }
+ }
+ else
+ {
+ SwWW8Writer::WriteShort( rStrm, 0 );
+ for( n = 0; n < nCount; ++n )
+ {
+ const String aNm(rStrings[n].Copy(0, 255));
+ rStrm << (BYTE)aNm.Len();
+ SwWW8Writer::WriteString8(rStrm, aNm, false,
+ RTL_TEXTENCODING_MS_1252);
+ if (nExtraLen)
+ SwWW8Writer::FillCount(rStrm, nExtraLen);
+ }
+ }
+ rlcbSttbf = rStrm.Tell() - rfcSttbf;
+ if( !bWrtWW8 )
+ SwWW8Writer::WriteShort( rStrm, rfcSttbf, (USHORT)rlcbSttbf );
+ }
+}
+
+// WriteShort() traegt an FilePos nPos den Wert nVal ein und seekt auf die
+// alte FilePos zurueck. Benutzt zum Nachtragen von Laengen.
+void SwWW8Writer::WriteShort( SvStream& rStrm, ULONG nPos, INT16 nVal )
+{
+ ULONG nOldPos = rStrm.Tell(); // Pos merken
+ rStrm.Seek( nPos );
+ SwWW8Writer::WriteShort( rStrm, nVal );
+ rStrm.Seek( nOldPos );
+}
+
+void SwWW8Writer::WriteLong( SvStream& rStrm, ULONG nPos, INT32 nVal )
+{
+ ULONG nOldPos = rStrm.Tell(); // Pos merken
+ rStrm.Seek( nPos );
+ SwWW8Writer::WriteLong( rStrm, nVal );
+ rStrm.Seek( nOldPos );
+}
+
+void SwWW8Writer::InsUInt16(ww::bytes &rO, sal_uInt16 n)
+{
+ SVBT16 nL;
+ ShortToSVBT16( n, nL );
+ rO.push_back(nL[0]);
+ rO.push_back(nL[1]);
+}
+
+void SwWW8Writer::InsUInt32(ww::bytes &rO, sal_uInt32 n)
+{
+ SVBT32 nL;
+ UInt32ToSVBT32( n, nL );
+ rO.push_back(nL[0]);
+ rO.push_back(nL[1]);
+ rO.push_back(nL[2]);
+ rO.push_back(nL[3]);
+}
+
+void SwWW8Writer::InsAsString16(ww::bytes &rO, const String& rStr)
+{
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ for( xub_StrLen n = 0, nLen = rStr.Len(); n < nLen; ++n, ++pStr )
+ SwWW8Writer::InsUInt16( rO, *pStr );
+}
+
+void SwWW8Writer::InsAsString8(ww::bytes &rO, const String& rStr,
+ rtl_TextEncoding eCodeSet)
+{
+ ByteString sTmp(rStr, eCodeSet);
+ const sal_Char *pStart = sTmp.GetBuffer();
+ const sal_Char *pEnd = pStart + sTmp.Len();
+ rO.reserve(rO.size() + sTmp.Len());
+
+ std::copy(pStart, pEnd, std::inserter(rO, rO.end()));
+}
+
+#ifdef __WW8_NEEDS_COPY
+
+void SwWW8Writer::InsUInt16( WW8Bytes& rO, UINT16 n )
+{
+ SVBT16 nL;
+ ShortToSVBT16( n, nL );
+ rO.Insert( nL, 2, rO.Count() );
+}
+void SwWW8Writer::InsUInt32( WW8Bytes& rO, UINT32 n )
+{
+ SVBT32 nL;
+ UInt32ToSVBT32( n, nL );
+ rO.Insert( nL, 4, rO.Count() );
+}
+
+#else
+
+void SwWW8Writer::InsUInt16( WW8Bytes& rO, UINT16 n )
+{
+ rO.Insert( (BYTE*)&n, 2, rO.Count() );
+}
+void SwWW8Writer::InsUInt32( WW8Bytes& rO, UINT32 n )
+{
+ rO.Insert( (BYTE*)&n, 4, rO.Count() );
+}
+
+#endif // defined __WW8_NEEDS_COPY
+
+void SwWW8Writer::InsAsString16( WW8Bytes& rO, const String& rStr )
+{
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ for( xub_StrLen n = 0, nLen = rStr.Len(); n < nLen; ++n, ++pStr )
+ SwWW8Writer::InsUInt16( rO, *pStr );
+}
+
+void SwWW8Writer::InsAsString8( WW8Bytes& rO, const String& rStr,
+ rtl_TextEncoding eCodeSet )
+{
+ ByteString sTmp( rStr, eCodeSet );
+ rO.Insert( (BYTE*)sTmp.GetBuffer(), sTmp.Len(), rO.Count() );
+}
+
+void SwWW8Writer::WriteString16(SvStream& rStrm, const String& rStr,
+ bool bAddZero)
+{
+ ww::bytes aBytes;
+ SwWW8Writer::InsAsString16(aBytes, rStr);
+ if (bAddZero)
+ SwWW8Writer::InsUInt16(aBytes, 0);
+ //vectors are guaranteed to have contiguous memory, so we can do
+ //this while migrating away from WW8Bytes. Meyers Effective STL, item 16
+ if (!aBytes.empty())
+ rStrm.Write(&aBytes[0], aBytes.size());
+}
+
+void SwWW8Writer::WriteString_xstz(SvStream& rStrm, const String& rStr, bool bAddZero)
+{
+ ww::bytes aBytes;
+ SwWW8Writer::InsUInt16(aBytes, rStr.Len());
+ SwWW8Writer::InsAsString16(aBytes, rStr);
+ if (bAddZero)
+ SwWW8Writer::InsUInt16(aBytes, 0);
+ rStrm.Write(&aBytes[0], aBytes.size());
+}
+
+
+void SwWW8Writer::WriteString8(SvStream& rStrm, const String& rStr,
+ bool bAddZero, rtl_TextEncoding eCodeSet)
+{
+ ww::bytes aBytes;
+ SwWW8Writer::InsAsString8(aBytes, rStr, eCodeSet);
+ if (bAddZero)
+ aBytes.push_back(0);
+ //vectors are guaranteed to have contiguous memory, so we can do
+ ////this while migrating away from WW8Bytes. Meyers Effective STL, item 16
+ if (!aBytes.empty())
+ rStrm.Write(&aBytes[0], aBytes.size());
+}
+
+void WW8Export::WriteStringAsPara( const String& rTxt, USHORT nStyleId )
+{
+ if( rTxt.Len() )
+ OutSwString( rTxt, 0, rTxt.Len(), IsUnicode(), RTL_TEXTENCODING_MS_1252 );
+ WriteCR(); // CR danach
+
+ WW8Bytes aArr( 10, 10 );
+ SwWW8Writer::InsUInt16( aArr, nStyleId );
+ if( bOutTable )
+ { // Tab-Attr
+ // sprmPFInTable
+ if( bWrtWW8 )
+ SwWW8Writer::InsUInt16( aArr, NS_sprm::LN_PFInTable );
+ else
+ aArr.Insert( 24, aArr.Count() );
+ aArr.Insert( 1, aArr.Count() );
+ }
+
+ ULONG nPos = Strm().Tell();
+ pPapPlc->AppendFkpEntry( nPos, aArr.Count(), aArr.GetData() );
+ pChpPlc->AppendFkpEntry( nPos );
+}
+
+void MSWordExportBase::WriteSpecialText( ULONG nStart, ULONG nEnd, BYTE nTTyp )
+{
+ BYTE nOldTyp = nTxtTyp;
+ nTxtTyp = nTTyp;
+ SwPaM* pOldPam = pCurPam; //!! Einfaches Umsetzen des PaM ohne
+ SwPaM* pOldEnd = pOrigPam; // Wiederherstellen muesste es auch tun
+ bool bOldPageDescs = bOutPageDescs;
+ bOutPageDescs = false;
+ // bOutKF wird in WriteKF1 gemerkt / gesetzt
+ pCurPam = Writer::NewSwPaM( *pDoc, nStart, nEnd );
+
+ // Tabelle in Sonderbereichen erkennen
+ if ( ( nStart != pCurPam->GetMark()->nNode.GetIndex() ) &&
+ pDoc->GetNodes()[ nStart ]->IsTableNode() )
+ {
+ pCurPam->GetMark()->nNode = nStart;
+ }
+
+ pOrigPam = pCurPam;
+ pCurPam->Exchange();
+
+ WriteText();
+
+ bOutPageDescs = bOldPageDescs;
+ delete pCurPam; // Pam wieder loeschen
+ pCurPam = pOldPam;
+ pOrigPam = pOldEnd;
+ nTxtTyp = nOldTyp;
+}
+
+void WW8Export::OutSwString(const String& rStr, xub_StrLen nStt,
+ xub_StrLen nLen, bool bUnicode, rtl_TextEncoding eChrSet)
+
+{
+#ifdef DEBUG
+ ::std::clog << "<OutSwString>" << ::std::endl;
+#endif
+
+ if( nLen )
+ {
+ if ( bUnicode != pPiece->IsUnicode() )
+ pPiece->AppendPc ( Strm().Tell(), bUnicode );
+
+ if( nStt || nLen != rStr.Len() )
+ {
+ String sOut( rStr.Copy( nStt, nLen ) );
+
+#ifdef DEBUG
+ ::std::clog << ::rtl::OUStringToOString(sOut, RTL_TEXTENCODING_ASCII_US).getStr() << ::std::endl;
+#endif
+
+ if (bUnicode)
+ SwWW8Writer::WriteString16(Strm(), sOut, false);
+ else
+ SwWW8Writer::WriteString8(Strm(), sOut, false, eChrSet);
+ }
+ else
+ {
+#ifdef DEBUG
+ ::std::clog << ::rtl::OUStringToOString(rStr, RTL_TEXTENCODING_ASCII_US).getStr() << ::std::endl;
+#endif
+
+ if (bUnicode)
+ SwWW8Writer::WriteString16(Strm(), rStr, false);
+ else
+ SwWW8Writer::WriteString8(Strm(), rStr, false, eChrSet);
+ }
+ }
+
+#ifdef DEBUG
+ ::std::clog << "</OutSwString>" << ::std::endl;
+#endif
+}
+
+void WW8Export::WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
+{
+ if (pTableTextNodeInfoInner.get() != NULL && pTableTextNodeInfoInner->getDepth() == 1 && pTableTextNodeInfoInner->isEndOfCell())
+ WriteChar('\007');
+ else
+ WriteChar( '\015' );
+
+ pPiece->SetParaBreak();
+}
+
+void WW8Export::WriteChar( sal_Unicode c )
+{
+ if( pPiece->IsUnicode() )
+ Strm() << c;
+ else
+ Strm() << (BYTE)c;
+}
+
+void MSWordExportBase::SaveData( ULONG nStt, ULONG nEnd )
+{
+ MSWordSaveData aData;
+
+ // WW8Export only stuff - zeroed here not to issue warnings
+ aData.pOOld = NULL;
+ aData.mpTableAtOld = NULL;
+ aData.mnTableStdAtLenOld = 0;
+
+ // Common stuff
+ aData.pOldPam = pCurPam;
+ aData.pOldEnd = pOrigPam;
+ aData.pOldFlyFmt = mpParentFrame;
+ aData.pOldPageDesc = pAktPageDesc;
+
+ aData.pOldFlyOffset = pFlyOffset;
+ aData.eOldAnchorType = eNewAnchorType;
+
+ aData.bOldOutTable = bOutTable;
+ aData.bOldIsInTable = bIsInTable;
+ aData.bOldFlyFrmAttrs = bOutFlyFrmAttrs;
+ aData.bOldStartTOX = bStartTOX;
+ aData.bOldInWriteTOX = bInWriteTOX;
+
+ pCurPam = Writer::NewSwPaM( *pDoc, nStt, nEnd );
+
+ // Recognize tables in special cases
+ if ( nStt != pCurPam->GetMark()->nNode.GetIndex() &&
+ pDoc->GetNodes()[ nStt ]->IsTableNode() )
+ {
+ pCurPam->GetMark()->nNode = nStt;
+ }
+
+ pOrigPam = pCurPam;
+ pCurPam->Exchange();
+
+ bOutTable = false;
+ // Caution: bIsInTable should not be set here
+ bOutFlyFrmAttrs = false;
+// pAttrSet = 0;
+ bStartTOX = false;
+ bInWriteTOX = false;
+
+ maSaveData.push( aData );
+}
+
+void MSWordExportBase::RestoreData()
+{
+ MSWordSaveData &rData = maSaveData.top();
+
+ delete pCurPam;
+ pCurPam = rData.pOldPam;
+ pOrigPam = rData.pOldEnd;
+
+ bOutTable = rData.bOldOutTable;
+ bIsInTable = rData.bOldIsInTable;
+ bOutFlyFrmAttrs = rData.bOldFlyFrmAttrs;
+ bStartTOX = rData.bOldStartTOX;
+ bInWriteTOX = rData.bOldInWriteTOX;
+
+ mpParentFrame = rData.pOldFlyFmt;
+ pAktPageDesc = rData.pOldPageDesc;
+
+ eNewAnchorType = rData.eOldAnchorType;
+ pFlyOffset = rData.pOldFlyOffset;
+
+ maSaveData.pop();
+}
+
+void WW8Export::SaveData( ULONG nStt, ULONG nEnd )
+{
+ MSWordExportBase::SaveData( nStt, nEnd );
+
+ MSWordSaveData &rData = maSaveData.top();
+
+ if ( pO->Count() )
+ {
+ rData.pOOld = pO;
+ pO = new WW8Bytes( 128, 128 );
+ }
+ else
+ rData.pOOld = 0; // reuse pO
+
+ rData.mpTableAtOld = mpTableAt;
+ mpTableAt = NULL;
+ rData.mnTableStdAtLenOld = mnTableStdAtLen;
+ mnTableStdAtLen = 0;
+
+ rData.bOldWriteAll = GetWriter().bWriteAll;
+ GetWriter().bWriteAll = true;
+}
+
+void WW8Export::RestoreData()
+{
+ MSWordSaveData &rData = maSaveData.top();
+
+ GetWriter().bWriteAll = rData.bOldWriteAll;
+
+ ASSERT( !pO->Count(), "pO is not empty in WW8Export::RestoreData()" );
+ if ( rData.pOOld )
+ {
+ delete pO;
+ pO = rData.pOOld;
+ }
+
+ ASSERT( !mpTableAt || !mpTableAt->Count(), "mpTableAt is not empty in WW8Export::RestoreData()" );
+ if ( mpTableAt )
+ delete mpTableAt;
+ mpTableAt = rData.mpTableAtOld;
+ mnTableStdAtLen = rData.mnTableStdAtLenOld;
+
+ MSWordExportBase::RestoreData();
+}
+
+void WW8AttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
+
+ if ( nDepth > 0 )
+ {
+ /* Cell */
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFInTable );
+ m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PTableDepth );
+ m_rWW8Export.InsUInt32( nDepth );
+
+ if ( nDepth > 1 && pTableTextNodeInfoInner->isEndOfCell() )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PCell );
+ m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
+ }
+ }
+}
+
+void WW8AttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
+
+ if ( nDepth > 0 )
+ {
+ /* Row */
+ if ( pTableTextNodeInfoInner->isEndOfLine() )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFInTable );
+ m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
+
+ if ( nDepth == 1 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFTtp );
+ m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
+ }
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PTableDepth );
+ m_rWW8Export.InsUInt32( nDepth );
+
+ if ( nDepth > 1 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PCell );
+ m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PRow );
+ m_rWW8Export.pO->Insert( (BYTE)0x1, m_rWW8Export.pO->Count() );
+ }
+
+ TableDefinition( pTableTextNodeInfoInner );
+ TableHeight( pTableTextNodeInfoInner );
+ TableBackgrounds( pTableTextNodeInfoInner );
+ TableDefaultBorders( pTableTextNodeInfoInner );
+ TableCanSplit( pTableTextNodeInfoInner );
+ TableBidi( pTableTextNodeInfoInner );
+ TableVerticalCell( pTableTextNodeInfoInner );
+ TableOrientation( pTableTextNodeInfoInner );
+ }
+ }
+}
+
+static sal_uInt16 lcl_TCFlags(const SwTableBox * pBox)
+{
+ sal_uInt16 nFlags = 0;
+
+ long nRowSpan = pBox->getRowSpan();
+
+ if (nRowSpan > 1)
+ nFlags |= (3 << 5);
+ else if (nRowSpan < 0)
+ nFlags |= (1 << 5);
+
+ const SwFrmFmt * pFmt = pBox->GetFrmFmt();
+ switch (pFmt->GetVertOrient().GetVertOrient())
+ {
+ case text::VertOrientation::CENTER:
+ nFlags |= (1 << 7);
+ break;
+ case text::VertOrientation::BOTTOM:
+ nFlags |= (2 << 7);
+ break;
+ default:
+ break;
+ }
+
+ return nFlags;
+}
+
+void WW8AttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwTableBoxes & rTblBoxes = pTabLine->GetTabBoxes();
+
+ sal_uInt8 nBoxes = rTblBoxes.Count();
+ for ( sal_uInt8 n = 0; n < nBoxes; n++ )
+ {
+ const SwTableBox * pTabBox1 = rTblBoxes[n];
+ const SwFrmFmt * pFrmFmt = pTabBox1->GetFrmFmt();
+
+ if ( FRMDIR_VERT_TOP_RIGHT == m_rWW8Export.TrueFrameDirection( *pFrmFmt ) )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TTextFlow );
+ m_rWW8Export.pO->Insert( BYTE(n), m_rWW8Export.pO->Count() ); //start range
+ m_rWW8Export.pO->Insert( BYTE(n + 1), m_rWW8Export.pO->Count() ); //end range
+ m_rWW8Export.InsUInt16( 5 ); //Equals vertical writing
+ }
+ }
+}
+
+void WW8AttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+
+ /*
+ By default the row can be split in word, and now in writer we have a
+ feature equivalent to this, Word stores 1 for fCantSplit if the row
+ cannot be split, we set true if we can split it. An example is #i4569#
+ */
+
+ const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit();
+ BYTE nCantSplit = (!rSplittable.GetValue()) ? 1 : 0;
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TFCantSplit );
+ m_rWW8Export.pO->Insert( nCantSplit, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TFCantSplit90 ); // also write fCantSplit90
+ }
+ else
+ {
+ m_rWW8Export.pO->Insert( 185, m_rWW8Export.pO->Count() );
+ }
+ m_rWW8Export.pO->Insert( nCantSplit, m_rWW8Export.pO->Count() );
+}
+
+void WW8AttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+ const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ if ( m_rWW8Export.TrueFrameDirection(*pFrmFmt) == FRMDIR_HORI_RIGHT_TOP )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TFBiDi );
+ m_rWW8Export.InsUInt16( 1 );
+ }
+ }
+}
+
+void WW8AttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+
+#if 0
+ const SwTable * pTable = pTableTextNodeInfo->getTable();
+ bool bNewTableModel = pTable->IsNewModel();
+ bool bFixRowHeight = false;
+ const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+ if (! bNewModel)
+ {
+ sal_uInt32 nBoxes = rTabBoxes.Count();
+
+ for (sal_uInt32 n = 0; n < nBoxes; n++)
+ {
+ SwTableBox * pBox1 = rTabBoxes[n];
+ if (pBox1->getRowspan() != 1)
+ {
+ bFixRowHeight = true;
+ break;
+ }
+ }
+ }
+#endif
+
+ // Zeilenhoehe ausgeben sprmTDyaRowHeight
+ long nHeight = 0;
+ const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
+ if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
+ {
+ if ( ATT_MIN_SIZE == rLSz.GetHeightSizeType() )
+ nHeight = rLSz.GetHeight();
+ else
+ nHeight = -rLSz.GetHeight();
+ }
+
+ if ( nHeight )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TDyaRowHeight );
+ else
+ m_rWW8Export.pO->Insert( 189, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( (USHORT)nHeight );
+ }
+
+}
+
+void WW8AttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt();
+ ASSERT(pFmt,"Impossible");
+ if (!pFmt)
+ return;
+
+ const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
+ const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
+
+ if (
+ (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
+ text::RelOrientation::FRAME == rHori.GetRelationOrient())
+ &&
+ (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
+ text::RelOrientation::FRAME == rVert.GetRelationOrient())
+ )
+ {
+ sal_Int16 eHOri = rHori.GetHoriOrient();
+ switch (eHOri)
+ {
+ case text::HoriOrientation::CENTER:
+ case text::HoriOrientation::RIGHT:
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TJc );
+ else
+ m_rWW8Export.pO->Insert( 182, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( text::HoriOrientation::RIGHT == eHOri ? 2 : 1 );
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void WW8AttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+
+ if ( pTable->GetRowsToRepeat() > pTableTextNodeInfoInner->getRow() )
+ {
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TTableHeader );
+ else
+ m_rWW8Export.pO->Insert( 186, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
+ }
+
+ // number of cell written
+ sal_uInt32 nBoxes = rTabBoxes.Count();
+ if ( nBoxes > 32 )
+ nBoxes = 32;
+
+ // sprm header
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTable );
+ sal_uInt16 nSprmSize = 2 + (nBoxes + 1) * 2 + nBoxes * 20;
+ m_rWW8Export.InsUInt16( nSprmSize ); // length
+
+ // number of boxes
+ m_rWW8Export.pO->Insert( static_cast<BYTE>(nBoxes), m_rWW8Export.pO->Count() );
+
+ /* cellxs */
+ /*
+ ALWAYS relative when text::HoriOrientation::NONE (nPageSize + ( nPageSize / 10 )) < nTblSz,
+ in that case the cell width's and table width's are not real. The table
+ width is maxed and cells relative, so we need the frame (generally page)
+ width that the table is in to work out the true widths.
+ */
+ //const bool bNewTableModel = pTbl->IsNewModel();
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt();
+ ASSERT(pFmt,"Impossible");
+ if (!pFmt)
+ return;
+
+ const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
+ const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
+
+ sal_uInt16 nTblOffset = 0;
+
+ if (
+ (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
+ text::RelOrientation::FRAME == rHori.GetRelationOrient())
+ &&
+ (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
+ text::RelOrientation::FRAME == rVert.GetRelationOrient())
+ )
+ {
+ sal_Int16 eHOri = rHori.GetHoriOrient();
+ switch ( eHOri )
+ {
+ case text::HoriOrientation::CENTER:
+ case text::HoriOrientation::RIGHT:
+ break;
+
+ default:
+ nTblOffset = rHori.GetPos();
+ const SvxLRSpaceItem& rLRSp = pFmt->GetLRSpace();
+ nTblOffset += rLRSp.GetLeft();
+ break;
+ }
+ }
+
+ sal_uInt32 n = 0;
+ m_rWW8Export.InsUInt16( nTblOffset );
+
+ std::vector<SwTwips> gridCols = GetGridCols( pTableTextNodeInfoInner );
+ for ( std::vector<SwTwips>::const_iterator it = gridCols.begin(), end = gridCols.end(); it != end; ++it )
+ {
+ m_rWW8Export.InsUInt16( static_cast<USHORT>( *it ) + nTblOffset );
+ }
+
+ /* TCs */
+ for ( n = 0; n < nBoxes; n++ )
+ {
+#ifdef DEBUG
+ sal_uInt16 npOCount = m_rWW8Export.pO->Count();
+#endif
+
+ SwTableBox * pTabBox1 = rTabBoxes[n];
+ const SwFrmFmt & rBoxFmt = *(pTabBox1->GetFrmFmt());
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ sal_uInt16 nFlags = lcl_TCFlags(pTabBox1);
+ m_rWW8Export.InsUInt16( nFlags );
+ }
+
+ static BYTE aNullBytes[] = { 0x0, 0x0 };
+
+ m_rWW8Export.pO->Insert( aNullBytes, 2, m_rWW8Export.pO->Count() ); // dummy
+ m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, rBoxFmt.GetBox() ); // 8/16 Byte
+
+#ifdef DEBUG
+ ::std::clog << "<tclength>" << m_rWW8Export.pO->Count() - npOCount << "</tclength>"
+ << ::std::endl;
+#endif
+ }
+}
+
+std::vector<SwTwips> AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ std::vector<SwTwips> gridCols;
+
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+ const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
+
+ // number of cell written
+ sal_uInt32 nBoxes = rTabBoxes.Count();
+ if ( nBoxes > 32 )
+ nBoxes = 32;
+
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt();
+ ASSERT(pFmt,"Impossible");
+ if (!pFmt)
+ return gridCols;
+
+ const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
+ unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
+
+ sal_uInt32 nPageSize = 0;
+ bool bRelBoxSize = false;
+
+ GetTablePageSize( pTableTextNodeInfoInner, nPageSize, bRelBoxSize );
+
+ SwTwips nSz = 0;
+ for ( sal_uInt32 n = 0; n < nBoxes; n++ )
+ {
+ const SwFrmFmt* pBoxFmt = rTabBoxes[ n ]->GetFrmFmt();
+ const SwFmtFrmSize& rLSz = pBoxFmt->GetFrmSize();
+ nSz += rLSz.GetWidth();
+ SwTwips nCalc = nSz;
+ if ( bRelBoxSize )
+ nCalc = ( nCalc * nPageSize ) / nTblSz;
+
+ gridCols.push_back( nCalc );
+ }
+
+ return gridCols;
+}
+
+void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner, sal_uInt32& rPageSize, bool& rRelBoxSize )
+{
+ sal_uInt32 nPageSize = 0;
+
+ const SwNode *pTxtNd = pTableTextNodeInfoInner->getNode( );
+ const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
+
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt();
+ ASSERT(pFmt,"Impossible");
+ if (!pFmt)
+ return;
+
+ const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
+ int nWidthPercent = rSize.GetWidthPercent();
+ bool bManualAligned = pFmt->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::NONE;
+ if ( (pFmt->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::FULL) || bManualAligned )
+ nWidthPercent = 100;
+ bool bRelBoxSize = nWidthPercent != 0;
+ unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
+ if (nTblSz > USHRT_MAX/2 && !bRelBoxSize)
+ {
+ ASSERT(bRelBoxSize, "huge table width but not relative, suspicious");
+ bRelBoxSize = true;
+ }
+
+ if ( bRelBoxSize )
+ {
+ Point aPt;
+ SwRect aRect( pFmt->FindLayoutRect( false, &aPt ) );
+ if ( aRect.IsEmpty() )
+ {
+ // dann besorge mal die Seitenbreite ohne Raender !!
+ const SwFrmFmt* pParentFmt =
+ GetExport().mpParentFrame ?
+ &(GetExport().mpParentFrame->GetFrmFmt()) :
+ const_cast<const SwDoc *>(GetExport().pDoc)->GetPageDesc(0).GetPageFmtOfNode(*pTxtNd, false);
+ aRect = pParentFmt->FindLayoutRect(true);
+ if ( 0 == ( nPageSize = aRect.Width() ) )
+ {
+ const SvxLRSpaceItem& rLR = pParentFmt->GetLRSpace();
+ nPageSize = pParentFmt->GetFrmSize().GetWidth() - rLR.GetLeft()
+ - rLR.GetRight();
+ }
+ }
+ else
+ {
+ nPageSize = aRect.Width();
+ if ( bManualAligned )
+ {
+ // #i37571# For manually aligned tables
+ const SvxLRSpaceItem &rLR = pFmt->GetLRSpace();
+ nPageSize -= (rLR.GetLeft() + rLR.GetRight());
+ }
+
+ }
+
+ ASSERT(nWidthPercent, "Impossible");
+ if (nWidthPercent)
+ {
+ nPageSize *= nWidthPercent;
+ nPageSize /= 100;
+ }
+ }
+
+ rPageSize = nPageSize;
+ rRelBoxSize = bRelBoxSize;
+}
+
+void WW8AttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
+
+ //Set Default, just taken from the first cell of the first
+ //row
+ static USHORT aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT,
+ BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+
+ for ( int i = 0; i < 4; ++i )
+ {
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, 0xD634 );
+ m_rWW8Export.pO->Insert( BYTE(6), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( BYTE(0), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( BYTE(1), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( BYTE(1 << i), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( BYTE(3), m_rWW8Export.pO->Count() );
+
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO,
+ pFrmFmt->GetBox().GetDistance( aBorders[i] ) );
+ }
+}
+
+void WW8AttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+
+ sal_uInt8 nBoxes = rTabBoxes.Count();
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTableShd );
+ else
+ m_rWW8Export.pO->Insert( (BYTE)191, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( (BYTE)(nBoxes * 2), m_rWW8Export.pO->Count() ); // Len
+
+ for ( sal_uInt8 n = 0; n < nBoxes; n++ )
+ {
+ const SwTableBox * pBox1 = rTabBoxes[n];
+ const SwFrmFmt * pFrmFmt = pBox1->GetFrmFmt();
+ const SfxPoolItem * pI = NULL;
+ Color aColor;
+
+ if ( SFX_ITEM_ON == pFrmFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
+ {
+ aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
+ }
+ else
+ aColor = COL_AUTO;
+
+ WW8_SHD aShd;
+ m_rWW8Export.TransBrush( aColor, aShd );
+ m_rWW8Export.InsUInt16( aShd.GetValue() );
+ }
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ sal_uInt32 aSprmIds[] = {NS_sprm::LN_TCellShd, NS_sprm::LN_TCellShadow};
+ sal_uInt8 nBoxes0 = rTabBoxes.Count();
+ if (nBoxes0 > 21)
+ nBoxes0 = 21;
+
+ for (sal_uInt32 m = 0; m < 2; m++)
+ {
+ m_rWW8Export.InsUInt16( aSprmIds[m] );
+ m_rWW8Export.pO->Insert( static_cast<BYTE>(nBoxes0 * 10),
+ m_rWW8Export.pO->Count() );
+
+ for ( sal_uInt8 n = 0; n < nBoxes0; n++ )
+ {
+ const SwTableBox * pBox1 = rTabBoxes[n];
+ const SwFrmFmt * pFrmFmt = pBox1->GetFrmFmt();
+ const SfxPoolItem * pI = NULL;
+ Color aColor;
+
+ if ( SFX_ITEM_ON ==
+ pFrmFmt->GetAttrSet().
+ GetItemState( RES_BACKGROUND, false, &pI ) )
+ {
+ aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
+ }
+ else
+ aColor = COL_AUTO;
+
+ WW8SHDLong aSHD;
+ aSHD.setCvFore( 0xFF000000 );
+
+ sal_uInt32 nBgColor = aColor.GetColor();
+ if ( nBgColor == COL_AUTO )
+ aSHD.setCvBack( 0xFF000000 );
+ else
+ aSHD.setCvBack( wwUtility::RGBToBGR( nBgColor ) );
+
+ aSHD.Write( m_rWW8Export );
+ }
+ }
+ }
+}
+
+void WW8Export::SectionBreaksAndFrames( const SwTxtNode& rNode )
+{
+ // output page/section breaks
+ OutputSectionBreaks( rNode.GetpSwAttrSet(), rNode );
+
+ // all textframes anchored as character for the winword 7- format
+ if ( !bWrtWW8 && !bIsInTable )
+ OutWW6FlyFrmsInCntnt( rNode );
+}
+
+#ifdef DEBUG
+struct SwNodeHash
+{
+ size_t operator()(SwNode * pNode) const { return reinterpret_cast<size_t>(pNode); }
+};
+
+typedef ::std::hash_set<SwNode *, SwNodeHash> SwNodeHashSet;
+typedef ::std::deque<SwNode *> SwNodeDeque;
+#endif
+
+void MSWordExportBase::WriteText()
+{
+#ifdef DEBUG
+ ::std::clog << "<WriteText>" << ::std::endl;
+ ::std::clog << dbg_out(pCurPam->GetDoc()->GetNodes()) << ::std::endl;
+
+ SwNodeHashSet aNodeSet;
+ SwNodeDeque aNodeDeque;
+#endif
+
+ while( pCurPam->GetPoint()->nNode < pCurPam->GetMark()->nNode ||
+ ( pCurPam->GetPoint()->nNode == pCurPam->GetMark()->nNode &&
+ pCurPam->GetPoint()->nContent.GetIndex() <= pCurPam->GetMark()->nContent.GetIndex() ) )
+ {
+ SwNode * pNd = pCurPam->GetNode();
+
+#ifdef DEBUG
+ if (aNodeSet.find(pNd) == aNodeSet.end())
+ {
+ aNodeSet.insert(pNd);
+ aNodeDeque.push_back(pNd);
+ }
+ else
+ {
+ ::std::clog << "<already-done><which>" << dbg_out(*pNd)
+ << "</which><nodes>" << ::std::endl;
+
+ SwNodeDeque::const_iterator aEnd = aNodeDeque.end();
+
+ for (SwNodeDeque::const_iterator aIt = aNodeDeque.begin();
+ aIt != aEnd; aIt++)
+ {
+ ::std::clog << dbg_out(**aIt) << ::std::endl;
+ }
+
+ ::std::clog << "</nodes></already-done>" << ::std::endl;
+ }
+#endif
+
+ if ( pNd->IsTxtNode() )
+ SectionBreaksAndFrames( *pNd->GetTxtNode() );
+
+ // output the various types of nodes
+ if ( pNd->IsCntntNode() )
+ {
+ SwCntntNode* pCNd = (SwCntntNode*)pNd;
+
+ const SwPageDesc* pTemp = pCNd->GetSwAttrSet().GetPageDesc().GetPageDesc();
+ if ( pTemp )
+ pAktPageDesc = pTemp;
+
+ pCurPam->GetPoint()->nContent.Assign( pCNd, 0 );
+ OutputContentNode( *pCNd );
+ }
+ else if ( pNd->IsTableNode() )
+ {
+ mpTableInfo->processSwTable( &pNd->GetTableNode()->GetTable() );
+ }
+ else if ( pNd->IsSectionNode() && TXT_MAINTEXT == nTxtTyp )
+ OutputSectionNode( *pNd->GetSectionNode() );
+ else if ( TXT_MAINTEXT == nTxtTyp && pNd->IsEndNode() &&
+ pNd->StartOfSectionNode()->IsSectionNode() )
+ {
+ const SwSection& rSect = pNd->StartOfSectionNode()->GetSectionNode()
+ ->GetSection();
+ if ( bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
+ bStartTOX = false;
+
+ SwNodeIndex aIdx( *pNd, 1 );
+ if ( aIdx.GetNode().IsEndNode() && aIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
+ ;
+ else if ( aIdx.GetNode().IsSectionNode() )
+ ;
+ else if ( !bIsInTable ) //No sections in table
+ {
+ ReplaceCr( (char)0xc ); // Indikator fuer Page/Section-Break
+
+ const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
+ if ( !pParentFmt )
+ pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
+
+ ULONG nRstLnNum;
+ if ( aIdx.GetNode().IsCntntNode() )
+ nRstLnNum = ((SwCntntNode&)aIdx.GetNode()).GetSwAttrSet().
+ GetLineNumber().GetStartValue();
+ else
+ nRstLnNum = 0;
+
+ AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
+ }
+ }
+ else if ( pNd->IsEndNode() )
+ {
+ OutputEndNode( *pNd->GetEndNode() );
+ }
+
+ if ( pNd == &pNd->GetNodes().GetEndOfContent() )
+ break;
+
+ SwNode * pCurrentNode = &pCurPam->GetPoint()->nNode.GetNode();
+ const SwNode * pNextNode = mpTableInfo->getNextNode(pCurrentNode);
+
+ if (pNextNode != NULL)
+ pCurPam->GetPoint()->nNode = SwNodeIndex(*pNextNode);
+ else
+ pCurPam->GetPoint()->nNode++;
+
+ ULONG nPos = pCurPam->GetPoint()->nNode.GetIndex();
+ ::SetProgressState( nPos, pCurPam->GetDoc()->GetDocShell() );
+ }
+
+#ifdef DEBUG
+ ::std::clog << "</WriteText>" << ::std::endl;
+#endif
+}
+
+void WW8Export::WriteMainText()
+{
+#ifdef DEBUG
+ ::std::clog << "<WriteMainText>" << ::std::endl;
+#endif
+
+ pFib->fcMin = Strm().Tell();
+
+ pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
+
+ WriteText();
+
+ if( 0 == Strm().Tell() - pFib->fcMin ) // kein Text ?
+ WriteCR(); // dann CR ans Ende ( sonst mault WW )
+
+ pFib->ccpText = Fc2Cp( Strm().Tell() );
+ pFldMain->Finish( pFib->ccpText, 0 );
+
+ // ccpText beinhaltet Ftn- und KF-Texte
+ // deshalb wird pFib->ccpText evtl. noch geupdated
+ // save the StyleId of the last paragraph. Because WW97 take the style
+ // from the last CR, that will be write after footer/Header/fontnotes/
+ // annotation usw.
+ const SwTxtNode* pLastNd = pCurPam->GetMark()->nNode.GetNode().GetTxtNode();
+ if( pLastNd )
+ nLastFmtId = GetId( (SwTxtFmtColl&)pLastNd->GetAnyFmtColl() );
+
+#ifdef DEBUG
+ ::std::clog << "</WriteMainText>" << ::std::endl;
+#endif
+}
+
+typedef ww8::WW8Sttb< ww8::WW8Struct > WW8SttbAssoc;
+
+void WW8Export::WriteFkpPlcUsw()
+{
+ if( !bWrtWW8 )
+ {
+ static const BYTE aSpec[2] =
+ {
+ 117, 1
+ };
+
+ pChpPlc->AppendFkpEntry( Strm().Tell() ); // Sepx mit fSpecial
+ pSepx->WriteSepx( Strm() ); // Slcx.Sepx
+ pGrf->Write(); // Grafiken
+ pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec ), aSpec );
+
+ pChpPlc->WriteFkps(); // Fkp.Chpx
+ pPapPlc->WriteFkps(); // Fkp.Papx
+ pStyles->OutputStylesTable(); // Styles
+ pFtn->WritePlc( *this ); // Footnote-Ref & Text Plc
+ pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
+ pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
+ pSepx->WritePlcSed( *this ); // Slcx.PlcSed
+ pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
+ pChpPlc->WritePlc(); // Plcx.Chpx
+ pPapPlc->WritePlc(); // Plcx.Papx
+ maFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
+ if( pRedlAuthors )
+ pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
+ pFldMain->Write( *this ); // Fields ( Main Text )
+ pFldHdFt->Write( *this ); // Fields ( Header/Footer )
+ pFldFtn->Write( *this ); // Fields ( FootNotes )
+ pFldEdn->Write( *this ); // Fields ( EndNotes )
+ pFldAtn->Write( *this ); // Fields ( Annotations )
+ pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
+ // plcfBkmkf/plcfBkmkl
+ WriteDop( *this ); // Document-Properties
+
+ }
+ else
+ {
+ // Grafiken in den Data-Tream
+ pGrf->Write(); // Grafiken
+
+ // Ausgabe in WordDocument-Stream
+ pChpPlc->WriteFkps(); // Fkp.Chpx
+ pPapPlc->WriteFkps(); // Fkp.Papx
+ pSepx->WriteSepx( Strm() ); // Sepx
+
+ // Ausagbe in Table-Stream
+ pStyles->OutputStylesTable(); // fuer WW8 StyleTab
+ pFtn->WritePlc( *this ); // Footnote-Ref & Text Plc
+ pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
+ pTxtBxs->WritePlc( *this ); // Textbox Text Plc
+ pHFTxtBxs->WritePlc( *this ); // Head/Foot-Textbox Text Plc
+ pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
+
+ pSepx->WritePlcSed( *this ); // Slcx.PlcSed
+ pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
+
+ pChpPlc->WritePlc(); // Plcx.Chpx
+ pPapPlc->WritePlc(); // Plcx.Papx
+
+ if( pRedlAuthors )
+ pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
+ pFldMain->Write( *this ); // Fields ( Main Text )
+ pFldHdFt->Write( *this ); // Fields ( Header/Footer )
+ pFldFtn->Write( *this ); // Fields ( FootNotes )
+ pFldEdn->Write( *this ); // Fields ( EndNotes )
+ pFldAtn->Write( *this ); // Fields ( Annotations )
+ pFldTxtBxs->Write( *this ); // Fields ( Textboxes )
+ pFldHFTxtBxs->Write( *this ); // Fields ( Head/Foot-Textboxes )
+
+ if (pEscher || pDoc->ContainsMSVBasic())
+ {
+ /*
+ #82587# Everytime MS 2000 creates an escher stream there is always
+ an ObjectPool dir (even if empty). It turns out that if a copy of
+ MS 2000 is used to open a document that contains escher graphics
+ exported from StarOffice without this empty dir then *if* that
+ copy of MS Office has never been used to open a MSOffice document
+ that has escher graphics (and an ObjectPool dir of course) and
+ that copy of office has not been used to draw escher graphics then
+ our exported graphics do not appear. Once you do open a ms
+ document with escher graphics or draw an escher graphic with that
+ copy of word, then all documents from staroffice that contain
+ escher work from then on. Tricky to track down, some sort of late
+ binding trickery in MS where solely for first time initialization
+ the existence of an ObjectPool dir is necessary for triggering
+ some magic. cmc
+ */
+ /*
+ #10570# Similiarly having msvbasic storage seems to also trigger
+ creating this stream
+ */
+ GetWriter().GetStorage().OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool),
+ STREAM_READWRITE | STREAM_SHARE_DENYALL);
+ }
+
+ // dggInfo - escher stream
+ WriteEscher();
+
+ pSdrObjs->WritePlc( *this );
+ pHFSdrObjs->WritePlc( *this );
+ // spamom - office drawing table
+ // spahdr - header office drawing table
+
+ pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
+ // plcfBkmkf/plcfBkmkl
+
+ WriteNumbering();
+
+ RestoreMacroCmds();
+
+ pMagicTable->Write( *this );
+
+ pPiece->WritePc( *this ); // Piece-Table
+ maFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
+
+ //Convert OOo asian typography into MS typography structure
+ ExportDopTypography(pDop->doptypography);
+
+ WriteDop( *this ); // Document-Properties
+
+ // Write SttbfAssoc
+ WW8SttbAssoc * pSttbfAssoc = dynamic_cast<WW8SttbAssoc *>
+ (pDoc->getExternalData(::sw::STTBF_ASSOC).get());
+ // --> OD 2009-10-19 #i106057#
+ if ( pSttbfAssoc )
+ // <--
+ {
+ ::std::vector<String> aStrings;
+
+ ::ww8::StringVector_t & aSttbStrings = pSttbfAssoc->getStrings();
+ ::ww8::StringVector_t::const_iterator aItEnd = aSttbStrings.end();
+ for (::ww8::StringVector_t::const_iterator aIt = aSttbStrings.begin();
+ aIt != aItEnd; aIt++)
+ {
+ String aStr(aIt->getStr());
+ aStrings.push_back(aStr);
+ }
+
+ WriteAsStringTable(aStrings, pFib->fcSttbfAssoc,
+ pFib->lcbSttbfAssoc);
+ }
+ }
+ Strm().Seek( 0 );
+
+ // Reclaim stored FIB data from document.
+ ::ww8::WW8FibData * pFibData = dynamic_cast<ww8::WW8FibData *>
+ (pDoc->getExternalData(::sw::FIB).get());
+
+ if ( pFibData )
+ // <--
+ {
+ pFib->fReadOnlyRecommended =
+ pFibData->getReadOnlyRecommended() ? 1 : 0;
+ pFib->fWriteReservation =
+ pFibData->getWriteReservation() ? 1 : 0;
+ }
+
+ pFib->Write( Strm() ); // FIB
+}
+
+void WW8Export::StoreDoc1()
+{
+ bool bNeedsFinalPara = false;
+ // Start of Text ( Mangel ueber )
+ SwWW8Writer::FillUntil( Strm(), pFib->fcMin );
+
+ WriteMainText(); // HauptText
+ BYTE nSprmsLen;
+ BYTE *pLastSprms = pPapPlc->CopyLastSprms(nSprmsLen);
+
+ bNeedsFinalPara |= pFtn->WriteTxt( *this ); // Footnote-Text
+ bNeedsFinalPara |= pSepx->WriteKFTxt( *this ); // K/F-Text
+ bNeedsFinalPara |= pAtn->WriteTxt( *this ); // Annotation-Text
+ bNeedsFinalPara |= pEdn->WriteTxt( *this ); // EndNote-Text
+
+ // create the escher streams
+ if( bWrtWW8 )
+ CreateEscher();
+
+ bNeedsFinalPara |= pTxtBxs->WriteTxt( *this ); //Textbox Text Plc
+ bNeedsFinalPara |= pHFTxtBxs->WriteTxt( *this );//Head/Foot-Textbox Text Plc
+
+ if (bNeedsFinalPara)
+ {
+ WriteCR();
+ pPapPlc->AppendFkpEntry(Strm().Tell(), nSprmsLen, pLastSprms);
+ }
+ delete[] pLastSprms;
+
+ pSepx->Finish( Fc2Cp( Strm().Tell() ));// Text + Ftn + HdFt als Section-Ende
+ pMagicTable->Finish( Fc2Cp( Strm().Tell() ),0);
+
+ pFib->fcMac = Strm().Tell(); // Ende aller Texte
+
+ WriteFkpPlcUsw(); // FKP, PLC, .....
+}
+
+void MSWordExportBase::AddLinkTarget(const String& rURL)
+{
+ if( !rURL.Len() || rURL.GetChar(0) != INET_MARK_TOKEN )
+ return;
+
+ String aURL( BookmarkToWriter( rURL.Copy( 1 ) ) );
+ xub_StrLen nPos = aURL.SearchBackward( cMarkSeperator );
+
+ if( nPos < 2 )
+ return;
+
+ String sCmp( aURL.Copy( nPos+1 ) );
+ sCmp.EraseAllChars();
+ if( !sCmp.Len() )
+ return;
+
+ sCmp.ToLowerAscii();
+
+ if( sCmp.EqualsAscii( pMarkToOutline ) )
+ {
+ SwPosition aPos( *pCurPam->GetPoint() );
+ String aOutline( BookmarkToWriter(aURL.Copy( 0, nPos )) );
+ // If we can find the outline this bookmark refers to
+ // save the name of the bookmark and the
+ // node index number of where it points to
+ if( pDoc->GotoOutline( aPos, aOutline ) )
+ {
+ ULONG nIdx = aPos.nNode.GetIndex();
+ aPair aImplicitBookmark;
+ aImplicitBookmark.first = aOutline;
+ aImplicitBookmark.second = nIdx;
+ maImplicitBookmarks.push_back(aImplicitBookmark);
+ }
+ }
+}
+
+void MSWordExportBase::CollectOutlineBookmarks(const SwDoc &rDoc)
+{
+ const SwFmtINetFmt* pINetFmt;
+ const SwTxtINetFmt* pTxtAttr;
+ const SwTxtNode* pTxtNd;
+
+ USHORT n, nMaxItems = rDoc.GetAttrPool().GetItemCount( RES_TXTATR_INETFMT );
+ for( n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 != (pINetFmt = (SwFmtINetFmt*)rDoc.GetAttrPool().GetItem(
+ RES_TXTATR_INETFMT, n ) ) &&
+ 0 != ( pTxtAttr = pINetFmt->GetTxtINetFmt()) &&
+ 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
+ pTxtNd->GetNodes().IsDocNodes() )
+ {
+ AddLinkTarget( pINetFmt->GetValue() );
+ }
+ }
+
+ const SwFmtURL *pURL;
+ nMaxItems = rDoc.GetAttrPool().GetItemCount( RES_URL );
+ for( n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 != (pURL = (SwFmtURL*)rDoc.GetAttrPool().GetItem(
+ RES_URL, n ) ) )
+ {
+ AddLinkTarget( pURL->GetURL() );
+ const ImageMap *pIMap = pURL->GetMap();
+ if( pIMap )
+ {
+ for( USHORT i=0; i<pIMap->GetIMapObjectCount(); i++ )
+ {
+ const IMapObject* pObj = pIMap->GetIMapObject( i );
+ if( pObj )
+ {
+ AddLinkTarget( pObj->GetURL() );
+ }
+ }
+ }
+ }
+ }
+}
+
+namespace
+{
+ const ULONG WW_BLOCKSIZE = 0x200;
+
+ void EncryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
+ {
+ rIn.Seek(STREAM_SEEK_TO_END);
+ ULONG nLen = rIn.Tell();
+ rIn.Seek(0);
+
+ sal_uInt8 in[WW_BLOCKSIZE];
+ for (ULONG nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
+ {
+ ULONG nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
+ rIn.Read(in, nBS);
+ rCtx.InitCipher(nBlock);
+ rCtx.Encode(in, nBS, in, nBS);
+ rOut.Write(in, nBS);
+ }
+ }
+}
+
+void MSWordExportBase::ExportDocument( bool bWriteAll )
+{
+ nCharFmtStart = ANZ_DEFAULT_STYLES;
+ nFmtCollStart = nCharFmtStart + pDoc->GetCharFmts()->Count() - 1;
+
+ bStyDef = bBreakBefore = bOutKF =
+ bOutFlyFrmAttrs = bOutPageDescs = bOutTable = bOutFirstPage =
+ bIsInTable = bOutGrf = bInWriteEscher = bStartTOX =
+ bInWriteTOX = false;
+
+ bFtnAtTxtEnd = bEndAtTxtEnd = true;
+
+ mpParentFrame = 0;
+ pFlyOffset = 0;
+ eNewAnchorType = FLY_AT_PAGE;
+ nTxtTyp = TXT_MAINTEXT;
+ // --> OD 2007-04-19 #i43447# - removed
+// nFlyWidth = nFlyHeight = 0;
+ // <--
+ nStyleBeforeFly = nLastFmtId = 0;
+ pStyAttr = 0;
+ pCurrentStyle = NULL;
+ pOutFmtNode = 0;
+ pEscher = 0;
+ pRedlAuthors = 0;
+ if ( aTOXArr.Count() )
+ aTOXArr.Remove( 0, aTOXArr.Count() );
+
+ if ( !pOLEExp )
+ {
+ UINT32 nSvxMSDffOLEConvFlags = 0;
+ const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
+ if ( pOpt->IsMath2MathType() )
+ nSvxMSDffOLEConvFlags |= OLE_STARMATH_2_MATHTYPE;
+ if ( pOpt->IsWriter2WinWord() )
+ nSvxMSDffOLEConvFlags |= OLE_STARWRITER_2_WINWORD;
+ if ( pOpt->IsCalc2Excel() )
+ nSvxMSDffOLEConvFlags |= OLE_STARCALC_2_EXCEL;
+ if ( pOpt->IsImpress2PowerPoint() )
+ nSvxMSDffOLEConvFlags |= OLE_STARIMPRESS_2_POWERPOINT;
+
+ pOLEExp = new SvxMSExportOLEObjects( nSvxMSDffOLEConvFlags );
+ }
+
+ if ( !pOleMap)
+ pOleMap = new WW8OleMaps;
+
+ if ( !pOCXExp )
+ pOCXExp = new SwMSConvertControls( pDoc->GetDocShell(), pCurPam );
+
+ // --> OD 2007-10-08 #i81405#
+ // Collect anchored objects before changing the redline mode.
+ maFrames = GetFrames( *pDoc, bWriteAll? NULL : pOrigPam );
+ // <--
+
+ mnRedlineMode = pDoc->GetRedlineMode();
+ if ( pDoc->GetRedlineTbl().Count() )
+ {
+ pDoc->SetRedlineMode( (RedlineMode_t)(mnRedlineMode | nsRedlineMode_t::REDLINE_SHOW_DELETE |
+ nsRedlineMode_t::REDLINE_SHOW_INSERT) );
+ }
+
+ maFontHelper.InitFontTable( HackIsWW8OrHigher(), *pDoc );
+ GatherChapterFields();
+
+ CollectOutlineBookmarks(*pDoc);
+
+ // make unique OrdNums (Z-Order) for all drawing-/fly Objects
+ if ( pDoc->GetDrawModel() )
+ pDoc->GetDrawModel()->GetPage( 0 )->RecalcObjOrdNums();
+
+ ExportDocument_Impl();
+
+ if ( mnRedlineMode != pDoc->GetRedlineMode() )
+ pDoc->SetRedlineMode( (RedlineMode_t)(mnRedlineMode) );
+}
+
+String SwWW8Writer::GetPassword()
+{
+ String sUniPassword;
+ if ( mpMedium )
+ {
+ SfxItemSet* pSet = mpMedium->GetItemSet();
+
+ const SfxPoolItem* pPasswordItem = NULL;
+ if ( pSet && SFX_ITEM_SET == pSet->GetItemState( SID_PASSWORD, sal_True, &pPasswordItem ) )
+ if( pPasswordItem != NULL )
+ sUniPassword = ( (const SfxStringItem*)pPasswordItem )->GetValue();
+ }
+
+ return sUniPassword;
+}
+
+void WW8Export::ExportDocument_Impl()
+{
+ PrepareStorage();
+
+ pFib = new WW8Fib( bWrtWW8 ? 8 : 6 );
+
+ SvStream* pOldStrm = &(Strm()); // JP 19.05.99: wozu das ???
+ SvStorageStreamRef xWwStrm( GetWriter().GetStorage().OpenSotStream( aMainStg ) );
+ SvStorageStreamRef xTableStrm( xWwStrm ), xDataStrm( xWwStrm );
+ xWwStrm->SetBufferSize( 32768 );
+
+ if( bWrtWW8 )
+ {
+ pFib->fWhichTblStm = 1;
+ xTableStrm = GetWriter().GetStorage().OpenSotStream(CREATE_CONST_ASC(SL::a1Table),
+ STREAM_STD_WRITE );
+ xDataStrm = GetWriter().GetStorage().OpenSotStream(CREATE_CONST_ASC(SL::aData),
+ STREAM_STD_WRITE );
+
+ xDataStrm->SetBufferSize( 32768 ); // fuer Grafiken
+ xTableStrm->SetBufferSize( 16384 ); // fuer die Font-/Style-Table, usw.
+
+ xTableStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ xDataStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ }
+
+ GetWriter().SetStrm( *xWwStrm );
+ pTableStrm = &xTableStrm;
+ pDataStrm = &xDataStrm;
+
+ Strm().SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ String sUniPassword( GetWriter().GetPassword() );
+
+ utl::TempFile aTempMain;
+ aTempMain.EnableKillingFile();
+ utl::TempFile aTempTable;
+ aTempTable.EnableKillingFile();
+ utl::TempFile aTempData;
+ aTempData.EnableKillingFile();
+
+ bool bEncrypt = false;
+
+ xub_StrLen nLen = sUniPassword.Len();
+ if ( nLen > 0 && nLen <= 15) // Password has been set
+ {
+ bEncrypt =true;
+
+ GetWriter().SetStrm( *aTempMain.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE ) );
+
+ pTableStrm = aTempTable.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
+
+ pDataStrm = aTempData.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
+
+ sal_uInt8 aRC4EncryptionHeader[ 52 ] = {0};
+ pTableStrm->Write( aRC4EncryptionHeader, 52 );
+ }
+
+ // Default: "Standard"
+ pSepx = new WW8_WrPlcSepx( *this ); // Sections/headers/footers
+
+ pFtn = new WW8_WrPlcFtnEdn( TXT_FTN ); // Footnotes
+ pEdn = new WW8_WrPlcFtnEdn( TXT_EDN ); // Endnotes
+ pAtn = new WW8_WrPlcAnnotations; // PostIts
+ pTxtBxs = new WW8_WrPlcTxtBoxes( TXT_TXTBOX );
+ pHFTxtBxs = new WW8_WrPlcTxtBoxes( TXT_HFTXTBOX );
+
+ pSdrObjs = new MainTxtPlcDrawObj; // Draw-/Fly-Objects for main text
+ pHFSdrObjs = new HdFtPlcDrawObj; // Draw-/Fly-Objects for header/footer
+
+ pBkmks = new WW8_WrtBookmarks; // Bookmarks
+ GetWriter().CreateBookmarkTbl();
+
+ pPapPlc = new WW8_WrPlcPn( *this, PAP, pFib->fcMin );
+ pChpPlc = new WW8_WrPlcPn( *this, CHP, pFib->fcMin );
+ pO = new WW8Bytes( 128, 128 );
+ pStyles = new MSWordStyles( *this );
+ pFldMain = new WW8_WrPlcFld( 2, TXT_MAINTEXT );
+ pFldHdFt = new WW8_WrPlcFld( 2, TXT_HDFT );
+ pFldFtn = new WW8_WrPlcFld( 2, TXT_FTN );
+ pFldEdn = new WW8_WrPlcFld( 2, TXT_EDN );
+ pFldAtn = new WW8_WrPlcFld( 2, TXT_ATN );
+ pFldTxtBxs = new WW8_WrPlcFld( 2, TXT_TXTBOX );
+ pFldHFTxtBxs = new WW8_WrPlcFld( 2, TXT_HFTXTBOX );
+
+ pMagicTable = new WW8_WrMagicTable;
+
+ pGrf = new SwWW8WrGrf( *this );
+ pPiece = new WW8_WrPct( pFib->fcMin, bWrtWW8 );
+ pDop = new WW8Dop;
+
+
+ pDop->fRevMarking = 0 != ( nsRedlineMode_t::REDLINE_ON & mnRedlineMode );
+ pDop->fRMView = 0 != ( nsRedlineMode_t::REDLINE_SHOW_DELETE & mnRedlineMode );
+ pDop->fRMPrint = pDop->fRMView;
+
+ // set AutoHyphenation flag if found in default para style
+ const SfxPoolItem* pItem;
+ SwTxtFmtColl* pStdTxtFmtColl =
+ pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false);
+ if (pStdTxtFmtColl && SFX_ITEM_SET == pStdTxtFmtColl->GetItemState(
+ RES_PARATR_HYPHENZONE, false, &pItem))
+ {
+ pDop->fAutoHyphen = ((const SvxHyphenZoneItem*)pItem)->IsHyphen();
+ }
+
+ StoreDoc1();
+
+ if ( bEncrypt )
+ {
+ // Generate random number with a seed of time as salt.
+ TimeValue aTime;
+ osl_getSystemTime( &aTime );
+ rtlRandomPool aRandomPool = rtl_random_createPool ();
+ rtl_random_addBytes ( aRandomPool, &aTime, 8 );
+
+ sal_uInt8 aDocId[ 16 ] = {0};
+ rtl_random_getBytes( aRandomPool, aDocId, 16 );
+
+ rtl_random_destroyPool( aRandomPool );
+
+ sal_Unicode aPassword[16] = {0};
+ for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
+ aPassword[nChar] = sUniPassword.GetChar(nChar);
+
+ msfilter::MSCodec_Std97 aCtx;
+ aCtx.InitKey(aPassword, aDocId);
+
+ SvStream *pStrmTemp, *pTableStrmTemp, *pDataStrmTemp;
+ pStrmTemp = &xWwStrm;
+ pTableStrmTemp = &xTableStrm;
+ pDataStrmTemp = &xDataStrm;
+
+ if ( pDataStrmTemp && pDataStrmTemp != pStrmTemp)
+ EncryptRC4(aCtx, *pDataStrm, *pDataStrmTemp);
+
+ EncryptRC4(aCtx, *pTableStrm, *pTableStrmTemp);
+
+ // Write Unencrypted Header 52 bytes to the start of the table stream
+ // EncryptionVersionInfo (4 bytes): A Version structure where Version.vMajor MUST be 0x0001, and Version.vMinor MUST be 0x0001.
+ pTableStrmTemp->Seek( 0 );
+ sal_uInt32 nEncType = 0x10001;
+ *pTableStrmTemp << nEncType;
+
+ sal_uInt8 pSaltData[16] = {0};
+ sal_uInt8 pSaltDigest[16] = {0};
+ aCtx.GetEncryptKey( aDocId, pSaltData, pSaltDigest );
+
+ pTableStrmTemp->Write( aDocId, 16 );
+ pTableStrmTemp->Write( pSaltData, 16 );
+ pTableStrmTemp->Write( pSaltDigest, 16 );
+
+ EncryptRC4(aCtx, GetWriter().Strm(), *pStrmTemp);
+
+ // Write Unencrypted Fib 68 bytes to the start of the workdocument stream
+ pFib->fEncrypted = 1; // fEncrypted indicates the document is encrypted.
+ pFib->fObfuscated = 0; // Must be 0 for RC4.
+ pFib->nHash = 0x34; // encrypt header bytes count of table stream.
+ pFib->nKey = 0; // lkey2 must be 0 for RC4.
+
+ pStrmTemp->Seek( 0 );
+ pFib->WriteHeader( *pStrmTemp );
+ }
+
+ if (pUsedNumTbl) // all used NumRules
+ {
+ // clear the part of the list array that was copied from the document
+ // - it's an auto delete array, so the rest of the array which are
+ // duplicated lists that were added during the export will be deleted.
+ pUsedNumTbl->Remove(0, pUsedNumTbl->Count()-nUniqueList);
+ delete pUsedNumTbl;
+ }
+
+ DELETEZ( pGrf );
+ DELETEZ( pMagicTable );
+ DELETEZ( pFldFtn );
+ DELETEZ( pFldTxtBxs );
+ DELETEZ( pFldHFTxtBxs );
+ DELETEZ( pFldAtn );
+ DELETEZ( pFldEdn );
+ DELETEZ( pFldHdFt );
+ DELETEZ( pFldMain );
+ DELETEZ( pStyles );
+ DELETEZ( pO );
+ DELETEZ( pChpPlc );
+ DELETEZ( pPapPlc );
+ DELETEZ( pSepx );
+
+ delete pRedlAuthors;
+ delete pSdrObjs;
+ delete pHFSdrObjs;
+ delete pTxtBxs;
+ delete pHFTxtBxs;
+ delete pAtn;
+ delete pEdn;
+ delete pFtn;
+ delete pBkmks;
+ delete pPiece;
+ delete pDop;
+ delete pFib;
+ GetWriter().SetStrm( *pOldStrm );
+
+
+ xWwStrm->SetBufferSize( 0 );
+ if( bWrtWW8 )
+ {
+ xTableStrm->SetBufferSize( 0 );
+ xDataStrm->SetBufferSize( 0 );
+ if( 0 == pDataStrm->Seek( STREAM_SEEK_TO_END ))
+ {
+ xDataStrm.Clear();
+ pDataStrm = 0;
+ GetWriter().GetStorage().Remove(CREATE_CONST_ASC(SL::aData));
+ }
+ }
+}
+
+
+void WW8Export::PrepareStorage()
+{
+ ULONG nLen;
+ const BYTE* pData;
+ const char* pName;
+ UINT32 nId1;
+
+ if (bWrtWW8)
+ {
+ static const char aUserName[] = "Microsoft Word-Document";
+ static const BYTE aCompObj[] =
+ {
+ 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x09, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x18, 0x00, 0x00, 0x00,
+ 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
+ 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x2D, 0x44,
+ 0x6F, 0x6B, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x00,
+ 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x53, 0x57, 0x6F,
+ 0x72, 0x64, 0x44, 0x6F, 0x63, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x57, 0x6F, 0x72, 0x64, 0x2E, 0x44,
+ 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E,
+ 0x38, 0x00, 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+ };
+
+ pName = aUserName;
+ pData = aCompObj;
+ nLen = sizeof( aCompObj );
+ nId1 = 0x00020906L;
+ }
+ else
+ {
+ static const char aUserName[] = "Microsoft Word 6.0 Document";
+ static const BYTE aCompObj[] =
+ {
+ 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x09, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1C, 0x00, 0x00, 0x00,
+ 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
+ 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x20, 0x36,
+ 0x2E, 0x30, 0x2D, 0x44, 0x6F, 0x6B, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x00, 0x0A, 0x00, 0x00, 0x00,
+ 0x4D, 0x53, 0x57, 0x6F, 0x72, 0x64, 0x44, 0x6F,
+ 0x63, 0x00, 0x10, 0x00, 0x00, 0x00, 0x57, 0x6F,
+ 0x72, 0x64, 0x2E, 0x44, 0x6F, 0x63, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x2E, 0x36, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+ };
+
+ pName = aUserName;
+ pData = aCompObj;
+ nLen = sizeof( aCompObj );
+ nId1 = 0x00020900L;
+ }
+
+ SvGlobalName aGName( nId1, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46 );
+ GetWriter().GetStorage().SetClass( aGName, 0, String::CreateFromAscii( pName ));
+ SvStorageStreamRef xStor( GetWriter().GetStorage().OpenSotStream(sCompObj) );
+ xStor->Write( pData, nLen );
+
+ SwDocShell* pDocShell = pDoc->GetDocShell ();
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
+
+ if (xDocProps.is())
+ {
+ if ( SvtFilterOptions::Get()->IsEnableWordPreview() )
+ {
+ ::boost::shared_ptr<GDIMetaFile> pMetaFile =
+ pDocShell->GetPreviewMetaFile (sal_False);
+ uno::Sequence<sal_uInt8> metaFile(
+ sfx2::convertMetaFile(pMetaFile.get()));
+ sfx2::SaveOlePropertySet(xDocProps, &GetWriter().GetStorage(), &metaFile);
+ }
+ else
+ sfx2::SaveOlePropertySet( xDocProps, &GetWriter().GetStorage() );
+ }
+ }
+}
+
+ULONG SwWW8Writer::WriteStorage()
+{
+ // #i34818# #120099# - update layout (if present), for SwWriteTable
+ ViewShell* pViewShell = NULL;
+ pDoc->GetEditShell( &pViewShell );
+ if( pViewShell != NULL )
+ pViewShell->CalcLayout();
+
+ long nMaxNode = pDoc->GetNodes().Count();
+ ::StartProgress( STR_STATSTR_W4WWRITE, 0, nMaxNode, pDoc->GetDocShell() );
+
+ // Tabelle am Doc.-Anfang beachten
+ {
+ SwTableNode * pTNd = pCurPam->GetNode()->FindTableNode();
+ if( pTNd && bWriteAll )
+ // mit dem TabellenNode anfangen !!
+ pCurPam->GetPoint()->nNode = *pTNd;
+ }
+
+ // Do the actual export
+ {
+ WW8Export aExport( this, pDoc, pCurPam, pOrigPam, m_bWrtWW8 );
+ m_pExport = &aExport;
+ aExport.ExportDocument( bWriteAll );
+ m_pExport = NULL;
+ }
+
+ ::EndProgress( pDoc->GetDocShell() );
+ return 0;
+}
+
+ULONG SwWW8Writer::WriteMedium( SfxMedium& )
+{
+ return WriteStorage();
+}
+
+ULONG SwWW8Writer::Write( SwPaM& rPaM, SfxMedium& rMed,
+ const String* pFileName )
+{
+ mpMedium = &rMed;
+ ULONG nRet = StgWriter::Write( rPaM, rMed, pFileName );
+ mpMedium = NULL;
+ return nRet;
+}
+
+MSWordExportBase::MSWordExportBase( SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
+ : aMainStg(sMainStream), pISet(0), pUsedNumTbl(0), mpTopNodeOfHdFtPage(0),
+ pBmpPal(0), pKeyMap(0), pOLEExp(0), pOCXExp(0), pOleMap(0),
+ mpTableInfo(new ww8::WW8TableInfo()), nUniqueList(0),
+ mnHdFtIndex(0), pAktPageDesc(0), pPapPlc(0), pChpPlc(0), pChpIter(0),
+ pStyles( NULL ),
+ bHasHdr(false), bHasFtr(false),
+ pDoc( pDocument ),
+ pCurPam( pCurrentPam ),
+ pOrigPam( pOriginalPam )
+{
+}
+
+MSWordExportBase::~MSWordExportBase()
+{
+ delete pBmpPal;
+ if (pKeyMap)
+ delete[] (NfKeywordTable*)pKeyMap;
+ delete pOLEExp;
+ delete pOCXExp;
+ delete pOleMap;
+}
+
+WW8Export::WW8Export( SwWW8Writer *pWriter,
+ SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam,
+ bool bIsWW8 )
+ : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
+ pO( NULL ),
+ mpTableAt( NULL ),
+ mnTableStdAtLen( 0 ),
+ pSepx( NULL ),
+ bWrtWW8( bIsWW8 ),
+ m_pWriter( pWriter ),
+ m_pAttrOutput( new WW8AttributeOutput( *this ) )
+{
+}
+
+WW8Export::~WW8Export()
+{
+ delete m_pAttrOutput, m_pAttrOutput = NULL;
+}
+
+AttributeOutputBase& WW8Export::AttrOutput() const
+{
+ return *m_pAttrOutput;
+}
+
+MSWordSections& WW8Export::Sections() const
+{
+ return *pSepx;
+}
+
+SwWW8Writer::SwWW8Writer(const String& rFltName, const String& rBaseURL)
+ : StgWriter(),
+ m_bWrtWW8( rFltName.EqualsAscii( FILTER_WW8 ) ),
+ m_pExport( NULL ),
+ mpMedium( 0 )
+{
+ SetBaseURL( rBaseURL );
+}
+
+SwWW8Writer::~SwWW8Writer()
+{
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT ULONG SAL_CALL SaveOrDelMSVBAStorage_ww8( SfxObjectShell& rDoc, SotStorage& rStor, BOOL bSaveInto, const String& rStorageName )
+{
+ SvxImportMSVBasic aTmp( rDoc, rStor );
+ return aTmp.SaveOrDelMSVBAStorage( bSaveInto, rStorageName );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL ExportDOC( const String& rFltName, const String& rBaseURL, WriterRef& xRet )
+{
+ xRet = new SwWW8Writer( rFltName, rBaseURL );
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT ULONG SAL_CALL GetSaveWarningOfMSVBAStorage_ww8( SfxObjectShell &rDocS )
+{
+ return SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( rDocS );
+}
+
+bool WW8_WrPlcFtnEdn::WriteTxt( WW8Export& rWrt )
+{
+ bool bRet = false;
+ if (TXT_FTN == nTyp)
+ {
+ bRet = WriteGenericTxt( rWrt, TXT_FTN, rWrt.pFib->ccpFtn );
+ rWrt.pFldFtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
+ rWrt.pFib->ccpText );
+ }
+ else
+ {
+ bRet = WriteGenericTxt( rWrt, TXT_EDN, rWrt.pFib->ccpEdn );
+ rWrt.pFldEdn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
+ rWrt.pFib->ccpText + rWrt.pFib->ccpFtn
+ + rWrt.pFib->ccpHdr + rWrt.pFib->ccpAtn );
+ }
+ return bRet;
+}
+
+void WW8_WrPlcFtnEdn::WritePlc( WW8Export& rWrt ) const
+{
+ if( TXT_FTN == nTyp )
+ {
+ WriteGenericPlc( rWrt, TXT_FTN, rWrt.pFib->fcPlcffndTxt,
+ rWrt.pFib->lcbPlcffndTxt, rWrt.pFib->fcPlcffndRef,
+ rWrt.pFib->lcbPlcffndRef );
+ }
+ else
+ {
+ WriteGenericPlc( rWrt, TXT_EDN, rWrt.pFib->fcPlcfendTxt,
+ rWrt.pFib->lcbPlcfendTxt, rWrt.pFib->fcPlcfendRef,
+ rWrt.pFib->lcbPlcfendRef );
+ }
+}
+
+
+bool WW8_WrPlcAnnotations::WriteTxt( WW8Export& rWrt )
+{
+ bool bRet = WriteGenericTxt( rWrt, TXT_ATN, rWrt.pFib->ccpAtn );
+ rWrt.pFldAtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
+ rWrt.pFib->ccpText + rWrt.pFib->ccpFtn
+ + rWrt.pFib->ccpHdr );
+ return bRet;
+}
+
+void WW8_WrPlcAnnotations::WritePlc( WW8Export& rWrt ) const
+{
+ WriteGenericPlc( rWrt, TXT_ATN, rWrt.pFib->fcPlcfandTxt,
+ rWrt.pFib->lcbPlcfandTxt, rWrt.pFib->fcPlcfandRef,
+ rWrt.pFib->lcbPlcfandRef );
+}
+
+void WW8_WrPlcTxtBoxes::WritePlc( WW8Export& rWrt ) const
+{
+ if( TXT_TXTBOX == nTyp )
+ {
+ WriteGenericPlc( rWrt, nTyp, rWrt.pFib->fcPlcftxbxBkd,
+ rWrt.pFib->lcbPlcftxbxBkd, rWrt.pFib->fcPlcftxbxTxt,
+ rWrt.pFib->lcbPlcftxbxTxt );
+ }
+ else
+ {
+ WriteGenericPlc( rWrt, nTyp, rWrt.pFib->fcPlcfHdrtxbxBkd,
+ rWrt.pFib->lcbPlcfHdrtxbxBkd, rWrt.pFib->fcPlcfHdrtxbxTxt,
+ rWrt.pFib->lcbPlcfHdrtxbxTxt );
+ }
+}
+
+void WW8Export::RestoreMacroCmds()
+{
+ pFib->fcCmds = pTableStrm->Tell();
+
+ uno::Reference < embed::XStorage > xSrcRoot(pDoc->GetDocShell()->GetStorage());
+ try
+ {
+ uno::Reference < io::XStream > xSrcStream =
+ xSrcRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READ );
+ SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xSrcStream );
+
+ if ( pStream && SVSTREAM_OK == pStream->GetError())
+ {
+ pStream->Seek(STREAM_SEEK_TO_END);
+ pFib->lcbCmds = pStream->Tell();
+ pStream->Seek(0);
+
+ sal_uInt8 *pBuffer = new sal_uInt8[pFib->lcbCmds];
+ pStream->Read(pBuffer, pFib->lcbCmds);
+ pTableStrm->Write(pBuffer, pFib->lcbCmds);
+ delete[] pBuffer;
+
+ }
+
+ delete pStream;
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ // set len to FIB
+ pFib->lcbCmds = pTableStrm->Tell() - pFib->fcCmds;
+}
+
+void WW8SHDLong::Write( WW8Export& rExport )
+{
+ rExport.InsUInt32( m_cvFore );
+ rExport.InsUInt32( m_cvBack );
+ rExport.InsUInt16( m_ipat );
+}
+
+void WW8Export::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
+{
+ ASSERT( bWrtWW8, "No 95 export yet" );
+ if ( !bWrtWW8 )
+ return;
+
+ const ::sw::mark::IFieldmark* pFieldmark = &rFieldmark;
+ const ::sw::mark::ICheckboxFieldmark* pAsCheckbox = dynamic_cast< const ::sw::mark::ICheckboxFieldmark* >( pFieldmark );
+
+
+ ASSERT(rFieldmark.GetFieldname().equalsAscii( ODF_FORMTEXT ) || rFieldmark.GetFieldname().equalsAscii( ODF_FORMDROPDOWN ) || rFieldmark.GetFieldname().equalsAscii( ODF_FORMCHECKBOX ), "Unknown field type!!!");
+ if ( ! ( rFieldmark.GetFieldname().equalsAscii( ODF_FORMTEXT ) ||
+ rFieldmark.GetFieldname().equalsAscii( ODF_FORMDROPDOWN ) ||
+ rFieldmark.GetFieldname().equalsAscii( ODF_FORMCHECKBOX ) ) )
+ return;
+
+ int type = 0; // TextFieldmark
+ if ( pAsCheckbox )
+ type = 1;
+ if ( rFieldmark.GetFieldname().equalsAscii( ODF_FORMDROPDOWN ) )
+ type=2;
+
+ ::sw::mark::IFieldmark::parameter_map_t::const_iterator pNameParameter = rFieldmark.GetParameters()->find(::rtl::OUString::createFromAscii("name"));
+ ::rtl::OUString ffname;
+ if(pNameParameter != rFieldmark.GetParameters()->end())
+ pNameParameter->second >>= ffname;
+
+ ULONG nDataStt = pDataStrm->Tell();
+ pChpPlc->AppendFkpEntry(Strm().Tell());
+
+ WriteChar(0x01);
+ static BYTE aArr1[] =
+ {
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x02, 0x08, 0x01 // sprmCFFldVanish
+ };
+ BYTE* pDataAdr = aArr1 + 2;
+ Set_UInt32(pDataAdr, nDataStt);
+
+ pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aArr1 ), aArr1 );
+
+ sal_uInt8 aFldHeader[] =
+ {
+ 0xFF, 0xFF, 0xFF, 0xFF, // Unicode Marker...
+ 0, 0, 0, 0,// 0, 0, 0, 0
+ };
+
+ aFldHeader[4] |= (type & 0x03);
+ sal_Int32 ffres = 0; // rFieldmark.GetFFRes();
+ if ( pAsCheckbox && pAsCheckbox->IsChecked() )
+ ffres = 1;
+ else if ( type == 2 )
+ {
+ ::sw::mark::IFieldmark::parameter_map_t::const_iterator pResParameter = rFieldmark.GetParameters()->find(::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN));
+ if(pResParameter != rFieldmark.GetParameters()->end())
+ pResParameter->second >>= ffres;
+ else
+ ffres = 0;
+ }
+ aFldHeader[4] |= ( (ffres<<2) & 0x7C );
+
+ std::vector< ::rtl::OUString > aListItems;
+ if (type==2)
+ {
+ aFldHeader[5] |= 0x80; // ffhaslistbox
+ const ::sw::mark::IFieldmark::parameter_map_t* const pParameters = rFieldmark.GetParameters();
+ ::sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN_LISTENTRY));
+ if(pListEntries != pParameters->end())
+ {
+ uno::Sequence< ::rtl::OUString > vListEntries;
+ pListEntries->second >>= vListEntries;
+ copy(::comphelper::stl_begin(vListEntries), ::comphelper::stl_end(vListEntries), back_inserter(aListItems));
+ }
+ }
+
+ const ::rtl::OUString ffdeftext;
+ const ::rtl::OUString ffformat;
+ const ::rtl::OUString ffhelptext;
+ const ::rtl::OUString ffstattext;
+ const ::rtl::OUString ffentrymcr;
+ const ::rtl::OUString ffexitmcr;
+
+
+ const sal_uInt8 aFldData[] =
+ {
+ 0x44,0, // the start of "next" data
+ 0,0,0,0,0,0,0,0,0,0, // PIC-Structure! /10
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
+ 0,0,0,0, // / /4
+ };
+ sal_uInt32 slen = sizeof(sal_uInt32)
+ + sizeof(aFldData)
+ + sizeof( aFldHeader )
+ + 2*ffname.getLength() + 4
+ + 2*ffdeftext.getLength() + 4
+ + 2*ffformat.getLength() + 4
+ + 2*ffhelptext.getLength() + 4
+ + 2*ffstattext.getLength() + 4
+ + 2*ffentrymcr.getLength() + 4
+ + 2*ffexitmcr.getLength() + 4;
+ if ( type==2 ) {
+ slen += 2; // for 0xFF, 0xFF
+ slen += 4; // for num of list items
+ const int items = aListItems.size();
+ for( int i = 0; i < items; i++ ) {
+ rtl::OUString item = aListItems[i];
+ slen += 2 * item.getLength() + 2;
+ }
+ }
+
+ *pDataStrm << slen;
+
+ int len = sizeof( aFldData );
+ OSL_ENSURE( len == 0x44-sizeof(sal_uInt32), "SwWW8Writer::WriteFormData(..) - wrong aFldData length" );
+ pDataStrm->Write( aFldData, len );
+
+ len = sizeof( aFldHeader );
+ OSL_ENSURE( len == 8, "SwWW8Writer::WriteFormData(..) - wrong aFldHeader length" );
+
+ pDataStrm->Write( aFldHeader, len );
+
+ SwWW8Writer::WriteString_xstz( *pDataStrm, ffname, true ); // Form field name
+
+ if ( type == 0 )
+ SwWW8Writer::WriteString_xstz( *pDataStrm, ffdeftext, true );
+ else
+ pDataStrm->WriteNumber( (sal_uInt16)0 );
+
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffformat ), true );
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffhelptext ), true );
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffstattext ), true );
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffentrymcr ), true );
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffexitmcr ), true );
+ if (type==2) {
+ *pDataStrm<<(sal_uInt16)0xFFFF;
+ const int items=aListItems.size();
+ *pDataStrm<<(sal_uInt32)items;
+ for(int i=0;i<items;i++) {
+ rtl::OUString item=aListItems[i];
+ SwWW8Writer::WriteString_xstz( *pDataStrm, item, false );
+ }
+ }
+}
+
+void WW8Export::WriteHyperlinkData( const sw::mark::IFieldmark& /*rFieldmark*/ )
+{
+ //@TODO implement me !!!
+}
+
+void WW8AttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
+{
+ SVBT16 nStyle;
+ ShortToSVBT16( m_rWW8Export.nStyleBeforeFly, nStyle );
+
+#ifdef DEBUG
+ ::std::clog << "<OutWW8_TableNodeInfoInner>" << pNodeInfoInner->toString();
+#endif
+
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+
+ if (pNodeInfoInner->isEndOfCell())
+ {
+#ifdef DEBUG
+ ::std::clog << "<endOfCell/>" << ::std::endl;
+#endif
+ m_rWW8Export.WriteCR(pNodeInfoInner);
+
+ m_rWW8Export.pO->Insert( (BYTE*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
+ TableInfoCell(pNodeInfoInner);
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+ m_rWW8Export.pO->GetData() );
+
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+ }
+
+ if (pNodeInfoInner->isEndOfLine())
+ {
+#ifdef DEBUG
+ ::std::clog << "<endOfLine/>" << ::std::endl;
+#endif
+ TableRowEnd(pNodeInfoInner->getDepth());
+
+ ShortToSVBT16(0, nStyle);
+ m_rWW8Export.pO->Insert( (BYTE*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
+ TableInfoRow(pNodeInfoInner);
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+ m_rWW8Export.pO->GetData() );
+
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+ }
+#ifdef DEBUG
+ ::std::clog << "</OutWW8_TableNodeInfoInner>" << ::std::endl;
+#endif
+}
+
+void MSWordExportBase::OutputEndNode( const SwEndNode &rNode )
+{
+#ifdef DEBUG
+ ::std::clog << "<OutWW8_SwEndNode>" << dbg_out(&rNode) << ::std::endl;
+#endif
+
+ ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = mpTableInfo->getTableNodeInfo( &rNode );
+
+ if (pNodeInfo)
+ {
+ if (pNodeInfo.get() != NULL)
+ {
+#ifdef DEBUG
+ ::std::clog << pNodeInfo->toString() << ::std::endl;
+#endif
+
+ const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
+ ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt(aInners.begin());
+ ww8::WW8TableNodeInfo::Inners_t::const_iterator aEnd(aInners.end());
+ while (aIt != aEnd)
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
+ AttrOutput().TableNodeInfoInner(pInner);
+ aIt++;
+ }
+ }
+ }
+#ifdef DEBUG
+ ::std::clog << "</OutWW8_SwEndNode>" << ::std::endl;
+#endif
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */