1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <stdio.h>
25 #include "Dff.hxx"
26 #include <doctok/resourceids.hxx>
27 #include <resourcemodel/WW8ResourceModel.hxx>
28 #include "resources.hxx"
29 
30 namespace writerfilter {
31 namespace doctok {
32 
33 typedef boost::shared_ptr<WW8Value> WW8ValueSharedPointer_t;
34 
DffRecord(WW8Stream & rStream,sal_uInt32 nOffset,sal_uInt32 nCount)35 DffRecord::DffRecord(WW8Stream & rStream, sal_uInt32 nOffset,
36                      sal_uInt32 nCount)
37 : WW8StructBase(rStream, nOffset, nCount), bInitialized(false)
38 {
39 }
40 
DffRecord(WW8StructBase * pParent,sal_uInt32 nOffset,sal_uInt32 nCount)41 DffRecord::DffRecord(WW8StructBase * pParent, sal_uInt32 nOffset,
42                      sal_uInt32 nCount)
43 : WW8StructBase(pParent, nOffset, nCount), bInitialized(false)
44 {
45 }
46 
begin()47 Records_t::iterator DffRecord::begin()
48 {
49     if (! bInitialized)
50         initChildren();
51 
52     return mRecords.begin();
53 }
54 
end()55 Records_t::iterator DffRecord::end()
56 {
57     if (! bInitialized)
58         initChildren();
59 
60     return mRecords.end();
61 }
62 
isContainer() const63 bool DffRecord::isContainer() const
64 {
65     return getVersion() == 0xf;
66 }
67 
calcSize() const68 sal_uInt32 DffRecord::calcSize() const
69 {
70     sal_uInt32 nResult = 0;
71 
72     switch (getRecordType())
73     {
74     case 0xf000:
75     case 0xf001:
76     case 0xf002:
77     case 0xf003:
78     case 0xf004:
79         nResult = getU32(0x4) + 8;
80 
81         break;
82     case 0xf700:
83         nResult = 8;
84 
85         break;
86     default:
87         nResult = getU32(0x4);
88 
89         if (! isContainer())
90             nResult += 8;
91         break;
92     }
93 
94     return nResult;
95 }
96 
getVersion() const97 sal_uInt32 DffRecord::getVersion() const
98 {
99     return getU8(0x0) & 0xf;
100 }
101 
getInstance() const102 sal_uInt32 DffRecord::getInstance() const
103 {
104     return (getU16(0x0) & 0xfff0) >> 4;
105 }
106 
getRecordType() const107 sal_uInt32 DffRecord::getRecordType() const
108 {
109     return getU16(0x2);
110 }
111 
initChildren()112 void DffRecord::initChildren()
113 {
114     if (isContainer())
115     {
116         sal_uInt32 nOffset = 8;
117         sal_uInt32 nCount = calcSize();
118 
119         while (nCount - nOffset >= 8)
120         {
121             sal_uInt32 nSize = 0;
122             boost::shared_ptr<DffRecord> pRec
123                 (createDffRecord(this, nOffset, &nSize));
124 
125             if (nSize == 0)
126                 break;
127 
128             mRecords.push_back(pRec);
129 
130             nOffset += nSize;
131         }
132     }
133 
134     bInitialized = true;
135 }
136 
findRecords(sal_uInt32 nType,bool bRecursive,bool bAny)137 Records_t DffRecord::findRecords(sal_uInt32 nType, bool bRecursive, bool bAny)
138 {
139     Records_t aResult;
140 
141     findRecords(nType, aResult, bRecursive, bAny);
142 
143     return aResult;
144 }
145 
findRecords(sal_uInt32 nType,Records_t & rRecords,bool bRecursive,bool bAny)146 void DffRecord::findRecords
147 (sal_uInt32 nType, Records_t & rRecords, bool bRecursive, bool bAny)
148 {
149     Records_t::iterator aIt = begin();
150 
151     while (aIt != end())
152     {
153         Pointer_t pPointer = *aIt;
154         if (bAny || pPointer->getRecordType() == nType)
155             rRecords.push_back(pPointer);
156 
157         if (bRecursive)
158             pPointer->findRecords(nType, rRecords, bRecursive,
159                                       bAny);
160 
161         ++aIt;
162     }
163 }
164 
resolveChildren(Properties & rHandler)165 void DffRecord::resolveChildren(Properties & rHandler)
166 {
167     Records_t::iterator aIt;
168     for (aIt = begin(); aIt != end(); ++aIt)
169     {
170         rHandler.sprm(**aIt);
171     }
172 }
173 
resolveLocal(Properties &)174 void DffRecord::resolveLocal(Properties &)
175 {
176 }
177 
resolve(Properties & rHandler)178 void DffRecord::resolve(Properties & rHandler)
179 {
180     WW8Value::Pointer_t pVal = createValue(getRecordType());
181     rHandler.attribute(NS_rtf::LN_dfftype, *pVal);
182 
183     pVal = createValue(getInstance());
184     rHandler.attribute(NS_rtf::LN_dffinstance, *pVal);
185 
186     pVal = createValue(getVersion());
187     rHandler.attribute(NS_rtf::LN_dffversion, *pVal);
188 
189     pVal = createValue(getU32(0x0));
190     rHandler.attribute(NS_rtf::LN_dffheader, *pVal);
191 
192     if (isContainer())
193     {
194         resolveChildren(rHandler);
195     }
196 
197     resolveLocal(rHandler);
198 
199 #if 1
200     WW8BinaryObjReference::Pointer_t pBinObjRef
201         (new WW8BinaryObjReference(this, 0, getCount()));
202     WW8Sprm aSprm(pBinObjRef);
203 
204     rHandler.sprm(aSprm);
205 #endif
206 }
207 
getShapeType()208 sal_uInt32 DffRecord::getShapeType()
209 {
210     sal_uInt32 nResult = 0;
211 
212     Records_t aRecords = findRecords(0xf00a);
213 
214     if (aRecords.size() > 0)
215     {
216         DffFSP * pDffFSP = dynamic_cast<DffFSP*>((*aRecords.begin()).get());
217         nResult = pDffFSP->get_shptype();
218     }
219 
220     return nResult;
221 }
222 
getShapeId()223 sal_uInt32 DffRecord::getShapeId()
224 {
225     sal_uInt32 nResult = 0;
226 
227     Records_t aRecords = findRecords(0xf00a);
228 
229     if (aRecords.size() > 0)
230     {
231         DffFSP * pDffFSP = dynamic_cast<DffFSP*>((*aRecords.begin()).get());
232         nResult = pDffFSP->get_shpid();
233     }
234 
235     return nResult;
236 }
237 
238 class DffOPTHandler : public Properties
239 {
240     map<int, WW8ValueSharedPointer_t> mMap;
241     int nId;
242 
243 public:
DffOPTHandler()244     DffOPTHandler() : nId(0) {}
~DffOPTHandler()245     virtual ~DffOPTHandler() {}
246 
attribute(Id name,Value & val)247     virtual void attribute(Id name, Value & val)
248     {
249         switch (name)
250         {
251         case NS_rtf::LN_shppid:
252             nId = val.getInt();
253             break;
254         case NS_rtf::LN_shpvalue:
255             {
256                 WW8Value & rTmpVal = dynamic_cast<WW8Value &>(val);
257                 WW8ValueSharedPointer_t
258                     pVal(dynamic_cast<WW8Value *>(rTmpVal.clone()));
259                 mMap[nId] = pVal;
260             }
261         }
262     }
263 
sprm(Sprm &)264     virtual void sprm(Sprm & /*sprm_*/)
265     {
266     }
267 
getValue(int nId_)268     WW8ValueSharedPointer_t & getValue(int nId_)
269     {
270         return mMap[nId_];
271     }
272 
273 };
274 
getShapeBid()275 sal_uInt32 DffRecord::getShapeBid()
276 {
277     sal_uInt32 nResult = 0;
278 
279     if (getShapeType() == 75)
280     {
281         Records_t aRecords = findRecords(0xf00b);
282 
283         if (aRecords.size() > 0)
284         {
285             DffOPTHandler aHandler;
286             DffOPT * pOpts = dynamic_cast<DffOPT*>((*aRecords.begin()).get());
287 
288             sal_uInt32 nCount = pOpts->get_property_count();
289 
290             for (sal_uInt32 n = 0; n < nCount; ++n)
291             {
292                 pOpts->get_property(n)->resolve(aHandler);
293             }
294 
295             WW8ValueSharedPointer_t pVal = aHandler.getValue(260);
296 
297             if (pVal.get() != NULL)
298                 nResult = pVal->getInt();
299         }
300     }
301 
302     return nResult;
303 }
304 
getType() const305 string DffRecord::getType() const
306 {
307     return "DffRecord";
308 }
309 
getValue()310 Value::Pointer_t DffRecord::getValue()
311 {
312     return Value::Pointer_t();
313 }
314 
getBinary()315 writerfilter::Reference<BinaryObj>::Pointer_t DffRecord::getBinary()
316 {
317     return writerfilter::Reference<BinaryObj>::Pointer_t();
318 }
319 
getStream()320 writerfilter::Reference<Stream>::Pointer_t DffRecord::getStream()
321 {
322     return writerfilter::Reference<Stream>::Pointer_t();
323 }
324 
getProps()325 writerfilter::Reference<Properties>::Pointer_t DffRecord::getProps()
326 {
327     return writerfilter::Reference<Properties>::Pointer_t(this->clone());
328 }
329 
toString() const330 string DffRecord::toString() const
331 {
332     char sBuffer[1024];
333 
334     snprintf(sBuffer, sizeof(sBuffer),
335              "<dffrecord type=\"%" SAL_PRIuUINT32 "\" instance=\"%" SAL_PRIuUINT32 "\" version=\"%" SAL_PRIuUINT32 "\">\n",
336              getRecordType(), getInstance(), getVersion());
337     string aResult = sBuffer;
338 
339 
340     if (!isContainer())
341         aResult += mSequence.toString();
342     else
343     {
344         WW8StructBase::Sequence aSeq(mSequence, 0, 8);
345         aResult += aSeq.toString();
346     }
347 
348     aResult += "</dffrecord>";
349 
350     return aResult;
351 }
352 
getName() const353 string DffRecord::getName() const
354 {
355     return "";
356 }
357 
getKind()358 Sprm::Kind DffRecord::getKind()
359 {
360     return Sprm::UNKNOWN;
361 }
362 
DffBlock(WW8Stream & rStream,sal_uInt32 nOffset,sal_uInt32 nCount,sal_uInt32 nPadding)363 DffBlock::DffBlock(WW8Stream & rStream, sal_uInt32 nOffset,
364                    sal_uInt32 nCount, sal_uInt32 nPadding)
365 : WW8StructBase(rStream, nOffset, nCount), bInitialized(false),
366   mnPadding(nPadding)
367 {
368 }
369 
DffBlock(WW8StructBase * pParent,sal_uInt32 nOffset,sal_uInt32 nCount,sal_uInt32 nPadding)370 DffBlock::DffBlock(WW8StructBase * pParent, sal_uInt32 nOffset,
371                    sal_uInt32 nCount, sal_uInt32 nPadding)
372 : WW8StructBase(pParent, nOffset, nCount), bInitialized(false),
373   mnPadding(nPadding)
374 {
375 }
376 
DffBlock(const DffBlock & rSrc)377 DffBlock::DffBlock(const DffBlock & rSrc)
378 : WW8StructBase(rSrc), writerfilter::Reference<Properties>(rSrc),
379   bInitialized(false), mnPadding(rSrc.mnPadding)
380 {
381 }
382 
initChildren()383 void DffBlock::initChildren()
384 {
385     sal_uInt32 nOffset = 0;
386     sal_uInt32 nCount = getCount();
387 
388     while (nOffset < nCount)
389     {
390         sal_uInt32 nSize = 0;
391         DffRecord::Pointer_t pDffRecord
392             (createDffRecord(this, nOffset, &nSize));
393 
394         if (nSize == 0)
395             break;
396 
397         mRecords.push_back(pDffRecord);
398 
399         nOffset +=  nSize + mnPadding;
400     }
401 
402     bInitialized = true;
403 }
404 
findRecords(sal_uInt32 nType,bool bRecursive,bool bAny)405 Records_t DffBlock::findRecords(sal_uInt32 nType, bool bRecursive, bool bAny)
406 {
407     Records_t aResult;
408 
409     findRecords(nType, aResult, bRecursive, bAny);
410 
411     return aResult;
412 }
413 
findRecords(sal_uInt32 nType,Records_t & rRecords,bool bRecursive,bool bAny)414 void DffBlock::findRecords
415 (sal_uInt32 nType, Records_t & rRecords, bool bRecursive, bool bAny)
416 {
417     Records_t::iterator aIt = begin();
418 
419     while (aIt != end())
420     {
421         DffRecord::Pointer_t pPointer(*aIt);
422 
423         if (bAny || pPointer->getRecordType() == nType)
424             rRecords.push_back(pPointer);
425 
426         if (bRecursive)
427             pPointer->findRecords(nType, rRecords, bRecursive,
428                                   bAny);
429 
430         ++aIt;
431     }
432 }
433 
resolve(Properties & rHandler)434 void DffBlock::resolve(Properties & rHandler)
435 {
436     Records_t::iterator aIt;
437 
438     for (aIt = begin(); aIt != end(); ++aIt)
439     {
440         DffRecord * pDff = aIt->get();
441         rHandler.sprm(*pDff);
442     }
443 }
444 
getShape(sal_uInt32 nSpid)445 DffRecord::Pointer_t DffBlock::getShape(sal_uInt32 nSpid)
446 {
447     DffRecord::Pointer_t pResult;
448 
449     Records_t aRecords = findRecords(0xf004);
450     Records_t::iterator aIt;
451     for (aIt = aRecords.begin(); aIt != aRecords.end(); ++aIt)
452     {
453         DffRecord::Pointer_t pPointer = *aIt;
454 
455         Records_t aFSPs = pPointer->findRecords(0xf00a);
456         Records_t::iterator aItFSP = aFSPs.begin();
457 
458         if (aItFSP != aFSPs.end())
459         {
460             DffFSP * pFSP = dynamic_cast<DffFSP *>((*aItFSP).get());
461 
462             if (pFSP->get_shpid() == nSpid)
463             {
464                 pResult = pPointer;
465 
466                 break;
467             }
468         }
469     }
470 
471     return pResult;
472 }
473 
getBlip(sal_uInt32 nBlip)474 DffRecord::Pointer_t DffBlock::getBlip(sal_uInt32 nBlip)
475 {
476     DffRecord::Pointer_t pResult;
477 
478     if (nBlip > 0)
479     {
480         nBlip--;
481 
482         Records_t aRecords = findRecords(0xf007);
483 
484         if (nBlip < aRecords.size())
485         {
486             pResult = aRecords[nBlip];
487         }
488     }
489 
490     return pResult;
491 }
492 
begin()493 Records_t::iterator DffBlock::begin()
494 {
495     if (! bInitialized)
496         initChildren();
497 
498     return mRecords.begin();
499 }
500 
end()501 Records_t::iterator DffBlock::end()
502 {
503     if (! bInitialized)
504         initChildren();
505 
506     return mRecords.end();
507 }
508 
getType() const509 string DffBlock::getType() const
510 {
511     return "DffBlock";
512 }
513 
514 }}
515