1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_SW_SOURCE_FILTER_WW8_WW8SCAN_HXX
21 #define INCLUDED_SW_SOURCE_FILTER_WW8_WW8SCAN_HXX
22 
23 #include <cassert>
24 #include <cstddef>
25 #include <deque>
26 #include <memory>
27 #include <stack>
28 #include <unordered_map>
29 #include <vector>
30 
31 #include <osl/endian.h>
32 #include <tools/solar.h>
33 #include <tools/stream.hxx>
34 #include <rtl/ustring.hxx>
35 
36 #include "ww8struc.hxx"
37 #include "types.hxx"
38 
39 class SvStream;
40 
41 //Commonly used string literals for stream and storage names in word docs
42 namespace SL
43 {
44     const char aObjectPool[]    = "ObjectPool";
45     const char a1Table[]        = "1Table";
46     const char a0Table[]        = "0Table";
47     const char aData[]          = "Data";
48     const char aCheckBox[]      = "CheckBox";
49     const char aListBox[]       = "ListBox";
50     const char aTextBox[]       = "TextBox";
51     const char aTextField[]     = "TextField";
52     const char aMSMacroCmds[]   = "MSMacroCmds";
53 }
54 
55 struct SprmInfo
56 {
57     unsigned int nLen : 6;
58     unsigned int nVari : 2;
59 };
60 
61 struct SprmInfoRow {
62     sal_uInt16 nId;         ///< A ww8 sprm is hardcoded as 16bits
63     SprmInfo info;
64 };
65 
66 class wwSprmSearcher {
67 public:
68     //see Read_AmbiguousSPRM for the bPatchCJK oddity
wwSprmSearcher(SprmInfoRow const * rows,std::size_t size,bool bPatchCJK=false)69     wwSprmSearcher(SprmInfoRow const * rows, std::size_t size, bool bPatchCJK = false) {
70         for (std::size_t i = 0; i != size; ++i) {
71             bool ins = map_.emplace(rows[i].nId, rows[i].info).second;
72             assert(ins); (void) ins;
73         }
74         if (bPatchCJK)
75             patchCJKVariant();
76     }
77 
search(sal_uInt16 id) const78     SprmInfo const * search(sal_uInt16 id) const {
79         Map::const_iterator i(map_.find(id));
80         return i == map_.end() ? nullptr : &i->second;
81     }
82 
83 private:
84     typedef std::unordered_map<sal_uInt16, SprmInfo> Map;
85 
86     Map map_;
87 
88     void patchCJKVariant();
89 };
90 
91 class WW8Fib;
92 
93 struct SprmResult
94 {
95     const sal_uInt8* pSprm;
96     sal_Int32 nRemainingData;
SprmResultSprmResult97     SprmResult()
98         : pSprm(nullptr)
99         , nRemainingData(0)
100     {
101     }
SprmResultSprmResult102     SprmResult(const sal_uInt8* pInSprm, sal_Int32 nInRemainingData)
103         : pSprm(pInSprm)
104         , nRemainingData(nInRemainingData)
105     {
106     }
107 };
108 
109 /**
110     wwSprmParser knows how to take a sequence of bytes and split it up into
111     sprms and their arguments
112 */
113 class wwSprmParser
114 {
115 private:
116     ww::WordVersion meVersion;
117     sal_uInt8 mnDelta;
118     const wwSprmSearcher *mpKnownSprms;
119     static const wwSprmSearcher* GetWW8SprmSearcher();
120     static const wwSprmSearcher* GetWW6SprmSearcher(const WW8Fib& rFib);
121     static const wwSprmSearcher* GetWW2SprmSearcher();
122 
123     SprmInfo GetSprmInfo(sal_uInt16 nId) const;
124 
125     sal_uInt8 SprmDataOfs(sal_uInt16 nId) const;
126 
127 public:
128     enum SprmType {L_FIX=0, L_VAR=1, L_VAR2=2};
129 
130     //7- ids are very different to 8+ ones
131     explicit wwSprmParser(const WW8Fib& rFib);
132     /// Return the SPRM id at the beginning of this byte sequence
133     sal_uInt16 GetSprmId(const sal_uInt8* pSp) const;
134 
135     sal_uInt16 GetSprmSize(sal_uInt16 nId, const sal_uInt8* pSprm, sal_Int32 nRemLen) const;
136 
137     /// Get known len of a sprms head, the bytes of the sprm id + any bytes
138     /// reserved to hold a variable length
139     sal_uInt16 DistanceToData(sal_uInt16 nId) const;
140 
141     /// Get len of a sprms data area, ignoring the bytes of the sprm id and
142     /// ignoring any len bytes. Reports the remaining data after those bytes
143     sal_uInt16 GetSprmTailLen(sal_uInt16 nId, const sal_uInt8* pSprm, sal_Int32 nRemLen) const;
144 
145     /// The minimum acceptable sprm len possible for this type of parser
MinSprmLen() const146     int MinSprmLen() const { return (IsSevenMinus(meVersion)) ? 2 : 3; }
147 
148     /// Returns the offset to data of the first sprm of id nId, 0
149     //  if not found. nLen must be the <= length of pSprms
150     SprmResult findSprmData(sal_uInt16 nId, sal_uInt8* pSprms, sal_uInt16 nLen) const;
151 };
152 
153 //Read a Pascal-style, i.e. single byte string length followed
154 //by string contents
read_uInt8_PascalString(SvStream & rStrm,rtl_TextEncoding eEnc)155 inline OUString read_uInt8_PascalString(SvStream& rStrm, rtl_TextEncoding eEnc)
156 {
157     return read_uInt8_lenPrefixed_uInt8s_ToOUString(rStrm, eEnc);
158 }
159 
read_uInt16_PascalString(SvStream & rStrm)160 inline OUString read_uInt16_PascalString(SvStream& rStrm)
161 {
162     return read_uInt16_lenPrefixed_uInt16s_ToOUString(rStrm);
163 }
164 
165 //Belt and Braces strings, i.e. Pascal-style strings followed by
166 //null termination, Spolsky calls them "fucked strings" FWIW
167 //http://www.joelonsoftware.com/articles/fog0000000319.html
168 OUString read_uInt8_BeltAndBracesString(SvStream& rStrm, rtl_TextEncoding eEnc);
169 OUString read_uInt16_BeltAndBracesString(SvStream& rStrm);
170 
171 //--Line above which the code has meaningful comments
172 
173 class  WW8ScannerBase;
174 class  WW8PLCFspecial;
175 struct WW8PLCFxDesc;
176 class  WW8PLCFx_PCD;
177 
178 /**
179  reads array of strings (see MS documentation: String Table stored in File)
180  returns NOT the original pascal strings but an array of converted char*
181 
182  attention: the *extra data* of each string are SKIPPED and ignored
183  */
184 void WW8ReadSTTBF(bool bVer8, SvStream& rStrm, sal_uInt32 nStart, sal_Int32 nLen,
185     sal_uInt16 nExtraLen, rtl_TextEncoding eCS, std::vector<OUString> &rArray,
186     std::vector<ww::bytes>* pExtraArray = nullptr, std::vector<OUString>* pValueArray = nullptr);
187 
188 struct WW8FieldDesc
189 {
190     WW8_CP nLen;            ///< total length (to skip over text)
191     WW8_CP nSCode;          ///< start of instructions code
192     WW8_CP nLCode;          ///< length
193     WW8_CP nSRes;           ///< start of result
194     WW8_CP nLRes;           ///< length ( == 0, if no result )
195     sal_uInt16 nId;         ///< WW-id for fields
196     sal_uInt8 nOpt;         ///< WW-Flags ( e.g.: changed by user )
197     bool bCodeNest:1;       ///< instruction used recursively
198     bool bResNest:1;        ///< instruction inserted into result
199 };
200 
201 struct WW8PLCFxSave1
202 {
203     sal_uInt32 nPLCFxPos;
204     sal_uInt32 nPLCFxPos2;       ///< for PLCF_Cp_Fkp: PieceIter-Pos
205     long nPLCFxMemOfs;
206     WW8_CP nStartCp;        ///< for cp based iterator like PAP and CHP
207     long nCpOfs;
208     WW8_FC nStartFC;
209     WW8_CP nAttrStart;
210     WW8_CP nAttrEnd;
211     bool bLineEnd;
212 };
213 
214 /**
215     among others for fields, that is, the same number of attr as positions,
216     if Ctor-Param bNoEnd = false
217 */
218 class WW8PLCFspecial        // iterator for PLCFs
219 {
220 private:
221     std::unique_ptr<sal_Int32[]> pPLCF_PosArray;  ///< pointer to Pos-array and to the whole structure
222     sal_uInt8*  pPLCF_Contents;  ///< pointer to content-array-part of Pos-array
223     long nIMax;             ///< number of elements
224     long nIdx;              ///< marker where we currently are
225     sal_uInt32 nStru;
226 
227     WW8PLCFspecial(const WW8PLCFspecial&) = delete;
228     WW8PLCFspecial& operator=(const WW8PLCFspecial&) = delete;
229 
230 public:
231     WW8PLCFspecial(SvStream* pSt, sal_uInt32 nFilePos, sal_uInt32 nPLCF,
232         sal_uInt32 nStruct);
GetIdx() const233     long GetIdx() const { return nIdx; }
SetIdx(long nI)234     void SetIdx( long nI ) { nIdx = nI; }
GetIMax() const235     long GetIMax() const { return nIMax; }
236     bool SeekPos(long nPos);            // walks over FC- or CP-value
237                                         // resp. next biggest value
238     bool SeekPosExact(long nPos);
Where() const239     sal_Int32 Where() const
240         { return ( nIdx >= nIMax ) ? SAL_MAX_INT32 : pPLCF_PosArray[nIdx]; }
241     bool Get(WW8_CP& rStart, void*& rpValue) const;
242     bool GetData(long nIdx, WW8_CP& rPos, void*& rpValue) const;
243 
GetData(long nInIdx) const244     const void* GetData( long nInIdx ) const
245     {
246         return ( nInIdx >= nIMax ) ? nullptr
247             : static_cast<const void*>(&pPLCF_Contents[nInIdx * nStru]);
248     }
GetPos(long nInIdx) const249     sal_Int32 GetPos( long nInIdx ) const
250         { return ( nInIdx >= nIMax ) ? SAL_MAX_INT32 : pPLCF_PosArray[nInIdx]; }
251 
advance()252     void advance()
253     {
254         if (nIdx <= nIMax)
255             ++nIdx;
256     }
257 };
258 
259 /** simple Iterator for SPRMs */
260 class WW8SprmIter
261 {
262 private:
263     const wwSprmParser &mrSprmParser;
264     // these members will be updated
265     const sal_uInt8* pSprms; // remaining part of the SPRMs ( == start of current SPRM)
266     const sal_uInt8* pCurrentParams; // start of current SPRM's parameters
267     sal_uInt16 nCurrentId;
268     sal_uInt16 nCurrentSize;
269 
270     sal_Int32 nRemLen;   // length of remaining SPRMs (including current SPRM)
271 
272     void UpdateMyMembers();
273 
274 public:
275     explicit WW8SprmIter(const sal_uInt8* pSprms_, sal_Int32 nLen_,
276         const wwSprmParser &rSprmParser);
277     void  SetSprms(const sal_uInt8* pSprms_, sal_Int32 nLen_);
278     SprmResult FindSprm(sal_uInt16 nId, const sal_uInt8* pNextByteMatch = nullptr);
279     void  advance();
GetSprms() const280     const sal_uInt8* GetSprms() const
281         { return ( pSprms && (0 < nRemLen) ) ? pSprms : nullptr; }
GetCurrentParams() const282     const sal_uInt8* GetCurrentParams() const { return pCurrentParams; }
GetCurrentId() const283     sal_uInt16 GetCurrentId() const { return nCurrentId; }
GetRemLen() const284     sal_Int32 GetRemLen() const { return nRemLen; }
285 
286 private:
287     WW8SprmIter(const WW8SprmIter&) = delete;
288     WW8SprmIter& operator=(const WW8SprmIter&) = delete;
289 };
290 
291 /* among others for FKPs to normal attr., i.e. one less attr than positions */
292 class WW8PLCF                       // Iterator for PLCFs
293 {
294 private:
295     std::unique_ptr<WW8_CP[]> pPLCF_PosArray; // pointer to Pos-array and the whole structure
296     sal_uInt8* pPLCF_Contents;   // pointer to content-array-part of Pos-array
297     sal_Int32 nIMax;            // number of elements
298     sal_Int32 nIdx;
299     int nStru;
300 
301     void ReadPLCF(SvStream& rSt, WW8_FC nFilePos, sal_uInt32 nPLCF);
302 
303     /*
304         If a PLC is missing in the doc and the FKPs stand alone,
305         we create a PLC with this:
306     */
307     void GeneratePLCF(SvStream& rSt, sal_Int32 nPN, sal_Int32 ncpN);
308 
309     void MakeFailedPLCF();
310 
311     void TruncToSortedRange();
312 public:
313     WW8PLCF(SvStream& rSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
314         WW8_CP nStartPos = -1);
315 
316     /*
317         the following ctor generates a PLC from nPN and ncpN, if necessary
318     */
319     WW8PLCF(SvStream& rSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
320         WW8_CP nStartPos, sal_Int32 nPN, sal_Int32 ncpN);
321 
GetIdx() const322     sal_Int32 GetIdx() const { return nIdx; }
SetIdx(sal_Int32 nI)323     void SetIdx( sal_Int32 nI ) { nIdx = nI; }
GetIMax() const324     sal_Int32 GetIMax() const { return nIMax; }
325     bool SeekPos(WW8_CP nPos);
326     WW8_CP Where() const;
327     bool Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const;
advance()328     void advance() { if( nIdx < nIMax ) ++nIdx; }
329 
GetData(sal_Int32 nInIdx) const330     const void* GetData( sal_Int32 nInIdx ) const
331     {
332         return ( nInIdx >= nIMax ) ? nullptr :
333             static_cast<const void*>(&pPLCF_Contents[nInIdx * nStru]);
334     }
335 };
336 
337 /* for Piece Table (.i.e. FastSave Table) */
338 class WW8PLCFpcd
339 {
340     friend class WW8PLCFpcd_Iter;
341 
342     std::unique_ptr<sal_Int32[]> pPLCF_PosArray;  // pointer to Pos-array and the whole structure
343     sal_uInt8*  pPLCF_Contents;  // pointer to content-array-part of Pos-array
344     long nIMax;
345     sal_uInt32 nStru;
346 
347     WW8PLCFpcd(const WW8PLCFpcd&) = delete;
348     WW8PLCFpcd& operator=(const WW8PLCFpcd&) = delete;
349 
350 public:
351     WW8PLCFpcd(SvStream* pSt, sal_uInt32 nFilePos, sal_uInt32 nPLCF,
352         sal_uInt32 nStruct);
353 };
354 
355 /* multiple WW8PLCFpcd_Iter may point to the same WW8PLCFpcd !!!  */
356 class WW8PLCFpcd_Iter
357 {
358 private:
359     WW8PLCFpcd& rPLCF;
360     long nIdx;
361 
362     WW8PLCFpcd_Iter(const WW8PLCFpcd_Iter&) = delete;
363     WW8PLCFpcd_Iter& operator=(const WW8PLCFpcd_Iter&) = delete;
364 
365 public:
366     WW8PLCFpcd_Iter( WW8PLCFpcd& rPLCFpcd, long nStartPos = -1 );
GetIdx() const367     long GetIdx() const { return nIdx; }
SetIdx(long nI)368     void SetIdx( long nI ) { nIdx = nI; }
GetIMax() const369     long GetIMax() const { return rPLCF.nIMax; }
370     bool SeekPos(long nPos);
371     sal_Int32 Where() const;
372     bool Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const;
advance()373     void advance()
374     {
375         if( nIdx < rPLCF.nIMax )
376             ++nIdx;
377     }
378 };
379 
380 // PLCF-type:
381 enum ePLCFT{ CHP=0, PAP, SEP, /*HED, FNR, ENR,*/ PLCF_END };
382 
383 //Its hardcoded that eFTN be the first one: A very poor hack, needs to be fixed
384 enum eExtSprm { eFTN = 256, eEDN = 257, eFLD = 258, eBKN = 259, eAND = 260, eATNBKN = 261, eFACTOIDBKN = 262 };
385 
386 /*
387     pure virtual:
388 */
389 class WW8PLCFx              // virtual iterator for Piece Table Exceptions
390 {
391 private:
392     const WW8Fib& mrFib;
393     bool bIsSprm;           // PLCF of Sprms or other stuff ( Footnote, ... )
394     WW8_FC nStartFc;
395     bool bDirty;
396 
397     WW8PLCFx(const WW8PLCFx&) = delete;
398     WW8PLCFx& operator=(const WW8PLCFx&) = delete;
399 
400 public:
WW8PLCFx(const WW8Fib & rFib,bool bSprm)401     WW8PLCFx(const WW8Fib& rFib, bool bSprm)
402         : mrFib(rFib)
403         , bIsSprm(bSprm)
404         , nStartFc(-1)
405         , bDirty(false)
406     {
407     }
~WW8PLCFx()408     virtual ~WW8PLCFx() {}
IsSprm() const409     bool IsSprm() const { return bIsSprm; }
410     virtual sal_uInt32 GetIdx() const = 0;
411     virtual void SetIdx(sal_uInt32 nIdx) = 0;
412     virtual sal_uInt32 GetIdx2() const;
413     virtual void SetIdx2(sal_uInt32 nIdx);
414     virtual bool SeekPos(WW8_CP nCpPos) = 0;
415     virtual WW8_FC Where() = 0;
416     virtual void GetSprms( WW8PLCFxDesc* p );
417     virtual long GetNoSprms( WW8_CP& rStart, WW8_CP&, sal_Int32& rLen );
418     virtual void advance() = 0;
GetIstd() const419     virtual sal_uInt16 GetIstd() const { return 0xffff; }
420     virtual void Save( WW8PLCFxSave1& rSave ) const;
421     virtual void Restore( const WW8PLCFxSave1& rSave );
422     ww::WordVersion GetFIBVersion() const;
GetFIB() const423     const WW8Fib& GetFIB() const { return mrFib; }
SetStartFc(WW8_FC nFc)424     void SetStartFc( WW8_FC nFc ) { nStartFc = nFc; }
GetStartFc() const425     WW8_FC GetStartFc() const { return nStartFc; }
SetDirty(bool bIn)426     void SetDirty(bool bIn) {bDirty=bIn;}
GetDirty() const427     bool GetDirty() const {return bDirty;}
428 };
429 
430 class WW8PLCFx_PCDAttrs : public WW8PLCFx
431 {
432 private:
433     WW8PLCFpcd_Iter* pPcdI;
434     WW8PLCFx_PCD* pPcd;
435     std::vector<std::unique_ptr<sal_uInt8[]>> const & mrGrpprls; // attribute of Piece-table
436     SVBT32 aShortSprm;          // mini storage: can contain ONE sprm with
437                                 // 1 byte param
438 
439     WW8PLCFx_PCDAttrs(const WW8PLCFx_PCDAttrs&) = delete;
440     WW8PLCFx_PCDAttrs& operator=(const WW8PLCFx_PCDAttrs&) = delete;
441 
442 public:
443     WW8PLCFx_PCDAttrs(const WW8Fib& rFib, WW8PLCFx_PCD* pPLCFx_PCD,
444         const WW8ScannerBase* pBase );
445     virtual sal_uInt32 GetIdx() const override;
446     virtual void SetIdx(sal_uInt32 nI) override;
447     virtual bool SeekPos(WW8_CP nCpPos) override;
448     virtual WW8_CP Where() override;
449     virtual void GetSprms( WW8PLCFxDesc* p ) override;
450     virtual void advance() override;
451 
GetIter() const452     WW8PLCFpcd_Iter* GetIter() const { return pPcdI; }
453 };
454 
455 class WW8PLCFx_PCD : public WW8PLCFx            // iterator for Piece table
456 {
457 private:
458     std::unique_ptr<WW8PLCFpcd_Iter> pPcdI;
459     bool bVer67;
460     WW8_CP nClipStart;
461 
462     WW8PLCFx_PCD(const WW8PLCFx_PCD&) = delete;
463     WW8PLCFx_PCD& operator=(const WW8PLCFx_PCD&) = delete;
464 
465 public:
466     WW8PLCFx_PCD(const WW8Fib& rFib, WW8PLCFpcd* pPLCFpcd,
467         WW8_CP nStartCp, bool bVer67P);
468     virtual ~WW8PLCFx_PCD() override;
469     sal_uInt32 GetIMax() const;
470     virtual sal_uInt32 GetIdx() const override;
471     virtual void SetIdx(sal_uInt32 nI) override;
472     virtual bool SeekPos(WW8_CP nCpPos) override;
473     virtual WW8_CP Where() override;
474     virtual long GetNoSprms( WW8_CP& rStart, WW8_CP&, sal_Int32& rLen ) override;
475     virtual void advance() override;
476     WW8_CP CurrentPieceStartFc2Cp( WW8_FC nStartPos );
477     WW8_FC CurrentPieceStartCp2Fc( WW8_CP nCp );
478     static void CurrentPieceFc2Cp(WW8_CP& rStartPos, WW8_CP& rEndPos,
479         const WW8ScannerBase *pSBase);
GetPLCFIter()480     WW8PLCFpcd_Iter* GetPLCFIter() { return pPcdI.get(); }
SetClipStart(WW8_CP nIn)481     void SetClipStart(WW8_CP nIn) { nClipStart = nIn; }
GetClipStart() const482     WW8_CP GetClipStart() const { return nClipStart; }
483 
TransformPieceAddress(long nfc,bool & bIsUnicodeAddress)484     static sal_Int32 TransformPieceAddress(long nfc, bool& bIsUnicodeAddress)
485     {
486         bIsUnicodeAddress = 0 == (0x40000000 & nfc);
487         return bIsUnicodeAddress ?  nfc : (nfc & 0x3fffFFFF) / 2;
488     }
489 };
490 
491 /**
492  Iterator for Piece Table Exceptions of Fkps
493  works only with FCs, not with CPs !  ( Low-Level )
494 */
495 class WW8PLCFx_Fc_FKP : public WW8PLCFx
496 {
497 public:
498     class WW8Fkp        // Iterator for Formatted Disk Page
499     {
500     private:
501         class Entry
502         {
503         public:
504             WW8_FC mnFC;
505 
506             sal_uInt8* mpData;
507             sal_uInt16 mnLen;
508             sal_uInt16 mnIStd; // only for Fkp.Papx (actually Style-Nr)
509             bool mbMustDelete;
510 
Entry(WW8_FC nFC)511             explicit Entry(WW8_FC nFC) : mnFC(nFC), mpData(nullptr), mnLen(0),
512                 mnIStd(0), mbMustDelete(false) {}
513             Entry(const Entry &rEntry);
514             ~Entry();
515             bool operator<(const Entry& rEntry) const;
516             Entry& operator=(const Entry& rEntry);
517         };
518 
519         sal_uInt8 maRawData[512];
520         std::vector<Entry> maEntries;
521 
522         long nItemSize;     // either 1 Byte or a complete BX
523 
524         // Offset in Stream where last read of 512 bytes took place
525         long nFilePos;
526         sal_uInt8 mnIdx;         // Pos marker
527         ePLCFT ePLCF;
528         sal_uInt8 mnIMax;         // number of entries
529         int mnMustRemainCached;  // after SaveAllPLCFx, before RestoreAllPLCFx
530 
531         wwSprmParser maSprmParser;
532 
533         //Fill in an Entry with sanity testing
534         void FillEntry(Entry &rEntry, std::size_t nDataOffset, sal_uInt16 nLen);
535 
536     public:
537         WW8Fkp (const WW8Fib& rFib, SvStream* pFKPStrm,
538             SvStream* pDataStrm, long _nFilePos, long nItemSiz, ePLCFT ePl,
539             WW8_FC nStartFc);
540         void Reset(WW8_FC nPos);
GetFilePos() const541         long GetFilePos() const { return nFilePos; }
GetIdx() const542         sal_uInt8 GetIdx() const { return mnIdx; }
543         void SetIdx(sal_uInt8 nI);
544         bool SeekPos(WW8_FC nFc);
Where() const545         WW8_FC Where() const
546         {
547             return (mnIdx < mnIMax) ? maEntries[mnIdx].mnFC : WW8_FC_MAX;
548         }
advance()549         void advance()
550         {
551             if (mnIdx < mnIMax)
552                 ++mnIdx;
553         }
554         sal_uInt8* Get( WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen ) const;
GetIstd() const555         sal_uInt16 GetIstd() const { return maEntries[mnIdx].mnIStd; }
556 
557         /*
558             returns a real pointer to the Sprm of type nId,
559             if such a thing is in the Fkp.
560         */
561         sal_uInt8* GetLenAndIStdAndSprms(sal_Int32& rLen) const;
562 
563         /*
564             calls GetLenAndIStdAndSprms()...
565         */
566         SprmResult HasSprm(sal_uInt16 nId);
567         void HasSprm(sal_uInt16 nId, std::vector<SprmResult> &rResult);
568 
GetSprmParser() const569         const wwSprmParser &GetSprmParser() const { return maSprmParser; }
570 
IncMustRemainCache()571         void IncMustRemainCache() { ++mnMustRemainCached; }
IsMustRemainCache() const572         bool IsMustRemainCache() const { return mnMustRemainCached > 0; }
DecMustRemainCache()573         void DecMustRemainCache() { --mnMustRemainCached; }
574     };
575 
576 private:
577     SvStream* pFKPStrm;         // input file
578     SvStream* pDataStrm;        // input file
579     std::unique_ptr<WW8PLCF> pPLCF;
580 protected:
581     WW8Fkp* pFkp;
582 private:
583 
584     /*
585         Keep a cache of eMaxCache entries of previously seen pFkps, which
586         speeds up considerably table parsing and load save plcfs for what turn
587         out to be small text frames, which frames generally are
588 
589         size      : cache hits
590         cache all : 19168 pap, 48 chp
591         == 100    : 19166 pap, 48 chp
592         == 50     : 18918 pap, 48 chp
593         == 10     : 18549 pap, 47 chp
594         == 5      : 18515 pap, 47 chp
595     */
596     std::deque<std::unique_ptr<WW8Fkp>> maFkpCache;
597     enum Limits {eMaxCache = 50000};
598 
599     bool NewFkp();
600 
601     WW8PLCFx_Fc_FKP(const WW8PLCFx_Fc_FKP&) = delete;
602     WW8PLCFx_Fc_FKP& operator=(const WW8PLCFx_Fc_FKP&) = delete;
603 
604 protected:
605     ePLCFT ePLCF;
606     std::unique_ptr<WW8PLCFx_PCDAttrs> pPCDAttrs;
607 
608 public:
609     WW8PLCFx_Fc_FKP( SvStream* pSt, SvStream* pTableSt, SvStream* pDataSt,
610         const WW8Fib& rFib, ePLCFT ePl, WW8_FC nStartFcL );
611     virtual ~WW8PLCFx_Fc_FKP() override;
612     virtual sal_uInt32 GetIdx() const override;
613     virtual void SetIdx(sal_uInt32 nIdx) override;
614     virtual bool SeekPos(WW8_FC nFcPos) override;
615     virtual WW8_FC Where() override;
616     sal_uInt8* GetSprmsAndPos( WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen );
617     virtual void advance() override;
618     virtual sal_uInt16 GetIstd() const override;
619     void GetPCDSprms( WW8PLCFxDesc& rDesc );
620     SprmResult HasSprm(sal_uInt16 nId);
621     void HasSprm(sal_uInt16 nId, std::vector<SprmResult> &rResult);
HasFkp() const622     bool HasFkp() const { return (nullptr != pFkp); }
623 };
624 
625 /// iterator for Piece Table Exceptions of Fkps works on CPs (high-level)
626 class WW8PLCFx_Cp_FKP : public WW8PLCFx_Fc_FKP
627 {
628 private:
629     const WW8ScannerBase& rSBase;
630     std::unique_ptr<WW8PLCFx_PCD> pPcd;
631     WW8PLCFpcd_Iter *pPieceIter;
632     WW8_CP nAttrStart, nAttrEnd;
633     bool bLineEnd : 1;
634     bool bComplex : 1;
635 
636     WW8PLCFx_Cp_FKP(const WW8PLCFx_Cp_FKP&) = delete;
637     WW8PLCFx_Cp_FKP& operator=(const WW8PLCFx_Cp_FKP&) = delete;
638 
639 public:
640     WW8PLCFx_Cp_FKP( SvStream* pSt, SvStream* pTableSt, SvStream* pDataSt,
641         const WW8ScannerBase& rBase,  ePLCFT ePl );
642     virtual ~WW8PLCFx_Cp_FKP() override;
643     void ResetAttrStartEnd();
644     sal_uInt32 GetPCDIdx() const;
645     virtual sal_uInt32 GetIdx2() const override;
646     virtual void  SetIdx2(sal_uInt32 nIdx) override;
647     virtual bool SeekPos(WW8_CP nCpPos) override;
648     virtual WW8_CP Where() override;
649     virtual void GetSprms( WW8PLCFxDesc* p ) override;
650     virtual void advance() override;
651     virtual void Save( WW8PLCFxSave1& rSave ) const override;
652     virtual void Restore( const WW8PLCFxSave1& rSave ) override;
653 };
654 
655 /// Iterator for Piece Table Exceptions of Sepx
656 class WW8PLCFx_SEPX : public WW8PLCFx
657 {
658 private:
659     wwSprmParser maSprmParser;
660     SvStream* pStrm;
661     std::unique_ptr<WW8PLCF> pPLCF;
662     std::unique_ptr<sal_uInt8[]> pSprms;
663     sal_uInt16 nArrMax;
664     sal_uInt16 nSprmSiz;
665 
666     WW8PLCFx_SEPX(const WW8PLCFx_SEPX&) = delete;
667     WW8PLCFx_SEPX& operator=(const WW8PLCFx_SEPX&) = delete;
668 
669 public:
670     WW8PLCFx_SEPX( SvStream* pSt, SvStream* pTablexySt, const WW8Fib& rFib,
671         WW8_CP nStartCp );
672     virtual ~WW8PLCFx_SEPX() override;
673     virtual sal_uInt32 GetIdx() const override;
674     virtual void SetIdx(sal_uInt32 nIdx) override;
675     virtual bool SeekPos(WW8_CP nCpPos) override;
676     virtual WW8_CP Where() override;
677     virtual void GetSprms( WW8PLCFxDesc* p ) override;
678     virtual void advance() override;
679     SprmResult HasSprm( sal_uInt16 nId ) const;
680     SprmResult HasSprm( sal_uInt16 nId, sal_uInt8 n2nd ) const;
681     SprmResult HasSprm( sal_uInt16 nId, const sal_uInt8* pOtherSprms,
682         long nOtherSprmSiz ) const;
683     bool Find4Sprms(sal_uInt16 nId1, sal_uInt16 nId2, sal_uInt16 nId3, sal_uInt16 nId4,
684                     SprmResult& r1, SprmResult& r2, SprmResult& r3, SprmResult& r4) const;
685 };
686 
687 /// iterator for footnotes/endnotes and comments
688 class WW8PLCFx_SubDoc : public WW8PLCFx
689 {
690 private:
691     std::unique_ptr<WW8PLCF> pRef;
692     std::unique_ptr<WW8PLCF> pText;
693 
694     WW8PLCFx_SubDoc(const WW8PLCFx_SubDoc&) = delete;
695     WW8PLCFx_SubDoc& operator=(const WW8PLCFx_SubDoc&) = delete;
696 
697 public:
698     WW8PLCFx_SubDoc(SvStream* pSt, const WW8Fib& rFib, WW8_CP nStartCp,
699                     long nFcRef, long nLenRef, long nFcText, long nLenText, long nStruc);
700     virtual ~WW8PLCFx_SubDoc() override;
701     virtual sal_uInt32 GetIdx() const override;
702     virtual void SetIdx(sal_uInt32 nIdx) override;
703     virtual bool SeekPos(WW8_CP nCpPos) override;
704     virtual WW8_CP Where() override;
705 
706     // returns reference descriptors
GetData() const707     const void* GetData() const
708     {
709         return pRef ? pRef->GetData( pRef->GetIdx() ) : nullptr;
710     }
711 
712     virtual void GetSprms(WW8PLCFxDesc* p) override;
713     virtual void advance() override;
Count() const714     long Count() const { return pRef ? pRef->GetIMax() : 0; }
715 };
716 
717 /// Iterator for fields
718 class WW8PLCFx_FLD : public WW8PLCFx
719 {
720 private:
721     std::unique_ptr<WW8PLCFspecial> pPLCF;
722     const WW8Fib& rFib;
723     WW8PLCFx_FLD(const WW8PLCFx_FLD&) = delete;
724     WW8PLCFx_FLD& operator=(const WW8PLCFx_FLD &) = delete;
725 
726 public:
727     WW8PLCFx_FLD(SvStream* pSt, const WW8Fib& rMyFib, short nType);
728     virtual ~WW8PLCFx_FLD() override;
729     virtual sal_uInt32 GetIdx() const override;
730     virtual void SetIdx(sal_uInt32 nIdx) override;
731     virtual bool SeekPos(WW8_CP nCpPos) override;
732     virtual WW8_CP Where() override;
733     virtual void GetSprms(WW8PLCFxDesc* p) override;
734     virtual void advance() override;
735     bool StartPosIsFieldStart();
736     bool EndPosIsFieldEnd(WW8_CP&);
737     bool GetPara(long nIdx, WW8FieldDesc& rF);
738 };
739 
740 enum eBookStatus { BOOK_NORMAL = 0, BOOK_IGNORE = 0x1, BOOK_FIELD = 0x2 };
741 
742 /// Iterator for Booknotes
743 class WW8PLCFx_Book : public WW8PLCFx
744 {
745 private:
746     std::unique_ptr<WW8PLCFspecial> pBook[2];           // Start and End Position
747     std::vector<OUString> aBookNames;   // Name
748     std::vector<eBookStatus> aStatus;
749     long nIMax;                         // Number of Booknotes
750     sal_uInt16 nIsEnd;
751     sal_Int32 nBookmarkId; // counter incremented by GetUniqueBookmarkName.
752 
753     WW8PLCFx_Book(const WW8PLCFx_Book&) = delete;
754     WW8PLCFx_Book& operator=(const WW8PLCFx_Book&) = delete;
755 
756 public:
757     WW8PLCFx_Book(SvStream* pTableSt,const WW8Fib& rFib);
758     virtual ~WW8PLCFx_Book() override;
GetIMax() const759     long GetIMax() const { return nIMax; }
760     virtual sal_uInt32 GetIdx() const override;
761     virtual void SetIdx(sal_uInt32 nI) override;
762     virtual sal_uInt32 GetIdx2() const override;
763     virtual void SetIdx2(sal_uInt32 nIdx) override;
764     virtual bool SeekPos(WW8_CP nCpPos) override;
765     virtual WW8_CP Where() override;
766     virtual long GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen ) override;
767     virtual void advance() override;
768     const OUString* GetName() const;
GetStartPos() const769     WW8_CP GetStartPos() const
770         { return nIsEnd ? WW8_CP_MAX : pBook[0]->Where(); }
771     long GetLen() const;
GetIsEnd() const772     bool GetIsEnd() const { return nIsEnd != 0; }
773     long GetHandle() const;
774     void SetStatus( sal_uInt16 nIndex, eBookStatus eStat );
775     void MapName(OUString& rName);
776     OUString GetBookmark(long nStart,long nEnd, sal_uInt16 &nIndex);
777     eBookStatus GetStatus() const;
778     OUString GetUniqueBookmarkName(const OUString &rSuggestedName);
779 };
780 
781 /// Handles the import of PlcfAtnBkf and PlcfAtnBkl: start / end position of annotation marks.
782 class WW8PLCFx_AtnBook : public WW8PLCFx
783 {
784 private:
785     /// Start and end positions.
786     std::unique_ptr<WW8PLCFspecial> m_pBook[2];
787     /// Number of annotation marks
788     sal_Int32 nIMax;
789     bool m_bIsEnd;
790 
791     WW8PLCFx_AtnBook(const WW8PLCFx_AtnBook&) = delete;
792     WW8PLCFx_AtnBook& operator=(const WW8PLCFx_AtnBook&) = delete;
793 
794 public:
795     WW8PLCFx_AtnBook(SvStream* pTableSt,const WW8Fib& rFib);
796     virtual ~WW8PLCFx_AtnBook() override;
797     virtual sal_uInt32 GetIdx() const override;
798     virtual void SetIdx(sal_uInt32 nI) override;
799     virtual sal_uInt32 GetIdx2() const override;
800     virtual void SetIdx2(sal_uInt32 nIdx) override;
801     virtual bool SeekPos(WW8_CP nCpPos) override;
802     virtual WW8_CP Where() override;
803     virtual long GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen ) override;
804     virtual void advance() override;
805 
806     /// Handle is the unique ID of an annotation mark.
807     long getHandle() const;
808     bool getIsEnd() const;
809 };
810 
811 /// Handles the import of PlcfBkfFactoid and PlcfBklFactoid: start / end position of factoids.
812 class WW8PLCFx_FactoidBook : public WW8PLCFx
813 {
814 private:
815     /// Start and end positions.
816     std::unique_ptr<WW8PLCFspecial> m_pBook[2];
817     /// Number of factoid marks
818     sal_Int32 m_nIMax;
819     bool m_bIsEnd;
820 
821     WW8PLCFx_FactoidBook(const WW8PLCFx_FactoidBook&) = delete;
822     WW8PLCFx_FactoidBook& operator=(const WW8PLCFx_FactoidBook&) = delete;
823 
824 public:
825     WW8PLCFx_FactoidBook(SvStream* pTableSt,const WW8Fib& rFib);
826     virtual ~WW8PLCFx_FactoidBook() override;
827     virtual sal_uInt32 GetIdx() const override;
828     virtual void SetIdx(sal_uInt32 nI) override;
829     virtual sal_uInt32 GetIdx2() const override;
830     virtual void SetIdx2(sal_uInt32 nIdx) override;
831     virtual bool SeekPos(WW8_CP nCpPos) override;
832     virtual WW8_CP Where() override;
833     virtual long GetNoSprms(WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen) override;
834     virtual void advance() override;
835 
836     /// Handle is the unique ID of a factoid mark.
837     long getHandle() const;
838     bool getIsEnd() const;
839 };
840 
841 /*
842     this is what we use outside:
843 */
844 struct WW8PLCFManResult
845 {
846     WW8_CP nCpPos;      // attribute starting position
847     long nMemLen;       // length for previous
848     long nCp2OrIdx;     // footnote-textpos or index in PLCF
849     WW8_CP nCurrentCp;  // only used by caller
850     const sal_uInt8* pMemPos;// Mem-Pos for Sprms
851     sal_uInt16 nSprmId;     // Sprm-Id ( 0 = invalid Id -> skip! )
852                         // (2..255) or pseudo-Sprm-Id (256..260)
853                         // from Winword-Ver8 Sprm-Id (800..) resp.
854     sal_uInt8 nFlags;        // start of paragraph or section
855 };
856 
857 enum ManMaskTypes
858 {
859     MAN_MASK_NEW_PAP = 1,       // new line
860     MAN_MASK_NEW_SEP = 2        // new section
861 };
862 
863 enum ManTypes // enums for PLCFMan-ctor
864 {
865     MAN_MAINTEXT = 0, MAN_FTN = 1, MAN_EDN = 2, MAN_HDFT = 3, MAN_AND = 4,
866     MAN_TXBX = 5, MAN_TXBX_HDFT = 6
867 };
868 
869 /*
870     this is what the manager uses inside:
871 */
872 struct WW8PLCFxDesc
873 {
874     WW8PLCFx* pPLCFx;
875     std::stack<sal_uInt16>* pIdStack;    // memory for Attr-Id for Attr-end(s)
876     const sal_uInt8* pMemPos;// where are the Sprm(s)
877     long nOrigSprmsLen;
878 
879     WW8_CP nStartPos;
880     WW8_CP nEndPos;
881 
882     WW8_CP nOrigStartPos;
883     WW8_CP nOrigEndPos;   // The ending character position of a paragraph is
884                           // always one before the end reported in the FKP,
885                           // also a character run that ends on the same location
886                           // as the paragraph mark is adjusted to end just before
887                           // the paragraph mark so as to handle their close
888                           // first. The value being used to determining where the
889                           // properties end is in nEndPos, but the original
890                           // unadjusted end character position is important as
891                           // it can be used as the beginning cp of the next set
892                           // of properties
893 
894     WW8_CP nCp2OrIdx;     // where are the NoSprm(s)
895     sal_Int32 nSprmsLen;  // how many bytes for further Sprms / length of footnote
896     long nCpOfs;          // for Offset Header .. Footnote
897     bool bFirstSprm;      // for recognizing the first Sprm of a group
898     bool bRealLineEnd;    // false for Pap-Piece-end
899     sal_Int16 nRelativeJustify;
900     void Save( WW8PLCFxSave1& rSave ) const;
901     void Restore( const WW8PLCFxSave1& rSave );
902     //With nStartPos set to WW8_CP_MAX then in the case of a pap or chp
903     //GetSprms will not search for the sprms, but instead take the
904     //existing ones.
WW8PLCFxDescWW8PLCFxDesc905     WW8PLCFxDesc()
906         : pPLCFx(nullptr)
907         , pIdStack(nullptr)
908         , pMemPos(nullptr)
909         , nOrigSprmsLen(0)
910         , nStartPos(WW8_CP_MAX)
911         , nEndPos(WW8_CP_MAX)
912         , nOrigStartPos(WW8_CP_MAX)
913         , nOrigEndPos(WW8_CP_MAX)
914         , nCp2OrIdx(WW8_CP_MAX)
915         , nSprmsLen(0)
916         , nCpOfs(0)
917         , bFirstSprm(false)
918         , bRealLineEnd(false)
919         , nRelativeJustify(-1)
920     {
921     }
922     void ReduceByOffset();
923 };
924 
925 struct WW8PLCFxSaveAll;
926 class WW8PLCFMan
927 {
928 public:
929     enum WW8PLCFManLimits {MAN_PLCF_COUNT = 12};
930 
931 private:
932     wwSprmParser maSprmParser;
933     WW8_CP m_nCpO;                  //< Origin Cp -- the basis for nNewCp
934 
935     WW8_CP m_nLineEnd;                // points *after* the <CR>
936     sal_uInt16 m_nPLCF;                   // this many PLCFs are managed
937     ManTypes m_nManType;
938     bool mbDoingDrawTextBox;        //Normally we adjust the end of attributes
939                                     //so that the end of a paragraph occurs
940                                     //before the para end mark, but for
941                                     //drawboxes we want the true offsets
942 
943     WW8PLCFxDesc m_aD[MAN_PLCF_COUNT];
944     WW8PLCFxDesc *m_pChp, *m_pPap, *m_pSep, *m_pField, *m_pFootnote, *m_pEdn, *m_pBkm, *m_pPcd,
945         *m_pPcdA, *m_pAnd, *m_pAtnBkm, *m_pFactoidBkm;
946     WW8PLCFspecial *m_pFdoa, *m_pTxbx, *m_pTxbxBkd,*m_pMagicTables, *m_pSubdocs;
947     sal_uInt8* m_pExtendedAtrds;
948 
949     const WW8Fib* m_pWwFib;
950 
951     sal_uInt16 WhereIdx(bool* pbStart, WW8_CP * pPos=nullptr) const;
952     void AdjustEnds(WW8PLCFxDesc& rDesc);
953     void GetNewSprms(WW8PLCFxDesc& rDesc);
954     static void GetNewNoSprms(WW8PLCFxDesc& rDesc);
955     void GetSprmStart(short nIdx, WW8PLCFManResult* pRes) const;
956     void GetSprmEnd(short nIdx, WW8PLCFManResult* pRes) const;
957     void GetNoSprmStart(short nIdx, WW8PLCFManResult* pRes) const;
958     void GetNoSprmEnd(short nIdx, WW8PLCFManResult* pRes) const;
959     void AdvSprm(short nIdx, bool bStart);
960     void AdvNoSprm(short nIdx, bool bStart);
961     sal_uInt16 GetId(const WW8PLCFxDesc* p ) const;
962 
963 public:
964     WW8PLCFMan(const WW8ScannerBase* pBase, ManTypes nType, long nStartCp,
965         bool bDoingDrawTextBox = false);
966     ~WW8PLCFMan();
967 
968     /*
969         Where asks on which following position any Attr changes...
970     */
971     WW8_CP Where() const;
972 
973     bool Get(WW8PLCFManResult* pResult) const;
974     void advance();
975     sal_uInt16 GetColl() const; // index of actual Style
976     WW8PLCFx_FLD* GetField() const;
GetEdn() const977     WW8PLCFx_SubDoc* GetEdn() const { return static_cast<WW8PLCFx_SubDoc*>(m_pEdn->pPLCFx); }
GetFootnote() const978     WW8PLCFx_SubDoc* GetFootnote() const { return static_cast<WW8PLCFx_SubDoc*>(m_pFootnote->pPLCFx); }
GetAtn() const979     WW8PLCFx_SubDoc* GetAtn() const { return static_cast<WW8PLCFx_SubDoc*>(m_pAnd->pPLCFx); }
GetBook() const980     WW8PLCFx_Book* GetBook() const { return static_cast<WW8PLCFx_Book*>(m_pBkm->pPLCFx); }
GetAtnBook() const981     WW8PLCFx_AtnBook* GetAtnBook() const { return static_cast<WW8PLCFx_AtnBook*>(m_pAtnBkm->pPLCFx); }
GetFactoidBook() const982     WW8PLCFx_FactoidBook* GetFactoidBook() const { return static_cast<WW8PLCFx_FactoidBook*>(m_pFactoidBkm->pPLCFx); }
GetCpOfs() const983     long GetCpOfs() const { return m_pChp->nCpOfs; }  // for Header/Footer...
984 
985     /* asks, if *current paragraph* has an Sprm of this type */
986     SprmResult HasParaSprm(sal_uInt16 nId) const;
987 
988     /* asks, if *current textrun* has an Sprm of this type */
989     SprmResult HasCharSprm(sal_uInt16 nId) const;
990     void HasCharSprm(sal_uInt16 nId, std::vector<SprmResult> &rResult) const;
991 
GetChpPLCF() const992     WW8PLCFx_Cp_FKP* GetChpPLCF() const
993         { return static_cast<WW8PLCFx_Cp_FKP*>(m_pChp->pPLCFx); }
GetPapPLCF() const994     WW8PLCFx_Cp_FKP* GetPapPLCF() const
995         { return static_cast<WW8PLCFx_Cp_FKP*>(m_pPap->pPLCFx); }
GetSepPLCF() const996     WW8PLCFx_SEPX* GetSepPLCF() const
997         { return static_cast<WW8PLCFx_SEPX*>(m_pSep->pPLCFx); }
GetPap() const998     WW8PLCFxDesc* GetPap() const { return m_pPap; }
999     void TransferOpenSprms(std::stack<sal_uInt16> &rStack);
1000     void SeekPos( long nNewCp );
1001     void SaveAllPLCFx( WW8PLCFxSaveAll& rSave ) const;
1002     void RestoreAllPLCFx( const WW8PLCFxSaveAll& rSave );
GetFdoa() const1003     WW8PLCFspecial* GetFdoa() const { return m_pFdoa; }
GetTxbx() const1004     WW8PLCFspecial* GetTxbx() const { return m_pTxbx; }
GetTxbxBkd() const1005     WW8PLCFspecial* GetTxbxBkd() const { return m_pTxbxBkd; }
GetMagicTables() const1006     WW8PLCFspecial* GetMagicTables() const { return m_pMagicTables; }
GetWkbPLCF() const1007     WW8PLCFspecial* GetWkbPLCF() const { return m_pSubdocs; }
GetExtendedAtrds() const1008     sal_uInt8* GetExtendedAtrds() const { return m_pExtendedAtrds; }
GetManType() const1009     ManTypes GetManType() const { return m_nManType; }
GetDoingDrawTextBox() const1010     bool GetDoingDrawTextBox() const { return mbDoingDrawTextBox; }
1011 };
1012 
1013 struct WW8PLCFxSaveAll
1014 {
1015     WW8PLCFxSave1 aS[WW8PLCFMan::MAN_PLCF_COUNT] = {};
1016     WW8PLCFxSaveAll() = default;
1017 };
1018 
1019 class WW8ScannerBase
1020 {
1021 friend WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(const WW8Fib& rFib,
1022     WW8PLCFx_PCD* pPLCFx_PCD, const WW8ScannerBase* pBase );
1023 friend WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream*, SvStream*, SvStream*,
1024     const WW8ScannerBase&, ePLCFT );
1025 
1026 friend WW8PLCFMan::WW8PLCFMan(const WW8ScannerBase*, ManTypes, long, bool);
1027 friend class SwWW8FltControlStack;
1028 
1029 private:
1030     WW8Fib* m_pWw8Fib;
1031     std::unique_ptr<WW8PLCFx_Cp_FKP>  m_pChpPLCF;         // Character-Attrs
1032     std::unique_ptr<WW8PLCFx_Cp_FKP>  m_pPapPLCF;         // Paragraph-Attrs
1033     std::unique_ptr<WW8PLCFx_SEPX>    m_pSepPLCF;         // Section-Attrs
1034     std::unique_ptr<WW8PLCFx_SubDoc>  m_pFootnotePLCF;         // Footnotes
1035     std::unique_ptr<WW8PLCFx_SubDoc>  m_pEdnPLCF;         // EndNotes
1036     std::unique_ptr<WW8PLCFx_SubDoc>  m_pAndPLCF;         // Comments
1037     std::unique_ptr<WW8PLCFx_FLD>     m_pFieldPLCF;         // Fields in Main Text
1038     std::unique_ptr<WW8PLCFx_FLD>     m_pFieldHdFtPLCF;     // Fields in Header / Footer
1039     std::unique_ptr<WW8PLCFx_FLD>     m_pFieldTxbxPLCF;     // Fields in Textboxes in Main Text
1040     std::unique_ptr<WW8PLCFx_FLD>     m_pFieldTxbxHdFtPLCF; // Fields in Textboxes in Header / Footer
1041     std::unique_ptr<WW8PLCFx_FLD>     m_pFieldFootnotePLCF;      // Fields in Footnotes
1042     std::unique_ptr<WW8PLCFx_FLD>     m_pFieldEdnPLCF;      // Fields in Endnotes
1043     std::unique_ptr<WW8PLCFx_FLD>     m_pFieldAndPLCF;      // Fields in Comments
1044     std::unique_ptr<WW8PLCFspecial>   m_pMainFdoa;        // Graphic Primitives in Main Text
1045     std::unique_ptr<WW8PLCFspecial>   m_pHdFtFdoa;        // Graphic Primitives in Header / Footer
1046     std::unique_ptr<WW8PLCFspecial>   m_pMainTxbx;        // Textboxes in Main Text
1047     std::unique_ptr<WW8PLCFspecial>   m_pMainTxbxBkd;     // Break-Descriptors for them
1048     std::unique_ptr<WW8PLCFspecial>   m_pHdFtTxbx;        // TextBoxes in Header / Footer
1049     std::unique_ptr<WW8PLCFspecial>   m_pHdFtTxbxBkd;     // Break-Descriptors for previous
1050     std::unique_ptr<WW8PLCFspecial>   m_pMagicTables;     // Break-Descriptors for them
1051     std::unique_ptr<WW8PLCFspecial>   m_pSubdocs;         // subdoc references in master document
1052     std::unique_ptr<sal_uInt8[]>
1053                       m_pExtendedAtrds;   // Extended ATRDs
1054     std::unique_ptr<WW8PLCFx_Book>    m_pBook;            // Bookmarks
1055     std::unique_ptr<WW8PLCFx_AtnBook> m_pAtnBook;         // Annotationmarks
1056     /// Smart tag bookmarks.
1057     std::unique_ptr<WW8PLCFx_FactoidBook> m_pFactoidBook;
1058 
1059     std::unique_ptr<WW8PLCFpcd>         m_pPiecePLCF; // for FastSave ( Basis-PLCF without iterator )
1060     std::unique_ptr<WW8PLCFpcd_Iter>    m_pPieceIter; // for FastSave ( iterator for previous )
1061     std::unique_ptr<WW8PLCFx_PCD>       m_pPLCFx_PCD;     // ditto
1062     std::unique_ptr<WW8PLCFx_PCDAttrs>  m_pPLCFx_PCDAttrs;
1063     std::vector<std::unique_ptr<sal_uInt8[]>> m_aPieceGrpprls;  // attributes of Piece-Table
1064 
1065     std::unique_ptr<WW8PLCFpcd> OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF );
1066 
1067     WW8ScannerBase(const WW8ScannerBase&) = delete;
1068     WW8ScannerBase& operator=(const WW8ScannerBase&) = delete;
1069 
1070 public:
1071     WW8ScannerBase( SvStream* pSt, SvStream* pTableSt, SvStream* pDataSt,
1072         WW8Fib* pWwF );
1073     ~WW8ScannerBase();
AreThereFootnotes() const1074     bool AreThereFootnotes() const { return m_pFootnotePLCF->Count() > 0; };
AreThereEndnotes() const1075     bool AreThereEndnotes()  const { return m_pEdnPLCF->Count() > 0; };
1076 
1077     //If you use WW8Fc2Cp you are almost certainly doing the wrong thing
1078     //when it comes to fastsaved files, avoid like the plague. For export
1079     //given that we never write fastsaved files you can use it, otherwise
1080     //I will beat you with a stick
1081     WW8_CP WW8Fc2Cp(WW8_FC nFcPos) const ;
1082     WW8_FC WW8Cp2Fc(WW8_CP nCpPos, bool* pIsUnicode = nullptr,
1083         WW8_CP* pNextPieceCp = nullptr, bool* pTestFlag = nullptr) const;
1084 
1085     sal_Int32 WW8ReadString(SvStream& rStrm, OUString& rStr, WW8_CP nCurrentStartCp,
1086         long nTotalLen, rtl_TextEncoding eEnc ) const;
1087 
1088 };
1089 
1090 /** FIB - the File Information Block
1091 
1092     The FIB contains a "magic word" and pointers to the various other parts of
1093     the file, as well as information about the length of the file.
1094     The FIB starts at the beginning of the file.
1095 */
1096 class WW8Fib
1097 {
1098 private:
1099     sal_Unicode m_nNumDecimalSep = u'\0';
1100 
1101 public:
1102     /**
1103         Program-Version asked for by us:
1104         in Ctor we check if it matches the value of nFib
1105 
1106         6 == "WinWord 6 or WinWord 95",
1107         7 == "only WinWord 95"
1108         8 == "WinWord 97 or newer"
1109     */
1110     sal_uInt8 m_nVersion = 0;
1111     /*
1112         error status
1113     */
1114     ErrCode   m_nFibError;
1115     /*
1116         data read from FIB by Ctor
1117         (corresponds only approximately to the real structure
1118         of the Winword-FIB)
1119     */
1120     sal_uInt16 m_wIdent = 0; // 0x0 int magic number
1121     /*
1122         File Information Block (FIB) values:
1123         WinWord 1.0 = 33
1124         WinWord 2.0 = 45
1125         WinWord 6.0c for 16bit = 101
1126         Word 6/32 bit = 104
1127         Word 95 = 104
1128         Word 97 = 193
1129         Word 2000 = 217
1130         Word 2002 = 257
1131         Word 2003 = 268
1132         Word 2007 = 274
1133     */
1134     sal_uInt16 m_nFib = 0;        // 0x2 FIB version written
1135     sal_uInt16 m_nProduct = 0;    // 0x4 product version written by
1136     LanguageType m_lid;       // 0x6 language stamp---localized version;
1137     WW8_PN m_pnNext = 0;          // 0x8
1138 
1139     bool m_fDot :1 /*= false*/;     // 0xa 0001
1140     bool m_fGlsy :1 /*= false*/;
1141     bool m_fComplex :1 /*= false*/; // 0004 when 1, file is in complex, fast-saved format.
1142     bool m_fHasPic :1 /*= false*/;  // 0008 file contains 1 or more pictures
1143     sal_uInt16 m_cQuickSaves :4 /*= 0*/; // 00F0 count of times file was quicksaved
1144     bool m_fEncrypted :1 /*= false*/; //0100 1 if file is encrypted, 0 if not
1145     bool m_fWhichTableStm :1 /*= false*/; //0200 When 0, this fib refers to the table stream
1146     bool m_fReadOnlyRecommended :1 /*= false*/;
1147     bool m_fWriteReservation :1 /*= false*/;
1148                                                     // named "0Table", when 1, this fib refers to the
1149                                                     // table stream named "1Table". Normally, a file
1150                                                     // will have only one table stream, but under unusual
1151                                                     // circumstances a file may have table streams with
1152                                                     // both names. In that case, this flag must be used
1153                                                     // to decide which table stream is valid.
1154 
1155     bool m_fExtChar :1 /*= false*/; // 1000 =1, when using extended character set in file
1156     bool m_fFarEast :1 /*= false*/; // 4000 =1, probably, when far-East language variants of Word is used to create a file #i90932#
1157 
1158     bool m_fObfuscated :1 /*= false*/; // 8000=1. specifies whether the document is obfuscated using XOR obfuscation. otherwise this bit MUST be ignored.
1159 
1160     sal_uInt16 m_nFibBack = 0;    // 0xc
1161     sal_uInt16 m_nHash = 0;       // 0xe  file encrypted hash
1162     sal_uInt16 m_nKey = 0;        // 0x10  file encrypted key
1163     sal_uInt8 m_envr = 0;         // 0x12 environment in which file was created
1164                                     //      0 created by Win Word / 1 created by Mac Word
1165     bool m_fMac              :1 /*= false*/;          // 0x13 when 1, this file was last saved in the Mac environment
1166     bool m_fEmptySpecial     :1 /*= false*/;
1167     bool m_fLoadOverridePage :1 /*= false*/;
1168     bool m_fFuturesavedUndo  :1 /*= false*/;
1169     bool m_fWord97Saved      :1 /*= false*/;
1170     bool m_fWord2000Saved    :1 /*= false*/;
1171     sal_uInt8 :2;
1172 
1173     sal_uInt16 m_chse = 0;        // 0x14 default extended character set id for text in document stream. (overridden by chp.chse)
1174                         //      0 = ANSI  / 256 Macintosh character set.
1175     sal_uInt16 m_chseTables = 0;  // 0x16 default extended character set id for text in
1176                         //      internal data structures: 0 = ANSI, 256 = Macintosh
1177     WW8_FC m_fcMin = 0;           // 0x18 file offset of first character of text
1178     WW8_FC m_fcMac = 0;           // 0x1c file offset of last character of text + 1
1179 
1180     // start of WW8 section
1181     sal_uInt16 m_csw = 0;             // Count of fields in the array of "shorts"
1182 
1183     // marker: "rgsw" Beginning of the array of shorts
1184     sal_uInt16 m_wMagicCreated = 0;   // unique number Identifying the File's creator
1185                                 // 0x6A62 is the creator ID for Word and is reserved.
1186                                 // Other creators should choose a different value.
1187     sal_uInt16 m_wMagicRevised = 0;   // identifies the File's last modifier
1188     sal_uInt16 m_wMagicCreatedPrivate = 0; // private data
1189     sal_uInt16 m_wMagicRevisedPrivate = 0; // private data
1190 
1191     LanguageType m_lidFE; // Language id if document was written by Far East version
1192                           // of Word (i.e. FIB.fFarEast is on)
1193     sal_uInt16 m_clw = 0; // Number of fields in the array of longs
1194 
1195     // end of WW8 section
1196 
1197     // Marker: "rglw" Beginning of the array of longs
1198     WW8_FC m_cbMac = 0;           // 0x20 file offset of last byte written to file + 1.
1199 
1200     // WW8_FC u4[4];        // 0x24
1201     WW8_CP m_ccpText = 0;         // 0x34 length of main document text stream
1202     WW8_CP m_ccpFootnote = 0;          // 0x38 length of footnote subdocument text stream
1203     WW8_CP m_ccpHdr = 0;          // 0x3c length of header subdocument text stream
1204     WW8_CP m_ccpMcr = 0;          // 0x40 length of macro subdocument text stream
1205     WW8_CP m_ccpAtn = 0;          // 0x44 length of annotation subdocument text stream
1206     WW8_CP m_ccpEdn = 0;          // 0x48 length of endnote subdocument text stream
1207     WW8_CP m_ccpTxbx = 0;         // 0x4c length of textbox subdocument text stream
1208     WW8_CP m_ccpHdrTxbx = 0;      // 0x50 length of header textbox subdocument text stream
1209 
1210     // start of WW8 section
1211     sal_Int32  m_pnFbpChpFirst = 0; // when there was insufficient memory for Word to expand
1212                               // the PLCFbte at save time, the PLCFbte is written
1213                               // to the file in a linked list of 512-byte pieces
1214                               // starting with this pn.
1215     sal_Int32  m_pnFbpPapFirst = 0; // when there was insufficient memory for Word to expand
1216                               // the PLCFbte at save time, the PLCFbte is written to
1217                               // the file in a linked list of 512-byte pieces
1218                               // starting with this pn
1219 
1220     sal_Int32  m_pnFbpLvcFirst = 0; // when there was insufficient memory for Word to expand
1221                               // the PLCFbte at save time, the PLCFbte is written to
1222                               // the file in a linked list of 512-byte pieces
1223                               // starting with this pn
1224     sal_Int32  m_pnLvcFirst = 0; // the page number of the lowest numbered page in the
1225                            // document that records LVC FKP information
1226     sal_Int32  m_cpnBteLvc = 0;  // count of LVC FKPs recorded in file. In non-complex
1227                            // files if the number of entries in the PLCFbtePapx is
1228                            // less than this, the PLCFbtePapx is incomplete.
1229     sal_Int32  m_fcIslandFirst = 0;   // ?
1230     sal_Int32  m_fcIslandLim = 0;     // ?
1231     sal_uInt16 m_cfclcb = 0; // Number of fields in the array of FC/LCB pairs.
1232     /// Specifies the count of 16-bit values corresponding to fibRgCswNew that follow.
1233     sal_uInt16 m_cswNew = 0;
1234 
1235     // end of WW8 section
1236 
1237     // Marker: "rgfclcb" Beginning of array of FC/LCB pairs.
1238     WW8_FC m_fcStshfOrig = 0;     // file offset of original allocation for STSH in table
1239                                                 // stream. During fast save Word will attempt to reuse
1240                                                 // this allocation if STSH is small enough to fit.
1241     sal_Int32 m_lcbStshfOrig = 0; // 0x5c count of bytes of original STSH allocation
1242     WW8_FC m_fcStshf = 0;         // 0x60 file offset of STSH in file.
1243     sal_Int32 m_lcbStshf = 0;     // 0x64 count of bytes of current STSH allocation
1244     WW8_FC m_fcPlcffndRef = 0;    // 0x68 file offset of footnote reference PLCF.
1245     sal_Int32 m_lcbPlcffndRef = 0;    // 0x6c count of bytes of footnote reference PLCF
1246                         //      == 0 if no footnotes defined in document.
1247 
1248     WW8_FC m_fcPlcffndText = 0;    // 0x70 file offset of footnote text PLCF.
1249     sal_Int32 m_lcbPlcffndText = 0;    // 0x74 count of bytes of footnote text PLCF.
1250                         //      == 0 if no footnotes defined in document
1251 
1252     WW8_FC m_fcPlcfandRef = 0;    // 0x78 file offset of annotation reference PLCF.
1253     sal_Int32 m_lcbPlcfandRef = 0;    // 0x7c count of bytes of annotation reference PLCF.
1254 
1255     WW8_FC m_fcPlcfandText = 0;    // 0x80 file offset of annotation text PLCF.
1256     sal_Int32 m_lcbPlcfandText = 0;    // 0x84 count of bytes of the annotation text PLCF
1257 
1258     WW8_FC m_fcPlcfsed = 0;       // 8x88 file offset of section descriptor PLCF.
1259     sal_Int32 m_lcbPlcfsed = 0;   // 0x8c count of bytes of section descriptor PLCF.
1260 
1261     WW8_FC m_fcPlcfpad = 0;       // 0x90 file offset of paragraph descriptor PLCF
1262     sal_Int32 m_lcbPlcfpad = 0;   // 0x94 count of bytes of paragraph descriptor PLCF.
1263                         // ==0 if file was never viewed in Outline view.
1264                         // Should not be written by third party creators
1265 
1266     WW8_FC m_fcPlcfphe = 0;       // 0x98 file offset of PLCF of paragraph heights.
1267     sal_Int32 m_lcbPlcfphe = 0;   // 0x9c count of bytes of paragraph height PLCF.
1268                         // ==0 when file is non-complex.
1269 
1270     WW8_FC m_fcSttbfglsy = 0;     // 0xa0 file offset of glossary string table.
1271     sal_Int32 m_lcbSttbfglsy = 0; // 0xa4 count of bytes of glossary string table.
1272                         //      == 0 for non-glossary documents.
1273                         //      !=0 for glossary documents.
1274 
1275     WW8_FC m_fcPlcfglsy = 0;      // 0xa8 file offset of glossary PLCF.
1276     sal_Int32 m_lcbPlcfglsy = 0;  // 0xac count of bytes of glossary PLCF.
1277                         //      == 0 for non-glossary documents.
1278                         //      !=0 for glossary documents.
1279 
1280     WW8_FC m_fcPlcfhdd = 0;       // 0xb0 byte offset of header PLCF.
1281     sal_Int32 m_lcbPlcfhdd = 0;   // 0xb4 count of bytes of header PLCF.
1282                         //      == 0 if document contains no headers
1283 
1284     WW8_FC m_fcPlcfbteChpx = 0;   // 0xb8 file offset of character property bin table.PLCF.
1285     sal_Int32 m_lcbPlcfbteChpx = 0;// 0xbc count of bytes of character property bin table PLCF.
1286 
1287     WW8_FC m_fcPlcfbtePapx = 0;   // 0xc0 file offset of paragraph property bin table.PLCF.
1288     sal_Int32 m_lcbPlcfbtePapx = 0;// 0xc4 count of bytes of paragraph  property bin table PLCF.
1289 
1290     WW8_FC m_fcPlcfsea = 0;       // 0xc8 file offset of PLCF reserved for private use. The SEA is 6 bytes long.
1291     sal_Int32 m_lcbPlcfsea = 0;   // 0xcc count of bytes of private use PLCF.
1292 
1293     WW8_FC m_fcSttbfffn = 0;      // 0xd0 file offset of font information STTBF. See the FFN file structure definition.
1294     sal_Int32 m_lcbSttbfffn = 0;  // 0xd4 count of bytes in sttbfffn.
1295 
1296     WW8_FC m_fcPlcffldMom = 0;    // 0xd8 offset in doc stream to the PLCF of field positions in the main document.
1297     sal_Int32 m_lcbPlcffldMom = 0;    // 0xdc
1298 
1299     WW8_FC m_fcPlcffldHdr = 0;    // 0xe0 offset in doc stream to the PLCF of field positions in the header subdocument.
1300     sal_Int32 m_lcbPlcffldHdr = 0;    // 0xe4
1301 
1302     WW8_FC m_fcPlcffldFootnote = 0;    // 0xe8 offset in doc stream to the PLCF of field positions in the footnote subdocument.
1303     sal_Int32 m_lcbPlcffldFootnote = 0;    // 0xec
1304 
1305     WW8_FC m_fcPlcffldAtn = 0;    // 0xf0 offset in doc stream to the PLCF of field positions in the annotation subdocument.
1306     sal_Int32 m_lcbPlcffldAtn = 0;    // 0xf4
1307 
1308     WW8_FC m_fcPlcffldMcr = 0;    // 0xf8 offset in doc stream to the PLCF of field positions in the macro subdocument.
1309     sal_Int32 m_lcbPlcffldMcr = 0;    // 9xfc
1310 
1311     WW8_FC m_fcSttbfbkmk = 0; // 0x100 offset in document stream of the STTBF that records bookmark names in the main document
1312     sal_Int32 m_lcbSttbfbkmk = 0; // 0x104
1313 
1314     WW8_FC m_fcPlcfbkf = 0;   // 0x108 offset in document stream of the PLCF that records the beginning CP offsets of bookmarks in the main document. See BKF
1315     sal_Int32 m_lcbPlcfbkf = 0;   // 0x10c
1316 
1317     WW8_FC m_fcPlcfbkl = 0;   // 0x110 offset in document stream of the PLCF that records the ending CP offsets of bookmarks recorded in the main document. See the BKL structure definition.
1318     sal_Int32 m_lcbPlcfbkl = 0;   // 0x114 sal_Int32
1319 
1320     WW8_FC m_fcCmds = 0;      // 0x118 FC
1321     sal_uInt32 m_lcbCmds = 0;      // 0x11c
1322 
1323     WW8_FC m_fcPlcfmcr = 0;       // 0x120 FC
1324     sal_Int32 m_lcbPlcfmcr = 0;       // 0x124
1325 
1326     WW8_FC m_fcSttbfmcr = 0;  // 0x128 FC
1327     sal_Int32 m_lcbSttbfmcr = 0;  // 0x12c
1328 
1329     WW8_FC m_fcPrDrvr = 0;        // 0x130 file offset of the printer driver information (names of drivers, port etc...)
1330     sal_Int32 m_lcbPrDrvr = 0;        // 0x134 count of bytes of the printer driver information (names of drivers, port etc...)
1331 
1332     WW8_FC m_fcPrEnvPort = 0; // 0x138 file offset of the print environment in portrait mode.
1333     sal_Int32 m_lcbPrEnvPort = 0; // 0x13c count of bytes of the print environment in portrait mode.
1334 
1335     WW8_FC m_fcPrEnvLand = 0; // 0x140 file offset of the print environment in landscape mode.
1336     sal_Int32 m_lcbPrEnvLand = 0; // 0x144 count of bytes of the print environment in landscape mode.
1337 
1338     WW8_FC m_fcWss = 0;       // 0x148 file offset of Window Save State data structure. See WSS.
1339     sal_Int32 m_lcbWss = 0;       // 0x14c count of bytes of WSS. ==0 if unable to store the window state.
1340 
1341     WW8_FC m_fcDop = 0;       // 0x150 file offset of document property data structure.
1342     sal_uInt32 m_lcbDop = 0;       // 0x154 count of bytes of document properties.
1343         // cbDOP is 84 when nFib < 103
1344 
1345     WW8_FC m_fcSttbfAssoc = 0;    // 0x158 offset to STTBF of associated strings. See STTBFASSOC.
1346     sal_Int32 m_lcbSttbfAssoc = 0; // 0x15C
1347 
1348     WW8_FC m_fcClx = 0;           // 0x160 file  offset of beginning of information for complex files.
1349     sal_Int32 m_lcbClx = 0;       // 0x164 count of bytes of complex file information. 0 if file is non-complex.
1350 
1351     WW8_FC m_fcPlcfpgdFootnote = 0;    // 0x168 file offset of page descriptor PLCF for footnote subdocument.
1352     sal_Int32 m_lcbPlcfpgdFootnote = 0;    // 0x16C count of bytes of page descriptor PLCF for footnote subdocument.
1353                         //  ==0 if document has not been paginated. The length of the PGD is 8 bytes.
1354 
1355     WW8_FC m_fcAutosaveSource = 0;    // 0x170 file offset of the name of the original file.
1356     sal_Int32 m_lcbAutosaveSource = 0;    // 0x174 count of bytes of the name of the original file.
1357 
1358     WW8_FC m_fcGrpStAtnOwners = 0;    // 0x178 group of strings recording the names of the owners of annotations
1359     sal_Int32 m_lcbGrpStAtnOwners = 0;    // 0x17C count of bytes of the group of strings
1360 
1361     WW8_FC m_fcSttbfAtnbkmk = 0;  // 0x180 file offset of the sttbf that records names of bookmarks in the annotation subdocument
1362     sal_Int32 m_lcbSttbfAtnbkmk = 0;  // 0x184 length in bytes of the sttbf that records names of bookmarks in the annotation subdocument
1363 
1364     // end of WW67 section
1365 
1366     WW8_FC m_fcPlcfdoaMom = 0;    // 0x192 file offset of the  FDOA (drawn object) PLCF for main document.
1367                         //  ==0 if document has no drawn objects. The length of the FDOA is 6 bytes.
1368                         // unused starting from Ver8
1369     sal_Int32 m_lcbPlcfdoaMom = 0;    // 0x196 length in bytes of the FDOA PLCF of the main document
1370                                                 // unused starting from Ver8
1371     WW8_FC m_fcPlcfdoaHdr = 0;    // 0x19A file offset of the  FDOA (drawn object) PLCF for the header document.
1372                         //  ==0 if document has no drawn objects. The length of the FDOA is 6 bytes.
1373                         // unused starting from Ver8
1374     sal_Int32 m_lcbPlcfdoaHdr = 0;    // 0x19E length in bytes of the FDOA PLCF of the header document
1375                                                 // unused starting from Ver8
1376 
1377     WW8_FC m_fcPlcfspaMom = 0;        // offset in table stream of the FSPA PLCF for main document.
1378                                                 // == 0 if document has no office art objects
1379                                                         // was empty reserve in Ver67
1380     sal_Int32 m_lcbPlcfspaMom = 0;        // length in bytes of the FSPA PLCF of the main document
1381                                                         // was empty reserve in Ver67
1382     WW8_FC m_fcPlcfspaHdr = 0;        // offset in table stream of the FSPA PLCF for header document.
1383                                                 // == 0 if document has no office art objects
1384                                                         // was empty reserve in Ver67
1385     sal_Int32 m_lcbPlcfspaHdr = 0;        // length in bytes of the FSPA PLCF of the header document
1386                                                         // was empty reserve in Ver67
1387 
1388     WW8_FC m_fcPlcfAtnbkf = 0;    // 0x1B2 file offset of BKF (bookmark first) PLCF of the annotation subdocument
1389     sal_Int32 m_lcbPlcfAtnbkf = 0;    // 0x1B6 length in bytes of BKF (bookmark first) PLCF of the annotation subdocument
1390 
1391     WW8_FC m_fcPlcfAtnbkl = 0;    // 0x1BA file offset of BKL (bookmark last) PLCF of the annotation subdocument
1392     sal_Int32 m_lcbPlcfAtnbkl = 0;    // 0x1BE length in bytes of BKL (bookmark first) PLCF of the annotation subdocument
1393 
1394     WW8_FC m_fcPms = 0;       // 0x1C2 file offset of PMS (Print Merge State) information block
1395     sal_Int32 m_lcbPMS = 0;       // 0x1C6 length in bytes of PMS
1396 
1397     WW8_FC m_fcFormFieldSttbf = 0;  // 0x1CA file offset of form field Sttbf which contains strings used in form field dropdown controls
1398     sal_Int32 m_lcbFormFieldSttbf = 0;  // 0x1CE length in bytes of form field Sttbf
1399 
1400     WW8_FC m_fcPlcfendRef = 0;    // 0x1D2 file offset of PLCFendRef which points to endnote references in the main document stream
1401     sal_Int32 m_lcbPlcfendRef = 0;    // 0x1D6
1402 
1403     WW8_FC m_fcPlcfendText = 0;    // 0x1DA file offset of PLCFendRef which points to endnote text  in the endnote document
1404                         //       stream which corresponds with the PLCFendRef
1405     sal_Int32 m_lcbPlcfendText = 0;    // 0x1DE
1406 
1407     WW8_FC m_fcPlcffldEdn = 0;    // 0x1E2 offset to PLCF of field positions in the endnote subdoc
1408     sal_Int32 m_lcbPlcffldEdn = 0;    // 0x1E6
1409 
1410     WW8_FC  m_fcPlcfpgdEdn = 0;   // 0x1EA offset to PLCF of page boundaries in the endnote subdoc.
1411     sal_Int32 m_lcbPlcfpgdEdn = 0;        // 0x1EE
1412 
1413     WW8_FC m_fcDggInfo = 0;           // offset in table stream of the office art object table data.
1414                                                 // The format of office art object table data is found in a separate document.
1415                                                         // was empty reserve in Ver67
1416     sal_Int32 m_lcbDggInfo = 0;           // length in bytes of the office art object table data
1417                                                         // was empty reserve in Ver67
1418 
1419     WW8_FC m_fcSttbfRMark = 0;        // 0x1fa offset to STTBF that records the author abbreviations...
1420     sal_Int32 m_lcbSttbfRMark = 0;        // 0x1fe
1421     WW8_FC m_fcSttbfCaption = 0;  // 0x202 offset to STTBF that records caption titles...
1422     sal_Int32 m_lcbSttbfCaption = 0;  // 0x206
1423     WW8_FC m_fcSttbAutoCaption = 0;   // offset in table stream to the STTBF that records the object names and
1424                                                         // indices into the caption STTBF for objects which get auto captions.
1425     sal_Int32 m_lcbSttbAutoCaption = 0;   // 0x20e
1426 
1427     WW8_FC m_fcPlcfwkb = 0;       // 0x212 offset to PLCF that describes the boundaries of contributing documents...
1428     sal_Int32 m_lcbPlcfwkb = 0;       // 0x216
1429 
1430     WW8_FC m_fcPlcfspl = 0;       // offset in table stream of PLCF (of SPLS structures) that records spell check state
1431                                                         // was empty reserve in Ver67
1432     sal_Int32 m_lcbPlcfspl = 0;                   // was empty reserve in Ver67
1433 
1434     WW8_FC m_fcPlcftxbxText = 0;   // 0x222 ...PLCF of beginning CP in the text box subdoc
1435     sal_Int32 m_lcbPlcftxbxText = 0;   // 0x226
1436     WW8_FC m_fcPlcffldTxbx = 0;   // 0x22a ...PLCF of field boundaries recorded in the textbox subdoc.
1437     sal_Int32 m_lcbPlcffldTxbx = 0;   // 0x22e
1438     WW8_FC m_fcPlcfHdrtxbxText = 0;// 0x232 ...PLCF of beginning CP in the header text box subdoc
1439     sal_Int32 m_lcbPlcfHdrtxbxText = 0;// 0x236
1440     WW8_FC m_fcPlcffldHdrTxbx = 0;// 0x23a ...PLCF of field boundaries recorded in the header textbox subdoc.
1441     sal_Int32 m_lcbPlcffldHdrTxbx = 0;// 0x23e
1442     WW8_FC m_fcStwUser = 0;
1443     sal_uInt32 m_lcbStwUser = 0;
1444     WW8_FC m_fcSttbttmbd = 0;
1445     sal_uInt32 m_lcbSttbttmbd = 0;
1446 
1447     WW8_FC m_fcSttbFnm = 0;       // 0x02da offset in the table stream of masters subdocument names
1448     sal_Int32 m_lcbSttbFnm = 0;       // 0x02de length
1449 
1450     /*
1451         special list handling for WW8
1452     */
1453     WW8_FC m_fcPlcfLst = 0;       // 0x02e2 offset in the table stream of list format information.
1454     sal_Int32 m_lcbPlcfLst = 0;       // 0x02e6 length
1455     WW8_FC m_fcPlfLfo = 0;        // 0x02ea offset in the table stream of list format override information.
1456     sal_Int32 m_lcbPlfLfo = 0;        // 0x02ee length
1457     /*
1458         special Break handling for text-box-stories in WW8
1459     */
1460     WW8_FC m_fcPlcftxbxBkd = 0;   // 0x02f2 PLCF for TextBox-Break-descriptors in the Maintext
1461     sal_Int32 m_lcbPlcftxbxBkd = 0;   // 0x02f6
1462     WW8_FC m_fcPlcfHdrtxbxBkd = 0;// 0x02fa PLCF for TextBox-Break-descriptors in the Header-/Footer- area
1463     sal_Int32 m_lcbPlcfHdrtxbxBkd = 0;// 0x02fe
1464 
1465     // 0x302 - 372 == ignore
1466     /*
1467         ListNames (skip to here!)
1468     */
1469     WW8_FC m_fcSttbListNames = 0;// 0x0372 PLCF for Listname Table
1470     sal_Int32 m_lcbSttbListNames = 0;// 0x0376
1471 
1472     WW8_FC m_fcPlcfTch = 0;
1473     sal_Int32 m_lcbPlcfTch = 0;
1474 
1475     // 0x38A - 41A == ignore
1476     WW8_FC m_fcAtrdExtra = 0;
1477     sal_uInt32 m_lcbAtrdExtra = 0;
1478 
1479     // 0x422 - 0x429 == ignore
1480 
1481     /// 0x42a smart-tag bookmark string table offset.
1482     WW8_FC m_fcSttbfBkmkFactoid = 0;
1483     /// 0x42e smart-tag bookmark string table length.
1484     sal_uInt32 m_lcbSttbfBkmkFactoid = 0;
1485     /// 0x432 smart-tag bookmark starts offset.
1486     WW8_FC m_fcPlcfBkfFactoid = 0;
1487     /// 0x436 smart-tag bookmark ends length.
1488     sal_uInt32 m_lcbPlcfBkfFactoid = 0;
1489 
1490     // 0x43a - 0x441 == ignore
1491 
1492     /// 0x442 smart-tag bookmark ends offset.
1493     WW8_FC m_fcPlcfBklFactoid = 0;
1494     /// 0x446 smart-tag bookmark ends length.
1495     sal_uInt32 m_lcbPlcfBklFactoid = 0;
1496     /// 0x44a smart tag data offset.
1497     WW8_FC m_fcFactoidData = 0;
1498     /// 0x44e smart tag data length.
1499     sal_uInt32 m_lcbFactoidData = 0;
1500 
1501     // 0x452 - 0x4b9 == ignore
1502 
1503     /// 0x4ba Plcffactoid offset.
1504     WW8_FC m_fcPlcffactoid = 0;
1505     /// 0x4be Plcffactoid offset.
1506     sal_uInt32 m_lcbPlcffactoid = 0;
1507 
1508     // 0x4bf - 0x4d4 == ignore
1509 
1510     WW8_FC m_fcHplxsdr = 0;    //bizarrely, word xp seems to require this set to shows dates from AtrdExtra
1511     sal_uInt32 m_lcbHplxsdr = 0;
1512 
1513     /*
1514         general variables that were used for Ver67 and Ver8,
1515         even though they had different sizes in the corresponding files:
1516     */
1517     sal_Int32 m_pnChpFirst = 0;
1518     sal_Int32 m_pnPapFirst = 0;
1519     sal_Int32 m_cpnBteChp = 0;
1520     sal_Int32 m_cpnBtePap = 0;
1521     /*
1522         The actual nFib, moved here because some readers assumed
1523         they couldn't read any format with nFib > some constant
1524     */
1525     sal_uInt16 m_nFib_actual = 0; // 0x05bc #i56856#
1526 
1527     WW8Fib(SvStream& rStrm, sal_uInt8 nWantedVersion,sal_uInt32 nOffset=0);
1528     explicit WW8Fib(sal_uInt8 nVersion, bool bDot = false);
1529 
1530     void WriteHeader(SvStream& rStrm);
1531     void Write(SvStream& rStrm);
1532     static rtl_TextEncoding GetFIBCharset(sal_uInt16 chs, LanguageType nLidLocale);
1533     ww::WordVersion GetFIBVersion() const;
1534     bool GetBaseCp(ManTypes nType, WW8_CP * cp) const;
getNumDecimalSep() const1535     sal_Unicode getNumDecimalSep() const { return m_nNumDecimalSep;}
1536 };
1537 
1538 class WW8Style
1539 {
1540 protected:
1541     WW8Fib& m_rFib;
1542     SvStream& m_rStream;
1543 
1544     sal_uInt16  m_cstd;                      // Count of styles in stylesheet
1545     sal_uInt16  m_cbSTDBaseInFile;           // Length of STD Base as stored in a file
1546     sal_uInt16  m_fStdStylenamesWritten : 1; // Are built-in stylenames stored?
1547     sal_uInt16  : 15;                      // Spare flags
1548     sal_uInt16  m_stiMaxWhenSaved;           // Max sti known when file was written
1549     sal_uInt16  m_istdMaxFixedWhenSaved;     // How many fixed-index istds are there?
1550     sal_uInt16  m_nVerBuiltInNamesWhenSaved; // Current version of built-in stylenames
1551     // ftc used by StandardChpStsh for this document
1552     sal_uInt16  m_ftcAsci;
1553     // CJK ftc used by StandardChpStsh for this document
1554     sal_uInt16  m_ftcFE;
1555     // CTL/Other ftc used by StandardChpStsh for this document
1556     sal_uInt16  m_ftcOther;
1557     // CTL ftc used by StandardChpStsh for this document
1558     sal_uInt16  m_ftcBi;
1559 
1560     //No copying
1561     WW8Style(const WW8Style&);
1562     WW8Style& operator=(const WW8Style&);
1563 
1564 public:
1565     WW8Style( SvStream& rSt, WW8Fib& rFibPara );
1566     std::unique_ptr<WW8_STD> Read1STDFixed(sal_uInt16& rSkip);
1567     std::unique_ptr<WW8_STD> Read1Style(sal_uInt16& rSkip, OUString* pString);
GetCount() const1568     sal_uInt16 GetCount() const { return m_cstd; }
1569 };
1570 
1571 class WW8Fonts final
1572 {
1573 private:
1574     WW8Fonts(const WW8Fonts&) = delete;
1575     WW8Fonts& operator=(const WW8Fonts&) = delete;
1576 
1577     std::vector<WW8_FFN> m_aFontA; // Array of Pointers to Font Description
1578 
1579 public:
1580     WW8Fonts( SvStream& rSt, WW8Fib const & rFib );
1581     const WW8_FFN* GetFont( sal_uInt16 nNum ) const;
GetMax() const1582     sal_uInt16 GetMax() const { return m_aFontA.size(); }
1583 };
1584 
1585 typedef sal_uInt8 HdFtFlags;
1586 namespace nsHdFtFlags
1587 {
1588     const HdFtFlags WW8_HEADER_EVEN     = 0x01;
1589     const HdFtFlags WW8_HEADER_ODD      = 0x02;
1590     const HdFtFlags WW8_FOOTER_EVEN     = 0x04;
1591     const HdFtFlags WW8_FOOTER_ODD      = 0x08;
1592     const HdFtFlags WW8_HEADER_FIRST    = 0x10;
1593     const HdFtFlags WW8_FOOTER_FIRST    = 0x20;
1594 }
1595 
1596 /// Document Properties
1597 struct WW8Dop
1598 {
1599 public:
1600     /* Error Status */
1601     ErrCode     nDopError;
1602     /*
1603     Corresponds only roughly to the actual structure of the Winword DOP,
1604     the winword FIB version matters to what exists.
1605     */
1606      bool        fFacingPages : 1 /*= false*/;   // 1 when facing pages should be printed
1607 
1608      bool        fWidowControl : 1 /*= false*/;  //a: orig 97 docs say
1609                                     //    1 when widow control is in effect. 0 when widow control disabled.
1610                                     //b: MS-DOC: Word Binary File Format (.doc) Structure Specification 2008 says
1611                                     //    B - unused1 (1 bit): Undefined and MUST be ignored.
1612 
1613      bool        fPMHMainDoc : 1 /*= false*/;    // 1 when doc is a main doc for Print Merge Helper, 0 when not; default=0
1614      sal_uInt16  grfSuppression : 2 /*= 0*/; // 0 Default line suppression storage; 0= form letter line suppression; 1= no line suppression; default=0
1615      sal_uInt16  fpc : 2 /*= 0*/;            // 1 footnote position code: 0 as endnotes, 1 at bottom of page, 2 immediately beneath text
1616     sal_uInt16  : 1;                // 0 unused
1617 
1618      sal_uInt16  grpfIhdt : 8 /*= 0*/;           // 0 specification of document headers and footers. See explanation under Headers and Footers topic.
1619 
1620      sal_uInt16  rncFootnote : 2 /*= 0*/;         // 0 restart index for footnotes, 0 don't restart note numbering, 1 section, 2 page
1621      sal_uInt16  nFootnote : 14 /*= 0*/;          // 1 initial footnote number for document
1622      bool        fOutlineDirtySave : 1 /*= false*/; // when 1, indicates that information in the hPLCFpad should be refreshed since outline has been dirtied
1623     sal_uInt16  : 7;                //   reserved
1624      bool        fOnlyMacPics : 1 /*= false*/;   //   when 1, Word believes all pictures recorded in the document were created on a Macintosh
1625      bool        fOnlyWinPics : 1 /*= false*/;   //   when 1, Word believes all pictures recorded in the document were created in Windows
1626      bool        fLabelDoc : 1 /*= false*/;      //   when 1, document was created as a print merge labels document
1627      bool        fHyphCapitals : 1 /*= false*/;  //   when 1, Word is allowed to hyphenate words that are capitalized. When 0, capitalized may not be hyphenated
1628      bool        fAutoHyphen : 1 /*= false*/;    //   when 1, Word will hyphenate newly typed text as a background task
1629      bool        fFormNoFields : 1 /*= false*/;
1630      bool        fLinkStyles : 1 /*= false*/;    //   when 1, Word will merge styles from its template
1631      bool        fRevMarking : 1 /*= false*/;    //   when 1, Word will mark revisions as the document is edited
1632      bool        fBackup : 1 /*= false*/;        //   always make backup when document saved when 1.
1633      bool        fExactCWords : 1 /*= false*/;
1634      bool        fPagHidden : 1 /*= false*/;
1635      bool        fPagResults : 1 /*= false*/;
1636      bool        fLockAtn : 1 /*= false*/;       //   when 1, annotations are locked for editing
1637      bool        fMirrorMargins : 1 /*= false*/; //   swap margins on left/right pages when 1.
1638      bool        fReadOnlyRecommended : 1 /*= false*/;// user has recommended that this doc be opened read-only when 1
1639      bool        fDfltTrueType : 1 /*= false*/;  //   when 1, use TrueType fonts by default (flag obeyed only when doc was created by WinWord 2.x)
1640      bool        fPagSuppressTopSpacing : 1 /*= false*/;//when 1, file created with SUPPRESSTOPSPACING=YES in win.ini. (flag obeyed only when doc was created by WinWord 2.x).
1641      bool        fProtEnabled : 1 /*= false*/;   //   when 1, document is protected from edit operations
1642      bool        fDispFormFieldSel : 1 /*= false*/;//   when 1, restrict selections to occur only within form fields
1643      bool        fRMView : 1 /*= false*/;        //   when 1, show revision markings on screen
1644      bool        fRMPrint : 1 /*= false*/;       //   when 1, print revision marks when document is printed
1645      bool        fWriteReservation : 1 /*= false*/;
1646      bool        fLockRev : 1 /*= false*/;       //   when 1, the current revision marking state is locked
1647      bool        fEmbedFonts : 1 /*= false*/;    //   when 1, document contains embedded True Type fonts
1648     //    compatibility options
1649      bool       copts_fNoTabForInd : 1 /*= false*/;          //    when 1, don't add automatic tab stops for hanging indent
1650      bool       copts_fNoSpaceRaiseLower : 1 /*= false*/;        //    when 1, don't add extra space for raised or lowered characters
1651      bool       copts_fSupressSpbfAfterPgBrk : 1 /*= false*/;    // when 1, suppress the paragraph Space Before and Space After options after a page break
1652      bool       copts_fWrapTrailSpaces : 1 /*= false*/;      //    when 1, wrap trailing spaces at the end of a line to the next line
1653      bool       copts_fMapPrintTextColor : 1 /*= false*/;        //    when 1, print colors as black on non-color printers
1654      bool       copts_fNoColumnBalance : 1 /*= false*/;      //    when 1, don't balance columns for Continuous Section starts
1655      bool       copts_fConvMailMergeEsc : 1 /*= false*/;
1656      bool       copts_fSupressTopSpacing : 1 /*= false*/;        //    when 1, suppress extra line spacing at top of page
1657      bool       copts_fOrigWordTableRules : 1 /*= false*/;   //    when 1, combine table borders like Word 5.x for the Macintosh
1658      bool       copts_fTransparentMetafiles : 1 /*= false*/; //    when 1, don't blank area between metafile pictures
1659      bool       copts_fShowBreaksInFrames : 1 /*= false*/;   //    when 1, show hard page or column breaks in frames
1660      bool       copts_fSwapBordersFacingPgs : 1 /*= false*/; //    when 1, swap left and right pages on odd facing pages
1661      bool       copts_fExpShRtn : 1 /*= false*/;             //    when 1, expand character spaces on the line ending SHIFT+RETURN  // #i56856#
1662 
1663     sal_Int16  dxaTab = 0;              //      720 twips - default tab width
1664     sal_uInt16 wSpare = 0;
1665     sal_uInt16 dxaHotZ = 0;             //      width of hyphenation hot zone measured in twips
1666     sal_uInt16 cConsecHypLim = 0;       //      number of lines allowed to have consecutive hyphens
1667     sal_uInt16 wSpare2 = 0;             //      reserved
1668     sal_Int32  dttmCreated = 0;         //      DTTM date and time document was created
1669     sal_Int32  dttmRevised = 0;         //      DTTM date and time document was last revised
1670     sal_Int32  dttmLastPrint = 0;       //      DTTM date and time document was last printed
1671     sal_Int16  nRevision = 0;           //      number of times document has been revised since its creation
1672     sal_Int32  tmEdited = 0;            //      time document was last edited
1673     sal_Int32  cWords = 0;              //      count of words tallied by last Word Count execution
1674     sal_Int32  cCh = 0;                 //      count of characters tallied by last Word Count execution
1675     sal_Int16  cPg = 0;                 //      count of pages tallied by last Word Count execution
1676     sal_Int32  cParas = 0;              //      count of paragraphs tallied by last Word Count execution
1677      sal_uInt16 rncEdn : 2 /*= 0*/;          //      restart endnote number code: 0 don't restart endnote numbering, 1 section, 2 page
1678      sal_uInt16 nEdn : 14 /*= 0*/;           //      beginning endnote number
1679      sal_uInt16 epc : 2 /*= 0*/;             //      endnote position code: 0 at end of section, 3 at end of document
1680 
1681      bool       fPrintFormData : 1 /*= false*/;  //      only print data inside of form fields
1682      bool       fSaveFormData : 1 /*= false*/;   //      only save document data that is inside of a form field.
1683      bool       fShadeFormData : 1 /*= false*/;  //      shade form fields
1684     sal_uInt16 : 2;                 //      reserved
1685      bool       fWCFootnoteEdn : 1 /*= false*/;       //      when 1, include footnotes and endnotes in word count
1686     sal_Int32   cLines = 0;             //      count of lines tallied by last Word Count operation
1687     sal_Int32   cWordsFootnoteEnd = 0;       //      count of words in footnotes and endnotes tallied by last Word Count operation
1688     sal_Int32   cChFootnoteEdn = 0;          //      count of characters in footnotes and endnotes tallied by last Word Count operation
1689     sal_Int16   cPgFootnoteEdn = 0;          //      count of pages in footnotes and endnotes tallied by last Word Count operation
1690     sal_Int32   cParasFootnoteEdn = 0;       //      count of paragraphs in footnotes and endnotes tallied by last Word Count operation
1691     sal_Int32   cLinesFootnoteEdn = 0;       //      count of paragraphs in footnotes and endnotes tallied by last Word Count operation
1692     sal_Int32   lKeyProtDoc = 0;        //      document protection password key, only valid if dop.fProtEnabled, dop.fLockAtn or dop.fLockRev are 1.
1693      sal_uInt16  wvkSaved : 3 /*= 0*/;       //      document view kind: 0 Normal view, 1 Outline view, 2 Page View
1694      sal_uInt16  wScaleSaved : 9 /*= 0*/;    ///< Specifies the zoom percentage that was in use when the document was saved.
1695      sal_uInt16  zkSaved : 2 /*= 0*/;        //      document zoom type: 0 percent, 1 whole/entire page, 2 page width, 3 text width/optimal
1696      bool        fRotateFontW6 : 1 /*= false*/;
1697      bool        iGutterPos : 1 /*= false*/;
1698 
1699     // this should be the end for nFib < 103, otherwise the file is broken!
1700 
1701     /*
1702         for nFib >= 103 it continues:
1703     */
1704      bool       fNoTabForInd : 1 /*= false*/;                      // see above in compatibility options
1705      bool       fNoSpaceRaiseLower : 1 /*= false*/;                // see above
1706      bool       fSupressSpbfAfterPageBreak : 1 /*= false*/;        // see above
1707      bool       fWrapTrailSpaces : 1 /*= false*/;                  // see above
1708      bool       fMapPrintTextColor : 1 /*= false*/;                // see above
1709      bool       fNoColumnBalance : 1 /*= false*/;                  // see above
1710      bool       fConvMailMergeEsc : 1 /*= false*/;                 // see above
1711      bool       fSupressTopSpacing : 1 /*= false*/;                // see above
1712      bool       fOrigWordTableRules : 1 /*= false*/;               // see above
1713      bool       fTransparentMetafiles : 1 /*= false*/;             // see above
1714      bool       fShowBreaksInFrames : 1 /*= false*/;               // see above
1715      bool       fSwapBordersFacingPgs : 1 /*= false*/;             // see above
1716      bool       fCompatibilityOptions_Unknown1_13 : 1 /*= false*/; // #i78591#
1717      bool       fExpShRtn : 1 /*= false*/;                         // #i78591# and #i56856#
1718      bool       fCompatibilityOptions_Unknown1_15 : 1 /*= false*/; // #i78591#
1719      bool       fCompatibilityOptions_Unknown1_16 : 1 /*= false*/; // #i78591#
1720      bool       fSuppressTopSpacingMac5 : 1 /*= false*/;           // Suppress extra line spacing at top
1721                                                       // of page like MacWord 5.x
1722      bool       fTruncDxaExpand : 1 /*= false*/;                    // Expand/Condense by whole number of points
1723      bool       fPrintBodyBeforeHdr : 1 /*= false*/;               // Print body text before header/footer
1724      bool       fNoLeading : 1 /*= false*/;                        // Don't add extra spacebetween rows of text
1725      bool       fCompatibilityOptions_Unknown1_21 : 1 /*= false*/; // #i78591#
1726      bool       fMWSmallCaps : 1 /*= false*/;                     // Use larger small caps like MacWord 5.x
1727      bool       fCompatibilityOptions_Unknown1_23 : 1 /*= false*/; // #i78591#
1728      bool       fCompatibilityOptions_Unknown1_24 : 1 /*= false*/; // #i78591#
1729      bool       fCompatibilityOptions_Unknown1_25 : 1 /*= false*/; // #i78591#
1730      bool       fCompatibilityOptions_Unknown1_26 : 1 /*= false*/; // #i78591#
1731      bool       fCompatibilityOptions_Unknown1_27 : 1 /*= false*/; // #i78591#
1732      bool       fCompatibilityOptions_Unknown1_28 : 1 /*= false*/; // #i78591#
1733      bool       fCompatibilityOptions_Unknown1_29 : 1 /*= false*/; // #i78591#
1734      bool       fCompatibilityOptions_Unknown1_30 : 1 /*= false*/; // #i78591#
1735      bool       fCompatibilityOptions_Unknown1_31 : 1 /*= false*/; // #i78591#
1736      bool       fUsePrinterMetrics : 1 /*= false*/;                //The magic option
1737 
1738     // this should be the end for nFib <= 105, otherwise the file is broken!
1739 
1740     /*
1741         for nFib > 105 it continues:
1742     */
1743     sal_Int16   adt = 0;                  // Autoformat Document Type:
1744                                       // 0 for normal.
1745                                       // 1 for letter, and
1746                                       // 2 for email.
1747     WW8DopTypography doptypography = {};   // see WW8STRUC.HXX
1748     WW8_DOGRID dogrid = {};                // see WW8STRUC.HXX
1749     sal_uInt16 : 1;                   // reserved
1750      sal_uInt16 lvl : 4 /*= 0*/;               // Which outline levels are showing in outline view
1751     sal_uInt16 : 4;                   // reserved
1752      bool       fHtmlDoc : 1 /*= false*/;          // This file is based upon an HTML file
1753     sal_uInt16 : 1;                   // reserved
1754      bool       fSnapBorder : 1 /*= false*/;       // Snap table and page borders to page border
1755      bool       fIncludeHeader : 1 /*= false*/;    // Place header inside page border
1756      bool       fIncludeFooter : 1 /*= false*/;    // Place footer inside page border
1757      bool       fForcePageSizePag : 1 /*= false*/; // Are we in online view
1758      bool       fMinFontSizePag : 1 /*= false*/;   // Are we auto-promoting fonts to >= hpsZoonFontPag?
1759      bool       fHaveVersions : 1 /*= false*/;     // versioning is turned on
1760      bool       fAutoVersion : 1 /*= false*/;      // autoversioning is enabled
1761     sal_uInt16 : 14;                  // reserved
1762     // Skip 12 Bytes here: ASUMI
1763     sal_Int32 cChWS = 0;
1764     sal_Int32 cChWSFootnoteEdn = 0;
1765     sal_Int32 grfDocEvents = 0;
1766     // Skip 4+30+8 Bytes here
1767     sal_Int32 cDBC = 0;
1768     sal_Int32 cDBCFootnoteEdn = 0;
1769     // Skip 4 Bytes here
1770     sal_Int16 nfcFootnoteRef = 0;
1771     sal_Int16 nfcEdnRef = 0;
1772     sal_Int16 hpsZoonFontPag = 0;
1773     sal_Int16 dywDispPag = 0;
1774 
1775      bool       fCompatibilityOptions_Unknown2_1 : 1 /*= false*/;  // #i78591#
1776      bool       fCompatibilityOptions_Unknown2_2 : 1 /*= false*/;  // #i78591#
1777      bool       fDontUseHTMLAutoSpacing : 1 /*= false*/;
1778      bool       fCompatibilityOptions_Unknown2_4 : 1 /*= false*/;  // #i78591#
1779      bool       fCompatibilityOptions_Unknown2_5 : 1 /*= false*/;  // #i78591#
1780      bool       fCompatibilityOptions_Unknown2_6 : 1 /*= false*/;  // #i78591#
1781      bool       fCompatibilityOptions_Unknown2_7 : 1 /*= false*/;  // #i78591#
1782      bool       fCompatibilityOptions_Unknown2_8 : 1 /*= false*/;  // #i78591#
1783      bool       fCompatibilityOptions_Unknown2_9 : 1 /*= false*/;  // #i78591#
1784      bool       fCompatibilityOptions_Unknown2_10 : 1 /*= false*/; // #i78591#
1785      bool       fCompatibilityOptions_Unknown2_11 : 1 /*= false*/; // #i78591#
1786      bool       fCompatibilityOptions_Unknown2_12 : 1 /*= false*/; // #i78591#
1787      bool       fCompatibilityOptions_Unknown2_13 : 1 /*= false*/; // #i78591#
1788      bool       fCompatibilityOptions_Unknown2_14 : 1 /*= false*/; // #i78591#
1789      bool       fCompatibilityOptions_Unknown2_15 : 1 /*= false*/; // #i78591#
1790      bool       fCompatibilityOptions_Unknown2_16 : 1 /*= false*/; // #i78591#
1791      bool       fCompatibilityOptions_Unknown2_17 : 1 /*= false*/; // #i78591#
1792      bool       fCompatibilityOptions_Unknown2_18 : 1 /*= false*/; // #i78591#
1793      bool       fCompatibilityOptions_Unknown2_19 : 1 /*= false*/; // #i78591#
1794      bool       fCompatibilityOptions_Unknown2_20 : 1 /*= false*/; // #i78591#
1795      bool       fCompatibilityOptions_Unknown2_21 : 1 /*= false*/; // #i78591#
1796      bool       fCompatibilityOptions_Unknown2_22 : 1 /*= false*/; // #i78591#
1797      bool       fCompatibilityOptions_Unknown2_23 : 1 /*= false*/; // #i78591#
1798      bool       fCompatibilityOptions_Unknown2_24 : 1 /*= false*/; // #i78591#
1799      bool       fCompatibilityOptions_Unknown2_25 : 1 /*= false*/; // #i78591#
1800      bool       fCompatibilityOptions_Unknown2_26 : 1 /*= false*/; // #i78591#
1801      bool       fCompatibilityOptions_Unknown2_27 : 1 /*= false*/; // #i78591#
1802      bool       fCompatibilityOptions_Unknown2_28 : 1 /*= false*/; // #i78591#
1803      bool       fCompatibilityOptions_Unknown2_29 : 1 /*= false*/; // #i78591#
1804      bool       fCompatibilityOptions_Unknown2_30 : 1 /*= false*/; // #i78591#
1805      bool       fCompatibilityOptions_Unknown2_31 : 1 /*= false*/; // #i78591#
1806      bool       fCompatibilityOptions_Unknown2_32 : 1 /*= false*/; // #i78591#
1807 
1808      sal_uInt16 fUnknown3 : 15 /*= 0*/;
1809      bool       fUseBackGroundInAllmodes : 1 /*= false*/;
1810 
1811      bool       fDoNotEmbedSystemFont : 1 /*= false*/;
1812      bool       fWordCompat : 1 /*= false*/;
1813      bool       fLiveRecover : 1 /*= false*/;
1814      bool       fEmbedFactoids : 1 /*= false*/;
1815      bool       fFactoidXML : 1 /*= false*/;
1816      bool       fFactoidAllDone : 1 /*= false*/;
1817      bool       fFolioPrint : 1 /*= false*/;
1818      bool       fReverseFolio : 1 /*= false*/;
1819      sal_uInt16 iTextLineEnding : 3 /*= 0*/;
1820      bool       fHideFcc : 1 /*= false*/;
1821      bool       fAcetateShowMarkup : 1 /*= false*/;
1822      bool       fAcetateShowAtn : 1 /*= false*/;
1823      bool       fAcetateShowInsDel : 1 /*= false*/;
1824      bool       fAcetateShowProps : 1 /*= false*/;
1825 
1826     bool bUseThaiLineBreakingRules = false;
1827 
1828     /* Constructor for importing, needs to know the version of word used */
1829     WW8Dop(SvStream& rSt, sal_Int16 nFib, sal_Int32 nPos, sal_uInt32 nSize);
1830 
1831     /* Constructs default DOP suitable for exporting */
1832     WW8Dop();
1833     void Write(SvStream& rStrm, WW8Fib& rFib) const;
1834 
1835     sal_uInt32 GetCompatibilityOptions() const;
1836     void SetCompatibilityOptions(sal_uInt32 a32Bit);
1837     // i#78591#
1838     sal_uInt32 GetCompatibilityOptions2() const;
1839     void SetCompatibilityOptions2(sal_uInt32 a32Bit);
1840 };
1841 
1842 class WW8PLCF_HdFt
1843 {
1844 private:
1845     WW8PLCF aPLCF;
1846     short nIdxOffset;
1847 
1848 public:
1849     WW8PLCF_HdFt( SvStream* pSt, WW8Fib const & rFib, WW8Dop const & rDop );
1850     bool GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart, WW8_CP& rLen);
1851     void GetTextPosExact(short nIdx, WW8_CP& rStart, WW8_CP& rLen);
1852     void UpdateIndex( sal_uInt8 grpfIhdt );
1853 };
1854 
1855 Word2CHPX ReadWord2Chpx(SvStream &rSt, std::size_t nOffset, sal_uInt8 nSize);
1856 std::vector<sal_uInt8> ChpxToSprms(const Word2CHPX &rChpx);
1857 
1858 [[nodiscard]] bool checkRead(SvStream &rSt, void *pDest, sal_uInt32 nLength);
1859 
1860 //MS has a (slightly) inaccurate view of how many twips
1861 //are in the default letter size of a page
1862 const sal_uInt16 lLetterWidth = 12242;
1863 const sal_uInt16 lLetterHeight = 15842;
1864 
1865 #ifdef OSL_BIGENDIAN
1866 void swapEndian(sal_Unicode *pString);
1867 #endif
1868 
1869 #endif
1870 
1871 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1872