blob: ee39f12c30bfa64f47f1a3b234206a7c6c1078f9 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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 <map>
#include <set>
#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/ulspitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/brshitem.hxx>
#include <swtypes.hxx>
#include <swrect.hxx>
#include <swtblfmt.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 <sfx2/request.hxx>
#include <sfx2/frame.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 <editeng/charrotateitem.hxx>
#include "WW8FibData.hxx"
#include "numrule.hxx"
#include <boost/scoped_ptr.hpp>
using namespace sw::util;
using namespace sw::types;
/** FKP - Formatted disK Page
*/
class WW8_WrFkp
{
sal_uInt8* pFkp; // gesamter Fkp ( zuerst nur FCs und Sprms )
sal_uInt8* pOfs; // Pointer auf Offset-Bereich, spaeter nach pFkp kopiert
ePLCFT ePlc;
short nStartGrp; // ab hier grpprls
short nOldStartGrp;
sal_uInt8 nItemSize;
sal_uInt8 nIMax; // Anzahl der Eintrags-Paare
sal_uInt8 nOldVarLen;
sal_uInt8 nMark;
bool bCombined; // true : Einfuegen verboten
sal_uInt8 SearchSameSprm( sal_uInt16 nVarLen, const sal_uInt8* pSprms );
public:
WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8);
~WW8_WrFkp();
bool Append( WW8_FC nEndFc, sal_uInt16 nVarLen = 0, const sal_uInt8* pSprms = 0 );
bool Combine();
void Write( SvStream& rStrm, SwWW8WrGrf& rGrf );
bool IsEqualPos(WW8_FC nEndFc) const
{ return !bCombined && nIMax && nEndFc == ((sal_Int32*)pFkp)[nIMax]; }
void MergeToNew( short& rVarLen, sal_uInt8 *& pNewSprms );
bool IsEmptySprm() const
{ return !bCombined && nIMax && !nOldVarLen; }
void SetNewEnd( WW8_FC nEnd )
{ ((sal_Int32*)pFkp)[nIMax] = nEnd; }
#ifdef __WW8_NEEDS_COPY
WW8_FC GetStartFc() const;
WW8_FC GetEndFc() const;
#else
WW8_FC GetStartFc() const { return ((sal_Int32*)pFkp)[0]; };
WW8_FC GetEndFc() const { return ((sal_Int32*)pFkp)[nIMax]; };
#endif // defined __WW8_NEEDS_COPY
sal_uInt8 *CopyLastSprms(sal_uInt8 &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
sal_uInt16 nStatus; // Absatzende im Piece ?
public:
WW8_WrPc(WW8_FC nSFc, WW8_CP nSCp )
: nStartCp( nSCp ), nStartFc( nSFc ), nStatus( 0x0040 )
{}
void SetStatus() { nStatus = 0x0050; }
sal_uInt16 GetStatus() const { return nStatus; }
WW8_CP GetStartCp() const { return nStartCp; }
WW8_FC GetStartFc() const { return nStartFc; }
};
typedef std::map<String,long> BKMKNames;
typedef BKMKNames::iterator BKMKNmItr;
typedef std::pair<bool,String> BKMK;
typedef std::pair<long,BKMK> BKMKCP;
typedef std::multimap<long,BKMKCP*> BKMKCPs;
typedef BKMKCPs::iterator CPItr;
class WW8_WrtBookmarks
{
private:
BKMKCPs aSttCps,aEndCps;
BKMKNames maSwBkmkNms;
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(sal_uLong nFrom,sal_uLong nTo);
};
WW8_WrtBookmarks::WW8_WrtBookmarks()
{}
WW8_WrtBookmarks::~WW8_WrtBookmarks()
{
CPItr aEnd = aSttCps.end();
for (CPItr aItr = aSttCps.begin();aItr!=aEnd;aItr++)
{
if (aItr->second)
{
delete aItr->second;
aItr->second = NULL;
}
}
}
void WW8_WrtBookmarks::Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark*)
{
std::pair<BKMKNmItr,bool> aResult = maSwBkmkNms.insert(std::pair<String,long>(rNm,0L));
if (aResult.second)
{
BKMK aBK(false,rNm);
BKMKCP* pBKCP = new BKMKCP((long)nStartCp,aBK);
aSttCps.insert(std::pair<long,BKMKCP*>(nStartCp,pBKCP));
aResult.first->second = (long)nStartCp;
}
else
{
std::pair<CPItr,CPItr> aRange = aSttCps.equal_range(aResult.first->second);
for (CPItr aItr = aRange.first;aItr != aRange.second;aItr++)
{
if (aItr->second && aItr->second->second.second == rNm)
{
if (aItr->second->second.first)
nStartCp--;
aItr->second->first = (long)nStartCp;
break;
}
}
}
}
void WW8_WrtBookmarks::Write( WW8Export& rWrt)
{
if (!aSttCps.size())
return;
CPItr aItr;
long n;
std::vector<String> aNames;
SvMemoryStream aTempStrm1(65535,65535);
SvMemoryStream aTempStrm2(65535,65535);
for (aItr = aSttCps.begin();aItr!=aSttCps.end();aItr++)
{
if (aItr->second)
{
aEndCps.insert(std::pair<long,BKMKCP*>(aItr->second->first,aItr->second));
aNames.push_back(aItr->second->second.second);
SwWW8Writer::WriteLong( aTempStrm1, aItr->first);
}
}
aTempStrm1.Seek(0L);
for (aItr = aEndCps.begin(), n = 0;aItr != aEndCps.end();aItr++,n++)
{
if (aItr->second)
{
aItr->second->first = n;
SwWW8Writer::WriteLong( aTempStrm2, aItr->first);
}
}
aTempStrm2.Seek(0L);
rWrt.WriteAsStringTable(aNames, rWrt.pFib->fcSttbfbkmk,rWrt.pFib->lcbSttbfbkmk);
SvStream& rStrm = rWrt.bWrtWW8 ? *rWrt.pTableStrm : rWrt.Strm();
rWrt.pFib->fcPlcfbkf = rStrm.Tell();
rStrm<<aTempStrm1;
SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
for (aItr = aSttCps.begin();aItr!=aSttCps.end();aItr++)
{
if (aItr->second)
{
SwWW8Writer::WriteLong(rStrm, aItr->second->first);
}
}
rWrt.pFib->lcbPlcfbkf = rStrm.Tell() - rWrt.pFib->fcPlcfbkf;
rWrt.pFib->fcPlcfbkl = rStrm.Tell();
rStrm<<aTempStrm2;
SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
rWrt.pFib->lcbPlcfbkl = rStrm.Tell() - rWrt.pFib->fcPlcfbkl;
}
void WW8_WrtBookmarks::MoveFieldMarks(sal_uLong nFrom,sal_uLong nTo)
{
std::pair<CPItr,CPItr> aRange = aSttCps.equal_range(nFrom);
CPItr aItr = aRange.first;
while (aItr != aRange.second)
{
if (aItr->second)
{
if (aItr->second->first == (long)nFrom)
{
aItr->second->second.first = true;
aItr->second->first = nTo;
}
aSttCps.insert(std::pair<long,BKMKCP*>(nTo,aItr->second));
aItr->second = NULL;
aRange = aSttCps.equal_range(nFrom);
aItr = aRange.first;
continue;
}
aItr++;
}
}
#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, sal_uInt8 )
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 = (sal_uInt16)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< sal_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;
uno::Reference<beans::XPropertySet> xProps;
if (pDocShell) {
uno::Reference<lang::XComponent> xModelComp(pDocShell->GetModel(),
uno::UNO_QUERY);
xProps = uno::Reference<beans::XPropertySet>(xModelComp,
uno::UNO_QUERY);
uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
xModelComp, uno::UNO_QUERY_THROW);
xDocProps = xDPS->getDocumentProperties();
DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
rDop.lKeyProtDoc = pDocShell->GetModifyPasswordHash();
}
if ((rWrt.pSepx && rWrt.pSepx->DocumentIsProtected()) ||
rDop.lKeyProtDoc != 0)
{
rDop.fProtEnabled = 1;
}
else
{
rDop.fProtEnabled = 0;
}
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));
}
// 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 = (sal_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;
sal_uInt8 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( sal_uInt16 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(sal_uInt16 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( sal_uInt16 nStructSz )
: aPos( 16, 16 ), nStructSiz( nStructSz )
{
nDataLen = 16 * nStructSz;
pData = new sal_uInt8[ nDataLen ];
}
WW8_WrPlc1::~WW8_WrPlc1()
{
delete[] pData;
}
WW8_CP WW8_WrPlc1::Prev() const
{
sal_uInt16 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 )
{
sal_uLong nInsPos = aPos.Count() * nStructSiz;
aPos.Insert( nCp, aPos.Count() );
if( nDataLen < nInsPos + nStructSiz )
{
sal_uInt8* pNew = new sal_uInt8[ 2 * nDataLen ];
memmove( pNew, pData, nDataLen );
delete[] pData;
pData = pNew;
nDataLen *= 2;
}
memcpy( pData + nInsPos, pNewData, nStructSiz );
}
void WW8_WrPlc1::Finish( sal_uLong nLastCp, sal_uLong nSttCp )
{
if( aPos.Count() )
{
aPos.Insert( nLastCp, aPos.Count() );
if( nSttCp )
for( sal_uInt16 n = 0; n < aPos.Count(); ++n )
aPos[ n ] -= nSttCp;
}
}
void WW8_WrPlc1::Write( SvStream& rStrm )
{
sal_uInt16 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 )
{
sal_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;
sal_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, sal_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, sal_uLong nCount )
{
static const sal_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
}
sal_uLong SwWW8Writer::FillUntil( SvStream& rStrm, sal_uLong nEndPos )
{
sal_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() );
}
sal_uInt8 *WW8_WrPlcPn::CopyLastSprms(sal_uInt8 &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 sal_uInt8* pSprms)
{
WW8_FkpPtr pF = aFkps.GetObject( aFkps.Count() - 1 );
// big sprm? build the sprmPHugePapx
sal_uInt8* pNewSprms = (sal_uInt8*)pSprms;
sal_uInt8 aHugePapx[ 8 ];
if( rWrt.bWrtWW8 && PAP == ePlc && 488 < nVarLen )
{
sal_uInt8* 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 = (sal_uInt16) ( SwWW8Writer::FillUntil( rWrt.Strm() ) >> 9 );
for( sal_uInt16 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()
{
sal_uLong nFcStart = rWrt.pTableStrm->Tell();
sal_uInt16 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 = (sal_uInt8*)new sal_Int32[128]; // 512 Byte
pOfs = (sal_uInt8*)new sal_Int32[128]; // 512 Byte
memset( pFkp, 0, 4 * 128 );
memset( pOfs, 0, 4 * 128 );
( (sal_Int32*)pFkp )[0] = nStartFc; // 0. FC-Eintrag auf nStartFc
}
WW8_WrFkp::~WW8_WrFkp()
{
delete[] (sal_Int32 *)pFkp;
delete[] (sal_Int32 *)pOfs;
}
sal_uInt8 WW8_WrFkp::SearchSameSprm( sal_uInt16 nVarLen, const sal_uInt8* pSprms )
{
if( 3 < nVarLen )
{
// if the sprms contained picture-references then never equal!
for( sal_uInt8 n = static_cast< sal_uInt8 >(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++ )
{
sal_uInt8 nStart = pOfs[i * nItemSize];
if( nStart )
{ // Hat Sprms
const sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
if( ( CHP == ePlc
? (*p++ == nVarLen)
: (((sal_uInt16)*p++ << 1 ) == (( nVarLen+1) & 0xfffe)) )
&& !memcmp( p, pSprms, nVarLen ) )
return nStart; // gefunden
}
}
return 0; // nicht gefunden
}
sal_uInt8 *WW8_WrFkp::CopyLastSprms(sal_uInt8 &rLen, bool bVer8)
{
rLen=0;
sal_uInt8 *pStart=0,*pRet=0;
if (!bCombined)
pStart = pOfs;
else
pStart = pFkp + ( nIMax + 1 ) * 4;
sal_uInt8 nStart = *(pStart + (nIMax-1) * nItemSize);
const sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
if (!*p && bVer8)
p++;
if (*p)
{
rLen = *p++;
if (PAP == ePlc)
rLen *= 2;
pRet = new sal_uInt8[rLen];
memcpy(pRet,p,rLen);
}
return pRet;
}
bool WW8_WrFkp::Append( WW8_FC nEndFc, sal_uInt16 nVarLen, const sal_uInt8* 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;
}
sal_Int32 n = ((sal_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
}
sal_uInt8 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( (sal_uInt16)nPos <= ( nIMax + 2U ) * 4U + ( nIMax + 1U ) * nItemSize )
// Passt hinter CPs und Offsets ?
return false; // Nein
((sal_Int32*)pFkp)[nIMax + 1] = nEndFc; // FC eintragen
nOldVarLen = (sal_uInt8)nVarLen;
if( nVarLen && !nOldP )
{ // echt eintragen
nOldStartGrp = nStartGrp;
nStartGrp = nPos;
pOfs[nIMax * nItemSize] = (sal_uInt8)( nStartGrp >> 1 );
// ( DatenAnfg >> 1 ) eintragen
sal_uInt8 nCnt = static_cast< sal_uInt8 >(CHP == ePlc
? ( nVarLen < 256 ) ? (sal_uInt8) 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 );
delete[] pOfs;
pOfs = 0;
((sal_uInt8*)pFkp)[511] = nIMax;
bCombined = true;
#if defined OSL_BIGENDIAN // Hier werden nur die FCs gedreht, die
sal_uInt16 i; // Sprms muessen an anderer Stelle gedreht
// werden
sal_uInt32* p;
for( i = 0, p = (sal_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
sal_uInt8* p; // Suche Magic fuer nPicLocFc
sal_uInt8* 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, sal_uInt8 *& rpNewSprms )
{
sal_uInt8 nStart = pOfs[ (nIMax-1) * nItemSize ];
if( nStart )
{ // Hat Sprms
sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
// old and new equal? Then copy only one into the new sprms
if( nOldVarLen == rVarLen && !memcmp( p+1, rpNewSprms, nOldVarLen ))
{
sal_uInt8* pNew = new sal_uInt8[ nOldVarLen ];
memcpy( pNew, p+1, nOldVarLen );
rpNewSprms = pNew;
}
else
{
sal_uInt8* pNew = new sal_uInt8[ 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 (sal_uInt16 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 ((sal_Int32*)pFkp)[0];
}
WW8_FC WW8_WrFkp::GetEndFc() const
{
if( bCombined )
return SVBT32ToUInt32( &(pFkp[nIMax*4]) ); // nIMax-tes SVBT32-Element
return ((sal_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 )
{
sal_uLong nPctStart;
sal_uLong nOldPos, nEndPos;
sal_uInt16 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
sal_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( sal_uLong nFc ) const
{
ASSERT( nFc >= (sal_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();
}
void WW8Export::AppendBookmarks( const SwTxtNode& rNd,
xub_StrLen nAktPos, xub_StrLen nLen )
{
SvPtrarr aArr( 8, 8 );
sal_uInt16 nCntnt;
xub_StrLen nAktEnd = nAktPos + nLen;
if( GetWriter().GetBookmarks( rNd, nAktPos, nAktEnd, aArr ))
{
sal_uLong nNd = rNd.GetIndex(), nSttCP = Fc2Cp( Strm().Tell() );
for( sal_uInt16 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 ) )
{
sal_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 )
{
sal_uLong nCp = nSttCP + pOPos->nContent.GetIndex() - nAktPos;
pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
}
}
}
}
void WW8Export::MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo)
{
pBkmks->MoveFieldMarks(nFrom, nTo);
}
void WW8Export::AppendBookmark( const rtl::OUString& rName, bool bSkip )
{
sal_uLong nSttCP = Fc2Cp( Strm().Tell() ) + ( bSkip? 1: 0 );
pBkmks->Append( nSttCP, rName );
}
//For i120928,collect all the graphics of bullets applied to paragraphs
int WW8Export::CollectGrfsOfBullets() const
{
m_vecBulletPic.clear();
if ( pDoc )
{
sal_uInt16 nCountRule = pDoc->GetNumRuleTbl().Count();
for (sal_uInt16 n = 0; n < nCountRule; ++n)
{
const SwNumRule &rRule = *(pDoc->GetNumRuleTbl().GetObject(n));
sal_uInt16 nLevels = rRule.IsContinusNum() ? 1 : 9;
for (sal_uInt16 nLvl = 0; nLvl < nLevels; ++nLvl)
{
const SwNumFmt &rFmt = rRule.Get(nLvl);
if (SVX_NUM_BITMAP != rFmt.GetNumberingType())
{
continue;
}
const Graphic *pGrf = rFmt.GetBrush()? rFmt.GetBrush()->GetGraphic():0;
if ( pGrf )
{
bool bHas = false;
for (sal_uInt16 i = 0; i < m_vecBulletPic.size(); ++i)
{
if (m_vecBulletPic[i]->GetChecksum() == pGrf->GetChecksum())
{
bHas = true;
break;
}
}
if (!bHas)
{
m_vecBulletPic.push_back(pGrf);
}
}
}
}
}
return m_vecBulletPic.size();
}
//Export Graphic of Bullets
void WW8Export::ExportGrfBullet(const SwTxtNode& rNd)
{
int nCount = CollectGrfsOfBullets();
if (nCount > 0)
{
SwPosition aPos(rNd);
String aPicBullets = String::CreateFromAscii("_PictureBullets");
AppendBookmark(aPicBullets);
for (int i = 0; i < nCount; i++)
{
sw::Frame aFrame(*(m_vecBulletPic[i]), aPos);
OutGrfBullets(aFrame);
}
AppendBookmark(aPicBullets);
}
}
static sal_uInt8 nAttrMagicIdx = 0;
void WW8Export::OutGrfBullets(const sw::Frame & rFrame)
{
if ( !pGrf || !pChpPlc || !pO )
return;
pGrf->Insert(rFrame);
pChpPlc->AppendFkpEntry( Strm().Tell(), pO->Count(), pO->GetData() );
pO->Remove( 0, pO->Count() );
//if links...
WriteChar( (char)1 );
sal_uInt8 aArr[ 22 ];
sal_uInt8* pArr = aArr;
// sprmCFSpec
if( bWrtWW8 )
Set_UInt16( pArr, 0x855 );
else
Set_UInt8( pArr, 117 );
Set_UInt8( pArr, 1 );
Set_UInt16( pArr, 0x083c );
Set_UInt8( pArr, 0x81 );
// sprmCPicLocation
if( bWrtWW8 )
Set_UInt16( pArr, 0x6a03 );
else
{
Set_UInt8( pArr, 68 );
Set_UInt8( pArr, 4 );
}
Set_UInt32( pArr, GRF_MAGIC_321 );
//extern nAttrMagicIdx;
--pArr;
Set_UInt8( pArr, nAttrMagicIdx++ );
pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
}
//Achieve the index position
int WW8Export::GetGrfIndex(const SvxBrushItem& rBrush)
{
int nIndex = -1;
if ( rBrush.GetGraphic() )
{
for (sal_uInt16 i = 0; i < m_vecBulletPic.size(); ++i)
{
if (m_vecBulletPic[i]->GetChecksum() == rBrush.GetGraphic()->GetChecksum())
{
nIndex = i;
break;
}
}
}
return nIndex;
}
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);
}
sal_uInt16 WW8Export::AddRedlineAuthor( sal_uInt16 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,
sal_Int32& rfcSttbf, sal_Int32& rlcbSttbf, sal_uInt16 nExtraLen)
{
sal_uInt16 n, nCount = static_cast< sal_uInt16 >(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 << (sal_uInt8)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, (sal_uInt16)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, sal_uLong nPos, sal_Int16 nVal )
{
sal_uLong nOldPos = rStrm.Tell(); // Pos merken
rStrm.Seek( nPos );
SwWW8Writer::WriteShort( rStrm, nVal );
rStrm.Seek( nOldPos );
}
void SwWW8Writer::WriteLong( SvStream& rStrm, sal_uLong nPos, sal_Int32 nVal )
{
sal_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, sal_uInt16 n )
{
SVBT16 nL;
ShortToSVBT16( n, nL );
rO.Insert( nL, 2, rO.Count() );
}
void SwWW8Writer::InsUInt32( WW8Bytes& rO, sal_uInt32 n )
{
SVBT32 nL;
UInt32ToSVBT32( n, nL );
rO.Insert( nL, 4, rO.Count() );
}
#else
void SwWW8Writer::InsUInt16( WW8Bytes& rO, sal_uInt16 n )
{
rO.Insert( (sal_uInt8*)&n, 2, rO.Count() );
}
void SwWW8Writer::InsUInt32( WW8Bytes& rO, sal_uInt32 n )
{
rO.Insert( (sal_uInt8*)&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( (sal_uInt8*)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, sal_uInt16 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() );
}
sal_uLong nPos = Strm().Tell();
pPapPlc->AppendFkpEntry( nPos, aArr.Count(), aArr.GetData() );
pChpPlc->AppendFkpEntry( nPos );
}
void MSWordExportBase::WriteSpecialText( sal_uLong nStart, sal_uLong nEnd, sal_uInt8 nTTyp )
{
sal_uInt8 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() << (sal_uInt8)c;
}
void MSWordExportBase::SaveData( sal_uLong nStt, sal_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.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;
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( sal_uLong nStt, sal_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( (sal_uInt8)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( (sal_uInt8)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( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
if ( nDepth == 1 )
{
m_rWW8Export.InsUInt16( NS_sprm::LN_PFTtp );
m_rWW8Export.pO->Insert( (sal_uInt8)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( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
m_rWW8Export.InsUInt16( NS_sprm::LN_PRow );
m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
}
TableDefinition( pTableTextNodeInfoInner );
TableHeight( pTableTextNodeInfoInner );
TableBackgrounds( pTableTextNodeInfoInner );
TableDefaultBorders( pTableTextNodeInfoInner );
TableCanSplit( pTableTextNodeInfoInner );
TableBidi( pTableTextNodeInfoInner );
TableVerticalCell( pTableTextNodeInfoInner );
TableOrientation( pTableTextNodeInfoInner );
TableSpacing( pTableTextNodeInfoInner );
}
}
}
static sal_uInt16 lcl_TCFlags(SwDoc &rDoc, const SwTableBox * pBox, const sal_Int32 nRowSpan)
{
sal_uInt16 nFlags = 0;
if (nRowSpan > 1)
nFlags |= (3 << 5);
else if (nRowSpan < 0)
nFlags |= (1 << 5);
if (pBox != NULL)
{
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;
}
const SwStartNode * pSttNd = pBox->GetSttNd();
if(pSttNd)
{
SwNodeIndex aIdx( *pSttNd );
const SwCntntNode * pCNd = pSttNd->GetNodes().GoNext( &aIdx );
if( pCNd && pCNd->IsTxtNode())
{
SfxItemSet aCoreSet(rDoc.GetAttrPool(), RES_CHRATR_ROTATE, RES_CHRATR_ROTATE);
((SwTxtNode*)pCNd)->GetAttr( aCoreSet, 0, ((SwTxtNode*)pCNd)->GetTxt().Len());
const SvxCharRotateItem * pRotate = NULL;
const SfxPoolItem * pRotItem;
if ( SFX_ITEM_SET == aCoreSet.GetItemState(RES_CHRATR_ROTATE, sal_True, &pRotItem))
{
pRotate = (SvxCharRotateItem*)pRotItem;
if(pRotate && pRotate->GetValue() == 900)
{
nFlags = nFlags | 0x0004 | 0x0008;
}
else if(pRotate && pRotate->GetValue() == 2700 )
{
nFlags = nFlags | 0x0004 | 0x0010;
}
}
}
}
}
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();
const sal_uInt16 nBoxes = rTblBoxes.Count();
for ( sal_uInt16 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( sal_uInt8(n), m_rWW8Export.pO->Count() ); //start range
m_rWW8Export.pO->Insert( sal_uInt8(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();
sal_uInt8 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( (sal_uInt16)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::TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
{
const SwTable * pTable = pTableTextNodeInfoInner->getTable();
const SwTableFmt * pTableFmt = pTable->GetTableFmt();
if (pTableFmt != NULL)
{
const SvxULSpaceItem & rUL = pTableFmt->GetULSpace();
if (rUL.GetUpper() > 0)
{
sal_uInt8 nPadding = 2;
sal_uInt8 nPcVert = 0;
sal_uInt8 nPcHorz = 0;
sal_uInt8 nTPc = (nPadding << 4) | (nPcVert << 2) | nPcHorz;
m_rWW8Export.InsUInt16(NS_sprm::LN_TPc);
m_rWW8Export.pO->Insert( nTPc, m_rWW8Export.pO->Count() );
m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaAbs);
m_rWW8Export.InsUInt16(rUL.GetUpper());
m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaFromText);
m_rWW8Export.InsUInt16(rUL.GetUpper());
}
if (rUL.GetLower() > 0)
{
m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaFromTextBottom);
m_rWW8Export.InsUInt16(rUL.GetLower());
}
}
}
void WW8AttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
{
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() );
}
ww8::TableBoxVectorPtr pTableBoxes = pTableTextNodeInfoInner->getTableBoxesOfRow();
// number of cell written
const sal_uInt16 nBoxes =
pTableBoxes->size() > ww8::MAXTABLECELLS
? ww8::MAXTABLECELLS
: static_cast< sal_uInt16 >(pTableBoxes->size());
// sprm header
m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTable );
const sal_uInt16 nSprmSize = 2 + (nBoxes + 1) * 2 + nBoxes * 20;
m_rWW8Export.InsUInt16( nSprmSize ); // length
// number of boxes
m_rWW8Export.pO->Insert( static_cast<sal_uInt8>(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 = static_cast< sal_uInt16 >(rHori.GetPos());
const SvxLRSpaceItem& rLRSp = pFmt->GetLRSpace();
nTblOffset += static_cast< sal_uInt16 >(rLRSp.GetLeft());
break;
}
}
m_rWW8Export.InsUInt16( nTblOffset );
ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
for ( ww8::GridCols::const_iterator it = pGridCols->begin(),
end = pGridCols->end(); it != end; ++it )
{
m_rWW8Export.InsUInt16( static_cast<sal_uInt16>( *it ) + nTblOffset );
}
/* TCs */
ww8::RowSpansPtr pRowSpans = pTableTextNodeInfoInner->getRowSpansOfRow();
ww8::RowSpans::const_iterator aItRowSpans = pRowSpans->begin();
ww8::TableBoxVector::const_iterator aIt;
ww8::TableBoxVector::const_iterator aItEnd = pTableBoxes->end();
#ifdef DEBUG
size_t nRowSpans = pRowSpans->size();
size_t nTableBoxes = pTableBoxes->size();
(void) nRowSpans;
(void) nTableBoxes;
#endif
for( aIt = pTableBoxes->begin(); aIt != aItEnd; ++aIt, ++aItRowSpans)
{
#ifdef DEBUG
sal_uInt16 npOCount = m_rWW8Export.pO->Count();
#endif
const SwTableBox * pTabBox1 = *aIt;
const SwFrmFmt * pBoxFmt = NULL;
if (pTabBox1 != NULL)
pBoxFmt = pTabBox1->GetFrmFmt();
if ( m_rWW8Export.bWrtWW8 )
{
sal_uInt16 nFlags =
lcl_TCFlags(*m_rWW8Export.pDoc, pTabBox1, *aItRowSpans);
m_rWW8Export.InsUInt16( nFlags );
}
static sal_uInt8 aNullBytes[] = { 0x0, 0x0 };
m_rWW8Export.pO->Insert( aNullBytes, 2, m_rWW8Export.pO->Count() ); // dummy
if (pBoxFmt != NULL)
{
const SvxBoxItem & rBoxItem = pBoxFmt->GetBox();
m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, &rBoxItem ); // 8/16 Byte
}
else
m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, NULL); // 8/16 Byte
#ifdef DEBUG
::std::clog << "<tclength>" << m_rWW8Export.pO->Count() - npOCount << "</tclength>"
<< ::std::endl;
#endif
}
}
ww8::GridColsPtr AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
{
return pTableTextNodeInfoInner->getGridColsOfRow(*this);
}
void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner * 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 sal_uInt16 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( sal_uInt8(6), m_rWW8Export.pO->Count() );
m_rWW8Export.pO->Insert( sal_uInt8(0), m_rWW8Export.pO->Count() );
m_rWW8Export.pO->Insert( sal_uInt8(1), m_rWW8Export.pO->Count() );
m_rWW8Export.pO->Insert( sal_uInt8(1 << i), m_rWW8Export.pO->Count() );
m_rWW8Export.pO->Insert( sal_uInt8(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();
const sal_uInt16 nBoxes = rTabBoxes.Count();
if ( m_rWW8Export.bWrtWW8 )
m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTableShd );
else
m_rWW8Export.pO->Insert( (sal_uInt8)191, m_rWW8Export.pO->Count() );
m_rWW8Export.pO->Insert( (sal_uInt8)(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 )
{
const sal_uInt16 aSprmIds[] = { NS_sprm::LN_TCellShd, NS_sprm::LN_TCellShadow };
sal_uInt16 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< sal_uInt8 >( nBoxes0 * 10 ),
m_rWW8Export.pO->Count() );
for ( sal_uInt16 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 && !IsInTable() )
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()
{
// whoever has need of the missing function should go and implement it!
// This piece of code always breaks builds...
//#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();
// whoever has need of the missing function should go and implement it!
// This piece of code always breaks builds...
#if 0
#ifdef DEBUG
if (aNodeSet.find(pNd) == aNodeSet.end())
{
aNodeSet.insert(pNd);
aNodeDeque.push_back(pNd);
}
else
{
::std::clog << "<already-done>" << dbg_out(*pNd) << "</already-done>" << ::std::endl;
}
#endif
#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 ( !IsInTable()
&& (rSect.GetType() != TOX_CONTENT_SECTION && rSect.GetType() != TOX_HEADER_SECTION )) //No sections in table
{
//#120140# Do not need to insert a page/section break after a section end. Check this case first
sal_Bool bNeedExportBreakHere = sal_True;
if ( aIdx.GetNode().IsTxtNode() )
{
SwTxtNode *pTempNext = aIdx.GetNode().GetTxtNode();
if ( pTempNext )
{
const SfxPoolItem * pTempItem = NULL;
if (pTempNext->GetpSwAttrSet() && SFX_ITEM_SET == pTempNext->GetpSwAttrSet()->GetItemState(RES_PAGEDESC, false, &pTempItem)
&& pTempItem && ((SwFmtPageDesc*)pTempItem)->GetRegisteredIn())
{
//Next node has a new page style which means this node is a section end. Do not insert another page/section break here
bNeedExportBreakHere = sal_False;
}
}
}
if (bNeedExportBreakHere) //#120140# End of check
{
ReplaceCr( (char)0xc ); // Indikator fuer Page/Section-Break
const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
if ( !pParentFmt )
pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
sal_uLong nRstLnNum;
if ( aIdx.GetNode().IsCntntNode() )
nRstLnNum = ((SwCntntNode&)aIdx.GetNode()).GetSwAttrSet().
GetLineNumber().GetStartValue();
else
nRstLnNum = 0;
AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
}
}
}
else if ( pNd->IsStartNode() )
{
OutputStartNode( *pNd->GetStartNode() );
}
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++;
sal_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
}
bool MSWordExportBase::IsInTable() const
{
bool bResult = false;
if (pCurPam != NULL)
{
SwNode * pNode = pCurPam->GetNode();
if (pNode != NULL && mpTableInfo.get() != NULL)
{
ww8::WW8TableNodeInfo::Pointer_t pTableNodeInfo = mpTableInfo->getTableNodeInfo(pNode);
if (pTableNodeInfo.get() != NULL && pTableNodeInfo->getDepth() > 0)
{
bResult = true;
}
}
}
return bResult;
}
typedef ww8::WW8Sttb< ww8::WW8Struct > WW8SttbAssoc;
void WW8Export::WriteFkpPlcUsw()
{
if( !bWrtWW8 )
{
static const sal_uInt8 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
sal_uInt8 nSprmsLen;
sal_uInt8 *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 ) )
{
sal_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;
sal_uInt32 n, nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
for( n = 0; n < nMaxItems; ++n )
{
if( 0 != (pINetFmt = (SwFmtINetFmt*)rDoc.GetAttrPool().GetItem2(
RES_TXTATR_INETFMT, n ) ) &&
0 != ( pTxtAttr = pINetFmt->GetTxtINetFmt()) &&
0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
pTxtNd->GetNodes().IsDocNodes() )
{
AddLinkTarget( pINetFmt->GetValue() );
}
}
const SwFmtURL *pURL;
nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_URL );
for( n = 0; n < nMaxItems; ++n )
{
if( 0 != (pURL = (SwFmtURL*)rDoc.GetAttrPool().GetItem2(
RES_URL, n ) ) )
{
AddLinkTarget( pURL->GetURL() );
const ImageMap *pIMap = pURL->GetMap();
if( pIMap )
{
for( sal_uInt16 i=0; i<pIMap->GetIMapObjectCount(); i++ )
{
const IMapObject* pObj = pIMap->GetIMapObject( i );
if( pObj )
{
AddLinkTarget( pObj->GetURL() );
}
}
}
}
}
}
namespace
{
const sal_uLong WW_BLOCKSIZE = 0x200;
void EncryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
{
rIn.Seek(STREAM_SEEK_TO_END);
sal_uLong nLen = rIn.Tell();
rIn.Seek(0);
sal_uInt8 in[WW_BLOCKSIZE];
for (sal_uLong nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
{
sal_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 =
bOutGrf = bInWriteEscher = bStartTOX =
bInWriteTOX = false;
bFtnAtTxtEnd = bEndAtTxtEnd = true;
mpParentFrame = 0;
pFlyOffset = 0;
eNewAnchorType = FLY_AT_PAGE;
nTxtTyp = TXT_MAINTEXT;
nStyleBeforeFly = nLastFmtId = 0;
pStyAttr = 0;
pCurrentStyle = NULL;
pOutFmtNode = 0;
pEscher = 0;
pRedlAuthors = 0;
if ( aTOXArr.Count() )
aTOXArr.Remove( 0, aTOXArr.Count() );
// update layout as it is needed for the export - e.g. for the export of tables
boost::scoped_ptr< ViewShell > pTemporaryViewShell( 0 );
{
ViewShell* pViewShell = NULL;
pDoc->GetEditShell( &pViewShell );
if ( pViewShell == NULL )
{
pTemporaryViewShell.reset( new ViewShell( *pDoc, 0 ) );
pViewShell = pTemporaryViewShell.get();
}
if ( pViewShell != NULL )
{
pViewShell->CalcLayout();
}
}
if ( !pOLEExp )
{
sal_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 );
// 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) );
}
bool SwWW8Writer::InitStd97CodecUpdateMedium( ::msfilter::MSCodec_Std97& rCodec )
{
uno::Sequence< beans::NamedValue > aEncryptionData;
if ( mpMedium )
{
SFX_ITEMSET_ARG( mpMedium->GetItemSet(), pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
if ( pEncryptionDataItem && ( pEncryptionDataItem->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
{
OSL_ENSURE( false, "Unexpected EncryptionData!" );
aEncryptionData.realloc( 0 );
}
if ( !aEncryptionData.getLength() )
{
// try to generate the encryption data based on password
SFX_ITEMSET_ARG( mpMedium->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False );
if ( pPasswordItem && pPasswordItem->GetValue().Len() && pPasswordItem->GetValue().Len() <= 15 )
{
// 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 pDocId[ 16 ];
rtl_random_getBytes( aRandomPool, pDocId, 16 );
rtl_random_destroyPool( aRandomPool );
sal_Unicode aPassword[16];
memset( aPassword, 0, sizeof( aPassword ) );
for ( xub_StrLen nChar = 0; nChar < pPasswordItem->GetValue().Len(); ++nChar )
aPassword[nChar] = pPasswordItem->GetValue().GetChar(nChar);
rCodec.InitKey( aPassword, pDocId );
aEncryptionData = rCodec.GetEncryptionData();
mpMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
}
}
if ( aEncryptionData.getLength() )
mpMedium->GetItemSet()->ClearItem( SID_PASSWORD );
}
// nonempty encryption data means hier that the codec was successfuly initialized
return ( aEncryptionData.getLength() != 0 );
}
void WW8Export::ExportDocument_Impl()
{
PrepareStorage();
pFib = new WW8Fib( bWrtWW8 ? 8 : 6 );
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().SetStream( & *xWwStrm );
pTableStrm = &xTableStrm;
pDataStrm = &xDataStrm;
Strm().SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
utl::TempFile aTempMain;
aTempMain.EnableKillingFile();
utl::TempFile aTempTable;
aTempTable.EnableKillingFile();
utl::TempFile aTempData;
aTempData.EnableKillingFile();
msfilter::MSCodec_Std97 aCtx;
bool bEncrypt = m_pWriter ? m_pWriter->InitStd97CodecUpdateMedium( aCtx ) : false;
if ( bEncrypt )
{
GetWriter().SetStream(
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 )
{
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 pDocId[16];
aCtx.GetDocId( pDocId );
sal_uInt8 pSaltData[16];
sal_uInt8 pSaltDigest[16];
aCtx.GetEncryptKey( pDocId, pSaltData, pSaltDigest );
pTableStrmTemp->Write( pDocId, 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().SetStream( 0 );
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()
{
sal_uLong nLen;
const sal_uInt8* pData;
const char* pName;
sal_uInt32 nId1;
if (bWrtWW8)
{
static const char aUserName[] = "Microsoft Word-Document";
static const sal_uInt8 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 sal_uInt8 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() );
}
}
}
sal_uLong SwWW8Writer::WriteStorage()
{
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;
}
sal_uLong SwWW8Writer::WriteMedium( SfxMedium& )
{
return WriteStorage();
}
sal_uLong SwWW8Writer::Write( SwPaM& rPaM, SfxMedium& rMed,
const String* pFileName )
{
mpMedium = &rMed;
sal_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), 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), bSubstituteBullets(true),
mbExportModeRTF( false ),
mbOutOutlineOnly( false ),
pDoc( pDocument ),
pCurPam( pCurrentPam ),
pOrigPam( pOriginalPam )
{
}
MSWordExportBase::~MSWordExportBase()
{
delete pBmpPal;
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 sal_uLong SAL_CALL SaveOrDelMSVBAStorage_ww8( SfxObjectShell& rDoc, SotStorage& rStor, sal_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 sal_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;
sal_uLong nDataStt = pDataStrm->Tell();
pChpPlc->AppendFkpEntry(Strm().Tell());
WriteChar(0x01);
static sal_uInt8 aArr1[] =
{
0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
0x06, 0x08, 0x01, // sprmCFData
0x55, 0x08, 0x01, // sprmCFSpec
0x02, 0x08, 0x01 // sprmCFFldVanish
};
sal_uInt8* 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
sal_uInt32 nShadowsBefore = pNodeInfoInner->getShadowsBefore();
if (nShadowsBefore > 0)
{
ww8::WW8TableNodeInfoInner::Pointer_t
pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL));
pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
pTmpNodeInfoInner->setEndOfCell(true);
for (sal_uInt32 n = 0; n < nShadowsBefore; ++n)
{
m_rWW8Export.WriteCR(pTmpNodeInfoInner);
m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2,
m_rWW8Export.pO->Count() ); // Style #
TableInfoCell(pTmpNodeInfoInner);
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->isEndOfCell())
{
#ifdef DEBUG
::std::clog << "<endOfCell/>" << ::std::endl;
#endif
m_rWW8Export.WriteCR(pNodeInfoInner);
m_rWW8Export.pO->Insert( (sal_uInt8*)&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
}
sal_uInt32 nShadowsAfter = pNodeInfoInner->getShadowsAfter();
if (nShadowsAfter > 0)
{
ww8::WW8TableNodeInfoInner::Pointer_t
pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL));
pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
pTmpNodeInfoInner->setEndOfCell(true);
for (sal_uInt32 n = 0; n < nShadowsAfter; ++n)
{
m_rWW8Export.WriteCR(pTmpNodeInfoInner);
m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
TableInfoCell(pTmpNodeInfoInner);
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( (sal_uInt8*)&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::OutputStartNode( const SwStartNode & rNode)
{
#if 0
#ifdef DEBUG
::std::clog << "<OutWW8_SwStartNode>" << dbg_out(&rNode) << ::std::endl;
#endif
#endif
ww8::WW8TableNodeInfo::Pointer_t pNodeInfo =
mpTableInfo->getTableNodeInfo( &rNode );
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_reverse_iterator aIt(aInners.rbegin());
ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aEnd(aInners.rend());
while (aIt != aEnd)
{
ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
AttrOutput().TableNodeInfoInner(pInner);
aIt++;
}
}
#ifdef DEBUG
::std::clog << "</OutWW8_SwStartNode>" << ::std::endl;
#endif
}
void MSWordExportBase::OutputEndNode( const SwEndNode &rNode )
{
#ifdef DEBUG
// whoever has need of the missing function should go and implement it!
// This piece of code always breaks builds...
// ::std::clog << "<OutWW8_SwEndNode>" << dbg_out(&rNode) << ::std::endl;
#endif
ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = mpTableInfo->getTableNodeInfo( &rNode );
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
}
const NfKeywordTable & MSWordExportBase::GetNfKeywordTable()
{
if (pKeyMap.get() == NULL)
{
pKeyMap.reset(new NfKeywordTable);
NfKeywordTable & rKeywordTable = *pKeyMap;
rKeywordTable[NF_KEY_D] = ::rtl::OUString::createFromAscii("d");
rKeywordTable[NF_KEY_DD] = ::rtl::OUString::createFromAscii("dd");
rKeywordTable[NF_KEY_DDD] = ::rtl::OUString::createFromAscii("ddd");
rKeywordTable[NF_KEY_DDDD] = ::rtl::OUString::createFromAscii("dddd");
rKeywordTable[NF_KEY_M] = ::rtl::OUString::createFromAscii("M");
rKeywordTable[NF_KEY_MM] = ::rtl::OUString::createFromAscii("MM");
rKeywordTable[NF_KEY_MMM] = ::rtl::OUString::createFromAscii("MMM");
rKeywordTable[NF_KEY_MMMM] = ::rtl::OUString::createFromAscii("MMMM");
rKeywordTable[NF_KEY_NN] = ::rtl::OUString::createFromAscii("ddd");
rKeywordTable[NF_KEY_NNN] = ::rtl::OUString::createFromAscii("dddd");
rKeywordTable[NF_KEY_NNNN] = ::rtl::OUString::createFromAscii("dddd");
rKeywordTable[NF_KEY_YY] = ::rtl::OUString::createFromAscii("yy");
rKeywordTable[NF_KEY_YYYY] = ::rtl::OUString::createFromAscii("yyyy");
rKeywordTable[NF_KEY_H] = ::rtl::OUString::createFromAscii("H");
rKeywordTable[NF_KEY_HH] = ::rtl::OUString::createFromAscii("HH");
rKeywordTable[NF_KEY_MI] = ::rtl::OUString::createFromAscii("m");
rKeywordTable[NF_KEY_MMI] = ::rtl::OUString::createFromAscii("mm");
rKeywordTable[NF_KEY_S] = ::rtl::OUString::createFromAscii("s");
rKeywordTable[NF_KEY_SS] = ::rtl::OUString::createFromAscii("ss");
rKeywordTable[NF_KEY_AMPM] = ::rtl::OUString::createFromAscii("AM/PM");
}
return *pKeyMap;
}
/* vi:set tabstop=4 shiftwidth=4 expandtab: */