blob: f322c59ab912890f81e33284df35cb926288d5e7 [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.
*
*************************************************************/
#include <stdio.h>
#include "Dff.hxx"
#include <doctok/resourceids.hxx>
#include <resourcemodel/WW8ResourceModel.hxx>
#include "resources.hxx"
namespace writerfilter {
namespace doctok {
typedef boost::shared_ptr<WW8Value> WW8ValueSharedPointer_t;
DffRecord::DffRecord(WW8Stream & rStream, sal_uInt32 nOffset,
sal_uInt32 nCount)
: WW8StructBase(rStream, nOffset, nCount), bInitialized(false)
{
}
DffRecord::DffRecord(WW8StructBase * pParent, sal_uInt32 nOffset,
sal_uInt32 nCount)
: WW8StructBase(pParent, nOffset, nCount), bInitialized(false)
{
}
Records_t::iterator DffRecord::begin()
{
if (! bInitialized)
initChildren();
return mRecords.begin();
}
Records_t::iterator DffRecord::end()
{
if (! bInitialized)
initChildren();
return mRecords.end();
}
bool DffRecord::isContainer() const
{
return getVersion() == 0xf;
}
sal_uInt32 DffRecord::calcSize() const
{
sal_uInt32 nResult = 0;
switch (getRecordType())
{
case 0xf000:
case 0xf001:
case 0xf002:
case 0xf003:
case 0xf004:
nResult = getU32(0x4) + 8;
break;
case 0xf700:
nResult = 8;
break;
default:
nResult = getU32(0x4);
if (! isContainer())
nResult += 8;
break;
}
return nResult;
}
sal_uInt32 DffRecord::getVersion() const
{
return getU8(0x0) & 0xf;
}
sal_uInt32 DffRecord::getInstance() const
{
return (getU16(0x0) & 0xfff0) >> 4;
}
sal_uInt32 DffRecord::getRecordType() const
{
return getU16(0x2);
}
void DffRecord::initChildren()
{
if (isContainer())
{
sal_uInt32 nOffset = 8;
sal_uInt32 nCount = calcSize();
while (nCount - nOffset >= 8)
{
sal_uInt32 nSize = 0;
boost::shared_ptr<DffRecord> pRec
(createDffRecord(this, nOffset, &nSize));
if (nSize == 0)
break;
mRecords.push_back(pRec);
nOffset += nSize;
}
}
bInitialized = true;
}
Records_t DffRecord::findRecords(sal_uInt32 nType, bool bRecursive, bool bAny)
{
Records_t aResult;
findRecords(nType, aResult, bRecursive, bAny);
return aResult;
}
void DffRecord::findRecords
(sal_uInt32 nType, Records_t & rRecords, bool bRecursive, bool bAny)
{
Records_t::iterator aIt = begin();
while (aIt != end())
{
Pointer_t pPointer = *aIt;
if (bAny || pPointer->getRecordType() == nType)
rRecords.push_back(pPointer);
if (bRecursive)
pPointer->findRecords(nType, rRecords, bRecursive,
bAny);
++aIt;
}
}
void DffRecord::resolveChildren(Properties & rHandler)
{
Records_t::iterator aIt;
for (aIt = begin(); aIt != end(); ++aIt)
{
rHandler.sprm(**aIt);
}
}
void DffRecord::resolveLocal(Properties &)
{
}
void DffRecord::resolve(Properties & rHandler)
{
WW8Value::Pointer_t pVal = createValue(getRecordType());
rHandler.attribute(NS_rtf::LN_dfftype, *pVal);
pVal = createValue(getInstance());
rHandler.attribute(NS_rtf::LN_dffinstance, *pVal);
pVal = createValue(getVersion());
rHandler.attribute(NS_rtf::LN_dffversion, *pVal);
pVal = createValue(getU32(0x0));
rHandler.attribute(NS_rtf::LN_dffheader, *pVal);
if (isContainer())
{
resolveChildren(rHandler);
}
resolveLocal(rHandler);
#if 1
WW8BinaryObjReference::Pointer_t pBinObjRef
(new WW8BinaryObjReference(this, 0, getCount()));
WW8Sprm aSprm(pBinObjRef);
rHandler.sprm(aSprm);
#endif
}
sal_uInt32 DffRecord::getShapeType()
{
sal_uInt32 nResult = 0;
Records_t aRecords = findRecords(0xf00a);
if (aRecords.size() > 0)
{
DffFSP * pDffFSP = dynamic_cast<DffFSP*>((*aRecords.begin()).get());
nResult = pDffFSP->get_shptype();
}
return nResult;
}
sal_uInt32 DffRecord::getShapeId()
{
sal_uInt32 nResult = 0;
Records_t aRecords = findRecords(0xf00a);
if (aRecords.size() > 0)
{
DffFSP * pDffFSP = dynamic_cast<DffFSP*>((*aRecords.begin()).get());
nResult = pDffFSP->get_shpid();
}
return nResult;
}
class DffOPTHandler : public Properties
{
map<int, WW8ValueSharedPointer_t> mMap;
int nId;
public:
DffOPTHandler() : nId(0) {}
virtual ~DffOPTHandler() {}
virtual void attribute(Id name, Value & val)
{
switch (name)
{
case NS_rtf::LN_shppid:
nId = val.getInt();
break;
case NS_rtf::LN_shpvalue:
{
WW8Value & rTmpVal = dynamic_cast<WW8Value &>(val);
WW8ValueSharedPointer_t
pVal(dynamic_cast<WW8Value *>(rTmpVal.clone()));
mMap[nId] = pVal;
}
}
}
virtual void sprm(Sprm & /*sprm_*/)
{
}
WW8ValueSharedPointer_t & getValue(int nId_)
{
return mMap[nId_];
}
};
sal_uInt32 DffRecord::getShapeBid()
{
sal_uInt32 nResult = 0;
if (getShapeType() == 75)
{
Records_t aRecords = findRecords(0xf00b);
if (aRecords.size() > 0)
{
DffOPTHandler aHandler;
DffOPT * pOpts = dynamic_cast<DffOPT*>((*aRecords.begin()).get());
sal_uInt32 nCount = pOpts->get_property_count();
for (sal_uInt32 n = 0; n < nCount; ++n)
{
pOpts->get_property(n)->resolve(aHandler);
}
WW8ValueSharedPointer_t pVal = aHandler.getValue(260);
if (pVal.get() != NULL)
nResult = pVal->getInt();
}
}
return nResult;
}
string DffRecord::getType() const
{
return "DffRecord";
}
Value::Pointer_t DffRecord::getValue()
{
return Value::Pointer_t();
}
writerfilter::Reference<BinaryObj>::Pointer_t DffRecord::getBinary()
{
return writerfilter::Reference<BinaryObj>::Pointer_t();
}
writerfilter::Reference<Stream>::Pointer_t DffRecord::getStream()
{
return writerfilter::Reference<Stream>::Pointer_t();
}
writerfilter::Reference<Properties>::Pointer_t DffRecord::getProps()
{
return writerfilter::Reference<Properties>::Pointer_t(this->clone());
}
string DffRecord::toString() const
{
char sBuffer[1024];
snprintf(sBuffer, sizeof(sBuffer),
"<dffrecord type=\"%" SAL_PRIuUINT32 "\" instance=\"%" SAL_PRIuUINT32 "\" version=\"%" SAL_PRIuUINT32 "\">\n",
getRecordType(), getInstance(), getVersion());
string aResult = sBuffer;
if (!isContainer())
aResult += mSequence.toString();
else
{
WW8StructBase::Sequence aSeq(mSequence, 0, 8);
aResult += aSeq.toString();
}
aResult += "</dffrecord>";
return aResult;
}
string DffRecord::getName() const
{
return "";
}
Sprm::Kind DffRecord::getKind()
{
return Sprm::UNKNOWN;
}
DffBlock::DffBlock(WW8Stream & rStream, sal_uInt32 nOffset,
sal_uInt32 nCount, sal_uInt32 nPadding)
: WW8StructBase(rStream, nOffset, nCount), bInitialized(false),
mnPadding(nPadding)
{
}
DffBlock::DffBlock(WW8StructBase * pParent, sal_uInt32 nOffset,
sal_uInt32 nCount, sal_uInt32 nPadding)
: WW8StructBase(pParent, nOffset, nCount), bInitialized(false),
mnPadding(nPadding)
{
}
DffBlock::DffBlock(const DffBlock & rSrc)
: WW8StructBase(rSrc), writerfilter::Reference<Properties>(rSrc),
bInitialized(false), mnPadding(rSrc.mnPadding)
{
}
void DffBlock::initChildren()
{
sal_uInt32 nOffset = 0;
sal_uInt32 nCount = getCount();
while (nOffset < nCount)
{
sal_uInt32 nSize = 0;
DffRecord::Pointer_t pDffRecord
(createDffRecord(this, nOffset, &nSize));
if (nSize == 0)
break;
mRecords.push_back(pDffRecord);
nOffset += nSize + mnPadding;
}
bInitialized = true;
}
Records_t DffBlock::findRecords(sal_uInt32 nType, bool bRecursive, bool bAny)
{
Records_t aResult;
findRecords(nType, aResult, bRecursive, bAny);
return aResult;
}
void DffBlock::findRecords
(sal_uInt32 nType, Records_t & rRecords, bool bRecursive, bool bAny)
{
Records_t::iterator aIt = begin();
while (aIt != end())
{
DffRecord::Pointer_t pPointer(*aIt);
if (bAny || pPointer->getRecordType() == nType)
rRecords.push_back(pPointer);
if (bRecursive)
pPointer->findRecords(nType, rRecords, bRecursive,
bAny);
++aIt;
}
}
void DffBlock::resolve(Properties & rHandler)
{
Records_t::iterator aIt;
for (aIt = begin(); aIt != end(); ++aIt)
{
DffRecord * pDff = aIt->get();
rHandler.sprm(*pDff);
}
}
DffRecord::Pointer_t DffBlock::getShape(sal_uInt32 nSpid)
{
DffRecord::Pointer_t pResult;
Records_t aRecords = findRecords(0xf004);
Records_t::iterator aIt;
for (aIt = aRecords.begin(); aIt != aRecords.end(); ++aIt)
{
DffRecord::Pointer_t pPointer = *aIt;
Records_t aFSPs = pPointer->findRecords(0xf00a);
Records_t::iterator aItFSP = aFSPs.begin();
if (aItFSP != aFSPs.end())
{
DffFSP * pFSP = dynamic_cast<DffFSP *>((*aItFSP).get());
if (pFSP->get_shpid() == nSpid)
{
pResult = pPointer;
break;
}
}
}
return pResult;
}
DffRecord::Pointer_t DffBlock::getBlip(sal_uInt32 nBlip)
{
DffRecord::Pointer_t pResult;
if (nBlip > 0)
{
nBlip--;
Records_t aRecords = findRecords(0xf007);
if (nBlip < aRecords.size())
{
pResult = aRecords[nBlip];
}
}
return pResult;
}
Records_t::iterator DffBlock::begin()
{
if (! bInitialized)
initChildren();
return mRecords.begin();
}
Records_t::iterator DffBlock::end()
{
if (! bInitialized)
initChildren();
return mRecords.end();
}
string DffBlock::getType() const
{
return "DffBlock";
}
}}