1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
28
29
30 #include <algorithm>
31 #include <functional>
32
33 #include <string.h> // memset()
34 #include <osl/endian.h>
35 #include <rtl/tencinfo.h>
36
37 #ifdef DUMP
38
39 #define ERR_SWG_READ_ERROR 1234
40 #define ASSERT( a, b )
41
42 #else // dump
43 #include <swerror.h> // ERR_WW6_...
44 #include <errhdl.hxx> // ASSERT()
45 #include <swtypes.hxx> // DELETEZ
46
47 #endif // dump
48 #include <tools/debug.hxx>
49 #include "ww8scan.hxx"
50
51 #define ASSERT_RET_ON_FAIL( aCon, aError, aRet ) \
52 ASSERT(aCon, aError); \
53 if (!(aCon)) \
54 return aRet;
55
56 //-begin
57 namespace SL
58 {
59 # define IMPLCONSTSTRINGARRAY(X) const char a##X[] = "" #X ""
60 IMPLCONSTSTRINGARRAY(ObjectPool);
61 IMPLCONSTSTRINGARRAY(1Table);
62 IMPLCONSTSTRINGARRAY(0Table);
63 IMPLCONSTSTRINGARRAY(Data);
64 IMPLCONSTSTRINGARRAY(CheckBox);
65 IMPLCONSTSTRINGARRAY(TextBox);
66 IMPLCONSTSTRINGARRAY(TextField);
67 IMPLCONSTSTRINGARRAY(MSMacroCmds);
68 }
69
TestBeltAndBraces(const SvStream & rStrm)70 template<class C> bool wwString<C>::TestBeltAndBraces(const SvStream& rStrm)
71 {
72 bool bRet = false;
73 sal_uInt32 nOldPos = rStrm.Tell();
74 SvStream &rMutableStrm = const_cast<SvStream &>(rStrm);
75 sal_uInt32 nLen = rMutableStrm.Seek(STREAM_SEEK_TO_END);
76 rMutableStrm.Seek(nOldPos);
77 C nBelt;
78 rMutableStrm >> nBelt;
79 nBelt *= sizeof(C);
80 if (nOldPos + sizeof(C) + nBelt + sizeof(C) <= nLen &&
81 !rStrm.GetError() && !rStrm.IsEof())
82 {
83 rMutableStrm.SeekRel(nBelt);
84 if (!rStrm.GetError())
85 {
86 C cBraces;
87 rMutableStrm >> cBraces;
88 if (!rMutableStrm.GetError() && cBraces == 0)
89 bRet = true;
90 }
91 }
92 rMutableStrm.Seek(nOldPos);
93 return bRet;
94 }
95
96 template<class C> class wwSortedArray
97 {
98 private:
99 //The array e.g. of sprms.
100 C *mpWwSprmTab;
101 size_t mnNoElems;
102 public:
wwSortedArray(C * pWwSprmTab,size_t nNoElems)103 wwSortedArray(C *pWwSprmTab, size_t nNoElems)
104 : mpWwSprmTab(pWwSprmTab), mnNoElems(nNoElems)
105 {
106 ASSERT(mnNoElems && pWwSprmTab, "WW8: empty Array: Don't do that");
107 std::sort(mpWwSprmTab, mpWwSprmTab + mnNoElems);
108 #ifdef DEBUG
109 bool bBroken=false;
110 rtl::OUString sError;
111 const C *pIter = mpWwSprmTab;
112 const C *pBeforeEnd = mpWwSprmTab + mnNoElems - 1;
113 while (pIter < pBeforeEnd)
114 {
115 if (*pIter == *(pIter+1))
116 {
117 if (!bBroken)
118 {
119 sError = rtl::OUString::createFromAscii(
120 "WW8: Duplicate in list, almost certainly don't want that!\n"
121 "(You will not see this message again unless you restart)\n"
122 "Extra entries are...\n");
123 bBroken=true;
124 }
125
126 size_t nSize = sizeof(C);
127 const sal_uInt8 *pHack =
128 reinterpret_cast<const sal_uInt8 *>(&(*pIter));
129 for (size_t i=0; i < nSize; ++i)
130 {
131 sError += rtl::OUString::valueOf(
132 static_cast<sal_Int32>(pHack[i]), 16);
133 sError += rtl::OUString::valueOf(sal_Unicode(' '));
134 }
135 sError += rtl::OUString::valueOf(sal_Unicode('\n'));
136 while (*pIter == *(pIter+1) && pIter < pBeforeEnd)
137 ++pIter;
138 }
139 else
140 ++pIter;
141 }
142 if (bBroken)
143 DbgError(rtl::OUStringToOString(sError, RTL_TEXTENCODING_ASCII_US));
144 #endif
145 }
146
147 //Find an entry, return its address if found and 0 if not
148 const C *search(C aSrch) const;
149 };
150
search(C aSrch) const151 template<class C> const C *wwSortedArray<C>::search(C aSrch) const
152 {
153 std::pair<C *, C *> aPair =
154 std::equal_range(mpWwSprmTab, mpWwSprmTab + mnNoElems, aSrch);
155 if (aPair.first != aPair.second)
156 return aPair.first;
157 else
158 return 0;
159 }
160
operator ==(const SprmInfo & rFirst,const SprmInfo & rSecond)161 bool operator==(const SprmInfo &rFirst, const SprmInfo &rSecond)
162 {
163 return (rFirst.nId == rSecond.nId);
164 }
165
operator <(const SprmInfo & rFirst,const SprmInfo & rSecond)166 bool operator<(const SprmInfo &rFirst, const SprmInfo &rSecond)
167 {
168 return (rFirst.nId < rSecond.nId);
169 }
170
GetWW6SprmSearcher()171 const wwSprmSearcher *wwSprmParser::GetWW6SprmSearcher()
172 {
173 //double lock me
174 // WW7- Sprms
175 static SprmInfo aSprms[] =
176 {
177 { 0, 0, L_FIX}, // "Default-sprm", wird uebersprungen
178 { 2, 2, L_FIX}, // "sprmPIstd", pap.istd (style code)
179 { 3, 3, L_VAR}, // "sprmPIstdPermute pap.istd permutation
180 { 4, 1, L_FIX}, // "sprmPIncLv1" pap.istddifference
181 { 5, 1, L_FIX}, // "sprmPJc" pap.jc (justification)
182 { 6, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide
183 { 7, 1, L_FIX}, // "sprmPFKeep" pap.fKeep
184 { 8, 1, L_FIX}, // "sprmPFKeepFollow " pap.fKeepFollow
185 { 9, 1, L_FIX}, // "sprmPPageBreakBefore" pap.fPageBreakBefore
186 { 10, 1, L_FIX}, // "sprmPBrcl" pap.brcl
187 { 11, 1, L_FIX}, // "sprmPBrcp" pap.brcp
188 { 12, 0, L_VAR}, // "sprmPAnld" pap.anld (ANLD structure)
189 { 13, 1, L_FIX}, // "sprmPNLvlAnm" pap.nLvlAnm nn
190 { 14, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn
191 { 15, 0, L_VAR}, // "?sprmPChgTabsPapx" pap.itbdMac, ...
192 { 16, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight
193 { 17, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft
194 { 18, 2, L_FIX}, // "sprmPNest" pap.dxaLeft
195 { 19, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1
196 { 20, 4, L_FIX}, // "sprmPDyaLine" pap.lspd an LSPD
197 { 21, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore
198 { 22, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter
199 { 23, 0, L_VAR}, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
200 { 24, 1, L_FIX}, // "sprmPFInTable" pap.fInTable
201 { 25, 1, L_FIX}, // "sprmPTtp" pap.fTtp
202 { 26, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs
203 { 27, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs
204 { 28, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth
205 { 29, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert
206 { 30, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop BRC10
207 { 31, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft BRC10
208 { 32, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom BRC10
209 { 33, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight BRC10
210 { 34, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween BRC10
211 { 35, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar BRC10
212 { 36, 2, L_FIX}, // "sprmPFromText10" pap.dxaFromText dxa
213 { 37, 1, L_FIX}, // "sprmPWr" pap.wr wr
214 { 38, 2, L_FIX}, // "sprmPBrcTop" pap.brcTop BRC
215 { 39, 2, L_FIX}, // "sprmPBrcLeft" pap.brcLeft BRC
216 { 40, 2, L_FIX}, // "sprmPBrcBottom" pap.brcBottom BRC
217 { 41, 2, L_FIX}, // "sprmPBrcRight" pap.brcRight BRC
218 { 42, 2, L_FIX}, // "sprmPBrcBetween" pap.brcBetween BRC
219 { 43, 2, L_FIX}, // "sprmPBrcBar" pap.brcBar BRC word
220 { 44, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
221 { 45, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs w
222 { 46, 2, L_FIX}, // "sprmPDcs" pap.dcs DCS
223 { 47, 2, L_FIX}, // "sprmPShd" pap.shd SHD
224 { 48, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText dya
225 { 49, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText dxa
226 { 50, 1, L_FIX}, // "sprmPFLocked" pap.fLocked 0 or 1 byte
227 { 51, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
228 { 52, 0, L_FIX}, // "?sprmPRuler 52"
229 { 64, 0, L_VAR}, // rtl property ?
230 { 65, 1, L_FIX}, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
231 { 66, 1, L_FIX}, // "sprmCFRMark" chp.fRMark 1 or 0 bit
232 { 67, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish 1 or 0 bit
233 { 68, 0, L_VAR}, // "sprmCPicLocation" chp.fcPic and chp.fSpec
234 { 69, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark index into sttbRMark
235 { 70, 4, L_FIX}, // "sprmCDttmRMark" chp.dttm DTTM long
236 { 71, 1, L_FIX}, // "sprmCFData" chp.fData 1 or 0 bit
237 { 72, 2, L_FIX}, // "sprmCRMReason" chp.idslRMReason an index to a table
238 { 73, 3, L_FIX}, // "sprmCChse" chp.fChsDiff and chp.chse
239 { 74, 0, L_VAR}, // "sprmCSymbol" chp.fSpec, chp.chSym and chp.ftcSym
240 { 75, 1, L_FIX}, // "sprmCFOle2" chp.fOle2 1 or 0 bit
241 { 79, 0, L_VAR}, // unknown
242 { 80, 2, L_FIX}, // "sprmCIstd" chp.istd istd, see stylesheet definition
243 { 81, 0, L_VAR}, // "sprmCIstdPermute" chp.istd permutation vector
244 { 82, 0, L_VAR}, // "sprmCDefault" whole CHP
245 { 83, 0, L_FIX}, // "sprmCPlain" whole CHP
246 { 85, 1, L_FIX}, // "sprmCFBold" chp.fBold 0,1, 128, or 129
247 { 86, 1, L_FIX}, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
248 { 87, 1, L_FIX}, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
249 { 88, 1, L_FIX}, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
250 { 89, 1, L_FIX}, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
251 { 90, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
252 { 91, 1, L_FIX}, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
253 { 92, 1, L_FIX}, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
254 { 93, 2, L_FIX}, // "sprmCFtc" chp.ftc ftc word
255 { 94, 1, L_FIX}, // "sprmCKul" chp.kul kul byte
256 { 95, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos
257 { 96, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace dxa
258 { 97, 2, L_FIX}, // "sprmCLid" chp.lid LID
259 { 98, 1, L_FIX}, // "sprmCIco" chp.ico ico byte
260 { 99, 2, L_FIX}, // "sprmCHps" chp.hps hps !word!
261 {100, 1, L_FIX}, // "sprmCHpsInc" chp.hps
262 {101, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos hps !word!
263 {102, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos hps
264 {103, 0, L_VAR}, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
265 {104, 1, L_FIX}, // "sprmCIss" chp.iss iss
266 {105, 0, L_VAR}, // "sprmCHpsNew50" chp.hps hps variable width
267 {106, 0, L_VAR}, // "sprmCHpsInc1" chp.hps complex
268 {107, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern hps
269 {108, 0, L_VAR}, // "sprmCMajority50" chp.fBold, chp.fItalic, ...
270 {109, 2, L_FIX}, // "sprmCHpsMul" chp.hps percentage to grow hps
271 {110, 2, L_FIX}, // "sprmCCondHyhen" chp.ysri ysri
272 {111, 2, L_FIX}, // unknown
273 {112, 2, L_FIX}, // unknown
274 {113, 0, L_VAR}, // rtl property ?
275 {115, 0, L_VAR}, // rtl property ?
276 {116, 0, L_VAR}, // unknown
277 {117, 1, L_FIX}, // "sprmCFSpec" chp.fSpec 1 or 0 bit
278 {118, 1, L_FIX}, // "sprmCFObj" chp.fObj 1 or 0 bit
279 {119, 1, L_FIX}, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
280 {120,12, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
281 {121, 2, L_FIX}, // "sprmPicBrcTop" pic.brcTop BRC word
282 {122, 2, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft BRC word
283 {123, 2, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom BRC word
284 {124, 2, L_FIX}, // "sprmPicBrcRight" pic.brcRight BRC word
285 {131, 1, L_FIX}, // "sprmSScnsPgn" sep.cnsPgn cns byte
286 {132, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn
287 {133, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm OLST variable length
288 {136, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing complex
289 {137, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing
290 {138, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced 1 or 0
291 {139, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked 1 or 0 byte
292 {140, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst word
293 {141, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther word
294 {142, 1, L_FIX}, // "sprmSBkc" sep.bkc bkc byte
295 {143, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
296 {144, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
297 {145, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns dxa word
298 {146, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
299 {147, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn nfc byte
300 {148, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn dya short
301 {149, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn dya short
302 {150, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
303 {151, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
304 {152, 1, L_FIX}, // "sprmSLnc" sep.lnc lnc byte
305 {153, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
306 {154, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
307 {155, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn dxa word
308 {156, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
309 {157, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
310 {158, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
311 {159, 1, L_FIX}, // "sprmSVjc" sep.vjc vjc byte
312 {160, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin lnn word
313 {161, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart pgn word
314 {162, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage dm byte
315 {163, 0, L_FIX}, // "?SprmSBCustomize 163"
316 {164, 2, L_FIX}, // "sprmSXaPage" sep.xaPage xa word
317 {165, 2, L_FIX}, // "sprmSYaPage" sep.yaPage ya word
318 {166, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft dxa word
319 {167, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight dxa word
320 {168, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop dya word
321 {169, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom dya word
322 {170, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter dza word
323 {171, 2, L_FIX}, // "sprmSDMPaperReq" sep.dmPaperReq dm word
324 {179, 0, L_VAR}, // rtl property ?
325 {181, 0, L_VAR}, // rtl property ?
326 {182, 2, L_FIX}, // "sprmTJc" tap.jc jc (low order byte is significant)
327 {183, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
328 {184, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
329 {185, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit 1 or 0 byte
330 {186, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader 1 or 0 byte
331 {187,12, L_FIX}, // "sprmTTableBorders" tap.rgbrcTable complex 12 bytes
332 {188, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
333 {189, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
334 {190, 0, L_VAR2},// "sprmTDefTable" tap.rgtc complex
335 {191, 1, L_VAR}, // "sprmTDefTableShd" tap.rgshd complex
336 {192, 4, L_FIX}, // "sprmTTlp" tap.tlp TLP 4 bytes
337 {193, 5, L_FIX}, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
338 {194, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
339 {195, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
340 {196, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter complex
341 {197, 2, L_FIX}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
342 {198, 2, L_FIX}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
343 {199, 5, L_FIX}, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
344 {200, 4, L_FIX} // "sprmTSetShd", tap.rgshd complex 4 bytes
345 };
346
347 static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0]));
348 return &aSprmSrch;
349 };
350
GetWW8SprmSearcher()351 const wwSprmSearcher *wwSprmParser::GetWW8SprmSearcher()
352 {
353 //double lock me
354 //WW8+ Sprms
355 static SprmInfo aSprms[] =
356 {
357 { 0, 0, L_FIX}, // "Default-sprm"/ wird uebersprungen
358 {0x4600, 2, L_FIX}, // "sprmPIstd" pap.istd;istd (style code);short;
359 {0xC601, 0, L_VAR}, // "sprmPIstdPermute" pap.istd;permutation vector
360 {0x2602, 1, L_FIX}, // "sprmPIncLvl" pap.istd, pap.lvl;difference
361 // between istd of base PAP and istd of PAP to be
362 // produced
363 {0x2403, 1, L_FIX}, // "sprmPJc" pap.jc;jc (justification);byte;
364 {0x2404, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide;0 or 1;byte;
365 {0x2405, 1, L_FIX}, // "sprmPFKeep" pap.fKeep;0 or 1;byte;
366 {0x2406, 1, L_FIX}, // "sprmPFKeepFollow" pap.fKeepFollow;0 or 1;byte;
367 {0x2407, 1, L_FIX}, // "sprmPFPageBreakBefore" pap.fPageBreakBefore;
368 // 0 or 1
369 {0x2408, 1, L_FIX}, // "sprmPBrcl" pap.brcl;brcl;byte;
370 {0x2409, 1, L_FIX}, // "sprmPBrcp" pap.brcp;brcp;byte;
371 {0x260A, 1, L_FIX}, // "sprmPIlvl" pap.ilvl;ilvl;byte;
372 {0x460B, 2, L_FIX}, // "sprmPIlfo" pap.ilfo;ilfo (list index) ;short;
373 {0x240C, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn;0 or 1;byte;
374 {0xC60D, 0, L_VAR}, // "sprmPChgTabsPapx" pap.itbdMac, pap.rgdxaTab,
375 // pap.rgtbd;complex
376 {0x840E, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight;dxa;word;
377 {0x840F, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft;dxa;word;
378 {0x4610, 2, L_FIX}, // "sprmPNest" pap.dxaLeft;dxa
379 {0x8411, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word;
380 {0x6412, 4, L_FIX}, // "sprmPDyaLine" pap.lspd;an LSPD, a long word
381 // structure consisting of a short of dyaLine
382 // followed by a short of fMultLinespace
383 {0xA413, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore;dya;word;
384 {0xA414, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter;dya;word;
385 {0xC615, 0, L_VAR}, // "sprmPChgTabs" pap.itbdMac, pap.rgdxaTab,
386 // pap.rgtbd;complex
387 {0x2416, 1, L_FIX}, // "sprmPFInTable" pap.fInTable;0 or 1;byte;
388 {0x2417, 1, L_FIX}, // "sprmPFTtp" pap.fTtp;0 or 1;byte;
389 {0x8418, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs;dxa;word;
390 {0x8419, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs;dya;word;
391 {0x841A, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth;dxa;word;
392 {0x261B, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert;complex
393 {0x461C, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop;BRC10;word;
394 {0x461D, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft;BRC10;word;
395 {0x461E, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom;BRC10;word;
396 {0x461F, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight;BRC10;word;
397 {0x4620, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween;BRC10;word;
398 {0x4621, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar;BRC10;word;
399 {0x4622, 2, L_FIX}, // "sprmPDxaFromText10" pap.dxaFromText;dxa;word;
400 {0x2423, 1, L_FIX}, // "sprmPWr" pap.wr;wr
401 {0x6424, 4, L_FIX}, // "sprmPBrcTop" pap.brcTop;BRC;long;
402 {0x6425, 4, L_FIX}, // "sprmPBrcLeft" pap.brcLeft;BRC;long;
403 {0x6426, 4, L_FIX}, // "sprmPBrcBottom" pap.brcBottom;BRC;long;
404 {0x6427, 4, L_FIX}, // "sprmPBrcRight" pap.brcRight;BRC;long;
405 {0x6428, 4, L_FIX}, // "sprmPBrcBetween" pap.brcBetween;BRC;long;
406 {0x6629, 4, L_FIX}, // "sprmPBrcBar" pap.brcBar;BRC;long;
407 {0x242A, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph;0 or 1;byte;
408 {0x442B, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs;w;word;
409 {0x442C, 2, L_FIX}, // "sprmPDcs" pap.dcs;DCS;short;
410 {0x442D, 2, L_FIX}, // "sprmPShd" pap.shd;SHD;word;
411 {0x842E, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText;dya;word;
412 {0x842F, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText;dxa;word;
413 {0x2430, 1, L_FIX}, // "sprmPFLocked" pap.fLocked;0 or 1;byte;
414 {0x2431, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl;0 or 1
415 {0xC632, 0, L_VAR}, // "sprmPRuler" ;;variable length;
416 {0x2433, 1, L_FIX}, // "sprmPFKinsoku" pap.fKinsoku;0 or 1;byte;
417 {0x2434, 1, L_FIX}, // "sprmPFWordWrap" pap.fWordWrap;0 or 1;byte;
418 {0x2435, 1, L_FIX}, // "sprmPFOverflowPunct" pap.fOverflowPunct;0 or 1
419 {0x2436, 1, L_FIX}, // "sprmPFTopLinePunct" pap.fTopLinePunct;0 or 1
420 {0x2437, 1, L_FIX}, // "sprmPFAutoSpaceDE" pap.fAutoSpaceDE;0 or 1
421 {0x2438, 1, L_FIX}, // "sprmPFAutoSpaceDN" pap.fAutoSpaceDN;0 or 1
422 {0x4439, 2, L_FIX}, // "sprmPWAlignFont" pap.wAlignFont;iFa
423 {0x443A, 2, L_FIX}, // "sprmPFrameTextFlow" pap.fVertical pap.fBackward
424 // pap.fRotateFont;complex
425 {0x243B, 1, L_FIX}, // "sprmPISnapBaseLine" obsolete: not applicable in
426 // Word97 and later versions;
427 {0xC63E, 0, L_VAR}, // "sprmPAnld" pap.anld;;variable length;
428 {0xC63F, 0, L_VAR}, // "sprmPPropRMark" pap.fPropRMark;complex
429 {0x2640, 1, L_FIX}, // "sprmPOutLvl" pap.lvl;has no effect if pap.istd
430 // is < 1 or is > 9
431 {0x2441, 1, L_FIX}, // "sprmPFBiDi" ;;byte;
432 {0x2443, 1, L_FIX}, // "sprmPFNumRMIns" pap.fNumRMIns;1 or 0;bit;
433 {0x2444, 1, L_FIX}, // "sprmPCrLf" ;;byte;
434 {0xC645, 0, L_VAR}, // "sprmPNumRM" pap.numrm;;variable length;
435 {0x6645, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate
436 // the huge grpprl
437 {0x6646, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate
438 // the huge grpprl
439 {0x2447, 1, L_FIX}, // "sprmPFUsePgsuSettings" pap.fUsePgsuSettings;
440 // 1 or 0
441 {0x2448, 1, L_FIX}, // "sprmPFAdjustRight" pap.fAdjustRight;1 or 0;byte;
442 {0x0800, 1, L_FIX}, // "sprmCFRMarkDel" chp.fRMarkDel;1 or 0;bit;
443 {0x0801, 1, L_FIX}, // "sprmCFRMark" chp.fRMark;1 or 0;bit;
444 {0x0802, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish;1 or 0;bit;
445 {0x6A03, 4, L_FIX}, // "sprmCPicLocation" chp.fcPic and chp.fSpec;
446 {0x4804, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark;index into
447 // sttbRMark
448 {0x6805, 4, L_FIX}, // "sprmCDttmRMark" chp.dttmRMark;DTTM;long;
449 {0x0806, 1, L_FIX}, // "sprmCFData" chp.fData;1 or 0;bit;
450 {0x4807, 2, L_FIX}, // "sprmCIdslRMark" chp.idslRMReason;an index to a
451 // table of strings defined in Word 6.0
452 // executables;short;
453 {0xEA08, 1, L_FIX}, // "sprmCChs" chp.fChsDiff and chp.chse;
454 {0x6A09, 4, L_FIX}, // "sprmCSymbol" chp.fSpec, chp.xchSym and
455 // chp.ftcSym
456 {0x080A, 1, L_FIX}, // "sprmCFOle2" chp.fOle2;1 or 0;bit;
457 {0x480B, 0, L_FIX}, // "sprmCIdCharType" obsolete: not applicable in
458 // Word97 and later versions;;;
459 {0x2A0C, 1, L_FIX}, // "sprmCHighlight" chp.fHighlight,
460 // chp.icoHighlight;ico (fHighlight is set to 1 iff
461 // ico is not 0)
462 {0x680E, 4, L_FIX}, // "sprmCObjLocation" chp.fcObj;FC;long;
463 {0x2A10, 0, L_FIX}, // "sprmCFFtcAsciSymb" ;;;
464 {0x4A30, 2, L_FIX}, // "sprmCIstd" chp.istd;istd, see stylesheet def
465 {0xCA31, 0, L_VAR}, // "sprmCIstdPermute" chp.istd;permutation vector
466 {0x2A32, 0, L_VAR}, // "sprmCDefault" whole CHP;none;variable length;
467 {0x2A33, 0, L_FIX}, // "sprmCPlain" whole CHP;none;0;
468 {0x2A34, 1, L_FIX}, // "sprmCKcd" ;;;
469 {0x0835, 1, L_FIX}, // "sprmCFBold" chp.fBold;0,1, 128, or 129
470 {0x0836, 1, L_FIX}, // "sprmCFItalic" chp.fItalic;0,1, 128, or 129
471 {0x0837, 1, L_FIX}, // "sprmCFStrike" chp.fStrike;0,1, 128, or 129
472 {0x0838, 1, L_FIX}, // "sprmCFOutline" chp.fOutline;0,1, 128, or 129
473 {0x0839, 1, L_FIX}, // "sprmCFShadow" chp.fShadow;0,1, 128, or 129
474 {0x083A, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps;0,1, 128, or 129
475 {0x083B, 1, L_FIX}, // "sprmCFCaps" chp.fCaps;0,1, 128, or 129
476 {0x083C, 1, L_FIX}, // "sprmCFVanish" chp.fVanish;0,1, 128, or 129
477 {0x4A3D, 2, L_FIX}, // "sprmCFtcDefault" ;ftc, only used internally
478 {0x2A3E, 1, L_FIX}, // "sprmCKul" chp.kul;kul;byte;
479 {0xEA3F, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos;3 bytes;
480 {0x8840, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace;dxa;word;
481 {0x4A41, 2, L_FIX}, // "sprmCLid" ;only used internally never stored
482 {0x2A42, 1, L_FIX}, // "sprmCIco" chp.ico;ico;byte;
483 {0x4A43, 2, L_FIX}, // "sprmCHps" chp.hps;hps
484 {0x2A44, 1, L_FIX}, // "sprmCHpsInc" chp.hps;
485 {0x4845, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos;hps;short; (doc wrong)
486 {0x2A46, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos;hps
487 {0xCA47, 0, L_VAR}, // "sprmCMajority" chp.fBold, chp.fItalic,
488 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
489 // chp.fCaps, chp.rgftc, chp.hps, chp.hpsPos,
490 // chp.kul, chp.dxaSpace, chp.ico,
491 // chp.rglid;complex;variable length, length byte
492 // plus size of following grpprl;
493 {0x2A48, 1, L_FIX}, // "sprmCIss" chp.iss;iss;byte;
494 {0xCA49, 0, L_VAR}, // "sprmCHpsNew50" chp.hps;hps;variable width
495 {0xCA4A, 0, L_VAR}, // "sprmCHpsInc1" chp.hps;complex
496 {0x484B, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern;hps;short;
497 {0xCA4C, 2, L_FIX}, // "sprmCMajority50" chp.fBold, chp.fItalic,
498 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
499 // chp.fCaps, chp.ftc, chp.hps, chp.hpsPos, chp.kul,
500 // chp.dxaSpace, chp.ico,;complex
501 {0x4A4D, 2, L_FIX}, // "sprmCHpsMul" chp.hps;percentage to grow hps
502 {0x484E, 2, L_FIX}, // "sprmCYsri" chp.ysri;ysri;short;
503 {0x4A4F, 2, L_FIX}, // "sprmCRgFtc0" chp.rgftc[0];ftc for ASCII text
504 {0x4A50, 2, L_FIX}, // "sprmCRgFtc1" chp.rgftc[1];ftc for Far East text
505 {0x4A51, 2, L_FIX}, // "sprmCRgFtc2" chp.rgftc[2];ftc for non-FE text
506 {0x4852, 2, L_FIX}, // "sprmCCharScale"
507 {0x2A53, 1, L_FIX}, // "sprmCFDStrike" chp.fDStrike;;byte;
508 {0x0854, 1, L_FIX}, // "sprmCFImprint" chp.fImprint;1 or 0;bit;
509 {0x0855, 1, L_FIX}, // "sprmCFSpec" chp.fSpec ;1 or 0;bit;
510 {0x0856, 1, L_FIX}, // "sprmCFObj" chp.fObj;1 or 0;bit;
511 {0xCA57, 0, L_VAR}, // "sprmCPropRMark" chp.fPropRMark,
512 // chp.ibstPropRMark, chp.dttmPropRMark;Complex
513 {0x0858, 1, L_FIX}, // "sprmCFEmboss" chp.fEmboss;1 or 0;bit;
514 {0x2859, 1, L_FIX}, // "sprmCSfxText" chp.sfxtText;text animation;byte;
515 {0x085A, 1, L_FIX}, // "sprmCFBiDi" ;;;
516 {0x085B, 1, L_FIX}, // "sprmCFDiacColor" ;;;
517 {0x085C, 1, L_FIX}, // "sprmCFBoldBi" ;;;
518 {0x085D, 1, L_FIX}, // "sprmCFItalicBi" ;;;
519 {0x4A5E, 2, L_FIX},
520 {0x485F, 2, L_FIX}, // "sprmCLidBi" ;;;
521 {0x4A60, 1, L_FIX}, // "sprmCIcoBi" ;;;
522 {0x4A61, 2, L_FIX}, // "sprmCHpsBi" ;;;
523 {0xCA62, 0, L_VAR}, // "sprmCDispFldRMark" chp.fDispFldRMark,
524 // chp.ibstDispFldRMark, chp.dttmDispFldRMark ;
525 {0x4863, 2, L_FIX}, // "sprmCIbstRMarkDel" chp.ibstRMarkDel;index into
526 // sttbRMark;short;
527 {0x6864, 4, L_FIX}, // "sprmCDttmRMarkDel" chp.dttmRMarkDel;DTTM;long;
528 {0x6865, 4, L_FIX}, // "sprmCBrc" chp.brc;BRC;long;
529 {0x4866, 2, L_FIX}, // "sprmCShd" chp.shd;SHD;short;
530 {0x4867, 2, L_FIX}, // "sprmCIdslRMarkDel" chp.idslRMReasonDel;an index
531 // to a table of strings defined in Word 6.0
532 // executables;short;
533 {0x0868, 1, L_FIX}, // "sprmCFUsePgsuSettings"
534 // chp.fUsePgsuSettings;1 or 0
535 {0x486B, 2, L_FIX}, // "sprmCCpg" ;;word;
536 {0x486D, 2, L_FIX}, // "sprmCRgLid0" chp.rglid[0];LID: for non-FE text
537 {0x486E, 2, L_FIX}, // "sprmCRgLid1" chp.rglid[1];LID: for Far East text
538 {0x286F, 1, L_FIX}, // "sprmCIdctHint" chp.idctHint;IDCT:
539 {0x2E00, 1, L_FIX}, // "sprmPicBrcl" pic.brcl;brcl (see PIC definition)
540 {0xCE01, 0, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
541 // pic.dyaCropTop pic.dxaCropRight,
542 // pic.dyaCropBottom;Complex
543 {0x6C02, 4, L_FIX}, // "sprmPicBrcTop" pic.brcTop;BRC;long;
544 {0x6C03, 4, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft;BRC;long;
545 {0x6C04, 4, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom;BRC;long;
546 {0x6C05, 4, L_FIX}, // "sprmPicBrcRight" pic.brcRight;BRC;long;
547 {0x3000, 1, L_FIX}, // "sprmScnsPgn" sep.cnsPgn;cns;byte;
548 {0x3001, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn;heading number
549 // level;byte;
550 {0xD202, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm;OLST;variable length;
551 {0xF203, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing;
552 {0xF204, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing;
553 // complex
554 {0x3005, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced;1 or 0
555 {0x3006, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked;1 or 0;byte;
556 {0x5007, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst;;word;
557 {0x5008, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther;;word;
558 {0x3009, 1, L_FIX}, // "sprmSBkc" sep.bkc;bkc;byte;
559 {0x300A, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage;0 or 1;byte;
560 {0x500B, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1;# of cols - 1;word;
561 {0x900C, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns;dxa;word;
562 {0x300D, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn;obsolete;byte;
563 {0x300E, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn;nfc;byte;
564 {0xB00F, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn;dya;short;
565 {0xB010, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn;dya;short;
566 {0x3011, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart;0 or 1;byte;
567 {0x3012, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote;0 or 1;byte;
568 {0x3013, 1, L_FIX}, // "sprmSLnc" sep.lnc;lnc;byte;
569 {0x3014, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt;grpfihdt
570 {0x5015, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod;non-neg int.;word;
571 {0x9016, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn;dxa;word;
572 {0xB017, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop;dya;word;
573 {0xB018, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom;dya;word;
574 {0x3019, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween;0 or 1;byte;
575 {0x301A, 1, L_FIX}, // "sprmSVjc" sep.vjc;vjc;byte;
576 {0x501B, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin;lnn;word;
577 {0x501C, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart;pgn;word;
578 {0x301D, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage;dm;byte;
579 {0x301E, 1, L_FIX}, // "sprmSBCustomize" ;;;
580 {0xB01F, 2, L_FIX}, // "sprmSXaPage" sep.xaPage;xa;word;
581 {0xB020, 2, L_FIX}, // "sprmSYaPage" sep.yaPage;ya;word;
582 {0xB021, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft;dxa;word;
583 {0xB022, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight;dxa;word;
584 {0x9023, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop;dya;word;
585 {0x9024, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom;dya;word;
586 {0xB025, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter;dza;word;
587 {0x5026, 2, L_FIX}, // "sprmSDmPaperReq" sep.dmPaperReq;dm;word;
588 {0xD227, 0, L_VAR}, // "sprmSPropRMark" sep.fPropRMark,
589 // sep.ibstPropRMark, sep.dttmPropRMark ;complex
590 {0x3228, 1, L_FIX}, // "sprmSFBiDi" ;;;
591 {0x3229, 1, L_FIX}, // "sprmSFFacingCol" ;;;
592 {0x322A, 1, L_FIX}, // "sprmSFRTLGutter", set to one if gutter is on
593 // right
594 {0x702B, 4, L_FIX}, // "sprmSBrcTop" sep.brcTop;BRC;long;
595 {0x702C, 4, L_FIX}, // "sprmSBrcLeft" sep.brcLeft;BRC;long;
596 {0x702D, 4, L_FIX}, // "sprmSBrcBottom" sep.brcBottom;BRC;long;
597 {0x702E, 4, L_FIX}, // "sprmSBrcRight" sep.brcRight;BRC;long;
598 {0x522F, 2, L_FIX}, // "sprmSPgbProp" sep.pgbProp;;word;
599 {0x7030, 4, L_FIX}, // "sprmSDxtCharSpace" sep.dxtCharSpace;dxt;long;
600 {0x9031, 2, L_FIX}, // "sprmSDyaLinePitch"
601 // sep.dyaLinePitch;dya; WRONG:long; RIGHT:short; !
602 {0x5032, 2, L_FIX}, // "sprmSClm" ;;;
603 {0x5033, 2, L_FIX}, // "sprmSTextFlow" sep.wTextFlow;complex
604 {0x5400, 2, L_FIX}, // "sprmTJc" tap.jc;jc;word (low order byte is
605 // significant);
606 {0x9601, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter
607 {0x9602, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf,
608 // tap.rgdxaCenter
609 {0x3403, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit;1 or 0;byte;
610 {0x3404, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader;1 or 0;byte;
611 {0xD605, 0, L_VAR}, // "sprmTTableBorders" tap.rgbrcTable;complex
612 {0xD606, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter,
613 // tap.rgtc;complex
614 {0x9407, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight;dya;word;
615 {0xD608, 0, L_VAR}, // "sprmTDefTable" tap.rgtc;complex
616 {0xD609, 0, L_VAR}, // "sprmTDefTableShd" tap.rgshd;complex
617 {0x740A, 4, L_FIX}, // "sprmTTlp" tap.tlp;TLP;4 bytes;
618 {0x560B, 1, L_FIX}, // "sprmTFBiDi" ;;;
619 {0x740C, 1, L_FIX}, // "sprmTHTMLProps" ;;;
620 {0xD620, 0, L_VAR}, // "sprmTSetBrc" tap.rgtc[].rgbrc;complex
621 {0x7621, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter, tap.rgtc;complex
622 {0x5622, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc;complex
623 {0x7623, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter;complex
624 {0x5624, 0, L_VAR}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged;
625 {0x5625, 0, L_VAR}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged;
626 {0xD626, 0, L_VAR}, // "sprmTSetBrc10" tap.rgtc[].rgbrc;complex
627 {0x7627, 0, L_VAR}, // "sprmTSetShd" tap.rgshd;complex
628 {0x7628, 0, L_VAR}, // "sprmTSetShdOdd" tap.rgshd;complex
629 {0x7629, 0, L_VAR}, // "sprmTTextFlow" tap.rgtc[].fVerticaltap,
630 // rgtc[].fBackwardtap, rgtc[].fRotateFont;0 or 10
631 // or 10 or 1;word;
632 {0xD62A, 1, L_FIX}, // "sprmTDiagLine" ;;;
633 {0xD62B, 0, L_VAR}, // "sprmTVertMerge" tap.rgtc[].vertMerge
634 {0xD62C, 0, L_VAR}, // "sprmTVertAlign" tap.rgtc[].vertAlign
635 {0xCA78, 0, L_VAR}, // undocumented "sprmCDoubleLine ?"
636 {0x6649, 4, L_FIX}, // undocumented
637 {0xF614, 3, L_FIX}, // undocumented
638 {0xD612, 0, L_VAR}, // undocumented, new background colours.
639 {0xD613, 0, L_VAR}, // undocumented
640 {0xD61A, 0, L_VAR}, // undocumented
641 {0xD61B, 0, L_VAR}, // undocumented
642 {0xD61C, 0, L_VAR}, // undocumented
643 {0xD61D, 0, L_VAR}, // undocumented
644 {0xD632, 0, L_VAR}, // undocumented
645 {0xD634, 0, L_VAR}, // undocumented
646 {0xD238, 0, L_VAR}, // undocumented sep
647 {0xC64E, 0, L_VAR}, // undocumented
648 {0xC64F, 0, L_VAR}, // undocumented
649 {0xC650, 0, L_VAR}, // undocumented
650 {0xC651, 0, L_VAR}, // undocumented
651 {0xF661, 3, L_FIX}, // undocumented
652 {0x4873, 2, L_FIX}, // undocumented
653 {0x4874, 2, L_FIX}, // undocumented
654 {0x6463, 4, L_FIX}, // undocumented
655 {0x2461, 1, L_FIX}, // undoc, must be asian version of "sprmPJc"
656 {0x845D, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaRight"
657 {0x845E, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft"
658 {0x8460, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft1"
659 {0x3615, 1, L_FIX}, // undocumented
660 {0x360D, 1, L_FIX}, // undocumented
661 {0x703A, 4, L_FIX}, // undocumented, sep, perhaps related to textgrids ?
662 {0x303B, 1, L_FIX}, // undocumented, sep
663 {0x244B, 1, L_FIX}, // undocumented, subtable "sprmPFInTable" equiv ?
664 {0x244C, 1, L_FIX}, // undocumented, subtable "sprmPFTtp" equiv ?
665 {0x940E, 2, L_FIX}, // undocumented
666 {0x940F, 2, L_FIX}, // undocumented
667 {0x9410, 2, L_FIX}, // undocumented
668 {0x6815, 4, L_FIX}, // undocumented
669 {0x6816, 4, L_FIX}, // undocumented
670 {0x6870, 4, L_FIX}, // undocumented, text colour
671 {0xC64D, 0, L_VAR}, // undocumented, para back colour
672 {0x6467, 4, L_FIX}, // undocumented
673 {0x646B, 4, L_FIX}, // undocumented
674 {0xF617, 3, L_FIX}, // undocumented
675 {0xD660, 0, L_VAR}, // undocumented, something to do with colour.
676 {0xD670, 0, L_VAR}, // undocumented, something to do with colour.
677 {0xCA71, 0, L_VAR}, // undocumented, text backcolour
678 {0x303C, 1, L_FIX}, // undocumented, sep
679 {0x245B, 1, L_FIX}, // undocumented, para autobefore
680 {0x245C, 1, L_FIX} // undocumented, para autoafter
681 };
682
683 static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0]));
684 return &aSprmSrch;
685 };
686
wwSprmParser(int nVersion)687 wwSprmParser::wwSprmParser(int nVersion) : mnVersion(nVersion)
688 {
689 ASSERT((mnVersion >= 6 && mnVersion <= 8), "Impossible value for version");
690
691 mnDelta = (8 > mnVersion) ? 0 : 1;
692
693 if (mnVersion < 8)
694 mpKnownSprms = GetWW6SprmSearcher();
695 else
696 mpKnownSprms = GetWW8SprmSearcher();
697 }
698
GetSprmInfo(sal_uInt16 nId) const699 SprmInfo wwSprmParser::GetSprmInfo(sal_uInt16 nId) const
700 {
701 // Find sprm
702 SprmInfo aSrch;
703 aSrch.nId = nId;
704 const SprmInfo* pFound = mpKnownSprms->search(aSrch);
705 if (pFound == 0)
706 {
707 ASSERT(mnVersion >= 8,
708 "Unknown ww6 sprm, dangerous, report to development");
709
710 aSrch.nId = 0;
711 aSrch.nLen = 0;
712 //All the unknown ww7 sprms appear to be variable (which makes sense)
713 aSrch.nVari = L_VAR;
714
715 if (mnVersion == 8) //We can recover perfectly in this case
716 {
717 aSrch.nVari = L_FIX;
718 switch (nId >> 13)
719 {
720 case 0:
721 case 1:
722 aSrch.nLen = 1;
723 break;
724 case 2:
725 aSrch.nLen = 2;
726 break;
727 case 3:
728 aSrch.nLen = 4;
729 break;
730 case 4:
731 case 5:
732 aSrch.nLen = 2;
733 break;
734 case 6:
735 aSrch.nLen = 0;
736 aSrch.nVari = L_VAR;
737 break;
738 case 7:
739 default:
740 aSrch.nLen = 3;
741 break;
742 }
743 }
744
745 pFound = &aSrch;
746 }
747 return *pFound;
748 }
749
750 //-end
751
Get_Byte(sal_uInt8 * & p)752 inline sal_uInt8 Get_Byte( sal_uInt8 *& p )
753 {
754 sal_uInt8 n = SVBT8ToByte( *(SVBT8*)p );
755 p += 1;
756 return n;
757 }
758
Get_UShort(sal_uInt8 * & p)759 inline sal_uInt16 Get_UShort( sal_uInt8 *& p )
760 {
761 sal_uInt16 n = SVBT16ToShort( *(SVBT16*)p );
762 p += 2;
763 return n;
764 }
765
Get_Short(sal_uInt8 * & p)766 inline short Get_Short( sal_uInt8 *& p )
767 {
768 return Get_UShort(p);
769 }
770
Get_ULong(sal_uInt8 * & p)771 inline sal_uLong Get_ULong( sal_uInt8 *& p )
772 {
773 sal_uLong n = SVBT32ToUInt32( *(SVBT32*)p );
774 p += 4;
775 return n;
776 }
777
Get_Long(sal_uInt8 * & p)778 inline long Get_Long( sal_uInt8 *& p )
779 {
780 return Get_ULong(p);
781 }
782
WW8SprmIter(const sal_uInt8 * pSprms_,long nLen_,const wwSprmParser & rParser)783 WW8SprmIter::WW8SprmIter(const sal_uInt8* pSprms_, long nLen_,
784 const wwSprmParser &rParser)
785 : mrSprmParser(rParser), pSprms( pSprms_), nRemLen( nLen_)
786 {
787 UpdateMyMembers();
788 }
789
SetSprms(const sal_uInt8 * pSprms_,long nLen_)790 void WW8SprmIter::SetSprms(const sal_uInt8* pSprms_, long nLen_)
791 {
792 pSprms = pSprms_;
793 nRemLen = nLen_;
794 UpdateMyMembers();
795 }
796
operator ++(int)797 const sal_uInt8* WW8SprmIter::operator ++( int )
798 {
799 if (nRemLen > 0)
800 {
801 pSprms += nAktSize;
802 nRemLen -= nAktSize;
803 UpdateMyMembers();
804 }
805 return pSprms;
806 }
807
UpdateMyMembers()808 void WW8SprmIter::UpdateMyMembers()
809 {
810 if (pSprms && nRemLen > 0)
811 {
812 nAktId = mrSprmParser.GetSprmId(pSprms);
813 pAktParams = pSprms + mrSprmParser.DistanceToData(nAktId);
814 nAktSize = mrSprmParser.GetSprmSize(nAktId, pSprms);
815 }
816 else
817 {
818 nAktId = 0;
819 pAktParams = 0;
820 nAktSize = 0;
821 nRemLen = 0;
822 }
823 }
824
FindSprm(sal_uInt16 nId)825 const sal_uInt8* WW8SprmIter::FindSprm(sal_uInt16 nId)
826 {
827 while(GetSprms())
828 {
829 if( GetAktId() == nId )
830 return GetAktParams(); // SPRM found!
831 operator ++(0);
832 }
833
834 return 0; // SPRM _not_ found
835 }
836
837 //-----------------------------------------
838 // temporaerer Test
839 //-----------------------------------------
840 // WW8PLCFx_PCDAttrs halten sich an WW8PLCF_Pcd fest und besitzen deshalb keine
841 // eigenen Iteratoren. Alle sich auf Iteratoren beziehenden Methoden
842 // sind deshalb Dummies.
843
WW8PLCFx_PCDAttrs(sal_uInt8 nVersion,WW8PLCFx_PCD * pPLCFx_PCD,const WW8ScannerBase * pBase)844 WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(sal_uInt8 nVersion, WW8PLCFx_PCD* pPLCFx_PCD,
845 const WW8ScannerBase* pBase)
846 : WW8PLCFx(nVersion, true), pPcdI(pPLCFx_PCD->GetPLCFIter()),
847 pPcd(pPLCFx_PCD), pGrpprls(pBase->pPieceGrpprls),
848 nGrpprls(pBase->nPieceGrpprls)
849 {
850 }
851
GetIdx() const852 sal_uLong WW8PLCFx_PCDAttrs::GetIdx() const
853 {
854 return 0;
855 }
856
SetIdx(sal_uLong)857 void WW8PLCFx_PCDAttrs::SetIdx( sal_uLong )
858 {
859 }
860
SeekPos(WW8_CP)861 bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP )
862 {
863 return true;
864 }
865
operator ++(int)866 WW8PLCFx& WW8PLCFx_PCDAttrs::operator ++( int )
867 {
868 return *this;
869 }
870
Where()871 WW8_CP WW8PLCFx_PCDAttrs::Where()
872 {
873 return ( pPcd ) ? pPcd->Where() : LONG_MAX;
874 }
875
GetSprms(WW8PLCFxDesc * p)876 void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc* p)
877 {
878 void* pData;
879
880 p->bRealLineEnd = false;
881 if ( !pPcdI || !pPcdI->Get(p->nStartPos, p->nEndPos, pData) )
882 {
883 // PLCF fully processed
884 p->nStartPos = p->nEndPos = LONG_MAX;
885 p->pMemPos = 0;
886 p->nSprmsLen = 0;
887 return;
888 }
889
890 sal_uInt16 nPrm = SVBT16ToShort( ( (WW8_PCD*)pData )->prm );
891 if ( nPrm & 1 )
892 {
893 // PRM Variant 2
894 sal_uInt16 nSprmIdx = nPrm >> 1;
895
896 if( nSprmIdx >= nGrpprls )
897 {
898 // Invalid Index
899 p->nStartPos = p->nEndPos = LONG_MAX;
900 p->pMemPos = 0;
901 p->nSprmsLen = 0;
902 return;
903 }
904 const sal_uInt8* pSprms = pGrpprls[ nSprmIdx ];
905
906 p->nSprmsLen = SVBT16ToShort( pSprms ); // Length
907 pSprms += 2;
908 p->pMemPos = pSprms; // Position
909 }
910 else
911 {
912 // PRM Variante 1: Sprm wird direkt in Member-Var abgelegt
913 /*
914 Dies sind die Attr, die in der Piece-Table stehen, statt im Text !
915 */
916
917 if(8 > GetVersion())
918 {
919 aShortSprm[0] = (sal_uInt8)( ( nPrm & 0xfe) >> 1 );
920 aShortSprm[1] = (sal_uInt8)( nPrm >> 8 );
921 p->nSprmsLen = ( nPrm ) ? 2 : 0; // Laenge
922
923 // store Postion of internal mini storage in Data Pointer
924 p->pMemPos = aShortSprm;
925 }
926 else
927 {
928 p->pMemPos = 0;
929 p->nSprmsLen = 0;
930 sal_uInt8 nSprmListIdx = (sal_uInt8)((nPrm & 0xfe) >> 1);
931 if( nSprmListIdx )
932 {
933 // process Sprm Id Matching as explained in MS Doku
934 //
935 // ''Property Modifier(variant 1) (PRM)''
936 // see file: s62f39.htm
937 //
938 // Since isprm is 7 bits, rgsprmPrm can hold 0x80 entries.
939 static const sal_uInt16 aSprmId[0x80] =
940 {
941 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
942 0x0000,0x0000,0x0000,0x0000,
943 // sprmPIncLvl, sprmPJc, sprmPFSideBySide, sprmPFKeep
944 0x2402,0x2403,0x2404,0x2405,
945 // sprmPFKeepFollow, sprmPFPageBreakBefore, sprmPBrcl,
946 // sprmPBrcp
947 0x2406,0x2407,0x2408,0x2409,
948 // sprmPIlvl, sprmNoop, sprmPFNoLineNumb, sprmNoop
949 0x260A,0x0000,0x240C,0x0000,
950 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
951 0x0000,0x0000,0x0000,0x0000,
952 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
953 0x0000,0x0000,0x0000,0x0000,
954 // sprmPFInTable, sprmPFTtp, sprmNoop, sprmNoop
955 0x2416,0x2417,0x0000,0x0000,
956 // sprmNoop, sprmPPc, sprmNoop, sprmNoop
957 0x0000,0x261B,0x0000,0x0000,
958 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
959 0x0000,0x0000,0x0000,0x0000,
960 // sprmNoop, sprmPWr, sprmNoop, sprmNoop
961 0x0000,0x2423,0x0000,0x0000,
962 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
963 0x0000,0x0000,0x0000,0x0000,
964 // sprmPFNoAutoHyph, sprmNoop, sprmNoop, sprmNoop
965 0x242A,0x0000,0x0000,0x0000,
966 // sprmNoop, sprmNoop, sprmPFLocked, sprmPFWidowControl
967 0x0000,0x0000,0x2430,0x2431,
968 // sprmNoop, sprmPFKinsoku, sprmPFWordWrap,
969 // sprmPFOverflowPunct
970 0x0000,0x2433,0x2434,0x2435,
971 // sprmPFTopLinePunct, sprmPFAutoSpaceDE,
972 // sprmPFAutoSpaceDN, sprmNoop
973 0x2436,0x2437,0x2438,0x0000,
974 // sprmNoop, sprmPISnapBaseLine, sprmNoop, sprmNoop
975 0x0000,0x243B,0x000,0x0000,
976 // sprmNoop, sprmCFStrikeRM, sprmCFRMark, sprmCFFldVanish
977 0x0000,0x0800,0x0801,0x0802,
978 // sprmNoop, sprmNoop, sprmNoop, sprmCFData
979 0x0000,0x0000,0x0000,0x0806,
980 // sprmNoop, sprmNoop, sprmNoop, sprmCFOle2
981 0x0000,0x0000,0x0000,0x080A,
982 // sprmNoop, sprmCHighlight, sprmCFEmboss, sprmCSfxText
983 0x0000,0x2A0C,0x0858,0x2859,
984 // sprmNoop, sprmNoop, sprmNoop, sprmCPlain
985 0x0000,0x0000,0x0000,0x2A33,
986 // sprmNoop, sprmCFBold, sprmCFItalic, sprmCFStrike
987 0x0000,0x0835,0x0836,0x0837,
988 // sprmCFOutline, sprmCFShadow, sprmCFSmallCaps, sprmCFCaps,
989 0x0838,0x0839,0x083a,0x083b,
990 // sprmCFVanish, sprmNoop, sprmCKul, sprmNoop,
991 0x083C,0x0000,0x2A3E,0x0000,
992 // sprmNoop, sprmNoop, sprmCIco, sprmNoop,
993 0x0000,0x0000,0x2A42,0x0000,
994 // sprmCHpsInc, sprmNoop, sprmCHpsPosAdj, sprmNoop,
995 0x2A44,0x0000,0x2A46,0x0000,
996 // sprmCIss, sprmNoop, sprmNoop, sprmNoop,
997 0x2A48,0x0000,0x0000,0x0000,
998 // sprmNoop, sprmNoop, sprmNoop, sprmNoop,
999 0x0000,0x0000,0x0000,0x0000,
1000 // sprmNoop, sprmNoop, sprmNoop, sprmCFDStrike,
1001 0x0000,0x0000,0x0000,0x2A53,
1002 // sprmCFImprint, sprmCFSpec, sprmCFObj, sprmPicBrcl,
1003 0x0854,0x0855,0x0856,0x2E00,
1004 // sprmPOutLvl, sprmPFBiDi, sprmNoop, sprmNoop,
1005 0x2640,0x2441,0x0000,0x0000,
1006 // sprmNoop, sprmNoop, sprmPPnbrRMarkNot
1007 0x0000,0x0000,0x0000,0x0000
1008 };
1009
1010 // find real Sprm Id:
1011 sal_uInt16 nSprmId = aSprmId[ nSprmListIdx ];
1012
1013 if( nSprmId )
1014 {
1015 // move Sprm Id and Sprm Param to internal mini storage:
1016 aShortSprm[0] = (sal_uInt8)( ( nSprmId & 0x00ff) );
1017 aShortSprm[1] = (sal_uInt8)( ( nSprmId & 0xff00) >> 8 );
1018 aShortSprm[2] = (sal_uInt8)( nPrm >> 8 );
1019
1020 // store Sprm Length in member:
1021 p->nSprmsLen = ( nPrm ) ? 3 : 0;
1022
1023 // store Postion of internal mini storage in Data Pointer
1024 p->pMemPos = aShortSprm;
1025 }
1026 }
1027 }
1028 }
1029 }
1030
1031 //------------------------------------------------------------------------
1032
WW8PLCFx_PCD(sal_uInt8 nVersion,WW8PLCFpcd * pPLCFpcd,WW8_CP nStartCp,bool bVer67P)1033 WW8PLCFx_PCD::WW8PLCFx_PCD(sal_uInt8 nVersion, WW8PLCFpcd* pPLCFpcd,
1034 WW8_CP nStartCp, bool bVer67P)
1035 : WW8PLCFx(nVersion, false), nClipStart(-1)
1036 {
1037 // eigenen Iterator konstruieren
1038 pPcdI = new WW8PLCFpcd_Iter(*pPLCFpcd, nStartCp);
1039 bVer67= bVer67P;
1040 }
1041
~WW8PLCFx_PCD()1042 WW8PLCFx_PCD::~WW8PLCFx_PCD()
1043 {
1044 // pPcd-Dtor which in called from WW8ScannerBase
1045 delete pPcdI;
1046 }
1047
GetIMax() const1048 sal_uLong WW8PLCFx_PCD::GetIMax() const
1049 {
1050 return pPcdI ? pPcdI->GetIMax() : 0;
1051 }
1052
GetIdx() const1053 sal_uLong WW8PLCFx_PCD::GetIdx() const
1054 {
1055 return pPcdI ? pPcdI->GetIdx() : 0;
1056 }
1057
SetIdx(sal_uLong nIdx)1058 void WW8PLCFx_PCD::SetIdx( sal_uLong nIdx )
1059 {
1060 if (pPcdI)
1061 pPcdI->SetIdx( nIdx );
1062 }
1063
SeekPos(WW8_CP nCpPos)1064 bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos)
1065 {
1066 return pPcdI ? pPcdI->SeekPos( nCpPos ) : false;
1067 }
1068
Where()1069 WW8_CP WW8PLCFx_PCD::Where()
1070 {
1071 return pPcdI ? pPcdI->Where() : LONG_MAX;
1072 }
1073
GetNoSprms(long & rStart,long & rEnd,long & rLen)1074 long WW8PLCFx_PCD::GetNoSprms( long& rStart, long& rEnd, long& rLen )
1075 {
1076 void* pData;
1077 rLen = 0;
1078
1079 if ( !pPcdI || !pPcdI->Get(rStart, rEnd, pData) )
1080 {
1081 rStart = rEnd = LONG_MAX;
1082 return -1;
1083 }
1084 return pPcdI->GetIdx();
1085 }
1086
operator ++(int)1087 WW8PLCFx& WW8PLCFx_PCD::operator ++( int )
1088 {
1089 if (pPcdI)
1090 (*pPcdI)++;
1091 else
1092 ASSERT( !this, "pPcdI fehlt");
1093 return *this;
1094 }
1095
AktPieceStartCp2Fc(WW8_CP nCp)1096 WW8_FC WW8PLCFx_PCD::AktPieceStartCp2Fc( WW8_CP nCp )
1097 {
1098 WW8_CP nCpStart, nCpEnd;
1099 void* pData;
1100
1101 if ( !pPcdI->Get(nCpStart, nCpEnd, pData) )
1102 {
1103 ASSERT( !this, "AktPieceStartCp2Fc() with false Cp found (1)" );
1104 return LONG_MAX;
1105 }
1106
1107 ASSERT( nCp >= nCpStart && nCp < nCpEnd,
1108 "AktPieceCp2Fc() with false Cp found (2)" );
1109
1110 if( nCp < nCpStart )
1111 nCp = nCpStart;
1112 if( nCp >= nCpEnd )
1113 nCp = nCpEnd - 1;
1114
1115 bool bIsUnicode = false;
1116 WW8_FC nFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1117 if( !bVer67 )
1118 nFC = WW8PLCFx_PCD::TransformPieceAddress( nFC, bIsUnicode );
1119
1120 return nFC + (nCp - nCpStart) * (bIsUnicode ? 2 : 1);
1121 }
1122
1123
AktPieceFc2Cp(long & rStartPos,long & rEndPos,const WW8ScannerBase * pSBase)1124 void WW8PLCFx_PCD::AktPieceFc2Cp( long& rStartPos, long& rEndPos,
1125 const WW8ScannerBase *pSBase )
1126 {
1127 //No point going anywhere with this
1128 if ((rStartPos == LONG_MAX) && (rEndPos == LONG_MAX))
1129 return;
1130
1131 rStartPos = pSBase->WW8Fc2Cp( rStartPos );
1132 rEndPos = pSBase->WW8Fc2Cp( rEndPos );
1133 }
1134
AktPieceStartFc2Cp(WW8_FC nStartPos)1135 WW8_CP WW8PLCFx_PCD::AktPieceStartFc2Cp( WW8_FC nStartPos )
1136 {
1137 WW8_CP nCpStart, nCpEnd;
1138 void* pData;
1139 if ( !pPcdI->Get( nCpStart, nCpEnd, pData ) )
1140 {
1141 ASSERT( !this, "AktPieceStartFc2Cp() - Fehler" );
1142 return LONG_MAX;
1143 }
1144 bool bIsUnicode = false;
1145 sal_Int32 nFcStart = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1146 if( !bVer67 )
1147 nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart, bIsUnicode );
1148
1149 sal_Int32 nUnicodeFactor = bIsUnicode ? 2 : 1;
1150
1151 if( nStartPos < nFcStart )
1152 nStartPos = nFcStart;
1153
1154 if( nStartPos >= nFcStart + (nCpEnd - nCpStart) * nUnicodeFactor )
1155 nStartPos = nFcStart + (nCpEnd - nCpStart - 1) * nUnicodeFactor;
1156
1157 return nCpStart + (nStartPos - nFcStart) / nUnicodeFactor;
1158 }
1159
1160 //-----------------------------------------
1161 // Hilfsroutinen fuer alle
1162 //-----------------------------------------
1163
WW8DTTM2DateTime(long lDTTM)1164 DateTime WW8ScannerBase::WW8DTTM2DateTime(long lDTTM)
1165 {
1166 /*
1167 mint short :6 0000003F minutes (0-59)
1168 hr short :5 000007C0 hours (0-23)
1169 dom short :5 0000F800 days of month (1-31)
1170 mon short :4 000F0000 months (1-12)
1171 yr short :9 1FF00000 years (1900-2411)-1900
1172 wdy short :3 E0000000 weekday(Sunday=0
1173 Monday=1
1174 ( wdy can be ignored ) Tuesday=2
1175 Wednesday=3
1176 Thursday=4
1177 Friday=5
1178 Saturday=6)
1179 */
1180 DateTime aDateTime(Date( 0 ), Time( 0 ));
1181 if( lDTTM )
1182 {
1183 sal_uInt16 lMin = (sal_uInt16)(lDTTM & 0x0000003F);
1184 lDTTM >>= 6;
1185 sal_uInt16 lHour= (sal_uInt16)(lDTTM & 0x0000001F);
1186 lDTTM >>= 5;
1187 sal_uInt16 lDay = (sal_uInt16)(lDTTM & 0x0000001F);
1188 lDTTM >>= 5;
1189 sal_uInt16 lMon = (sal_uInt16)(lDTTM & 0x0000000F);
1190 lDTTM >>= 4;
1191 sal_uInt16 lYear= (sal_uInt16)(lDTTM & 0x000001FF) + 1900;
1192 aDateTime = DateTime(Date(lDay, lMon, lYear), Time(lHour, lMin));
1193 }
1194 return aDateTime;
1195 }
1196
DetermineBorderProperties(bool bVer67,short * pSpace,sal_uInt8 * pCol,short * pIdx) const1197 short WW8_BRC::DetermineBorderProperties(bool bVer67, short *pSpace,
1198 sal_uInt8 *pCol, short *pIdx) const
1199 {
1200 /*
1201 Word does not factor the width of the border into the width/height
1202 stored in the information for graphic/table/object widths, so we need
1203 to figure out this extra width here and utilize the returned size in
1204 our calculations
1205 */
1206 short nMSTotalWidth;
1207 sal_uInt8 nCol;
1208 short nIdx,nSpace;
1209 if( bVer67 )
1210 {
1211 sal_uInt16 aBrc1 = SVBT16ToShort(aBits1);
1212 nCol = ((aBrc1 >> 6) & 0x1f); // aBor.ico
1213 nSpace = (aBrc1 & 0xF800) >> 11;
1214
1215 nMSTotalWidth = aBrc1 & 0x07;
1216 nIdx = (aBrc1 & 0x18) >> 3;
1217 //Dashed/Dotted unsets double/thick
1218 if (nMSTotalWidth > 5)
1219 {
1220 nMSTotalWidth=1;
1221 nIdx = 1;
1222 }
1223 nMSTotalWidth *= nIdx;
1224 nMSTotalWidth *= 15;
1225 }
1226 else
1227 {
1228 nIdx = aBits1[1];
1229 nCol = aBits2[0]; // aBor.ico
1230 nSpace = aBits2[1] & 0x1F; //space between line and object
1231
1232 //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5
1233 nMSTotalWidth = aBits1[ 0 ] * 20 / 8;
1234
1235 //Figure out the real size of the border according to word
1236 switch (nIdx)
1237 {
1238 //Note that codes over 25 are undocumented, and I can't create
1239 //these 4 here in the wild.
1240 default:
1241 case 2:
1242 case 4:
1243 case 5:
1244 case 22:
1245 DBG_WARNING("Can't create these from the menus, please report");
1246 case 1:
1247 case 6:
1248 case 7:
1249 case 8:
1250 case 9:
1251 case 23: //Only 3pt in the menus, but honours the size setting.
1252 break;
1253 case 3:
1254 /*
1255 double line is three times the width of an ordinary line,
1256 except for the smallest 1/4 point size which appears to have
1257 exactly the same total border width as a 1/2 point size
1258 ordinary line, i.e. twice the nominal line width
1259 */
1260 nMSTotalWidth = (nMSTotalWidth == 5) ?
1261 nMSTotalWidth*2 : nMSTotalWidth*3;
1262 break;
1263 case 10:
1264 /*
1265 triple line is five times the width of an ordinary line,
1266 except that the smallest 1/4 point size appears to have
1267 exactly the same total border width as a 3/4 point size
1268 ordinary line, i.e. three times the nominal line width. The
1269 second smallest 1/2 point size appears to have exactly the
1270 total border width as a 2 1/4 border, i.e 4.5 times the size.
1271 */
1272 if (nMSTotalWidth == 5)
1273 nMSTotalWidth*=3;
1274 else if (nMSTotalWidth == 10)
1275 nMSTotalWidth = nMSTotalWidth*9/2;
1276 else
1277 nMSTotalWidth*=5;
1278 break;
1279 case 11:
1280 case 12:
1281 /*
1282 small gap thin thick and thick thin appears to have a 3/4
1283 point line, a 3/4 point gap and a thick line of the specified
1284 width
1285 */
1286 nMSTotalWidth = nMSTotalWidth + 15*2;
1287 break;
1288 case 13:
1289 /*
1290 thin thick thin appears to have two outside 3/4 point lines,
1291 two 3/4 point gaps and a thick line of the specified width
1292 */
1293 nMSTotalWidth = nMSTotalWidth + 15*4;
1294 break;
1295 case 14:
1296 case 15:
1297 /*
1298 medium gap thin thick and thick thin appears to have a line
1299 50% of the thick line, and an equal sized gap and then the
1300 thick line of the specified width. But it appears to only
1301 use one of the existing predefined widths for the thin line,
1302 so the closest smallest existing border to the halved thick
1303 line is used.
1304 */
1305 switch (nMSTotalWidth)
1306 {
1307 case 45: //2 1/4, closest to half is 1
1308 nMSTotalWidth += 20 + (nMSTotalWidth-1)/2;
1309 break;
1310 case 5:
1311 case 10:
1312 nMSTotalWidth += 5;
1313 break;
1314 case 15: //3/4, closest to half is 1/4
1315 nMSTotalWidth += 5 + (nMSTotalWidth-1)/2;
1316 break;
1317 default:
1318 nMSTotalWidth*=2;
1319 break;
1320 }
1321 break;
1322 case 16:
1323 /*
1324 medium gap thin thick thin appears to have a line
1325 50% of the thick line, and an equal sized gap and then the
1326 thick line of the specified width. But it appears to only
1327 use one of the existing predefined widths for the thin
1328 line, so the closest smallest existing border to the halved
1329 thick line is used. Though some fudging at smaller sizes is
1330 still required.
1331 */
1332 switch (nMSTotalWidth)
1333 {
1334 case 45: //2 1/4, closest to half is 1
1335 nMSTotalWidth += nMSTotalWidth + 20 * 2;
1336 break;
1337 case 20:
1338 case 15:
1339 nMSTotalWidth += nMSTotalWidth + 7 * 2;
1340 break;
1341 case 10:
1342 case 5:
1343 nMSTotalWidth += 5 + 4;
1344 break;
1345 default:
1346 nMSTotalWidth*=3;
1347 break;
1348 }
1349 break;
1350 case 17:
1351 case 18:
1352 /*
1353 large gap thin thick and thick thin appears to have a thick
1354 line of 1 1/2 pt and a narrow of 3/4 point, with a distance
1355 between the two of the explicitly set line width
1356 */
1357 nMSTotalWidth+=15+30;
1358 break;
1359 case 19:
1360 /*
1361 large gap thin thick thin appears to have a thick line of 1
1362 1/2 pt and two narrows of 3/4 point, with a distance between
1363 the two of the explicitly set line width, though the narrowest
1364 line appears to behave as if it was even smaller
1365 */
1366 if (nMSTotalWidth == 5)
1367 nMSTotalWidth = 3;
1368 nMSTotalWidth = nMSTotalWidth*2 + 15*2 + 30;
1369 break;
1370 case 20:
1371 /*
1372 wave, the dimensions appear to be created by the drawing of
1373 the wave, so we have only two possibilites in the menus, 3/4
1374 point is equal to solid 3 point. This calculation seems to
1375 match well to results.
1376 */
1377 nMSTotalWidth +=45;
1378 break;
1379 case 21:
1380 /*
1381 double wave, the dimensions appear to be created by the
1382 drawing of the wave, so we have only one possibilites in the
1383 menus, that of 3/4 point is equal to solid 3 point. This
1384 calculation seems to match well to results.
1385 */
1386 nMSTotalWidth += 45*2;
1387 break;
1388 case 24:
1389 case 25:
1390 /*
1391 emboss and engrave consist of a three lines, the central is of
1392 the explicit point width, the other two (of equal size to each
1393 other are the shadows and are either 3/4 pt of 1 1/2 depending
1394 on if the central line is greater of less than 2 1/4 pt
1395 */
1396 if (nMSTotalWidth <= 45)
1397 nMSTotalWidth += 2*15;
1398 else
1399 nMSTotalWidth += 2*30;
1400 break;
1401 }
1402 }
1403
1404 if (pIdx)
1405 *pIdx = nIdx;
1406 if (pSpace)
1407 *pSpace = nSpace*20;
1408 if (pCol)
1409 *pCol = nCol;
1410 return nMSTotalWidth;
1411 }
1412
WW8Fc2Cp(WW8_FC nFcPos) const1413 WW8_CP WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos ) const
1414 {
1415 WW8_CP nFallBackCpEnd = LONG_MAX;
1416 if( nFcPos == LONG_MAX )
1417 return nFallBackCpEnd;
1418
1419 bool bIsUnicode = false;
1420 if( pPieceIter ) // Complex File ?
1421 {
1422 sal_uLong nOldPos = pPieceIter->GetIdx();
1423
1424 for (pPieceIter->SetIdx(0);
1425 pPieceIter->GetIdx() < pPieceIter->GetIMax();(*pPieceIter)++)
1426 {
1427 long nCpStart, nCpEnd;
1428 void* pData;
1429 if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
1430 { // ausserhalb PLCFfpcd ?
1431 ASSERT( !this, "PLCFpcd-WW8Fc2Cp() ging schief" );
1432 break;
1433 }
1434 sal_Int32 nFcStart = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1435 if( 8 <= pWw8Fib->nVersion )
1436 nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart,
1437 bIsUnicode );
1438 sal_Int32 nLen = (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1);
1439
1440 /*
1441 If this cp is inside this piece, or its the last piece and we are
1442 on the very last cp of that piece
1443 */
1444 if (nFcPos >= nFcStart)
1445 {
1446 // found
1447 WW8_CP nTempCp =
1448 nCpStart + ((nFcPos - nFcStart) / (bIsUnicode ? 2 : 1));
1449 if (nFcPos < nFcStart + nLen)
1450 {
1451 pPieceIter->SetIdx( nOldPos );
1452 return nTempCp;
1453 }
1454 else if (nFcPos == nFcStart + nLen)
1455 {
1456 //Keep this cp as its on a piece boundary because we might
1457 //need it if tests fail
1458 nFallBackCpEnd = nTempCp;
1459 }
1460 }
1461 }
1462 // not found
1463 pPieceIter->SetIdx( nOldPos ); // not found
1464 /*
1465 If it was not found, then this is because it has fallen between two
1466 stools, i.e. either it is the last cp/fc of the last piece, or it is
1467 the last cp/fc of a disjoint piece.
1468 */
1469 return nFallBackCpEnd;
1470 }
1471 // No complex file
1472 if (pWw8Fib->fExtChar)
1473 bIsUnicode=true;
1474 return ((nFcPos - pWw8Fib->fcMin) / (bIsUnicode ? 2 : 1));
1475 }
1476
WW8Cp2Fc(WW8_CP nCpPos,bool * pIsUnicode,WW8_CP * pNextPieceCp,bool * pTestFlag) const1477 WW8_FC WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos, bool* pIsUnicode,
1478 WW8_CP* pNextPieceCp, bool* pTestFlag) const
1479 {
1480 if( pTestFlag )
1481 *pTestFlag = true;
1482 if( LONG_MAX == nCpPos )
1483 return LONG_MAX;
1484
1485 bool bIsUnicode;
1486 if( !pIsUnicode )
1487 pIsUnicode = &bIsUnicode;
1488
1489 if( pPieceIter )
1490 { // Complex File
1491 if( pNextPieceCp )
1492 *pNextPieceCp = LONG_MAX;
1493
1494 if( !pPieceIter->SeekPos( nCpPos ) )
1495 {
1496 if( pTestFlag )
1497 *pTestFlag = false;
1498 else
1499 ASSERT( !this, "Falscher CP an WW8Cp2Fc() uebergeben" );
1500 return LONG_MAX;
1501 }
1502 long nCpStart, nCpEnd;
1503 void* pData;
1504 if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
1505 {
1506 if( pTestFlag )
1507 *pTestFlag = false;
1508 else
1509 ASSERT( !this, "PLCFfpcd-Get ging schief" );
1510 return LONG_MAX;
1511 }
1512 if( pNextPieceCp )
1513 *pNextPieceCp = nCpEnd;
1514
1515 WW8_FC nRet = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1516 if (8 > pWw8Fib->nVersion)
1517 *pIsUnicode = false;
1518 else
1519 nRet = WW8PLCFx_PCD::TransformPieceAddress( nRet, *pIsUnicode );
1520
1521
1522 nRet += (nCpPos - nCpStart) * (*pIsUnicode ? 2 : 1);
1523
1524 return nRet;
1525 }
1526
1527 // No complex file
1528 if (pWw8Fib->fExtChar)
1529 *pIsUnicode = true;
1530 else
1531 *pIsUnicode = false;
1532 return pWw8Fib->fcMin + nCpPos * (*pIsUnicode ? 2 : 1);
1533 }
1534
1535 //-----------------------------------------
1536 // class WW8ScannerBase
1537 //-----------------------------------------
1538
OpenPieceTable(SvStream * pStr,const WW8Fib * pWwF)1539 WW8PLCFpcd* WW8ScannerBase::OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF )
1540 {
1541 if ( ((8 > pWw8Fib->nVersion) && !pWwF->fComplex) || !pWwF->lcbClx )
1542 return 0;
1543
1544 WW8_FC nClxPos = pWwF->fcClx;
1545 sal_Int32 nClxLen = pWwF->lcbClx;
1546 sal_Int32 nLeft = nClxLen;
1547 sal_Int16 nGrpprl = 0;
1548 sal_uInt8 clxt;
1549
1550 pStr->Seek( nClxPos );
1551 while( nGrpprl < SAL_MAX_INT16 ) // Zaehle Zahl der Grpprls
1552 {
1553 *pStr >> clxt;
1554 nLeft--;
1555 if( 2 == clxt ) // PLCFfpcd ?
1556 break; // PLCFfpcd gefunden
1557 if( 1 == clxt ) // clxtGrpprl ?
1558 nGrpprl++;
1559 sal_uInt16 nLen;
1560 *pStr >> nLen;
1561 nLeft -= 2 + nLen;
1562 if( nLeft < 0 )
1563 return 0; // schiefgegangen
1564 pStr->SeekRel( nLen ); // ueberlies grpprl
1565 }
1566 if ( nGrpprl == SAL_MAX_INT16 )
1567 return 0;
1568 pStr->Seek( nClxPos );
1569 nLeft = nClxLen;
1570 pPieceGrpprls = new sal_uInt8*[nGrpprl + 1];
1571 memset( pPieceGrpprls, 0, ( nGrpprl + 1 ) * 4 );
1572 nPieceGrpprls = nGrpprl;
1573 sal_Int16 nAktGrpprl = 0; // lies Grpprls ein
1574 while( 1 )
1575 {
1576 *pStr >> clxt;
1577 nLeft--;
1578 if( 2 == clxt) // PLCFfpcd ?
1579 break; // PLCFfpcd gefunden
1580 sal_uInt16 nLen;
1581 *pStr >> nLen;
1582 nLeft -= 2 + nLen;
1583 if( nLeft < 0 )
1584 return 0; // schiefgegangen
1585 if( 1 == clxt ) // clxtGrpprl ?
1586 {
1587 sal_uInt8* p = new sal_uInt8[nLen+2]; // alloziere
1588 ShortToSVBT16(nLen, p); // trage Laenge ein
1589 pStr->Read( p+2, nLen ); // lies grpprl
1590 pPieceGrpprls[nAktGrpprl++] = p; // trage in Array ein
1591 }
1592 else
1593 pStr->SeekRel( nLen ); // ueberlies nicht-Grpprl
1594 }
1595 // lies Piece Table PLCF ein
1596 sal_Int32 nPLCFfLen;
1597 *pStr >> nPLCFfLen;
1598 ASSERT( 65536 > nPLCFfLen, "PLCFfpcd ueber 64 k" );
1599 return new WW8PLCFpcd( pStr, pStr->Tell(), nPLCFfLen, 8 );
1600 }
1601
DeletePieceTable()1602 void WW8ScannerBase::DeletePieceTable()
1603 {
1604 if( pPieceGrpprls )
1605 {
1606 for( sal_uInt8** p = pPieceGrpprls; *p; p++ )
1607 delete[] (*p);
1608 delete[] pPieceGrpprls;
1609 pPieceGrpprls = 0;
1610 }
1611 }
1612
WW8ScannerBase(SvStream * pSt,SvStream * pTblSt,SvStream * pDataSt,const WW8Fib * pWwFib)1613 WW8ScannerBase::WW8ScannerBase( SvStream* pSt, SvStream* pTblSt,
1614 SvStream* pDataSt, const WW8Fib* pWwFib )
1615 : pWw8Fib(pWwFib), pMainFdoa(0), pHdFtFdoa(0), pMainTxbx(0),
1616 pMainTxbxBkd(0), pHdFtTxbx(0), pHdFtTxbxBkd(0), pMagicTables(0),
1617 pPieceGrpprls(0)
1618 {
1619 pPiecePLCF = OpenPieceTable( pTblSt, pWw8Fib ); // Complex
1620 if( pPiecePLCF )
1621 {
1622 pPieceIter = new WW8PLCFpcd_Iter( *pPiecePLCF );
1623 pPLCFx_PCD = new WW8PLCFx_PCD( pWwFib->nVersion, pPiecePLCF, 0,
1624 8 > pWw8Fib->nVersion );
1625 pPLCFx_PCDAttrs = new WW8PLCFx_PCDAttrs( pWwFib->nVersion, pPLCFx_PCD,
1626 this);
1627 }
1628 else
1629 {
1630 pPieceIter = 0;
1631 pPLCFx_PCD = 0;
1632 pPLCFx_PCDAttrs = 0;
1633 }
1634
1635 // pChpPLCF and pPapPLCF may NOT be created before pPLCFx_PCD !!
1636 pChpPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, CHP ); // CHPX
1637 pPapPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, PAP ); // PAPX
1638
1639 pSepPLCF = new WW8PLCFx_SEPX( pSt, pTblSt, *pWwFib, 0 ); // SEPX
1640
1641 // Footnotes
1642 pFtnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0,
1643 pWwFib->fcPlcffndRef, pWwFib->lcbPlcffndRef, pWwFib->fcPlcffndTxt,
1644 pWwFib->lcbPlcffndTxt, 2 );
1645 // Endnotes
1646 pEdnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0,
1647 pWwFib->fcPlcfendRef, pWwFib->lcbPlcfendRef, pWwFib->fcPlcfendTxt,
1648 pWwFib->lcbPlcfendTxt, 2 );
1649 // Anmerkungen
1650 pAndPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0,
1651 pWwFib->fcPlcfandRef, pWwFib->lcbPlcfandRef, pWwFib->fcPlcfandTxt,
1652 pWwFib->lcbPlcfandTxt, (8 > pWwFib->nVersion) ? 20 : 30 );
1653
1654 // Fields Main Text
1655 pFldPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_MAINTEXT);
1656 // Fields Header / Footer
1657 pFldHdFtPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_HDFT);
1658 // Fields Footnote
1659 pFldFtnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_FTN);
1660 // Fields Endnote
1661 pFldEdnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_EDN);
1662 // Fields Anmerkungen
1663 pFldAndPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_AND);
1664 // Fields in Textboxes in Main Text
1665 pFldTxbxPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_TXBX);
1666 // Fields in Textboxes in Header / Footer
1667 pFldTxbxHdFtPLCF = new WW8PLCFx_FLD(pTblSt,*pWwFib,MAN_TXBX_HDFT);
1668
1669 // Note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
1670 switch( pWw8Fib->nVersion )
1671 {
1672 case 6:
1673 case 7:
1674 if( pWwFib->fcPlcfdoaMom && pWwFib->lcbPlcfdoaMom )
1675 {
1676 pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaMom,
1677 pWwFib->lcbPlcfdoaMom, 6 );
1678 }
1679 if( pWwFib->fcPlcfdoaHdr && pWwFib->lcbPlcfdoaHdr )
1680 {
1681 pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaHdr,
1682 pWwFib->lcbPlcfdoaHdr, 6 );
1683 }
1684 break;
1685 case 8:
1686 if( pWwFib->fcPlcfspaMom && pWwFib->lcbPlcfspaMom )
1687 {
1688 pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaMom,
1689 pWwFib->lcbPlcfspaMom, 26 );
1690 }
1691 if( pWwFib->fcPlcfspaHdr && pWwFib->lcbPlcfspaHdr )
1692 {
1693 pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaHdr,
1694 pWwFib->lcbPlcfspaHdr, 26 );
1695 }
1696 // PLCF fuer TextBox-Break-Deskriptoren im Maintext
1697 if( pWwFib->fcPlcftxbxBkd && pWwFib->lcbPlcftxbxBkd )
1698 {
1699 pMainTxbxBkd = new WW8PLCFspecial( pTblSt,
1700 pWwFib->fcPlcftxbxBkd, pWwFib->lcbPlcftxbxBkd, 0);
1701 }
1702 // PLCF fuer TextBox-Break-Deskriptoren im Header-/Footer-Bereich
1703 if( pWwFib->fcPlcfHdrtxbxBkd && pWwFib->lcbPlcfHdrtxbxBkd )
1704 {
1705 pHdFtTxbxBkd = new WW8PLCFspecial( pTblSt,
1706 pWwFib->fcPlcfHdrtxbxBkd, pWwFib->lcbPlcfHdrtxbxBkd, 0);
1707 }
1708 // Sub table cp positions
1709 if (pWwFib->fcMagicTable && pWwFib->lcbMagicTable)
1710 {
1711 pMagicTables = new WW8PLCFspecial( pTblSt,
1712 pWwFib->fcMagicTable, pWwFib->lcbMagicTable, 4);
1713 }
1714 break;
1715 default:
1716 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
1717 break;
1718 }
1719
1720 // PLCF fuer TextBox-Stories im Maintext
1721 long nLenTxBxS = (8 > pWw8Fib->nVersion) ? 0 : 22;
1722 if( pWwFib->fcPlcftxbxTxt && pWwFib->lcbPlcftxbxTxt )
1723 {
1724 pMainTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcftxbxTxt,
1725 pWwFib->lcbPlcftxbxTxt, nLenTxBxS );
1726 }
1727
1728 // PLCF fuer TextBox-Stories im Header-/Footer-Bereich
1729 if( pWwFib->fcPlcfHdrtxbxTxt && pWwFib->lcbPlcfHdrtxbxTxt )
1730 {
1731 pHdFtTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfHdrtxbxTxt,
1732 pWwFib->lcbPlcfHdrtxbxTxt, nLenTxBxS );
1733 }
1734
1735 pBook = new WW8PLCFx_Book(pTblSt, *pWwFib);
1736 }
1737
~WW8ScannerBase()1738 WW8ScannerBase::~WW8ScannerBase()
1739 {
1740 DeletePieceTable();
1741 delete pPLCFx_PCDAttrs;
1742 delete pPLCFx_PCD;
1743 delete pPieceIter;
1744 delete pPiecePLCF;
1745 delete pBook;
1746 delete pFldEdnPLCF;
1747 delete pFldFtnPLCF;
1748 delete pFldAndPLCF;
1749 delete pFldHdFtPLCF;
1750 delete pFldPLCF;
1751 delete pFldTxbxPLCF;
1752 delete pFldTxbxHdFtPLCF;
1753 delete pEdnPLCF;
1754 delete pFtnPLCF;
1755 delete pAndPLCF;
1756 delete pSepPLCF;
1757 delete pPapPLCF;
1758 delete pChpPLCF;
1759 // vergessene Schaeflein
1760 delete pMainFdoa;
1761 delete pHdFtFdoa;
1762 delete pMainTxbx;
1763 delete pMainTxbxBkd;
1764 delete pHdFtTxbx;
1765 delete pHdFtTxbxBkd;
1766 delete pMagicTables;
1767 }
1768
1769 //-----------------------------------------
1770 // Fields
1771 //-----------------------------------------
WW8SkipField(WW8PLCFspecial & rPLCF)1772 static bool WW8SkipField(WW8PLCFspecial& rPLCF)
1773 {
1774 void* pData;
1775 long nP;
1776
1777 if (!rPLCF.Get(nP, pData)) // Ende des PLCFspecial ?
1778 return false;
1779
1780 rPLCF++;
1781
1782 if((((sal_uInt8*)pData)[0] & 0x1f ) != 0x13 ) // Kein Anfang ?
1783 return true; // Bei Fehler nicht abbrechen
1784
1785 if( !rPLCF.Get( nP, pData ) )
1786 return false;
1787
1788
1789 while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1790 {
1791 // immer noch neue (nested) Anfaenge ?
1792 WW8SkipField( rPLCF ); // nested Field im Beschreibungsteil
1793 if( !rPLCF.Get( nP, pData ) )
1794 return false;
1795 }
1796
1797 if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x14 )
1798 {
1799
1800 // Field Separator ?
1801 rPLCF++;
1802
1803 if( !rPLCF.Get( nP, pData ) )
1804 return false;
1805
1806 while ((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13)
1807 {
1808 // immer noch neue (nested) Anfaenge ?
1809 WW8SkipField( rPLCF ); // nested Field im Resultatteil
1810 if( !rPLCF.Get( nP, pData ) )
1811 return false;
1812 }
1813 }
1814 rPLCF++;
1815
1816 return true;
1817 }
1818
WW8GetFieldPara(WW8PLCFspecial & rPLCF,WW8FieldDesc & rF)1819 static bool WW8GetFieldPara(WW8PLCFspecial& rPLCF, WW8FieldDesc& rF)
1820 {
1821 void* pData;
1822 sal_uLong nOldIdx = rPLCF.GetIdx();
1823
1824 rF.nLen = rF.nId = rF.nOpt = rF.bCodeNest = rF.bResNest = 0;
1825
1826 if( !rPLCF.Get( rF.nSCode, pData ) ) // Ende des PLCFspecial ?
1827 goto Err;
1828
1829 rPLCF++;
1830
1831 if((((sal_uInt8*)pData)[0] & 0x1f ) != 0x13 ) // Kein Anfang ?
1832 goto Err;
1833
1834 rF.nId = ((sal_uInt8*)pData)[1];
1835
1836 if( !rPLCF.Get( rF.nLCode, pData ) )
1837 goto Err;
1838
1839 rF.nSRes = rF.nLCode; // Default
1840 rF.nSCode++; // ohne Marken
1841 rF.nLCode -= rF.nSCode; // Pos zu Laenge
1842
1843 while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1844 {
1845 // immer noch neue (nested) Anfaenge ?
1846 WW8SkipField( rPLCF ); // nested Field im Beschreibungsteil
1847 rF.bCodeNest = true;
1848 if( !rPLCF.Get( rF.nSRes, pData ) )
1849 goto Err;
1850 }
1851
1852 if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x14 ){ // Field Separator ?
1853 rPLCF++;
1854
1855 if( !rPLCF.Get( rF.nLRes, pData ) )
1856 goto Err;
1857
1858 while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1859 {
1860 // immer noch neue (nested) Anfaenge ?
1861 WW8SkipField( rPLCF ); // nested Field im Resultatteil
1862 rF.bResNest = true;
1863 if( !rPLCF.Get( rF.nLRes, pData ) )
1864 goto Err;
1865 }
1866 rF.nLen = rF.nLRes - rF.nSCode + 2; // nLRes ist noch die Endposition
1867 rF.nLRes -= rF.nSRes; // nun: nLRes = Laenge
1868 rF.nSRes++; // Endpos encl. Marken
1869 rF.nLRes--;
1870
1871 }else{
1872 rF.nLRes = 0; // Kein Result vorhanden
1873 rF.nLen = rF.nSRes - rF.nSCode + 2; // Gesamtlaenge
1874 }
1875
1876 rPLCF++;
1877 if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x15 )
1878 {
1879 // Field Ende ?
1880 // INDEX-Fld hat Bit7 gesetzt!?!
1881 rF.nOpt = ((sal_uInt8*)pData)[1]; // Ja -> Flags uebernehmen
1882 }else{
1883 rF.nId = 0; // Nein -> Feld ungueltig
1884 }
1885
1886 rPLCF.SetIdx( nOldIdx );
1887 return true;
1888 Err:
1889 rPLCF.SetIdx( nOldIdx );
1890 return false;
1891 }
1892
1893
1894 //-----------------------------------------
1895
1896
1897 // WW8ReadPString liest einen Pascal-String ein und gibt ihn zurueck. Der
1898 // Pascal- String hat am Ende ein \0, der aber im Laengenbyte nicht
1899 // mitgezaehlt wird. Der Speicher fuer den Pascalstring wird alloziert.
WW8ReadPString(SvStream & rStrm,rtl_TextEncoding eEnc,bool bAtEndSeekRel1)1900 String WW8ReadPString(SvStream& rStrm, rtl_TextEncoding eEnc,
1901 bool bAtEndSeekRel1)
1902 {
1903 ByteString aByteStr;
1904 sal_uInt8 b;
1905 rStrm >> b;
1906
1907 if (b)
1908 {
1909 // Alloc methode automatically sets Zero at the end
1910 sal_Char* pByteData = aByteStr.AllocBuffer( b );
1911
1912 sal_uLong nWasRead = rStrm.Read( pByteData, b );
1913 if( nWasRead != b )
1914 aByteStr.ReleaseBufferAccess(static_cast<xub_StrLen>(nWasRead));
1915 }
1916
1917 if( bAtEndSeekRel1 )
1918 rStrm.SeekRel( 1 ); // ueberspringe das Null-Byte am Ende.
1919
1920
1921 return String( aByteStr, eEnc );
1922 }
1923
WW8Read_xstz(SvStream & rStrm,sal_uInt16 nChars,bool bAtEndSeekRel1)1924 String WW8Read_xstz(SvStream& rStrm, sal_uInt16 nChars, bool bAtEndSeekRel1)
1925 {
1926 sal_uInt16 b;
1927
1928 if( nChars )
1929 b = nChars;
1930 else
1931 rStrm >> b;
1932
1933 String aStr;
1934 if (b)
1935 {
1936 // Alloc methode automatically sets Zero at the end
1937 sal_Unicode* pData = aStr.AllocBuffer( b );
1938
1939 sal_uLong nWasRead = rStrm.Read( (sal_Char*)pData, b * 2 );
1940 if( nWasRead != static_cast<sal_uLong>(b*2) )
1941 {
1942 b = static_cast<sal_uInt16>(nWasRead / 2);
1943 aStr.ReleaseBufferAccess( b );
1944 pData = aStr.GetBufferAccess();
1945 }
1946
1947 #ifdef OSL_BIGENDIAN
1948 sal_uLong n;
1949 sal_Unicode *pWork;
1950 for( n = 0, pWork = pData; n < b; ++n, ++pWork )
1951 *pWork = SWAPSHORT( *pWork );
1952 #endif // ifdef OSL_BIGENDIAN
1953 }
1954
1955 if( bAtEndSeekRel1 )
1956 rStrm.SeekRel( 2 ); // ueberspringe das Null-Character am Ende.
1957
1958 return aStr;
1959 }
1960
SafeReadString(ByteString & rStr,sal_uInt16 nLen,SvStream & rStrm)1961 static sal_uLong SafeReadString(ByteString &rStr,sal_uInt16 nLen,SvStream &rStrm)
1962 {
1963 sal_uLong nWasRead=0;
1964 if (nLen)
1965 {
1966 nWasRead = rStrm.Read( rStr.AllocBuffer( nLen ), nLen);
1967 if( nWasRead != nLen )
1968 rStr.ReleaseBufferAccess(static_cast<xub_StrLen>(nWasRead));
1969 }
1970 return nWasRead;
1971 }
1972
WW8ReadString(SvStream & rStrm,String & rStr,WW8_CP nAktStartCp,long nTotalLen,rtl_TextEncoding eEnc) const1973 sal_uInt16 WW8ScannerBase::WW8ReadString( SvStream& rStrm, String& rStr,
1974 WW8_CP nAktStartCp, long nTotalLen, rtl_TextEncoding eEnc ) const
1975 {
1976 // Klartext einlesen, der sich ueber mehrere Pieces erstrecken kann
1977 rStr.Erase();
1978
1979 long nTotalRead = 0;
1980 WW8_CP nBehindTextCp = nAktStartCp + nTotalLen;
1981 WW8_CP nNextPieceCp = nBehindTextCp; // Initialisierung wichtig fuer Ver6
1982 do
1983 {
1984 bool bIsUnicode, bPosOk;
1985 WW8_FC fcAct = WW8Cp2Fc(nAktStartCp,&bIsUnicode,&nNextPieceCp,&bPosOk);
1986
1987 // vermutlich uebers Dateiende hinaus gezielt, macht nix!
1988 if( !bPosOk )
1989 break;
1990
1991 rStrm.Seek( fcAct );
1992
1993 long nLen = ( (nNextPieceCp < nBehindTextCp) ? nNextPieceCp
1994 : nBehindTextCp ) - nAktStartCp;
1995
1996 if( 0 >= nLen )
1997 break;
1998
1999 if( nLen > USHRT_MAX - 1 )
2000 nLen = USHRT_MAX - 1;
2001
2002 if( bIsUnicode )
2003 rStr.Append(WW8Read_xstz(rStrm, (sal_uInt16)nLen, false));
2004 else
2005 {
2006 // Alloc method automatically sets Zero at the end
2007 ByteString aByteStr;
2008 SafeReadString(aByteStr,(sal_uInt16)nLen,rStrm);
2009 rStr += String( aByteStr, eEnc );
2010 }
2011 nTotalRead += nLen;
2012 nAktStartCp += nLen;
2013 if ( nTotalRead != rStr.Len() )
2014 break;
2015 }
2016 while( nTotalRead < nTotalLen );
2017
2018 return rStr.Len();
2019 }
2020
2021 //-----------------------------------------
2022 // WW8PLCFspecial
2023 //-----------------------------------------
2024
2025 // Bei nStartPos < 0 wird das erste Element des PLCFs genommen
WW8PLCFspecial(SvStream * pSt,long nFilePos,long nPLCF,long nStruct,long nStartPos,bool bNoEnd)2026 WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, long nFilePos, long nPLCF,
2027 long nStruct, long nStartPos, bool bNoEnd)
2028 : nIdx(0), nStru(nStruct)
2029 {
2030 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2031 // Pointer auf Pos- u. Struct-Array
2032 pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ];
2033
2034 long nOldPos = pSt->Tell();
2035
2036 pSt->Seek( nFilePos );
2037 pSt->Read( pPLCF_PosArray, nPLCF );
2038 #ifdef OSL_BIGENDIAN
2039 for( nIdx = 0; nIdx <= nIMax; nIdx++ )
2040 pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] );
2041 nIdx = 0;
2042 #endif // OSL_BIGENDIAN
2043 if( bNoEnd )
2044 nIMax++;
2045 if( nStruct ) // Pointer auf Inhalts-Array
2046 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2047 else
2048 pPLCF_Contents = 0; // kein Inhalt
2049 if( nStartPos >= 0 )
2050 SeekPos( nStartPos );
2051
2052 pSt->Seek( nOldPos );
2053 }
2054
2055 // WW8PLCFspecial::SeekPos() stellt den WW8PLCFspecial auf die Stelle nPos, wobei auch noch der
2056 // Eintrag benutzt wird, der vor nPos beginnt und bis hinter nPos reicht.
2057 // geeignet fuer normale Attribute. Allerdings wird der Attributanfang nicht
2058 // auf die Position nPos korrigiert.
SeekPos(long nP)2059 bool WW8PLCFspecial::SeekPos(long nP)
2060 {
2061 if( nP < pPLCF_PosArray[0] )
2062 {
2063 nIdx = 0;
2064 return false; // Not found: nP unterhalb kleinstem Eintrag
2065 }
2066
2067 // Search from beginning?
2068 if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) )
2069 nIdx = 1;
2070
2071 long nI = nIdx ? nIdx : 1;
2072 long nEnd = nIMax;
2073
2074 for(int n = (1==nIdx ? 1 : 2); n; --n )
2075 {
2076 for( ; nI <=nEnd; ++nI)
2077 { // Suchen mit um 1 erhoehtem Index
2078 if( nP < pPLCF_PosArray[nI] )
2079 { // Position gefunden
2080 nIdx = nI - 1; // nI - 1 ist der richtige Index
2081 return true; // ... und fertig
2082 }
2083 }
2084 nI = 1;
2085 nEnd = nIdx-1;
2086 }
2087 nIdx = nIMax; // Nicht gefunden, groesser als alle Eintraege
2088 return false;
2089 }
2090
2091 // WW8PLCFspecial::SeekPosExact() wie SeekPos(), aber es wird sichergestellt,
2092 // dass kein Attribut angeschnitten wird, d.h. das naechste gelieferte
2093 // Attribut beginnt auf oder hinter nPos. Wird benutzt fuer Felder +
2094 // Bookmarks.
SeekPosExact(long nP)2095 bool WW8PLCFspecial::SeekPosExact(long nP)
2096 {
2097 if( nP < pPLCF_PosArray[0] )
2098 {
2099 nIdx = 0;
2100 return false; // Not found: nP unterhalb kleinstem Eintrag
2101 }
2102 // Search from beginning?
2103 if( nP <=pPLCF_PosArray[nIdx] )
2104 nIdx = 0;
2105
2106 long nI = nIdx ? nIdx-1 : 0;
2107 long nEnd = nIMax;
2108
2109 for(int n = (0==nIdx ? 1 : 2); n; --n )
2110 {
2111 for( ; nI < nEnd; ++nI)
2112 {
2113 if( nP <=pPLCF_PosArray[nI] )
2114 { // Position gefunden
2115 nIdx = nI; // nI ist der richtige Index
2116 return true; // ... und fertig
2117 }
2118 }
2119 nI = 0;
2120 nEnd = nIdx;
2121 }
2122 nIdx = nIMax; // Not found, groesser als alle Eintraege
2123 return false;
2124 }
2125
Get(long & rPos,void * & rpValue) const2126 bool WW8PLCFspecial::Get(long& rPos, void*& rpValue) const
2127 {
2128 return GetData( nIdx, rPos, rpValue );
2129 }
2130
GetData(long nInIdx,long & rPos,void * & rpValue) const2131 bool WW8PLCFspecial::GetData(long nInIdx, long& rPos, void*& rpValue) const
2132 {
2133 if ( nInIdx >= nIMax )
2134 {
2135 rPos = LONG_MAX;
2136 return false;
2137 }
2138 rPos = pPLCF_PosArray[nInIdx];
2139 rpValue = pPLCF_Contents ? (void*)&pPLCF_Contents[nInIdx * nStru] : 0;
2140 return true;
2141 }
2142
2143 //-----------------------------------------
2144 // WW8PLCF z.B. fuer SEPX
2145 //-----------------------------------------
2146
2147 // Ctor fuer *andere* als Fkps
2148 // Bei nStartPos < 0 wird das erste Element des PLCFs genommen
WW8PLCF(SvStream * pSt,long nFilePos,long nPLCF,long nStruct,long nStartPos)2149 WW8PLCF::WW8PLCF( SvStream* pSt, long nFilePos, long nPLCF, long nStruct,
2150 long nStartPos ) :nIdx( 0 ), nStru( nStruct )
2151 {
2152 ASSERT( nPLCF, "WW8PLCF: nPLCF ist Null!" );
2153
2154 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2155
2156 ReadPLCF( pSt, nFilePos, nPLCF );
2157
2158 if( nStartPos >= 0 )
2159 SeekPos( nStartPos );
2160 }
2161
2162 // Ctor *nur* fuer Fkps
2163 // Die letzten 2 Parameter sind fuer PLCF.Chpx und PLCF.Papx noetig. ist ncpN
2164 // != 0, dann wird ein unvollstaendiger PLCF vervollstaendigt. Das ist bei
2165 // WW6 bei Resourcenmangel und bei WordPad (W95) immer noetig. Bei nStartPos
2166 // < 0 wird das erste Element des PLCFs genommen
WW8PLCF(SvStream * pSt,long nFilePos,long nPLCF,long nStruct,long nStartPos,long nPN,long ncpN)2167 WW8PLCF::WW8PLCF( SvStream* pSt, long nFilePos, long nPLCF, long nStruct,
2168 long nStartPos, long nPN, long ncpN ) :nIdx( 0 ), nStru( nStruct )
2169 {
2170 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2171
2172 if( nIMax >= (long) ncpN )
2173 ReadPLCF( pSt, nFilePos, nPLCF );
2174 else
2175 GeneratePLCF( pSt, nPN, ncpN );
2176
2177 if( nStartPos >= 0 )
2178 SeekPos( nStartPos );
2179 }
2180
ReadPLCF(SvStream * pSt,long nFilePos,long nPLCF)2181 void WW8PLCF::ReadPLCF( SvStream* pSt, long nFilePos, long nPLCF )
2182 {
2183 // Pointer auf Pos-Array
2184 pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ];
2185
2186 long nOldPos = pSt->Tell();
2187
2188 pSt->Seek( nFilePos );
2189 pSt->Read( pPLCF_PosArray, nPLCF );
2190 #ifdef OSL_BIGENDIAN
2191 for( nIdx = 0; nIdx <= nIMax; nIdx++ )
2192 pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] );
2193 nIdx = 0;
2194 #endif // OSL_BIGENDIAN
2195 // Pointer auf Inhalts-Array
2196 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2197
2198 pSt->Seek( nOldPos );
2199 }
2200
GeneratePLCF(SvStream * pSt,long nPN,long ncpN)2201 void WW8PLCF::GeneratePLCF( SvStream* pSt, long nPN, long ncpN )
2202 {
2203 ASSERT( nIMax < (long)ncpN, "Pcl.Fkp: Warum ist PLCF zu gross ?" );
2204 nIMax = ncpN;
2205 long nSiz = 6 * nIMax + 4;
2206 pPLCF_PosArray = new sal_Int32[ ( nSiz + 3 ) / 4 ]; // Pointer auf Pos-Array
2207 memset( pPLCF_PosArray, 0, (size_t)nSiz );
2208
2209 sal_Int32 nFc;
2210 sal_uInt16 i;
2211
2212 for( i = 0; i < ncpN; i++ ){ // Baue FC-Eintraege
2213 pSt->Seek( ( nPN + i ) << 9 ); // erster FC-Eintrag jedes Fkp
2214 *pSt >> nFc;
2215 pPLCF_PosArray[i] = nFc;
2216 }
2217 sal_uLong nLastFkpPos = ( ( nPN + nIMax - 1 ) << 9 );
2218 pSt->Seek( nLastFkpPos + 511 ); // Anz. Fkp-Eintraege des letzten Fkp
2219 sal_uInt8 nb;
2220 *pSt >> nb;
2221 pSt->Seek( nLastFkpPos + nb * 4 ); // letzer FC-Eintrag des letzten Fkp
2222 *pSt >> nFc;
2223 pPLCF_PosArray[nIMax] = nFc; // Ende des letzten Fkp
2224
2225 // Pointer auf Inhalts-Array
2226 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2227 sal_uInt8* p = pPLCF_Contents;
2228
2229 for( i = 0; i < ncpN; i++ ) // Baue PNs
2230 {
2231 ShortToSVBT16(nPN + i, p);
2232 p+=2;
2233 }
2234 }
2235
SeekPos(long nPos)2236 bool WW8PLCF::SeekPos(long nPos)
2237 {
2238 long nP = nPos;
2239
2240 if( nP < pPLCF_PosArray[0] )
2241 {
2242 nIdx = 0;
2243 // Nicht gefunden: nPos unterhalb kleinstem Eintrag
2244 return false;
2245 }
2246
2247 // Search from beginning?
2248 if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) )
2249 nIdx = 1;
2250
2251 long nI = nIdx ? nIdx : 1;
2252 long nEnd = nIMax;
2253
2254 for(int n = (1==nIdx ? 1 : 2); n; --n )
2255 {
2256 for( ; nI <=nEnd; ++nI) // Suchen mit um 1 erhoehtem Index
2257 {
2258 if( nP < pPLCF_PosArray[nI] ) // Position gefunden
2259 {
2260 nIdx = nI - 1; // nI - 1 ist der richtige Index
2261 return true; // ... und fertig
2262 }
2263 }
2264 nI = 1;
2265 nEnd = nIdx-1;
2266 }
2267
2268 nIdx = nIMax; // Nicht gefunden, groesser als alle Eintraege
2269 return false;
2270 }
2271
Get(long & rStart,long & rEnd,void * & rpValue) const2272 bool WW8PLCF::Get(long& rStart, long& rEnd, void*& rpValue) const
2273 {
2274 if ( nIdx >= nIMax )
2275 {
2276 rStart = rEnd = LONG_MAX;
2277 return false;
2278 }
2279 rStart = pPLCF_PosArray[ nIdx ];
2280 rEnd = pPLCF_PosArray[ nIdx + 1 ];
2281 rpValue = (void*)&pPLCF_Contents[nIdx * nStru];
2282 return true;
2283 }
2284
Where() const2285 long WW8PLCF::Where() const
2286 {
2287 if ( nIdx >= nIMax )
2288 return LONG_MAX;
2289
2290 return pPLCF_PosArray[nIdx];
2291 }
2292
2293 //-----------------------------------------
2294 // WW8PLCFpcd
2295 //-----------------------------------------
2296
WW8PLCFpcd(SvStream * pSt,long nFilePos,long nPLCF,long nStruct)2297 WW8PLCFpcd::WW8PLCFpcd( SvStream* pSt, long nFilePos, long nPLCF, long nStruct )
2298 :nStru( nStruct )
2299 {
2300 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2301 pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ]; // Pointer auf Pos-Array
2302
2303 long nOldPos = pSt->Tell();
2304
2305 pSt->Seek( nFilePos );
2306 pSt->Read( pPLCF_PosArray, nPLCF );
2307 #ifdef OSL_BIGENDIAN
2308 for( long nI = 0; nI <= nIMax; nI++ )
2309 pPLCF_PosArray[nI] = SWAPLONG( pPLCF_PosArray[nI] );
2310 #endif // OSL_BIGENDIAN
2311
2312 // Pointer auf Inhalts-Array
2313 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2314
2315 pSt->Seek( nOldPos );
2316 }
2317
2318 // Bei nStartPos < 0 wird das erste Element des PLCFs genommen
WW8PLCFpcd_Iter(WW8PLCFpcd & rPLCFpcd,long nStartPos)2319 WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd& rPLCFpcd, long nStartPos )
2320 :rPLCF( rPLCFpcd ), nIdx( 0 )
2321 {
2322 if( nStartPos >= 0 )
2323 SeekPos( nStartPos );
2324 }
2325
SeekPos(long nPos)2326 bool WW8PLCFpcd_Iter::SeekPos(long nPos)
2327 {
2328 long nP = nPos;
2329
2330 if( nP < rPLCF.pPLCF_PosArray[0] )
2331 {
2332 nIdx = 0;
2333 return false; // Nicht gefunden: nPos unterhalb kleinstem Eintrag
2334 }
2335 // Search from beginning?
2336 if( (1 > nIdx) || (nP < rPLCF.pPLCF_PosArray[ nIdx-1 ]) )
2337 nIdx = 1;
2338
2339 long nI = nIdx ? nIdx : 1;
2340 long nEnd = rPLCF.nIMax;
2341
2342 for(int n = (1==nIdx ? 1 : 2); n; --n )
2343 {
2344 for( ; nI <=nEnd; ++nI)
2345 { // Suchen mit um 1 erhoehtem Index
2346 if( nP < rPLCF.pPLCF_PosArray[nI] )
2347 { // Position gefunden
2348 nIdx = nI - 1; // nI - 1 ist der richtige Index
2349 return true; // ... und fertig
2350 }
2351 }
2352 nI = 1;
2353 nEnd = nIdx-1;
2354 }
2355 nIdx = rPLCF.nIMax; // Nicht gefunden, groesser als alle Eintraege
2356 return false;
2357 }
2358
Get(long & rStart,long & rEnd,void * & rpValue) const2359 bool WW8PLCFpcd_Iter::Get(long& rStart, long& rEnd, void*& rpValue) const
2360 {
2361 if( nIdx >= rPLCF.nIMax )
2362 {
2363 rStart = rEnd = LONG_MAX;
2364 return false;
2365 }
2366 rStart = rPLCF.pPLCF_PosArray[nIdx];
2367 rEnd = rPLCF.pPLCF_PosArray[nIdx + 1];
2368 rpValue = (void*)&rPLCF.pPLCF_Contents[nIdx * rPLCF.nStru];
2369 return true;
2370 }
2371
Where() const2372 long WW8PLCFpcd_Iter::Where() const
2373 {
2374 if ( nIdx >= rPLCF.nIMax )
2375 return LONG_MAX;
2376
2377 return rPLCF.pPLCF_PosArray[nIdx];
2378 }
2379
2380 //-----------------------------------------
operator <(const WW8PLCFx_Fc_FKP::WW8Fkp::Entry & rSecond) const2381 bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator<
2382 (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry& rSecond) const
2383 {
2384 return (mnFC < rSecond.mnFC);
2385 }
2386
WW8Fkp(sal_uInt8 nFibVer,SvStream * pSt,SvStream * pDataSt,long _nFilePos,long nItemSiz,ePLCFT ePl,WW8_FC nStartFc)2387 WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(sal_uInt8 nFibVer, SvStream* pSt, SvStream* pDataSt,
2388 long _nFilePos, long nItemSiz, ePLCFT ePl, WW8_FC nStartFc)
2389 : nItemSize(nItemSiz), nFilePos(_nFilePos), nIdx(0), ePLCF(ePl),
2390 maSprmParser(nFibVer)
2391 {
2392 long nOldPos = pSt->Tell();
2393
2394 pSt->Seek(nFilePos);
2395 pSt->Read(maRawData, 512);
2396 nIMax = maRawData[511];
2397
2398 sal_uInt8 *pStart = maRawData;
2399 // Pointer to Offset-Location in maRawData
2400 sal_uInt8* pOfs = maRawData + (nIMax + 1) * 4;
2401
2402 for (nIdx = 0; nIdx < nIMax; ++nIdx)
2403 {
2404 sal_uInt16 nOfs = (*(pOfs + nIdx * nItemSize)) * 2;
2405 Entry aEntry(Get_Long(pStart));
2406
2407 if (nOfs)
2408 {
2409 switch (ePLCF)
2410 {
2411 case CHP:
2412 aEntry.mnLen = maRawData[nOfs];
2413 aEntry.mpData = maRawData + nOfs + 1;
2414 break;
2415 case PAP:
2416 sal_uInt8 nDelta = 0;
2417
2418 aEntry.mnLen = maRawData[nOfs];
2419 if (8 <= nFibVer && !aEntry.mnLen)
2420 {
2421 aEntry.mnLen = maRawData[ nOfs+1 ];
2422 nDelta++;
2423 }
2424
2425 aEntry.mnIStd = SVBT16ToShort(maRawData+nOfs+1+nDelta);
2426
2427 aEntry.mpData = maRawData + nOfs + 3+ nDelta;
2428
2429 sal_uInt16 nSpId = maSprmParser.GetSprmId(aEntry.mpData);
2430
2431 if (0x6645 == nSpId || 0x6646 == nSpId)
2432 {
2433 sal_uInt32 nCurr = pDataSt->Tell();
2434
2435 sal_uInt32 nPos = SVBT32ToUInt32(aEntry.mpData + 2);
2436 pDataSt->Seek(nPos);
2437 *pDataSt >> aEntry.mnLen;
2438 aEntry.mpData = new sal_uInt8[aEntry.mnLen];
2439 aEntry.mbMustDelete = true;
2440 pDataSt->Read(aEntry.mpData, aEntry.mnLen);
2441
2442 pDataSt->Seek( nCurr );
2443 }
2444 else
2445 {
2446 aEntry.mnLen *= 2;
2447 aEntry.mnLen -= 2;
2448 }
2449 break;
2450 }
2451 }
2452
2453 maEntries.push_back(aEntry);
2454 }
2455
2456 //one more FC than grrpl entries
2457 maEntries.push_back(Entry(Get_Long(pStart)));
2458
2459 //#104773#, we expect them sorted, but it appears possible
2460 //for them to arive unsorted
2461 std::sort(maEntries.begin(), maEntries.end());
2462
2463 nIdx = 0;
2464
2465 if (nStartFc >= 0)
2466 SeekPos(nStartFc);
2467
2468 pSt->Seek(nOldPos);
2469 }
2470
Entry(const Entry & rEntry)2471 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry &rEntry)
2472 : mnFC(rEntry.mnFC), mnLen(rEntry.mnLen), mnIStd(rEntry.mnIStd),
2473 mbMustDelete(rEntry.mbMustDelete)
2474 {
2475 if (mbMustDelete)
2476 {
2477 mpData = new sal_uInt8[mnLen];
2478 memcpy(mpData, rEntry.mpData, mnLen);
2479 }
2480 else
2481 mpData = rEntry.mpData;
2482 }
2483
2484 WW8PLCFx_Fc_FKP::WW8Fkp::Entry&
operator =(const Entry & rEntry)2485 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry &rEntry)
2486 {
2487 if (mbMustDelete)
2488 delete[] mpData;
2489
2490 mnFC = rEntry.mnFC;
2491 mnLen = rEntry.mnLen;
2492 mnIStd = rEntry.mnIStd;
2493 mbMustDelete = rEntry.mbMustDelete;
2494
2495 if (mbMustDelete)
2496 {
2497 mpData = new sal_uInt8[mnLen];
2498 memcpy(mpData, rEntry.mpData, mnLen);
2499 }
2500 else
2501 mpData = rEntry.mpData;
2502 return *this;
2503 }
2504
~Entry()2505 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry()
2506 {
2507 if (mbMustDelete)
2508 delete[] mpData;
2509 }
2510
Reset(WW8_FC nFc)2511 void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc)
2512 {
2513 SetIdx(0);
2514 if (nFc >= 0)
2515 SeekPos(nFc);
2516 }
2517
SeekPos(WW8_FC nFc)2518 bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc)
2519 {
2520 if (nFc < maEntries[0].mnFC)
2521 {
2522 nIdx = 0;
2523 return false; // Nicht gefunden: nPos unterhalb kleinstem Eintrag
2524 }
2525 // Search from beginning?
2526 if( (1 > nIdx) || (nFc < maEntries[nIdx-1].mnFC) )
2527 nIdx = 1;
2528
2529 long nI = nIdx ? nIdx : 1;
2530 long nEnd = nIMax;
2531
2532 for(int n = (1==nIdx ? 1 : 2); n; --n )
2533 {
2534 for( ; nI <=nEnd; ++nI)
2535 { // Suchen mit um 1 erhoehtem Index
2536 if (nFc < maEntries[nI].mnFC)
2537 { // Position gefunden
2538 nIdx = nI - 1; // nI - 1 ist der richtige Index
2539 return true; // ... und fertig
2540 }
2541 }
2542 nI = 1;
2543 nEnd = nIdx-1;
2544 }
2545 nIdx = nIMax; // Nicht gefunden, groesser als alle Eintraege
2546 return false;
2547 }
2548
Get(WW8_FC & rStart,WW8_FC & rEnd,long & rLen) const2549 sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::Get( WW8_FC& rStart, WW8_FC& rEnd, long& rLen )
2550 const
2551 {
2552 rLen = 0;
2553
2554 if( nIdx >= nIMax )
2555 {
2556 rStart = LONG_MAX;
2557 return 0;
2558 }
2559
2560 rStart = maEntries[nIdx].mnFC;
2561 rEnd = maEntries[nIdx + 1].mnFC;
2562
2563 sal_uInt8* pSprms = GetLenAndIStdAndSprms( rLen );
2564 return pSprms;
2565 }
2566
SetIdx(sal_uLong nI)2567 void WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx( sal_uLong nI )
2568 {
2569 if( nI < nIMax)
2570 nIdx = (short)nI;
2571 }
2572
GetLenAndIStdAndSprms(long & rLen) const2573 sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(long& rLen) const
2574 {
2575 rLen = maEntries[nIdx].mnLen;
2576 return maEntries[nIdx].mpData;
2577 }
2578
HasSprm(sal_uInt16 nId)2579 const sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId )
2580 {
2581 if( nIdx >= nIMax )
2582 return 0;
2583
2584 long nLen;
2585 sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2586
2587 WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2588 return aIter.FindSprm(nId);
2589 }
2590
HasSprm(sal_uInt16 nId,std::vector<const sal_uInt8 * > & rResult)2591 bool WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId,
2592 std::vector<const sal_uInt8 *> &rResult)
2593 {
2594 if (nIdx >= nIMax)
2595 return false;
2596
2597 long nLen;
2598 sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2599
2600 WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2601
2602 while(aIter.GetSprms())
2603 {
2604 if (aIter.GetAktId() == nId)
2605 rResult.push_back(aIter.GetAktParams());
2606 aIter++;
2607 };
2608 return !rResult.empty();
2609 }
2610
2611 //-----------------------------------------
GetSprms(WW8PLCFxDesc * p)2612 void WW8PLCFx::GetSprms( WW8PLCFxDesc* p )
2613 {
2614 ASSERT( !this, "Falsches GetSprms gerufen" );
2615 p->nStartPos = p->nEndPos = LONG_MAX;
2616 p->pMemPos = 0;
2617 p->nSprmsLen = 0;
2618 p->bRealLineEnd = false;
2619 return;
2620 }
2621
GetNoSprms(long & rStart,long & rEnd,long & rLen)2622 long WW8PLCFx::GetNoSprms( long& rStart, long& rEnd, long& rLen )
2623 {
2624 ASSERT( !this, "Falsches GetNoSprms gerufen" );
2625 rStart = rEnd = LONG_MAX;
2626 rLen = 0;
2627 return 0;
2628 }
2629
2630 // ...Idx2: Default: ignorieren
GetIdx2() const2631 sal_uLong WW8PLCFx::GetIdx2() const
2632 {
2633 return 0;
2634 }
2635
SetIdx2(sal_uLong)2636 void WW8PLCFx::SetIdx2(sal_uLong )
2637 {
2638 }
2639
2640 class SamePos :
2641 public std::unary_function<const WW8PLCFx_Fc_FKP::WW8Fkp *, bool>
2642 {
2643 private:
2644 long mnPo;
2645 public:
SamePos(long nPo)2646 SamePos(long nPo) : mnPo(nPo) {};
operator ()(const WW8PLCFx_Fc_FKP::WW8Fkp * pFkp)2647 bool operator()(const WW8PLCFx_Fc_FKP::WW8Fkp *pFkp)
2648 {return mnPo == pFkp->GetFilePos();}
2649 };
2650
2651 //-----------------------------------------
NewFkp()2652 bool WW8PLCFx_Fc_FKP::NewFkp()
2653 {
2654 long nPLCFStart, nPLCFEnd;
2655 void* pPage;
2656
2657 static const int WW8FkpSizeTabVer6[ PLCF_END ] =
2658 {
2659 1, 7, 0 /*, 0, 0, 0*/
2660 };
2661 static const int WW8FkpSizeTabVer8[ PLCF_END ] =
2662 {
2663 1, 13, 0 /*, 0, 0, 0*/
2664 };
2665 const int* pFkpSizeTab;
2666 switch (GetVersion())
2667 {
2668 case 6:
2669 case 7:
2670 pFkpSizeTab = WW8FkpSizeTabVer6;
2671 break;
2672 case 8:
2673 pFkpSizeTab = WW8FkpSizeTabVer8;
2674 break;
2675 default:
2676 // Programm-Fehler!
2677 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
2678 return false;
2679 }
2680
2681 if (!pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ))
2682 {
2683 pFkp = 0;
2684 return false; // PLCF fertig abgearbeitet
2685 }
2686 (*pPLCF)++;
2687 long nPo = SVBT16ToShort( (sal_uInt8 *)pPage );
2688 nPo <<= 9; // shift als LONG
2689
2690 long nAktFkpFilePos = pFkp ? pFkp->GetFilePos() : -1;
2691 if (nAktFkpFilePos == nPo)
2692 pFkp->Reset(GetStartFc()); // #79464# //
2693 else
2694 {
2695 myiter aIter =
2696 std::find_if(maFkpCache.begin(), maFkpCache.end(), SamePos(nPo));
2697 if (aIter != maFkpCache.end())
2698 {
2699 pFkp = *aIter;
2700 pFkp->Reset(GetStartFc());
2701 }
2702 else if ((pFkp = new WW8Fkp(GetVersion(), pFKPStrm, pDataStrm, nPo,
2703 pFkpSizeTab[ ePLCF ], ePLCF, GetStartFc())))
2704 {
2705 maFkpCache.push_back(pFkp);
2706
2707 if (maFkpCache.size() > eMaxCache)
2708 {
2709 delete maFkpCache.front();
2710 maFkpCache.pop_front();
2711 }
2712 }
2713 }
2714
2715 SetStartFc( -1 ); // Nur das erste Mal
2716 return true;
2717 }
2718
WW8PLCFx_Fc_FKP(SvStream * pSt,SvStream * pTblSt,SvStream * pDataSt,const WW8Fib & rFib,ePLCFT ePl,WW8_FC nStartFcL)2719 WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream* pSt, SvStream* pTblSt,
2720 SvStream* pDataSt, const WW8Fib& rFib, ePLCFT ePl, WW8_FC nStartFcL)
2721 : WW8PLCFx(rFib.nVersion, true), pFKPStrm(pSt), pDataStrm(pDataSt),
2722 pFkp(0), ePLCF(ePl), pPCDAttrs(0)
2723 {
2724 SetStartFc(nStartFcL);
2725 long nLenStruct = (8 > rFib.nVersion) ? 2 : 4;
2726 if (ePl == CHP)
2727 {
2728 pPLCF = new WW8PLCF(pTblSt, rFib.fcPlcfbteChpx, rFib.lcbPlcfbteChpx,
2729 nLenStruct, GetStartFc(), rFib.pnChpFirst, rFib.cpnBteChp);
2730 }
2731 else
2732 {
2733 pPLCF = new WW8PLCF(pTblSt, rFib.fcPlcfbtePapx, rFib.lcbPlcfbtePapx,
2734 nLenStruct, GetStartFc(), rFib.pnPapFirst, rFib.cpnBtePap);
2735 }
2736 }
2737
~WW8PLCFx_Fc_FKP()2738 WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP()
2739 {
2740 myiter aEnd = maFkpCache.end();
2741 for (myiter aIter = maFkpCache.begin(); aIter != aEnd; ++aIter)
2742 delete *aIter;
2743 delete pPLCF;
2744 delete pPCDAttrs;
2745 }
2746
GetIdx() const2747 sal_uLong WW8PLCFx_Fc_FKP::GetIdx() const
2748 {
2749 sal_uLong u = pPLCF->GetIdx() << 8;
2750 if (pFkp)
2751 u |= pFkp->GetIdx();
2752 return u;
2753 }
2754
SetIdx(sal_uLong nIdx)2755 void WW8PLCFx_Fc_FKP::SetIdx( sal_uLong nIdx )
2756 {
2757 if( !( nIdx & 0xffffff00L ) )
2758 {
2759 pPLCF->SetIdx( nIdx >> 8 );
2760 pFkp = 0;
2761 }
2762 else
2763 { //Es gab einen Fkp
2764 //Lese PLCF um 1 Pos zurueck, um die Adresse des Fkp wiederzubekommen
2765 pPLCF->SetIdx( ( nIdx >> 8 ) - 1 );
2766 if ( NewFkp() ) // und lese Fkp wieder ein
2767 pFkp->SetIdx( nIdx & 0xff ); // Dann stelle Fkp-Pos wieder ein
2768 }
2769 }
2770
SeekPos(WW8_FC nFcPos)2771 bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos)
2772 {
2773 // StartPos for next Where()
2774 SetStartFc( nFcPos );
2775
2776 // find StartPos for next pPLCF->Get()
2777 bool bRet = pPLCF->SeekPos(nFcPos);
2778
2779 // make FKP invalid?
2780 long nPLCFStart, nPLCFEnd;
2781 void* pPage;
2782 if( pFkp && pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ) )
2783 {
2784 long nPo = SVBT16ToShort( (sal_uInt8 *)pPage );
2785 nPo <<= 9; // shift als LONG
2786 if (nPo != pFkp->GetFilePos())
2787 pFkp = 0;
2788 else
2789 pFkp->SeekPos( nFcPos );
2790 }
2791 return bRet;
2792 }
2793
Where()2794 WW8_FC WW8PLCFx_Fc_FKP::Where()
2795 {
2796 if( !pFkp )
2797 {
2798 if( !NewFkp() )
2799 return LONG_MAX;
2800 }
2801 WW8_FC nP = pFkp->Where();
2802 if( nP != LONG_MAX )
2803 return nP;
2804
2805 pFkp = 0; // FKP beendet -> hole neuen
2806 return Where(); // am einfachsten rekursiv
2807 }
2808
GetSprmsAndPos(WW8_FC & rStart,WW8_FC & rEnd,long & rLen)2809 sal_uInt8* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC& rStart, WW8_FC& rEnd, long& rLen)
2810 {
2811 rLen = 0; // Default
2812 rStart = rEnd = LONG_MAX;
2813
2814 if( !pFkp ) // Fkp not there ?
2815 {
2816 if( !NewFkp() )
2817 return 0;
2818 }
2819
2820 sal_uInt8* pPos = pFkp->Get( rStart, rEnd, rLen );
2821 if( rStart == LONG_MAX ) //Not found
2822 return 0;
2823 return pPos;
2824 }
2825
operator ++(int)2826 WW8PLCFx& WW8PLCFx_Fc_FKP::operator ++( int )
2827 {
2828 if( !pFkp )
2829 {
2830 if( !NewFkp() )
2831 return *this;
2832 }
2833
2834 (*pFkp)++;
2835 if( pFkp->Where() == LONG_MAX )
2836 NewFkp();
2837
2838 return *this;
2839 }
2840
GetIstd() const2841 sal_uInt16 WW8PLCFx_Fc_FKP::GetIstd() const
2842 {
2843 return pFkp ? pFkp->GetIstd() : 0xFFFF;
2844 }
2845
GetPCDSprms(WW8PLCFxDesc & rDesc)2846 void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc& rDesc )
2847 {
2848 rDesc.pMemPos = 0;
2849 rDesc.nSprmsLen = 0;
2850 if( pPCDAttrs )
2851 {
2852 if( !pFkp )
2853 {
2854 DBG_WARNING(
2855 "+Problem: GetPCDSprms: NewFkp necessay (not possible!)" );
2856 if( !NewFkp() )
2857 return;
2858 }
2859 pPCDAttrs->GetSprms(&rDesc);
2860 }
2861 }
2862
HasSprm(sal_uInt16 nId)2863 const sal_uInt8* WW8PLCFx_Fc_FKP::HasSprm( sal_uInt16 nId )
2864 {
2865 // const waere schoener, aber dafuer muesste NewFkp() ersetzt werden oder
2866 // wegfallen
2867 if( !pFkp )
2868 {
2869 DBG_WARNING( "+Motz: HasSprm: NewFkp noetig ( kein const moeglich )" );
2870 // Passiert bei BugDoc 31722
2871 if( !NewFkp() )
2872 return 0;
2873 }
2874
2875 const sal_uInt8* pRes = pFkp->HasSprm( nId );
2876
2877 if( !pRes )
2878 {
2879 WW8PLCFxDesc aDesc;
2880 GetPCDSprms( aDesc );
2881
2882 if (aDesc.pMemPos)
2883 {
2884 WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
2885 pFkp->GetSprmParser());
2886 pRes = aIter.FindSprm(nId);
2887 }
2888 }
2889
2890 return pRes;
2891 }
2892
HasSprm(sal_uInt16 nId,std::vector<const sal_uInt8 * > & rResult)2893 bool WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId, std::vector<const sal_uInt8 *> &rResult)
2894 {
2895 // const waere schoener, aber dafuer muesste NewFkp() ersetzt werden oder
2896 // wegfallen
2897 if (!pFkp)
2898 {
2899 DBG_WARNING( "+Motz: HasSprm: NewFkp noetig ( kein const moeglich )" );
2900 // Passiert bei BugDoc 31722
2901 if( !NewFkp() )
2902 return 0;
2903 }
2904
2905 pFkp->HasSprm(nId, rResult);
2906
2907 WW8PLCFxDesc aDesc;
2908 GetPCDSprms( aDesc );
2909
2910 if (aDesc.pMemPos)
2911 {
2912 WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
2913 pFkp->GetSprmParser());
2914 while(aIter.GetSprms())
2915 {
2916 if (aIter.GetAktId() == nId)
2917 rResult.push_back(aIter.GetAktParams());
2918 aIter++;
2919 };
2920 }
2921 return !rResult.empty();
2922 }
2923
2924 //-----------------------------------------
2925
WW8PLCFx_Cp_FKP(SvStream * pSt,SvStream * pTblSt,SvStream * pDataSt,const WW8ScannerBase & rBase,ePLCFT ePl)2926 WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream* pSt, SvStream* pTblSt,
2927 SvStream* pDataSt, const WW8ScannerBase& rBase, ePLCFT ePl )
2928 : WW8PLCFx_Fc_FKP(pSt, pTblSt, pDataSt, *rBase.pWw8Fib, ePl,
2929 rBase.WW8Cp2Fc(0)), rSBase(rBase), nAttrStart(-1), nAttrEnd(-1),
2930 bLineEnd(false),
2931 bComplex( (7 < rBase.pWw8Fib->nVersion) || (0 != rBase.pWw8Fib->fComplex) )
2932 {
2933 ResetAttrStartEnd();
2934
2935 pPcd = rSBase.pPiecePLCF ? new WW8PLCFx_PCD( rBase.pWw8Fib->nVersion,
2936 rBase.pPiecePLCF, 0, ((6 == GetVersion()) || (7 == GetVersion())) )
2937 : 0;
2938
2939 /*
2940 Make a copy of the piece attributes for so that the calls to HasSprm on a
2941 Fc_FKP will be able to take into account the current piece attributes,
2942 despite the fact that such attributes can only be found through a cp based
2943 mechanism.
2944 */
2945 if (pPcd)
2946 {
2947 pPCDAttrs = rSBase.pPLCFx_PCDAttrs ? new WW8PLCFx_PCDAttrs(
2948 rSBase.pWw8Fib->nVersion, pPcd, &rSBase) : 0;
2949 }
2950
2951 pPieceIter = rSBase.pPieceIter;
2952 }
2953
~WW8PLCFx_Cp_FKP()2954 WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP()
2955 {
2956 delete pPcd;
2957 }
2958
ResetAttrStartEnd()2959 void WW8PLCFx_Cp_FKP::ResetAttrStartEnd()
2960 {
2961 nAttrStart = -1;
2962 nAttrEnd = -1;
2963 bLineEnd = false;
2964 }
2965
GetPCDIMax() const2966 sal_uLong WW8PLCFx_Cp_FKP::GetPCDIMax() const
2967 {
2968 return pPcd ? pPcd->GetIMax() : 0;
2969 }
2970
GetPCDIdx() const2971 sal_uLong WW8PLCFx_Cp_FKP::GetPCDIdx() const
2972 {
2973 return pPcd ? pPcd->GetIdx() : 0;
2974 }
2975
SetPCDIdx(sal_uLong nIdx)2976 void WW8PLCFx_Cp_FKP::SetPCDIdx( sal_uLong nIdx )
2977 {
2978 if( pPcd )
2979 pPcd->SetIdx( nIdx );
2980 }
2981
SeekPos(WW8_CP nCpPos)2982 bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos)
2983 {
2984 if( pPcd ) // Complex
2985 {
2986 if( !pPcd->SeekPos( nCpPos ) ) // Piece setzen
2987 return false;
2988 if (pPCDAttrs && !pPCDAttrs->GetIter()->SeekPos(nCpPos))
2989 return false;
2990 return WW8PLCFx_Fc_FKP::SeekPos(pPcd->AktPieceStartCp2Fc(nCpPos));
2991 }
2992 // KEINE Piece-Table !!!
2993 return WW8PLCFx_Fc_FKP::SeekPos( rSBase.WW8Cp2Fc(nCpPos) );
2994 }
2995
Where()2996 WW8_CP WW8PLCFx_Cp_FKP::Where()
2997 {
2998 WW8_FC nFc = WW8PLCFx_Fc_FKP::Where();
2999 if( pPcd )
3000 return pPcd->AktPieceStartFc2Cp( nFc ); // Piece ermitteln
3001 return rSBase.WW8Fc2Cp( nFc ); // KEINE Piece-Table !!!
3002 }
3003
GetSprms(WW8PLCFxDesc * p)3004 void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc* p)
3005 {
3006 WW8_CP nOrigCp = p->nStartPos;
3007
3008 if (!GetDirty()) //Normal case
3009 {
3010 p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(p->nStartPos, p->nEndPos,
3011 p->nSprmsLen);
3012 }
3013 else
3014 {
3015 /*
3016 #93702#
3017 For the odd case where we have a location in a fastsaved file which
3018 does not have an entry in the FKP, perhaps its para end is in the next
3019 piece, or perhaps the cp just doesn't exist at all in this document.
3020 AdvSprm doesn't know so it sets the PLCF as dirty and we figure out
3021 in this method what the situation is
3022
3023 It doesn't exist then the piece iterator will not be able to find it.
3024 Otherwise our cool fastsave algorithm can be brought to bear on the
3025 problem.
3026 */
3027 sal_uLong nOldPos = pPieceIter->GetIdx();
3028 bool bOk = pPieceIter->SeekPos(nOrigCp);
3029 pPieceIter->SetIdx( nOldPos );
3030 if (!bOk)
3031 return;
3032 }
3033
3034 if( pPcd ) // Piece-Table vorhanden !!!
3035 {
3036 // Init ( noch kein ++ gerufen )
3037 if( (nAttrStart > nAttrEnd) || (nAttrStart == -1) )
3038 {
3039 p->bRealLineEnd = (ePLCF == PAP);
3040
3041 if ( ((ePLCF == PAP ) || (ePLCF == CHP)) && (nOrigCp != LONG_MAX) )
3042 {
3043 bool bIsUnicode=false;
3044 /*
3045 To find the end of a paragraph for a character in a
3046 complex format file.
3047
3048 It is necessary to know the piece that contains the
3049 character and the FC assigned to the character.
3050 */
3051
3052 //We set the piece iterator to the piece that contains the
3053 //character, now we have the correct piece for this character
3054 sal_uLong nOldPos = pPieceIter->GetIdx();
3055 p->nStartPos = nOrigCp;
3056 pPieceIter->SeekPos( p->nStartPos);
3057
3058 //This is the FC assigned to the character, but we already
3059 //have the result of the next stage, so we can skip this step
3060 //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode);
3061
3062 /*
3063 Using the FC of the character, first search the FKP that
3064 describes the character to find the smallest FC in the rgfc
3065 that is larger than the character FC.
3066 */
3067 //But the search has already been done, the next largest FC is
3068 //p->nEndPos.
3069 WW8_FC nOldEndPos = p->nEndPos;
3070
3071 /*
3072 If the FC found in the FKP is less than or equal to the limit
3073 FC of the piece, the end of the paragraph that contains the
3074 character is at the FKP FC minus 1.
3075 */
3076 long nCpStart, nCpEnd;
3077 void* pData;
3078 pPieceIter->Get(nCpStart, nCpEnd, pData);
3079
3080 WW8_FC nLimitFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
3081 WW8_FC nBeginLimitFC = nLimitFC;
3082 if( 8 <= GetVersion() )
3083 {
3084 nBeginLimitFC =
3085 WW8PLCFx_PCD::TransformPieceAddress(nLimitFC,
3086 bIsUnicode);
3087 }
3088 nLimitFC = nBeginLimitFC +
3089 (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1);
3090
3091 if (nOldEndPos <= nLimitFC)
3092 {
3093 p->nEndPos = nCpEnd -
3094 (nLimitFC-nOldEndPos) / (bIsUnicode ? 2 : 1);
3095 }
3096 else
3097 {
3098 if (ePLCF == CHP)
3099 p->nEndPos = nCpEnd;
3100 else
3101 {
3102 /*
3103 If the FKP FC that was found was greater than the FC
3104 of the end of the piece, scan piece by piece toward
3105 the end of the document until a piece is found that
3106 contains a paragraph end mark.
3107 */
3108
3109 /*
3110 It's possible to check if a piece contains a paragraph
3111 mark by using the FC of the beginning of the piece to
3112 search in the FKPs for the smallest FC in the FKP rgfc
3113 that is greater than the FC of the beginning of the
3114 piece. If the FC found is less than or equal to the
3115 limit FC of the piece, then the character that ends
3116 the paragraph is the character immediately before the
3117 FKP fc
3118 */
3119
3120 (*pPieceIter)++;
3121
3122 for (;pPieceIter->GetIdx() < pPieceIter->GetIMax();
3123 (*pPieceIter)++)
3124 {
3125 if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
3126 {
3127 ASSERT( !this, "piece iter broken!" );
3128 break;
3129 }
3130 bIsUnicode = false;
3131 sal_Int32 nFcStart=SVBT32ToUInt32(((WW8_PCD*)pData)->fc);
3132
3133 if( 8 <= GetVersion() )
3134 {
3135 nFcStart =
3136 WW8PLCFx_PCD::TransformPieceAddress(
3137 nFcStart,bIsUnicode );
3138 }
3139 nLimitFC = nFcStart + (nCpEnd - nCpStart) *
3140 (bIsUnicode ? 2 : 1);
3141
3142 //if it doesn't exist, skip it
3143 if (!SeekPos(nCpStart))
3144 continue;
3145
3146 WW8_FC nOne,nSmallest;
3147 p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne,
3148 nSmallest, p->nSprmsLen);
3149
3150 if (nSmallest <= nLimitFC)
3151 {
3152 p->nEndPos = nCpEnd -
3153 (nLimitFC-nSmallest) / (bIsUnicode ? 2 : 1);
3154 break;
3155 }
3156 }
3157 }
3158 }
3159 pPieceIter->SetIdx( nOldPos );
3160 }
3161 else
3162 pPcd->AktPieceFc2Cp( p->nStartPos, p->nEndPos,&rSBase );
3163 }
3164 else
3165 {
3166 p->nStartPos = nAttrStart;
3167 p->nEndPos = nAttrEnd;
3168 p->bRealLineEnd = bLineEnd;
3169 }
3170 }
3171 else // KEINE Piece-Table !!!
3172 {
3173 p->nStartPos = rSBase.WW8Fc2Cp( p->nStartPos );
3174 p->nEndPos = rSBase.WW8Fc2Cp( p->nEndPos );
3175 p->bRealLineEnd = ePLCF == PAP;
3176 }
3177 }
3178
operator ++(int)3179 WW8PLCFx& WW8PLCFx_Cp_FKP::operator ++( int )
3180 {
3181 WW8PLCFx_Fc_FKP::operator ++( 0 );
3182 // !pPcd: Notbremse
3183 if ( !bComplex || !pPcd )
3184 return *this;
3185
3186 if( GetPCDIdx() >= GetPCDIMax() ) // End of PLCF
3187 {
3188 nAttrStart = nAttrEnd = LONG_MAX;
3189 return *this;
3190 }
3191
3192 long nFkpLen; // Fkp-Eintrag
3193 // Fkp-Eintrag holen
3194 WW8PLCFx_Fc_FKP::GetSprmsAndPos(nAttrStart, nAttrEnd, nFkpLen);
3195
3196 pPcd->AktPieceFc2Cp( nAttrStart, nAttrEnd, &rSBase );
3197 bLineEnd = (ePLCF == PAP);
3198 return *this;
3199 }
3200
3201 //-----------------------------------------
3202 //-----------------------------------------
3203
WW8PLCFx_SEPX(SvStream * pSt,SvStream * pTblSt,const WW8Fib & rFib,WW8_CP nStartCp)3204 WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream* pSt, SvStream* pTblSt,
3205 const WW8Fib& rFib, WW8_CP nStartCp)
3206 : WW8PLCFx(rFib.nVersion, true), maSprmParser(rFib.nVersion), pStrm(pSt),
3207 nArrMax(256), nSprmSiz(0)
3208 {
3209 pPLCF = rFib.lcbPlcfsed
3210 ? new WW8PLCF(pTblSt, rFib.fcPlcfsed, rFib.lcbPlcfsed, 12, nStartCp)
3211 : 0;
3212
3213 pSprms = new sal_uInt8[nArrMax]; // maximum length
3214 }
3215
~WW8PLCFx_SEPX()3216 WW8PLCFx_SEPX::~WW8PLCFx_SEPX()
3217 {
3218 delete pPLCF;
3219 delete[] pSprms;
3220 }
3221
GetIdx() const3222 sal_uLong WW8PLCFx_SEPX::GetIdx() const
3223 {
3224 return pPLCF ? pPLCF->GetIdx() : 0;
3225 }
3226
SetIdx(sal_uLong nIdx)3227 void WW8PLCFx_SEPX::SetIdx( sal_uLong nIdx )
3228 {
3229 if( pPLCF ) pPLCF->SetIdx( nIdx );
3230 }
3231
SeekPos(WW8_CP nCpPos)3232 bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos)
3233 {
3234 return pPLCF ? pPLCF->SeekPos( nCpPos ) : 0;
3235 }
3236
Where()3237 WW8_CP WW8PLCFx_SEPX::Where()
3238 {
3239 return pPLCF ? pPLCF->Where() : 0;
3240 }
3241
GetSprms(WW8PLCFxDesc * p)3242 void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc* p)
3243 {
3244 if( !pPLCF ) return;
3245
3246 void* pData;
3247
3248 p->bRealLineEnd = false;
3249 if (!pPLCF->Get( p->nStartPos, p->nEndPos, pData ))
3250 {
3251 p->nStartPos = p->nEndPos = LONG_MAX; // PLCF fertig abgearbeitet
3252 p->pMemPos = 0;
3253 p->nSprmsLen = 0;
3254 }
3255 else
3256 {
3257 long nPo = SVBT32ToUInt32( (sal_uInt8*)pData+2 );
3258 if (nPo == -1L)
3259 {
3260 p->nStartPos = p->nEndPos = LONG_MAX; // Sepx empty
3261 p->pMemPos = 0;
3262 p->nSprmsLen = 0;
3263 }
3264 else
3265 {
3266 pStrm->Seek( nPo );
3267 *pStrm >> nSprmSiz; // read len
3268
3269 if( nSprmSiz > nArrMax )
3270 { // passt nicht
3271 delete[] pSprms;
3272 nArrMax = nSprmSiz; // Hole mehr Speicher
3273 pSprms = new sal_uInt8[nArrMax];
3274 }
3275 pStrm->Read( pSprms, nSprmSiz ); // read Sprms
3276
3277 p->nSprmsLen = nSprmSiz;
3278 p->pMemPos = pSprms; // return Position
3279 }
3280 }
3281 }
3282
operator ++(int)3283 WW8PLCFx& WW8PLCFx_SEPX::operator ++( int )
3284 {
3285 if( pPLCF )
3286 (*pPLCF)++;
3287 return *this;
3288 }
3289
HasSprm(sal_uInt16 nId) const3290 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId ) const
3291 {
3292 return HasSprm( nId, pSprms, nSprmSiz);
3293 }
3294
HasSprm(sal_uInt16 nId,const sal_uInt8 * pOtherSprms,long nOtherSprmSiz) const3295 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, const sal_uInt8* pOtherSprms,
3296 long nOtherSprmSiz ) const
3297 {
3298 const sal_uInt8 *pRet = 0;
3299 if (pPLCF)
3300 {
3301 WW8SprmIter aIter(pOtherSprms, nOtherSprmSiz, maSprmParser);
3302 pRet = aIter.FindSprm(nId);
3303 }
3304 return pRet;
3305 }
3306
Find4Sprms(sal_uInt16 nId1,sal_uInt16 nId2,sal_uInt16 nId3,sal_uInt16 nId4,sal_uInt8 * & p1,sal_uInt8 * & p2,sal_uInt8 * & p3,sal_uInt8 * & p4) const3307 bool WW8PLCFx_SEPX::Find4Sprms(sal_uInt16 nId1,sal_uInt16 nId2,sal_uInt16 nId3,sal_uInt16 nId4,
3308 sal_uInt8*& p1, sal_uInt8*& p2, sal_uInt8*& p3, sal_uInt8*& p4) const
3309 {
3310 if( !pPLCF )
3311 return 0;
3312
3313 bool bFound = false;
3314 p1 = 0;
3315 p2 = 0;
3316 p3 = 0;
3317 p4 = 0;
3318
3319 sal_uInt8* pSp = pSprms;
3320 sal_uInt16 i=0;
3321 while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
3322 {
3323 // Sprm gefunden?
3324 sal_uInt16 nAktId = maSprmParser.GetSprmId(pSp);
3325 bool bOk = true;
3326 if( nAktId == nId1 )
3327 p1 = pSp + maSprmParser.DistanceToData(nId1);
3328 else if( nAktId == nId2 )
3329 p2 = pSp + maSprmParser.DistanceToData(nId2);
3330 else if( nAktId == nId3 )
3331 p3 = pSp + maSprmParser.DistanceToData(nId3);
3332 else if( nAktId == nId4 )
3333 p4 = pSp + maSprmParser.DistanceToData(nId4);
3334 else
3335 bOk = false;
3336 bFound |= bOk;
3337 // erhoehe Zeiger, so dass er auf naechsten Sprm zeigt
3338 sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSp);
3339 i += x;
3340 pSp += x;
3341 }
3342 return bFound;
3343 }
3344
HasSprm(sal_uInt16 nId,sal_uInt8 n2nd) const3345 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, sal_uInt8 n2nd ) const
3346 {
3347 if( !pPLCF )
3348 return 0;
3349
3350 sal_uInt8* pSp = pSprms;
3351
3352 sal_uInt16 i=0;
3353 while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
3354 {
3355 // Sprm gefunden?
3356 sal_uInt16 nAktId = maSprmParser.GetSprmId(pSp);
3357 if (nAktId == nId)
3358 {
3359 sal_uInt8 *pRet = pSp + maSprmParser.DistanceToData(nId);
3360 if (*pRet == n2nd)
3361 return pRet;
3362 }
3363 // erhoehe Zeiger, so dass er auf naechsten Sprm zeigt
3364 sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSp);
3365 i += x;
3366 pSp += x;
3367 }
3368
3369 return 0; // Sprm nicht gefunden
3370 }
3371
3372 //-----------------------------------------
WW8PLCFx_SubDoc(SvStream * pSt,sal_uInt8 nVersion,WW8_CP nStartCp,long nFcRef,long nLenRef,long nFcTxt,long nLenTxt,long nStruct)3373 WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream* pSt, sal_uInt8 nVersion,
3374 WW8_CP nStartCp, long nFcRef, long nLenRef, long nFcTxt, long nLenTxt,
3375 long nStruct)
3376 : WW8PLCFx(nVersion, false), pRef(0), pTxt(0)
3377 {
3378 if( nLenRef && nLenTxt )
3379 {
3380 pRef = new WW8PLCF( pSt, nFcRef, nLenRef, nStruct, nStartCp );
3381 pTxt = new WW8PLCF( pSt, nFcTxt, nLenTxt, 0, nStartCp );
3382 }
3383 }
3384
~WW8PLCFx_SubDoc()3385 WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc()
3386 {
3387 delete pRef;
3388 delete pTxt;
3389 }
3390
GetIdx() const3391 sal_uLong WW8PLCFx_SubDoc::GetIdx() const
3392 {
3393 // Wahrscheinlich pTxt... nicht noetig
3394 if( pRef )
3395 return ( pRef->GetIdx() << 16 | pTxt->GetIdx() );
3396 return 0;
3397 }
3398
SetIdx(sal_uLong nIdx)3399 void WW8PLCFx_SubDoc::SetIdx( sal_uLong nIdx )
3400 {
3401 if( pRef )
3402 {
3403 pRef->SetIdx( nIdx >> 16 );
3404 // Wahrscheinlich pTxt... nicht noetig
3405 pTxt->SetIdx( nIdx & 0xFFFF );
3406 }
3407 }
3408
SeekPos(WW8_CP nCpPos)3409 bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos )
3410 {
3411 return ( pRef ) ? pRef->SeekPos( nCpPos ) : false;
3412 }
3413
Where()3414 WW8_CP WW8PLCFx_SubDoc::Where()
3415 {
3416 return ( pRef ) ? pRef->Where() : LONG_MAX;
3417 }
3418
GetNoSprms(WW8_CP & rStart,long & rEnd,long & rLen)3419 long WW8PLCFx_SubDoc::GetNoSprms( WW8_CP& rStart, long& rEnd, long& rLen )
3420 {
3421 void* pData;
3422 long nSt, nE;
3423 rEnd = LONG_MAX;
3424
3425 if ( !pRef )
3426 {
3427 rStart = LONG_MAX; // Es gibt keine Noten
3428 rLen = 0;
3429 return -1;
3430 }
3431
3432 sal_uLong nNr = pRef->GetIdx();
3433
3434 if (!pRef->Get( rStart, nE, pData ))
3435 {
3436 rStart = LONG_MAX; // PLCF fertig abgearbeitet
3437 rLen = 0;
3438 return -1;
3439 }
3440 pTxt->SetIdx( nNr );
3441
3442 if(!pTxt->Get( nSt, rLen, pData ))
3443 {
3444 rStart = LONG_MAX; // PLCF fertig abgearbeitet
3445 rLen = 0;
3446 return -1;
3447 }
3448
3449 rLen -= nSt;
3450 return nSt;
3451 }
3452
operator ++(int)3453 WW8PLCFx& WW8PLCFx_SubDoc::operator ++( int )
3454 {
3455 if( pRef && pTxt )
3456 {
3457 (*pRef)++;
3458 (*pTxt)++;
3459 }
3460 return *this;
3461 }
3462
3463 //-----------------------------------------
3464 // Felder
3465 //-----------------------------------------
3466
WW8PLCFx_FLD(SvStream * pSt,const WW8Fib & rMyFib,short nType)3467 WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream* pSt, const WW8Fib& rMyFib, short nType)
3468 : WW8PLCFx(rMyFib.nVersion, true), pPLCF(0), rFib(rMyFib)
3469 {
3470 long nFc, nLen;
3471
3472 switch( nType )
3473 {
3474 case MAN_HDFT:
3475 nFc = rFib.fcPlcffldHdr;
3476 nLen = rFib.lcbPlcffldHdr;
3477 break;
3478 case MAN_FTN:
3479 nFc = rFib.fcPlcffldFtn;
3480 nLen = rFib.lcbPlcffldFtn;
3481 break;
3482 case MAN_EDN:
3483 nFc = rFib.fcPlcffldEdn;
3484 nLen = rFib.lcbPlcffldEdn;
3485 break;
3486 case MAN_AND:
3487 nFc = rFib.fcPlcffldAtn;
3488 nLen = rFib.lcbPlcffldAtn;
3489 break;
3490 case MAN_TXBX:
3491 nFc = rFib.fcPlcffldTxbx;
3492 nLen = rFib.lcbPlcffldTxbx;
3493 break;
3494 case MAN_TXBX_HDFT:
3495 nFc = rFib.fcPlcffldHdrTxbx;
3496 nLen = rFib.lcbPlcffldHdrTxbx;
3497 break;
3498 default:
3499 nFc = rFib.fcPlcffldMom;
3500 nLen = rFib.lcbPlcffldMom;
3501 break;
3502 }
3503
3504 if( nLen )
3505 pPLCF = new WW8PLCFspecial( pSt, nFc, nLen, 2 );
3506 }
3507
~WW8PLCFx_FLD()3508 WW8PLCFx_FLD::~WW8PLCFx_FLD()
3509 {
3510 delete pPLCF;
3511 }
3512
GetIdx() const3513 sal_uLong WW8PLCFx_FLD::GetIdx() const
3514 {
3515 return pPLCF ? pPLCF->GetIdx() : 0;
3516 }
3517
SetIdx(sal_uLong nIdx)3518 void WW8PLCFx_FLD::SetIdx( sal_uLong nIdx )
3519 {
3520 if( pPLCF )
3521 pPLCF->SetIdx( nIdx );
3522 }
3523
SeekPos(WW8_CP nCpPos)3524 bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos)
3525 {
3526 return pPLCF ? pPLCF->SeekPosExact( nCpPos ) : false;
3527 }
3528
Where()3529 WW8_CP WW8PLCFx_FLD::Where()
3530 {
3531 return pPLCF ? pPLCF->Where() : LONG_MAX;
3532 }
3533
StartPosIsFieldStart()3534 bool WW8PLCFx_FLD::StartPosIsFieldStart()
3535 {
3536 void* pData;
3537 long nTest;
3538 if (
3539 (!pPLCF || !pPLCF->Get(nTest, pData) ||
3540 ((((sal_uInt8*)pData)[0] & 0x1f) != 0x13))
3541 )
3542 return false;
3543 return true;
3544 }
3545
EndPosIsFieldEnd(WW8_CP & nCP)3546 bool WW8PLCFx_FLD::EndPosIsFieldEnd(WW8_CP& nCP)
3547 {
3548 bool bRet = false;
3549
3550 if (pPLCF)
3551 {
3552 long n = pPLCF->GetIdx();
3553
3554 (*pPLCF)++;
3555
3556 void* pData;
3557 long nTest;
3558 if ( pPLCF->Get(nTest, pData) && ((((sal_uInt8*)pData)[0] & 0x1f) == 0x15) )
3559 {
3560 nCP = nTest;
3561 bRet = true;
3562 }
3563
3564 pPLCF->SetIdx(n);
3565 }
3566
3567 return bRet;
3568 }
3569
GetSprms(WW8PLCFxDesc * p)3570 void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc* p)
3571 {
3572 p->nStartPos = p->nEndPos = LONG_MAX;
3573 p->pMemPos = 0;
3574 p->nSprmsLen = 0;
3575 p->bRealLineEnd = false;
3576
3577 if (!pPLCF)
3578 {
3579 p->nStartPos = LONG_MAX; // Es gibt keine Felder
3580 return;
3581 }
3582
3583 long n = pPLCF->GetIdx();
3584
3585 long nP;
3586 void *pData;
3587 if (!pPLCF->Get(nP, pData)) // Ende des PLCFspecial ?
3588 {
3589 p->nStartPos = LONG_MAX; // PLCF fertig abgearbeitet
3590 return;
3591 }
3592
3593 p->nStartPos = nP;
3594
3595 (*pPLCF)++;
3596 if (!pPLCF->Get(nP, pData)) // Ende des PLCFspecial ?
3597 {
3598 p->nStartPos = LONG_MAX; // PLCF fertig abgearbeitet
3599 return;
3600 }
3601
3602 p->nEndPos = nP;
3603
3604 pPLCF->SetIdx(n);
3605
3606 p->nCp2OrIdx = pPLCF->GetIdx();
3607 }
3608
operator ++(int)3609 WW8PLCFx& WW8PLCFx_FLD::operator ++( int )
3610 {
3611 (*pPLCF)++;
3612 return *this;
3613 }
3614
GetPara(long nIdx,WW8FieldDesc & rF)3615 bool WW8PLCFx_FLD::GetPara(long nIdx, WW8FieldDesc& rF)
3616 {
3617 ASSERT( pPLCF, "Aufruf ohne Feld PLCFspecial" );
3618 if( !pPLCF )
3619 return false;
3620
3621 long n = pPLCF->GetIdx();
3622 pPLCF->SetIdx(nIdx);
3623
3624 bool bOk = WW8GetFieldPara(*pPLCF, rF);
3625
3626 pPLCF->SetIdx(n);
3627 return bOk;
3628 }
3629
3630 //-----------------------------------------
3631 // class WW8PLCF_Book
3632 //-----------------------------------------
3633
3634 /* to be optimized like this: */
WW8ReadSTTBF(bool bVer8,SvStream & rStrm,sal_uInt32 nStart,sal_Int32 nLen,sal_uInt16 nExtraLen,rtl_TextEncoding eCS,std::vector<String> & rArray,std::vector<String> * pExtraArray)3635 void WW8ReadSTTBF(bool bVer8, SvStream& rStrm, sal_uInt32 nStart, sal_Int32 nLen,
3636 sal_uInt16 nExtraLen, rtl_TextEncoding eCS, std::vector<String> &rArray,
3637 std::vector<String>* pExtraArray)
3638 {
3639 sal_uLong nOldPos = rStrm.Tell();
3640 rStrm.Seek( nStart );
3641
3642 sal_uInt16 nLen2;
3643 rStrm >> nLen2; // bVer67: total length of structure
3644 // bVer8 : count of strings
3645
3646 if( bVer8 )
3647 {
3648 sal_uInt16 nStrings;
3649 bool bUnicode = (0xFFFF == nLen2);
3650 if( bUnicode )
3651 rStrm >> nStrings;
3652 else
3653 nStrings = nLen2;
3654
3655 rStrm >> nExtraLen;
3656
3657 for( sal_uInt16 i=0; i < nStrings; i++ )
3658 {
3659 if( bUnicode )
3660 rArray.push_back(WW8Read_xstz(rStrm, 0, false));
3661 else
3662 {
3663 sal_uInt8 nBChar;
3664 rStrm >> nBChar;
3665 ByteString aTmp;
3666 SafeReadString(aTmp,nBChar,rStrm);
3667 rArray.push_back(String(aTmp, eCS));
3668 }
3669
3670 // Skip the extra data
3671 if( nExtraLen )
3672 {
3673 if (pExtraArray)
3674 {
3675 ByteString aTmp;
3676 SafeReadString(aTmp,nExtraLen,rStrm);
3677 pExtraArray->push_back(String(aTmp, eCS));
3678 }
3679 else
3680 rStrm.SeekRel( nExtraLen );
3681 }
3682 }
3683 }
3684 else
3685 {
3686 sal_uInt8 nBChar;
3687 if( nLen2 != nLen )
3688 {
3689 ASSERT( nLen2 == nLen, "Fib length and read length are different" );
3690 if (nLen > USHRT_MAX)
3691 nLen = USHRT_MAX;
3692 else if (nLen < 2 )
3693 nLen = 2;
3694 nLen2 = static_cast<sal_uInt16>(nLen);
3695 }
3696 sal_uLong nRead = 0;
3697 for( nLen2 -= 2; nRead < nLen2; )
3698 {
3699 rStrm >> nBChar; ++nRead;
3700 if (nBChar)
3701 {
3702 ByteString aTmp;
3703 nRead += SafeReadString(aTmp,nBChar,rStrm);
3704 rArray.push_back(String(aTmp, eCS));
3705 }
3706 else
3707 rArray.push_back(aEmptyStr);
3708
3709 // #89125# Skip the extra data (for bVer67 versions this must come
3710 // from external knowledge)
3711 if (nExtraLen)
3712 {
3713 if (pExtraArray)
3714 {
3715 ByteString aTmp;
3716 SafeReadString(aTmp,nExtraLen,rStrm);
3717 pExtraArray->push_back(String(aTmp, eCS));
3718 }
3719 else
3720 rStrm.SeekRel( nExtraLen );
3721 nRead+=nExtraLen;
3722 }
3723 }
3724 }
3725 rStrm.Seek( nOldPos );
3726 }
3727
WW8PLCFx_Book(SvStream * pTblSt,const WW8Fib & rFib)3728 WW8PLCFx_Book::WW8PLCFx_Book(SvStream* pTblSt, const WW8Fib& rFib)
3729 : WW8PLCFx(rFib.nVersion, false), pStatus(0), nIsEnd(0)
3730 {
3731 if( !rFib.fcPlcfbkf || !rFib.lcbPlcfbkf || !rFib.fcPlcfbkl ||
3732 !rFib.lcbPlcfbkl || !rFib.fcSttbfbkmk || !rFib.lcbSttbfbkmk )
3733 {
3734 pBook[0] = pBook[1] = 0;
3735 nIMax = 0;
3736 }
3737 else
3738 {
3739 pBook[0] = new WW8PLCFspecial(pTblSt,rFib.fcPlcfbkf,rFib.lcbPlcfbkf,4);
3740
3741 pBook[1] = new WW8PLCFspecial( pTblSt, rFib.fcPlcfbkl, rFib.lcbPlcfbkl,
3742 0, -1, true);
3743
3744 rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(rFib.chseTables);
3745
3746 WW8ReadSTTBF( (7 < rFib.nVersion), *pTblSt, rFib.fcSttbfbkmk,
3747 rFib.lcbSttbfbkmk, 0, eStructChrSet, aBookNames );
3748
3749 nIMax = aBookNames.size();
3750
3751 if( pBook[0]->GetIMax() < nIMax ) // Count of Bookmarks
3752 nIMax = pBook[0]->GetIMax();
3753 pStatus = new eBookStatus[ nIMax ];
3754 memset( pStatus, 0, nIMax * sizeof( eBookStatus ) );
3755 }
3756 }
3757
~WW8PLCFx_Book()3758 WW8PLCFx_Book::~WW8PLCFx_Book()
3759 {
3760 delete[] pStatus;
3761 delete pBook[1];
3762 delete pBook[0];
3763 }
3764
GetIdx() const3765 sal_uLong WW8PLCFx_Book::GetIdx() const
3766 {
3767 return nIMax ? pBook[0]->GetIdx() : 0;
3768 }
3769
SetIdx(sal_uLong nI)3770 void WW8PLCFx_Book::SetIdx( sal_uLong nI )
3771 {
3772 if( nIMax )
3773 pBook[0]->SetIdx( nI );
3774 }
3775
GetIdx2() const3776 sal_uLong WW8PLCFx_Book::GetIdx2() const
3777 {
3778 return nIMax ? ( pBook[1]->GetIdx() | ( ( nIsEnd ) ? 0x80000000 : 0 ) ) : 0;
3779 }
3780
SetIdx2(sal_uLong nI)3781 void WW8PLCFx_Book::SetIdx2( sal_uLong nI )
3782 {
3783 if( nIMax )
3784 {
3785 pBook[1]->SetIdx( nI & 0x7fffffff );
3786 nIsEnd = (sal_uInt16)( ( nI >> 31 ) & 1 ); // 0 oder 1
3787 }
3788 }
3789
SeekPos(WW8_CP nCpPos)3790 bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos)
3791 {
3792 if( !pBook[0] )
3793 return false;
3794
3795 bool bOk = pBook[0]->SeekPosExact( nCpPos );
3796 bOk &= pBook[1]->SeekPosExact( nCpPos );
3797 nIsEnd = 0;
3798
3799 return bOk;
3800 }
3801
Where()3802 WW8_CP WW8PLCFx_Book::Where()
3803 {
3804 return pBook[nIsEnd]->Where();
3805 }
3806
GetNoSprms(long & rStart,long & rEnd,long & rLen)3807 long WW8PLCFx_Book::GetNoSprms( long& rStart, long& rEnd, long& rLen )
3808 {
3809 void* pData;
3810 rEnd = LONG_MAX;
3811 rLen = 0;
3812
3813 if (!pBook[0] || !pBook[1] || !nIMax || (pBook[nIsEnd]->GetIdx()) >= nIMax)
3814 {
3815 rStart = rEnd = LONG_MAX;
3816 return -1;
3817 }
3818
3819 pBook[nIsEnd]->Get( rStart, pData ); // Pos. abfragen
3820
3821 return pBook[nIsEnd]->GetIdx();
3822 }
3823
3824 // Der Operator ++ hat eine Tuecke: Wenn 2 Bookmarks aneinandergrenzen, dann
3825 // sollte erst das Ende des ersten und dann der Anfang des 2. erreicht werden.
3826 // Liegen jedoch 2 Bookmarks der Laenge 0 aufeinander, *muss* von jedem Bookmark
3827 // erst der Anfang und dann das Ende gefunden werden.
3828 // Der Fall: ][
3829 // [...]
3830 // ][
3831 // ist noch nicht geloest, dabei muesste ich in den Anfangs- und Endindices
3832 // vor- und zurueckspringen, wobei ein weiterer Index oder ein Bitfeld
3833 // oder etwas aehnliches zum Merken der bereits abgearbeiteten Bookmarks
3834 // noetig wird.
operator ++(int)3835 WW8PLCFx& WW8PLCFx_Book::operator ++( int )
3836 {
3837 if( pBook[0] && pBook[1] && nIMax )
3838 {
3839 (*pBook[nIsEnd])++;
3840
3841 sal_uLong l0 = pBook[0]->Where();
3842 sal_uLong l1 = pBook[1]->Where();
3843 if( l0 < l1 )
3844 nIsEnd = 0;
3845 else if( l1 < l0 )
3846 nIsEnd = 1;
3847 else
3848 nIsEnd = ( nIsEnd ) ? 0 : 1;
3849 }
3850 return *this;
3851 }
3852
GetLen() const3853 long WW8PLCFx_Book::GetLen() const
3854 {
3855 if( nIsEnd )
3856 {
3857 ASSERT( !this, "Falscher Aufruf (1) von PLCF_Book::GetLen()" );
3858 return 0;
3859 }
3860 void * p;
3861 WW8_CP nStartPos;
3862 if( !pBook[0]->Get( nStartPos, p ) )
3863 {
3864 ASSERT( !this, "Falscher Aufruf (2) von PLCF_Book::GetLen()" );
3865 return 0;
3866 }
3867 sal_uInt16 nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
3868 long nNum = pBook[1]->GetPos( nEndIdx );
3869 nNum -= nStartPos;
3870 return nNum;
3871 }
3872
SetStatus(sal_uInt16 nIndex,eBookStatus eStat)3873 void WW8PLCFx_Book::SetStatus(sal_uInt16 nIndex, eBookStatus eStat )
3874 {
3875 ASSERT(nIndex < nIMax, "set status of non existing bookmark!");
3876 if ( nIndex < nIMax )
3877 pStatus[nIndex] = (eBookStatus)( pStatus[nIndex] | eStat );
3878 }
3879
GetStatus() const3880 eBookStatus WW8PLCFx_Book::GetStatus() const
3881 {
3882 if( !pStatus )
3883 return BOOK_NORMAL;
3884 long nEndIdx = GetHandle();
3885 return ( nEndIdx < nIMax ) ? pStatus[nEndIdx] : BOOK_NORMAL;
3886 }
3887
GetHandle() const3888 long WW8PLCFx_Book::GetHandle() const
3889 {
3890 if( !pBook[0] || !pBook[1] )
3891 return LONG_MAX;
3892
3893 if( nIsEnd )
3894 return pBook[1]->GetIdx();
3895 else
3896 {
3897 if (const void* p = pBook[0]->GetData(pBook[0]->GetIdx()))
3898 return SVBT16ToShort( *((SVBT16*)p) );
3899 else
3900 return LONG_MAX;
3901 }
3902 }
3903
GetBookmark(long nStart,long nEnd,sal_uInt16 & nIndex)3904 String WW8PLCFx_Book::GetBookmark(long nStart,long nEnd, sal_uInt16 &nIndex)
3905 {
3906 bool bFound = false;
3907 sal_uInt16 i = 0;
3908 if( pBook[0] && pBook[1] )
3909 {
3910 WW8_CP nStartAkt, nEndAkt;
3911 do
3912 {
3913 void* p;
3914 sal_uInt16 nEndIdx;
3915
3916 if( pBook[0]->GetData( i, nStartAkt, p ) && p )
3917 nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
3918 else
3919 {
3920 ASSERT( !this, "Bookmark-EndIdx nicht lesbar" );
3921 nEndIdx = i;
3922 }
3923
3924 nEndAkt = pBook[1]->GetPos( nEndIdx );
3925
3926 if ((nStartAkt >= nStart) && (nEndAkt <= nEnd))
3927 {
3928 nIndex = i;
3929 bFound=true;
3930 break;
3931 }
3932 ++i;
3933 }
3934 while (i < pBook[0]->GetIMax());
3935 }
3936 return bFound ? aBookNames[i] : aEmptyStr;
3937 }
3938
MapName(String & rName)3939 bool WW8PLCFx_Book::MapName(String& rName)
3940 {
3941 if( !pBook[0] || !pBook[1] )
3942 return false;
3943
3944 bool bFound = false;
3945 sal_uInt16 i = 0;
3946 WW8_CP nStartAkt, nEndAkt;
3947 do
3948 {
3949 void* p;
3950 sal_uInt16 nEndIdx;
3951
3952 if( pBook[0]->GetData( i, nStartAkt, p ) && p )
3953 nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
3954 else
3955 {
3956 ASSERT( !this, "Bookmark-EndIdx nicht lesbar" );
3957 nEndIdx = i;
3958 }
3959 nEndAkt = pBook[1]->GetPos( nEndIdx );
3960 if (COMPARE_EQUAL == rName.CompareIgnoreCaseToAscii(aBookNames[i]))
3961 {
3962 rName = aBookNames[i];
3963 bFound = true;
3964 }
3965 ++i;
3966 }
3967 while (!bFound && i < pBook[0]->GetIMax());
3968 return bFound;
3969 }
3970
GetName() const3971 const String* WW8PLCFx_Book::GetName() const
3972 {
3973 const String *pRet = 0;
3974 if (!nIsEnd && (pBook[0]->GetIdx() < nIMax))
3975 pRet = &(aBookNames[pBook[0]->GetIdx()]);
3976 return pRet;
3977 }
3978
3979 //-----------------------------------------
3980 // WW8PLCFMan
3981 //-----------------------------------------
3982
3983 #ifndef DUMP
3984
3985 // Am Ende eines Absatzes reichen bei WW6 die Attribute bis hinter das <CR>.
3986 // Das wird fuer die Verwendung mit dem SW um 1 Zeichen zurueckgesetzt, wenn
3987 // dadurch kein AErger zu erwarten ist.
AdjustEnds(WW8PLCFxDesc & rDesc)3988 void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc& rDesc )
3989 {
3990 //Store old end position for supercool new property finder that uses
3991 //cp instead of fc's as nature intended
3992 rDesc.nOrigEndPos = rDesc.nEndPos;
3993 rDesc.nOrigStartPos = rDesc.nStartPos;
3994
3995 /*
3996 Normally given ^XXX{para end}^ we don't actually insert a para end
3997 character into the document, so we clip the para end property one to the
3998 left to make the para properties end when the paragraph text does. In a
3999 drawing textbox we actually do insert a para end character, so we don't
4000 clip it. Making the para end properties end after the para end char.
4001 */
4002 if (GetDoingDrawTextBox())
4003 return;
4004
4005 if ( (&rDesc == pPap) && rDesc.bRealLineEnd )
4006 {
4007 if ( pPap->nEndPos != LONG_MAX ) // Para adjust
4008 {
4009 nLineEnd = pPap->nEndPos;// nLineEnd zeigt *hinter* das <CR>
4010 pPap->nEndPos--; // Absatzende um 1 Zeichen verkuerzen
4011
4012 // gibt es bereits ein CharAttr-Ende das auf das jetzige
4013 // Absatzende zeigt ? ... dann auch um 1 Zeichen verkuerzen
4014 if (pChp->nEndPos == nLineEnd)
4015 pChp->nEndPos--;
4016
4017 // gibt es bereits ein Sep-Ende, das auf das jetzige Absatzende
4018 // zeigt ? ... dann auch um 1 Zeichen verkuerzen
4019 if( pSep->nEndPos == nLineEnd )
4020 pSep->nEndPos--;
4021 }
4022 }
4023 else if ( (&rDesc == pChp) || (&rDesc == pSep) )
4024 {
4025 // Char Adjust oder Sep Adjust Wenn Ende Char-Attr == Absatzende ...
4026 if( (rDesc.nEndPos == nLineEnd) && (rDesc.nEndPos > rDesc.nStartPos) )
4027 rDesc.nEndPos--; // ... dann um 1 Zeichen verkuerzen
4028 }
4029 }
4030
ReduceByOffset()4031 void WW8PLCFxDesc::ReduceByOffset()
4032 {
4033 ASSERT((LONG_MAX == nStartPos) || (nStartPos <= nEndPos),
4034 "Attr-Anfang und -Ende ueber Kreuz" );
4035
4036 if( nStartPos != LONG_MAX )
4037 {
4038 /*
4039 ##516##,##517##
4040 Force the property change to happen at the beginning of this
4041 subdocument, same as in GetNewNoSprms, except that the target type is
4042 attributes attached to a piece that might span subdocument boundaries
4043 */
4044 if (nCpOfs > nStartPos)
4045 nStartPos = 0;
4046 else
4047 nStartPos -= nCpOfs;
4048 }
4049 if( nEndPos != LONG_MAX )
4050 {
4051 ASSERT(nCpOfs <= nEndPos,
4052 "oh oh, so much for the subdocument piece theory");
4053 nEndPos -= nCpOfs;
4054 }
4055 }
4056
GetNewSprms(WW8PLCFxDesc & rDesc)4057 void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc& rDesc )
4058 {
4059 rDesc.pPLCFx->GetSprms(&rDesc);
4060 rDesc.ReduceByOffset();
4061
4062 rDesc.bFirstSprm = true;
4063 AdjustEnds( rDesc );
4064 rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
4065 }
4066
GetNewNoSprms(WW8PLCFxDesc & rDesc)4067 void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc& rDesc )
4068 {
4069 rDesc.nCp2OrIdx = rDesc.pPLCFx->GetNoSprms(rDesc.nStartPos, rDesc.nEndPos,
4070 rDesc.nSprmsLen);
4071
4072 ASSERT((LONG_MAX == rDesc.nStartPos) || (rDesc.nStartPos <= rDesc.nEndPos),
4073 "Attr-Anfang und -Ende ueber Kreuz" );
4074
4075 rDesc.ReduceByOffset();
4076
4077 rDesc.bFirstSprm = true;
4078 rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
4079 }
4080
GetId(const WW8PLCFxDesc * p) const4081 sal_uInt16 WW8PLCFMan::GetId(const WW8PLCFxDesc* p) const
4082 {
4083 sal_uInt16 nId;
4084
4085 if (p == pFld)
4086 nId = eFLD;
4087 else if (p->nSprmsLen > 0)
4088 nId = maSprmParser.GetSprmId(p->pMemPos);
4089 else
4090 nId = 0; // Id = 0 for empty attributes
4091
4092 return nId;
4093 }
4094
WW8PLCFMan(WW8ScannerBase * pBase,short nType,long nStartCp,bool bDoingDrawTextBox)4095 WW8PLCFMan::WW8PLCFMan(WW8ScannerBase* pBase, short nType, long nStartCp,
4096 bool bDoingDrawTextBox)
4097 : maSprmParser(pBase->pWw8Fib->nVersion),
4098 mbDoingDrawTextBox(bDoingDrawTextBox)
4099 {
4100 pWwFib = pBase->pWw8Fib;
4101
4102 nLastWhereIdxCp = 0;
4103 memset( aD, 0, sizeof( aD ) );
4104 nLineEnd = LONG_MAX;
4105 nManType = nType;
4106 sal_uInt16 i;
4107
4108 if( MAN_MAINTEXT == nType )
4109 {
4110 // Suchreihenfolge der Attribute
4111 nPLCF = MAN_ANZ_PLCF;
4112 pFld = &aD[0];
4113 pBkm = &aD[1];
4114 pEdn = &aD[2];
4115 pFtn = &aD[3];
4116 pAnd = &aD[4];
4117
4118 pPcd = ( pBase->pPLCFx_PCD ) ? &aD[5] : 0;
4119 //pPcdA index == pPcd index + 1
4120 pPcdA = ( pBase->pPLCFx_PCDAttrs ) ? &aD[6] : 0;
4121
4122 pChp = &aD[7];
4123 pPap = &aD[8];
4124 pSep = &aD[9];
4125
4126 pSep->pPLCFx = pBase->pSepPLCF;
4127 pFtn->pPLCFx = pBase->pFtnPLCF;
4128 pEdn->pPLCFx = pBase->pEdnPLCF;
4129 pBkm->pPLCFx = pBase->pBook;
4130 pAnd->pPLCFx = pBase->pAndPLCF;
4131
4132 }
4133 else
4134 {
4135 // Suchreihenfolge der Attribute
4136 nPLCF = 7;
4137 pFld = &aD[0];
4138 pBkm = ( pBase->pBook ) ? &aD[1] : 0;
4139
4140 pPcd = ( pBase->pPLCFx_PCD ) ? &aD[2] : 0;
4141 //pPcdA index == pPcd index + 1
4142 pPcdA= ( pBase->pPLCFx_PCDAttrs ) ? &aD[3] : 0;
4143
4144 pChp = &aD[4];
4145 pPap = &aD[5];
4146 pSep = &aD[6]; // Dummy
4147
4148 pAnd = pFtn = pEdn = 0; // unbenutzt bei SpezText
4149 }
4150
4151 pChp->pPLCFx = pBase->pChpPLCF;
4152 pPap->pPLCFx = pBase->pPapPLCF;
4153 if( pPcd )
4154 pPcd->pPLCFx = pBase->pPLCFx_PCD;
4155 if( pPcdA )
4156 pPcdA->pPLCFx= pBase->pPLCFx_PCDAttrs;
4157 if( pBkm )
4158 pBkm->pPLCFx = pBase->pBook;
4159
4160 pMagicTables = pBase->pMagicTables;
4161
4162 switch( nType ) // Feld-Initialisierung
4163 {
4164 case MAN_HDFT:
4165 pFld->pPLCFx = pBase->pFldHdFtPLCF;
4166 nCpO = pWwFib->ccpText + pWwFib->ccpFtn;
4167 pFdoa = pBase->pHdFtFdoa;
4168 pTxbx = pBase->pHdFtTxbx;
4169 pTxbxBkd = pBase->pHdFtTxbxBkd;
4170 break;
4171 case MAN_FTN:
4172 pFld->pPLCFx = pBase->pFldFtnPLCF;
4173 nCpO = pWwFib->ccpText;
4174 pFdoa = pTxbx = pTxbxBkd = 0;
4175 break;
4176 case MAN_EDN:
4177 pFld->pPLCFx = pBase->pFldEdnPLCF;
4178 nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr +
4179 pWwFib->ccpAtn;
4180 pFdoa = pTxbx = pTxbxBkd = 0;
4181 break;
4182 case MAN_AND:
4183 pFld->pPLCFx = pBase->pFldAndPLCF;
4184 nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr;
4185 pFdoa = pTxbx = pTxbxBkd = 0;
4186 break;
4187 case MAN_TXBX:
4188 pFld->pPLCFx = pBase->pFldTxbxPLCF;
4189 nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr +
4190 pWwFib->ccpMcr + pWwFib->ccpAtn + pWwFib->ccpEdn;
4191 pTxbx = pBase->pMainTxbx;
4192 pTxbxBkd = pBase->pMainTxbxBkd;
4193 pFdoa = 0;
4194 break;
4195 case MAN_TXBX_HDFT:
4196 pFld->pPLCFx = pBase->pFldTxbxHdFtPLCF;
4197 nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr +
4198 pWwFib->ccpMcr + pWwFib->ccpAtn + pWwFib->ccpEdn +
4199 pWwFib->ccpTxbx;
4200 pTxbx = pBase->pHdFtTxbx;
4201 pTxbxBkd = pBase->pHdFtTxbxBkd;
4202 pFdoa = 0;
4203 break;
4204 default:
4205 pFld->pPLCFx = pBase->pFldPLCF;
4206 nCpO = 0;
4207 pFdoa = pBase->pMainFdoa;
4208 pTxbx = pBase->pMainTxbx;
4209 pTxbxBkd = pBase->pMainTxbxBkd;
4210 break;
4211 }
4212
4213 if( nStartCp || nCpO )
4214 SeekPos( nStartCp ); // PLCFe auf Text-StartPos einstellen
4215
4216 // initialisieren der Member-Vars Low-Level
4217 GetChpPLCF()->ResetAttrStartEnd();
4218 GetPapPLCF()->ResetAttrStartEnd();
4219 for( i=0; i < nPLCF; i++)
4220 {
4221 WW8PLCFxDesc* p = &aD[i];
4222
4223 /*
4224 ##516##,##517##
4225 For subdocuments we modify the cp of properties to be relative to
4226 the beginning of subdocuments, we should also do the same for
4227 piecetable changes, and piecetable properties, otherwise a piece
4228 change that happens in a subdocument is lost.
4229 */
4230 p->nCpOfs = ( p == pChp || p == pPap || p == pBkm || p == pPcd ||
4231 p == pPcdA ) ? nCpO : 0;
4232
4233 p->nCp2OrIdx = 0;
4234 p->bFirstSprm = false;
4235 p->pIdStk = 0;
4236
4237 if ((p == pChp) || (p == pPap))
4238 p->nStartPos = p->nEndPos = nStartCp;
4239 else
4240 p->nStartPos = p->nEndPos = LONG_MAX;
4241 }
4242
4243 // initialisieren der Member-Vars High-Level
4244 for( i=0; i<nPLCF; i++){
4245 WW8PLCFxDesc* p = &aD[i];
4246
4247 if( !p->pPLCFx )
4248 {
4249 p->nStartPos = p->nEndPos = LONG_MAX;
4250 continue;
4251 }
4252
4253 if( p->pPLCFx->IsSprm() )
4254 {
4255 // Vorsicht: nEndPos muss bereits
4256 p->pIdStk = new std::stack<sal_uInt16>;
4257 if ((p == pChp) || (p == pPap))
4258 {
4259 WW8_CP nTemp = p->nEndPos+p->nCpOfs;
4260 p->pMemPos = 0;
4261 p->nSprmsLen = 0;
4262 p->nStartPos = nTemp;
4263 if (!(*p->pPLCFx).SeekPos(p->nStartPos))
4264 p->nEndPos = p->nStartPos = LONG_MAX;
4265 else
4266 GetNewSprms( *p );
4267 }
4268 else
4269 GetNewSprms( *p ); // bei allen PLCFen initialisiert sein
4270 }
4271 else if( p->pPLCFx )
4272 GetNewNoSprms( *p );
4273 }
4274 }
4275
~WW8PLCFMan()4276 WW8PLCFMan::~WW8PLCFMan()
4277 {
4278 for( sal_uInt16 i=0; i<nPLCF; i++)
4279 delete aD[i].pIdStk;
4280 }
4281
4282 // 0. welche Attr.-Klasse,
4283 // 1. ob ein Attr.-Start ist,
4284 // 2. CP, wo ist naechste Attr.-Aenderung
WhereIdx(bool * pbStart,long * pPos) const4285 sal_uInt16 WW8PLCFMan::WhereIdx(bool* pbStart, long* pPos) const
4286 {
4287 ASSERT(nPLCF,"What the hell");
4288 long nNext = LONG_MAX; // SuchReihenfolge:
4289 sal_uInt16 nNextIdx = nPLCF;// first ending found ( CHP, PAP, ( SEP ) ),
4290 bool bStart = true; // dann Anfaenge finden ( ( SEP ), PAP, CHP )
4291 sal_uInt16 i;
4292 const WW8PLCFxDesc* pD;
4293 for (i=0; i < nPLCF; i++)
4294 {
4295 pD = &aD[i];
4296 if (pD != pPcdA)
4297 {
4298 if( (pD->nEndPos < nNext) && (pD->nStartPos == LONG_MAX) )
4299 {
4300 // sonst ist Anfang = Ende
4301 nNext = pD->nEndPos;
4302 nNextIdx = i;
4303 bStart = false;
4304 }
4305 }
4306 }
4307 for (i=nPLCF; i > 0; i--)
4308 {
4309 pD = &aD[i-1];
4310 if (pD != pPcdA)
4311 {
4312 if( pD->nStartPos < nNext )
4313 {
4314 nNext = pD->nStartPos;
4315 nNextIdx = i-1;
4316 bStart = true;
4317 }
4318 }
4319 }
4320 if( pPos )
4321 *pPos = nNext;
4322 if( pbStart )
4323 *pbStart = bStart;
4324 return nNextIdx;
4325 }
4326
4327 // gibt die CP-Pos der naechsten Attribut-Aenderung zurueck
Where() const4328 WW8_CP WW8PLCFMan::Where() const
4329 {
4330 long l;
4331 WhereIdx(0, &l);
4332 return l;
4333 }
4334
SeekPos(long nNewCp)4335 void WW8PLCFMan::SeekPos( long nNewCp )
4336 {
4337 pChp->pPLCFx->SeekPos( nNewCp + nCpO ); // Attribute neu
4338 pPap->pPLCFx->SeekPos( nNewCp + nCpO ); // aufsetzen
4339 pFld->pPLCFx->SeekPos( nNewCp );
4340 if( pPcd )
4341 pPcd->pPLCFx->SeekPos( nNewCp + nCpO );
4342 if( pBkm )
4343 pBkm->pPLCFx->SeekPos( nNewCp + nCpO );
4344 }
4345
SaveAllPLCFx(WW8PLCFxSaveAll & rSave) const4346 void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll& rSave ) const
4347 {
4348 sal_uInt16 i, n=0;
4349 if( pPcd )
4350 pPcd->Save( rSave.aS[n++] );
4351 if( pPcdA )
4352 pPcdA->Save( rSave.aS[n++] );
4353
4354 for(i=0; i<nPLCF; ++i)
4355 if( pPcd != &aD[i] && pPcdA != &aD[i] )
4356 aD[i].Save( rSave.aS[n++] );
4357 }
4358
RestoreAllPLCFx(const WW8PLCFxSaveAll & rSave)4359 void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll& rSave )
4360 {
4361 sal_uInt16 i, n=0;
4362 if( pPcd )
4363 pPcd->Restore( rSave.aS[n++] );
4364 if( pPcdA )
4365 pPcdA->Restore( rSave.aS[n++] );
4366
4367 for(i=0; i<nPLCF; ++i)
4368 if( pPcd != &aD[i] && pPcdA != &aD[i] )
4369 aD[i].Restore( rSave.aS[n++] );
4370 }
4371
GetSprmStart(short nIdx,WW8PLCFManResult * pRes) const4372 void WW8PLCFMan::GetSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
4373 {
4374 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4375
4376 // Pruefen !!!
4377
4378 pRes->nMemLen = 0;
4379
4380 const WW8PLCFxDesc* p = &aD[nIdx];
4381
4382 // first Sprm in a Group
4383 if( p->bFirstSprm )
4384 {
4385 if( p == pPap )
4386 pRes->nFlags |= MAN_MASK_NEW_PAP;
4387 else if( p == pSep )
4388 pRes->nFlags |= MAN_MASK_NEW_SEP;
4389 }
4390 pRes->pMemPos = p->pMemPos;
4391 pRes->nSprmId = GetId(p);
4392 pRes->nCp2OrIdx = p->nCp2OrIdx;
4393 if (p->nSprmsLen)
4394 {
4395 // Length of actual sprm
4396 pRes->nMemLen = maSprmParser.GetSprmSize(pRes->nSprmId, pRes->pMemPos);
4397 }
4398 }
4399
GetSprmEnd(short nIdx,WW8PLCFManResult * pRes) const4400 void WW8PLCFMan::GetSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
4401 {
4402 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4403
4404 const WW8PLCFxDesc* p = &aD[nIdx];
4405
4406 if (!(p->pIdStk->empty()))
4407 pRes->nSprmId = p->pIdStk->top(); // get end position
4408 else
4409 {
4410 ASSERT( !this, "No Id on the Stack" );
4411 pRes->nSprmId = 0;
4412 }
4413 }
4414
GetNoSprmStart(short nIdx,WW8PLCFManResult * pRes) const4415 void WW8PLCFMan::GetNoSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
4416 {
4417 const WW8PLCFxDesc* p = &aD[nIdx];
4418
4419 pRes->nCpPos = p->nStartPos;
4420 pRes->nMemLen = p->nSprmsLen;
4421 pRes->nCp2OrIdx = p->nCp2OrIdx;
4422
4423 if( p == pFld )
4424 pRes->nSprmId = eFLD;
4425 else if( p == pFtn )
4426 pRes->nSprmId = eFTN;
4427 else if( p == pEdn )
4428 pRes->nSprmId = eEDN;
4429 else if( p == pBkm )
4430 pRes->nSprmId = eBKN;
4431 else if( p == pAnd )
4432 pRes->nSprmId = eAND;
4433 else if( p == pPcd )
4434 {
4435 //We slave the piece table attributes to the piece table, the piece
4436 //table attribute iterator contains the sprms for this piece.
4437 GetSprmStart( nIdx+1, pRes );
4438 }
4439 else
4440 pRes->nSprmId = 0; // default: not found
4441 }
4442
GetNoSprmEnd(short nIdx,WW8PLCFManResult * pRes) const4443 void WW8PLCFMan::GetNoSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
4444 {
4445 pRes->nMemLen = -1; // Ende-Kennzeichen
4446
4447 if( &aD[nIdx] == pBkm )
4448 pRes->nSprmId = eBKN;
4449 else if( &aD[nIdx] == pPcd )
4450 {
4451 //We slave the piece table attributes to the piece table, the piece
4452 //table attribute iterator contains the sprms for this piece.
4453 GetSprmEnd( nIdx+1, pRes );
4454 }
4455 else
4456 pRes->nSprmId = 0;
4457 }
4458
TransferOpenSprms(std::stack<sal_uInt16> & rStack)4459 bool WW8PLCFMan::TransferOpenSprms(std::stack<sal_uInt16> &rStack)
4460 {
4461 for (int i = 0; i < nPLCF; ++i)
4462 {
4463 WW8PLCFxDesc* p = &aD[i];
4464 if (!p || !p->pIdStk)
4465 continue;
4466 while (!p->pIdStk->empty())
4467 {
4468 rStack.push(p->pIdStk->top());
4469 p->pIdStk->pop();
4470 }
4471 }
4472 return rStack.empty();
4473 }
4474
AdvSprm(short nIdx,bool bStart)4475 void WW8PLCFMan::AdvSprm(short nIdx, bool bStart)
4476 {
4477 WW8PLCFxDesc* p = &aD[nIdx]; // Sprm-Klasse(!) ermitteln
4478
4479 p->bFirstSprm = false;
4480 if( bStart )
4481 {
4482 sal_uInt16 nLastId = GetId(p);
4483 p->pIdStk->push(nLastId); // merke Id fuer Attribut-Ende
4484
4485 if( p->nSprmsLen )
4486 { /*
4487 Pruefe, ob noch Sprm(s) abzuarbeiten sind
4488 */
4489 if( p->pMemPos )
4490 {
4491 // Length of last sprm
4492 sal_uInt16 nSprmL = maSprmParser.GetSprmSize(nLastId, p->pMemPos);
4493
4494 // Gesamtlaenge Sprms um SprmLaenge verringern
4495 p->nSprmsLen -= nSprmL;
4496
4497 // Pos des evtl. naechsten Sprm
4498 if (p->nSprmsLen < maSprmParser.MinSprmLen())
4499 {
4500 // sicherheitshalber auf Null setzen, da Enden folgen!
4501 p->pMemPos = 0;
4502 p->nSprmsLen = 0;
4503 }
4504 else
4505 p->pMemPos += nSprmL;
4506 }
4507 else
4508 p->nSprmsLen = 0;
4509 }
4510 if (p->nSprmsLen < maSprmParser.MinSprmLen())
4511 p->nStartPos = LONG_MAX; // es folgen Enden
4512 }
4513 else
4514 {
4515 if (!(p->pIdStk->empty()))
4516 p->pIdStk->pop();
4517 if (p->pIdStk->empty())
4518 {
4519 if ( (p == pChp) || (p == pPap) )
4520 {
4521 p->pMemPos = 0;
4522 p->nSprmsLen = 0;
4523 p->nStartPos = p->nOrigEndPos+p->nCpOfs;
4524
4525 /*
4526 #93702#
4527 On failed seek we have run out of sprms, probably. But if its
4528 a fastsaved file (has pPcd) then we may be just in a sprm free
4529 gap between pieces that have them, so set dirty flag in sprm
4530 finder to consider than.
4531 */
4532 if (!(*p->pPLCFx).SeekPos(p->nStartPos))
4533 {
4534 p->nEndPos = LONG_MAX;
4535 p->pPLCFx->SetDirty(true);
4536 }
4537 if (!p->pPLCFx->GetDirty() || pPcd)
4538 GetNewSprms( *p );
4539 p->pPLCFx->SetDirty(false);
4540
4541 /*
4542 #i2325#
4543 To get the character and paragraph properties you first get
4544 the pap and chp and then apply the fastsaved pPcd properties
4545 to the range. If a pap or chp starts inside the pPcd range
4546 then we must bring the current pPcd range to a halt so as to
4547 end those sprms, then the pap/chp will be processed, and then
4548 we must force a restart of the pPcd on that pap/chp starting
4549 boundary. Doing that effectively means that the pPcd sprms will
4550 be applied to the new range. Not doing it means that the pPcd
4551 sprms will only be applied to the first pap/chp set of
4552 properties contained in the pap/chp range.
4553
4554 So we bring the pPcd to a halt on this location here, by
4555 settings its end to the current start, then store the starting
4556 position of the current range to clipstart. The pPcd sprms
4557 will end as normal (albeit earlier than originally expected),
4558 and the existence of a clipstart will force the pPcd iterater
4559 to reread the current set of sprms instead of advancing to its
4560 next set. Then the clipstart will be set as the starting
4561 position which will force them to be applied directly after
4562 the pap and chps.
4563 */
4564 if (pPcd && ((p->nStartPos > pPcd->nStartPos) ||
4565 (pPcd->nStartPos == LONG_MAX)) &&
4566 (pPcd->nEndPos != p->nStartPos))
4567 {
4568 pPcd->nEndPos = p->nStartPos;
4569 ((WW8PLCFx_PCD *)(pPcd->pPLCFx))->SetClipStart(
4570 p->nStartPos);
4571 }
4572
4573 }
4574 else
4575 {
4576 (*p->pPLCFx)++; // next Group of Sprms
4577 p->pMemPos = 0; // !!!
4578 p->nSprmsLen = 0;
4579 GetNewSprms( *p );
4580 }
4581 ASSERT( p->nStartPos <= p->nEndPos, "Attribut ueber Kreuz" );
4582 }
4583 }
4584 }
4585
AdvNoSprm(short nIdx,bool bStart)4586 void WW8PLCFMan::AdvNoSprm(short nIdx, bool bStart)
4587 {
4588 /*
4589 For the case of a piece table we slave the piece table attribute iterator
4590 to the piece table and access it through that only. They are two separate
4591 structures, but act together as one logical one. The attributes only go
4592 to the next entry when the piece changes
4593 */
4594 WW8PLCFxDesc* p = &aD[nIdx];
4595
4596 if( p == pPcd )
4597 {
4598 AdvSprm(nIdx+1,bStart);
4599 if( bStart )
4600 p->nStartPos = aD[nIdx+1].nStartPos;
4601 else
4602 {
4603 if (aD[nIdx+1].pIdStk->empty())
4604 {
4605 WW8PLCFx_PCD *pTemp = (WW8PLCFx_PCD*)(pPcd->pPLCFx);
4606 /*
4607 #i2325#
4608 As per normal, go on to the next set of properties, i.e. we
4609 have traversed over to the next piece. With a clipstart set
4610 we are being told to reread the current piece sprms so as to
4611 reapply them to a new chp or pap range.
4612 */
4613 if (pTemp->GetClipStart() == -1)
4614 (*p->pPLCFx)++;
4615 p->pMemPos = 0;
4616 p->nSprmsLen = 0;
4617 GetNewSprms( aD[nIdx+1] );
4618 GetNewNoSprms( *p );
4619 if (pTemp->GetClipStart() != -1)
4620 {
4621 /*
4622 #i2325#, now we will force our starting position to the
4623 clipping start so as to force the application of these
4624 sprms after the current pap/chp sprms so as to apply the
4625 fastsave sprms to the current range.
4626 */
4627 p->nStartPos = pTemp->GetClipStart();
4628 pTemp->SetClipStart(-1);
4629 }
4630 }
4631 }
4632 }
4633 else
4634 { // NoSprm ohne Ende
4635 (*p->pPLCFx)++;
4636 p->pMemPos = 0; // MemPos ungueltig
4637 p->nSprmsLen = 0;
4638 GetNewNoSprms( *p );
4639 }
4640 }
4641
operator ++(int)4642 WW8PLCFMan& WW8PLCFMan::operator ++(int)
4643 {
4644 bool bStart;
4645 sal_uInt16 nIdx = WhereIdx(&bStart);
4646 if (nIdx < nPLCF)
4647 {
4648 WW8PLCFxDesc* p = &aD[nIdx];
4649
4650 p->bFirstSprm = true; // Default
4651
4652 if( p->pPLCFx->IsSprm() )
4653 AdvSprm( nIdx, bStart );
4654 else // NoSprm
4655 AdvNoSprm( nIdx, bStart );
4656 }
4657 return *this;
4658 }
4659
4660 // Rueckgabe true fuer Anfang eines Attributes oder Fehler,
4661 // false fuer Ende d. Attr
4662 // Restliche Rueckgabewerte werden in der vom Aufrufer zu stellenden Struktur
4663 // WW8PclxManResults geliefert.
Get(WW8PLCFManResult * pRes) const4664 bool WW8PLCFMan::Get(WW8PLCFManResult* pRes) const
4665 {
4666 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4667 bool bStart;
4668 sal_uInt16 nIdx = WhereIdx(&bStart);
4669
4670 if( nIdx >= nPLCF )
4671 {
4672 ASSERT( !this, "Position not found" );
4673 return true;
4674 }
4675
4676 if( aD[nIdx].pPLCFx->IsSprm() )
4677 {
4678 if( bStart )
4679 {
4680 GetSprmStart( nIdx, pRes );
4681 return true;
4682 }
4683 else
4684 {
4685 GetSprmEnd( nIdx, pRes );
4686 return false;
4687 }
4688 }
4689 else
4690 {
4691 if( bStart )
4692 {
4693 GetNoSprmStart( nIdx, pRes );
4694 return true;
4695 }
4696 else
4697 {
4698 GetNoSprmEnd( nIdx, pRes );
4699 return false;
4700 }
4701 }
4702 }
4703
GetColl() const4704 sal_uInt16 WW8PLCFMan::GetColl() const
4705 {
4706 if( pPap->pPLCFx )
4707 return pPap->pPLCFx->GetIstd();
4708 else
4709 {
4710 ASSERT( !this, "GetColl ohne PLCF_Pap" );
4711 return 0;
4712 }
4713 }
4714
GetFld() const4715 WW8PLCFx_FLD* WW8PLCFMan::GetFld() const
4716 {
4717 return (WW8PLCFx_FLD*)pFld->pPLCFx;
4718 }
4719
HasParaSprm(sal_uInt16 nId) const4720 const sal_uInt8* WW8PLCFMan::HasParaSprm( sal_uInt16 nId ) const
4721 {
4722 return ((WW8PLCFx_Cp_FKP*)pPap->pPLCFx)->HasSprm( nId );
4723 }
4724
HasCharSprm(sal_uInt16 nId) const4725 const sal_uInt8* WW8PLCFMan::HasCharSprm( sal_uInt16 nId ) const
4726 {
4727 return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm( nId );
4728 }
4729
HasCharSprm(sal_uInt16 nId,std::vector<const sal_uInt8 * > & rResult) const4730 bool WW8PLCFMan::HasCharSprm(sal_uInt16 nId,
4731 std::vector<const sal_uInt8 *> &rResult) const
4732 {
4733 return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm(nId, rResult);
4734 }
4735
4736 #endif // !DUMP
4737
Save(WW8PLCFxSave1 & rSave) const4738 void WW8PLCFx::Save( WW8PLCFxSave1& rSave ) const
4739 {
4740 rSave.nPLCFxPos = GetIdx();
4741 rSave.nPLCFxPos2 = GetIdx2();
4742 rSave.nPLCFxMemOfs = 0;
4743 rSave.nStartFC = GetStartFc();
4744 }
4745
Restore(const WW8PLCFxSave1 & rSave)4746 void WW8PLCFx::Restore( const WW8PLCFxSave1& rSave )
4747 {
4748 SetIdx( rSave.nPLCFxPos );
4749 SetIdx2( rSave.nPLCFxPos2 );
4750 SetStartFc( rSave.nStartFC );
4751 }
4752
GetIdx2() const4753 sal_uLong WW8PLCFx_Cp_FKP::GetIdx2() const
4754 {
4755 return GetPCDIdx();
4756 }
4757
SetIdx2(sal_uLong nIdx)4758 void WW8PLCFx_Cp_FKP::SetIdx2( sal_uLong nIdx )
4759 {
4760 SetPCDIdx( nIdx );
4761 }
4762
Save(WW8PLCFxSave1 & rSave) const4763 void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1& rSave ) const
4764 {
4765 WW8PLCFx::Save( rSave );
4766
4767 rSave.nAttrStart = nAttrStart;
4768 rSave.nAttrEnd = nAttrEnd;
4769 rSave.bLineEnd = bLineEnd;
4770 }
4771
Restore(const WW8PLCFxSave1 & rSave)4772 void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1& rSave )
4773 {
4774 WW8PLCFx::Restore( rSave );
4775
4776 nAttrStart = rSave.nAttrStart;
4777 nAttrEnd = rSave.nAttrEnd;
4778 bLineEnd = rSave.bLineEnd;
4779 }
4780
Save(WW8PLCFxSave1 & rSave) const4781 void WW8PLCFxDesc::Save( WW8PLCFxSave1& rSave ) const
4782 {
4783 if( pPLCFx )
4784 {
4785 pPLCFx->Save( rSave );
4786 if( pPLCFx->IsSprm() )
4787 {
4788 WW8PLCFxDesc aD;
4789 aD.nStartPos = nOrigStartPos+nCpOfs;
4790 aD.nCpOfs = rSave.nCpOfs = nCpOfs;
4791 if (!(pPLCFx->SeekPos(aD.nStartPos)))
4792 {
4793 aD.nEndPos = LONG_MAX;
4794 pPLCFx->SetDirty(true);
4795 }
4796 pPLCFx->GetSprms(&aD);
4797 pPLCFx->SetDirty(false);
4798 aD.ReduceByOffset();
4799 rSave.nStartCp = aD.nStartPos;
4800 rSave.nPLCFxMemOfs = nOrigSprmsLen - nSprmsLen;
4801 }
4802 }
4803 }
4804
Restore(const WW8PLCFxSave1 & rSave)4805 void WW8PLCFxDesc::Restore( const WW8PLCFxSave1& rSave )
4806 {
4807 if( pPLCFx )
4808 {
4809 pPLCFx->Restore( rSave );
4810 if( pPLCFx->IsSprm() )
4811 {
4812 WW8PLCFxDesc aD;
4813 aD.nStartPos = rSave.nStartCp+rSave.nCpOfs;
4814 nCpOfs = aD.nCpOfs = rSave.nCpOfs;
4815 if (!(pPLCFx->SeekPos(aD.nStartPos)))
4816 {
4817 aD.nEndPos = LONG_MAX;
4818 pPLCFx->SetDirty(true);
4819 }
4820 pPLCFx->GetSprms(&aD);
4821 pPLCFx->SetDirty(false);
4822 aD.ReduceByOffset();
4823 pMemPos = aD.pMemPos + rSave.nPLCFxMemOfs;
4824 }
4825 }
4826 }
4827
4828 //-----------------------------------------
4829
4830
WW8Fib(SvStream & rSt,sal_uInt8 nWantedVersion,sal_uInt32 nOffset)4831 WW8Fib::WW8Fib( SvStream& rSt, sal_uInt8 nWantedVersion,sal_uInt32 nOffset )
4832 : nFibError( 0 )
4833 {
4834 sal_uInt8 aBits1;
4835 sal_uInt8 aBits2;
4836 sal_uInt8 aVer8Bits1; // nur ab WinWord 8 benutzt
4837 rSt.Seek( nOffset );
4838 /*
4839 Wunsch-Nr vermerken, File-Versionsnummer ermitteln
4840 und gegen Wunsch-Nr. checken !
4841 */
4842 nVersion = nWantedVersion;
4843 rSt >> wIdent;
4844 rSt >> nFib;
4845 rSt >> nProduct;
4846 if( 0 != rSt.GetError() )
4847 {
4848 sal_Int16 nFibMin;
4849 sal_Int16 nFibMax;
4850 // note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
4851 switch( nVersion )
4852 {
4853 case 6:
4854 nFibMin = 0x0065; // von 101 WinWord 6.0
4855 // 102 "
4856 // und 103 WinWord 6.0 fuer Macintosh
4857 // 104 "
4858 nFibMax = 0x0069; // bis 105 WinWord 95
4859 break;
4860 case 7:
4861 nFibMin = 0x0069; // von 105 WinWord 95
4862 nFibMax = 0x0069; // bis 105 WinWord 95
4863 break;
4864 case 8:
4865 nFibMin = 0x006A; // von 106 WinWord 97
4866 nFibMax = 0x00c1; // bis 193 WinWord 97 (?)
4867 break;
4868 default:
4869 nFibMin = 0; // Programm-Fehler!
4870 nFibMax = 0;
4871 nFib = 1;
4872 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
4873 break;
4874 }
4875 if ( (nFib < nFibMin) || (nFib > nFibMax) )
4876 {
4877 nFibError = ERR_SWG_READ_ERROR; // Error melden
4878 return; // und hopp raus!
4879 }
4880 }
4881
4882 // praktische Hilfsvariablen:
4883 bool bVer67 = ((6 == nVersion) || (7 == nVersion));
4884 bool bVer8 = (8 == nVersion);
4885
4886 // Hilfs-Varis fuer Ver67:
4887 sal_Int16 pnChpFirst_Ver67=0;
4888 sal_Int16 pnPapFirst_Ver67=0;
4889 sal_Int16 cpnBteChp_Ver67=0;
4890 sal_Int16 cpnBtePap_Ver67=0;
4891
4892 // und auf gehts: FIB einlesen
4893 rSt >> lid;
4894 rSt >> pnNext;
4895 rSt >> aBits1;
4896 rSt >> aBits2;
4897 rSt >> nFibBack;
4898 rSt >> lKey1;
4899 rSt >> lKey2;
4900 rSt >> envr;
4901 rSt >> aVer8Bits1; // unter Ver67 nur leeres Reservefeld
4902 // Inhalt von aVer8Bits1
4903 //
4904 // sal_uInt8 fMac :1;
4905 // sal_uInt8 fEmptySpecial :1;
4906 // sal_uInt8 fLoadOverridePage :1;
4907 // sal_uInt8 fFuturesavedUndo :1;
4908 // sal_uInt8 fWord97Saved :1;
4909 // sal_uInt8 :3;
4910 rSt >> chse;
4911 rSt >> chseTables;
4912 rSt >> fcMin;
4913 rSt >> fcMac;
4914
4915 // Einschub fuer WW8 *****************************************************
4916 if( !bVer67 )
4917 {
4918 rSt >> csw;
4919
4920 // Marke: "rgsw" Beginning of the array of shorts
4921 rSt >> wMagicCreated;
4922 rSt >> wMagicRevised;
4923 rSt >> wMagicCreatedPrivate;
4924 rSt >> wMagicRevisedPrivate;
4925 rSt.SeekRel( 9 * sizeof( sal_Int16 ) );
4926
4927 /*
4928 // dies sind die 9 unused Felder:
4929 && (bVer67 || WW8ReadINT16( rSt, pnFbpChpFirst_W6 )) // 1
4930 && (bVer67 || WW8ReadINT16( rSt, pnChpFirst_W6 )) // 2
4931 && (bVer67 || WW8ReadINT16( rSt, cpnBteChp_W6 )) // 3
4932 && (bVer67 || WW8ReadINT16( rSt, pnFbpPapFirst_W6 )) // 4
4933 && (bVer67 || WW8ReadINT16( rSt, pnPapFirst_W6 )) // 5
4934 && (bVer67 || WW8ReadINT16( rSt, cpnBtePap_W6 )) // 6
4935 && (bVer67 || WW8ReadINT16( rSt, pnFbpLvcFirst_W6 )) // 7
4936 && (bVer67 || WW8ReadINT16( rSt, pnLvcFirst_W6 )) // 8
4937 && (bVer67 || WW8ReadINT16( rSt, cpnBteLvc_W6 )) // 9
4938 */
4939 rSt >> lidFE;
4940 rSt >> clw;
4941 }
4942
4943 // Ende des Einschubs fuer WW8 *******************************************
4944
4945 // Marke: "rglw" Beginning of the array of longs
4946 rSt >> cbMac;
4947
4948 // 2 Longs uebergehen, da unwichtiger Quatsch
4949 rSt.SeekRel( 2 * sizeof( sal_Int32) );
4950
4951 // weitere 2 Longs nur bei Ver67 ueberspringen
4952 if( bVer67 )
4953 rSt.SeekRel( 2 * sizeof( sal_Int32) );
4954
4955 rSt >> ccpText;
4956 rSt >> ccpFtn;
4957 rSt >> ccpHdr;
4958 rSt >> ccpMcr;
4959 rSt >> ccpAtn;
4960 rSt >> ccpEdn;
4961 rSt >> ccpTxbx;
4962 rSt >> ccpHdrTxbx;
4963
4964 // weiteres Long nur bei Ver67 ueberspringen
4965 if( bVer67 )
4966 rSt.SeekRel( 1 * sizeof( sal_Int32) );
4967 else
4968 {
4969 // Einschub fuer WW8 *****************************************************
4970 rSt >> pnFbpChpFirst;
4971 rSt >> pnChpFirst;
4972 rSt >> cpnBteChp;
4973 rSt >> pnFbpPapFirst;
4974 rSt >> pnPapFirst;
4975 rSt >> cpnBtePap;
4976 rSt >> pnFbpLvcFirst;
4977 rSt >> pnLvcFirst;
4978 rSt >> cpnBteLvc;
4979 rSt >> fcIslandFirst;
4980 rSt >> fcIslandLim;
4981 rSt >> cfclcb;
4982 }
4983
4984 // Ende des Einschubs fuer WW8 *******************************************
4985
4986 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
4987 rSt >> fcStshfOrig;
4988 rSt >> lcbStshfOrig;
4989 rSt >> fcStshf;
4990 rSt >> lcbStshf;
4991 rSt >> fcPlcffndRef;
4992 rSt >> lcbPlcffndRef;
4993 rSt >> fcPlcffndTxt;
4994 rSt >> lcbPlcffndTxt;
4995 rSt >> fcPlcfandRef;
4996 rSt >> lcbPlcfandRef;
4997 rSt >> fcPlcfandTxt;
4998 rSt >> lcbPlcfandTxt;
4999 rSt >> fcPlcfsed;
5000 rSt >> lcbPlcfsed;
5001 rSt >> fcPlcfpad;
5002 rSt >> lcbPlcfpad;
5003 rSt >> fcPlcfphe;
5004 rSt >> lcbPlcfphe;
5005 rSt >> fcSttbfglsy;
5006 rSt >> lcbSttbfglsy;
5007 rSt >> fcPlcfglsy;
5008 rSt >> lcbPlcfglsy;
5009 rSt >> fcPlcfhdd;
5010 rSt >> lcbPlcfhdd;
5011 rSt >> fcPlcfbteChpx;
5012 rSt >> lcbPlcfbteChpx;
5013 rSt >> fcPlcfbtePapx;
5014 rSt >> lcbPlcfbtePapx;
5015 rSt >> fcPlcfsea;
5016 rSt >> lcbPlcfsea;
5017 rSt >> fcSttbfffn;
5018 rSt >> lcbSttbfffn;
5019 rSt >> fcPlcffldMom;
5020 rSt >> lcbPlcffldMom;
5021 rSt >> fcPlcffldHdr;
5022 rSt >> lcbPlcffldHdr;
5023 rSt >> fcPlcffldFtn;
5024 rSt >> lcbPlcffldFtn;
5025 rSt >> fcPlcffldAtn;
5026 rSt >> lcbPlcffldAtn;
5027 rSt >> fcPlcffldMcr;
5028 rSt >> lcbPlcffldMcr;
5029 rSt >> fcSttbfbkmk;
5030 rSt >> lcbSttbfbkmk;
5031 rSt >> fcPlcfbkf;
5032 rSt >> lcbPlcfbkf;
5033 rSt >> fcPlcfbkl;
5034 rSt >> lcbPlcfbkl;
5035 rSt >> fcCmds;
5036 rSt >> lcbCmds;
5037 rSt >> fcPlcfmcr;
5038 rSt >> lcbPlcfmcr;
5039 rSt >> fcSttbfmcr;
5040 rSt >> lcbSttbfmcr;
5041 rSt >> fcPrDrvr;
5042 rSt >> lcbPrDrvr;
5043 rSt >> fcPrEnvPort;
5044 rSt >> lcbPrEnvPort;
5045 rSt >> fcPrEnvLand;
5046 rSt >> lcbPrEnvLand;
5047 rSt >> fcWss;
5048 rSt >> lcbWss;
5049 rSt >> fcDop;
5050 rSt >> lcbDop;
5051 rSt >> fcSttbfAssoc;
5052 rSt >> cbSttbfAssoc;
5053 rSt >> fcClx;
5054 rSt >> lcbClx;
5055 rSt >> fcPlcfpgdFtn;
5056 rSt >> lcbPlcfpgdFtn;
5057 rSt >> fcAutosaveSource;
5058 rSt >> lcbAutosaveSource;
5059 rSt >> fcGrpStAtnOwners;
5060 rSt >> lcbGrpStAtnOwners;
5061 rSt >> fcSttbfAtnbkmk;
5062 rSt >> lcbSttbfAtnbkmk;
5063
5064 // weiteres short nur bei Ver67 ueberspringen
5065 if (bVer67)
5066 {
5067 rSt.SeekRel( 1*sizeof( sal_Int16) );
5068
5069 // folgende 4 Shorts existieren nur bei Ver67;
5070 rSt >> pnChpFirst_Ver67;
5071 rSt >> pnPapFirst_Ver67;
5072 rSt >> cpnBteChp_Ver67;
5073 rSt >> cpnBtePap_Ver67;
5074 }
5075
5076 rSt >> fcPlcfdoaMom;
5077 rSt >> lcbPlcfdoaMom;
5078 rSt >> fcPlcfdoaHdr;
5079 rSt >> lcbPlcfdoaHdr;
5080 rSt >> fcPlcfspaMom;
5081 rSt >> lcbPlcfspaMom;
5082 rSt >> fcPlcfspaHdr;
5083 rSt >> lcbPlcfspaHdr;
5084
5085 rSt >> fcPlcfAtnbkf;
5086 rSt >> lcbPlcfAtnbkf;
5087 rSt >> fcPlcfAtnbkl;
5088 rSt >> lcbPlcfAtnbkl;
5089 rSt >> fcPms;
5090 rSt >> lcbPMS;
5091 rSt >> fcFormFldSttbf;
5092 rSt >> lcbFormFldSttbf;
5093 rSt >> fcPlcfendRef;
5094 rSt >> lcbPlcfendRef;
5095 rSt >> fcPlcfendTxt;
5096 rSt >> lcbPlcfendTxt;
5097 rSt >> fcPlcffldEdn;
5098 rSt >> lcbPlcffldEdn;
5099 rSt >> fcPlcfpgdEdn;
5100 rSt >> lcbPlcfpgdEdn;
5101 rSt >> fcDggInfo;
5102 rSt >> lcbDggInfo;
5103 rSt >> fcSttbfRMark;
5104 rSt >> lcbSttbfRMark;
5105 rSt >> fcSttbfCaption;
5106 rSt >> lcbSttbfCaption;
5107 rSt >> fcSttbAutoCaption;
5108 rSt >> lcbSttbAutoCaption;
5109 rSt >> fcPlcfwkb;
5110 rSt >> lcbPlcfwkb;
5111 rSt >> fcPlcfspl;
5112 rSt >> lcbPlcfspl;
5113 rSt >> fcPlcftxbxTxt;
5114 rSt >> lcbPlcftxbxTxt;
5115 rSt >> fcPlcffldTxbx;
5116 rSt >> lcbPlcffldTxbx;
5117 rSt >> fcPlcfHdrtxbxTxt;
5118 rSt >> lcbPlcfHdrtxbxTxt;
5119 rSt >> fcPlcffldHdrTxbx;
5120 rSt >> lcbPlcffldHdrTxbx;
5121
5122 if( 0 == rSt.GetError() )
5123 {
5124 // Bit-Flags setzen
5125 fDot = aBits1 & 0x01 ;
5126 fGlsy = ( aBits1 & 0x02 ) >> 1;
5127 fComplex = ( aBits1 & 0x04 ) >> 2;
5128 fHasPic = ( aBits1 & 0x08 ) >> 3;
5129 cQuickSaves = ( aBits1 & 0xf0 ) >> 4;
5130 fEncrypted = aBits2 & 0x01 ;
5131 fWhichTblStm= ( aBits2 & 0x02 ) >> 1;
5132 // dummy = ( aBits2 & 0x0e ) >> 1;
5133 fExtChar = ( aBits2 & 0x10 ) >> 4;
5134 // dummy = ( aBits2 & 0xe0 ) >> 5;
5135
5136 /*
5137 ggfs. Ziel-Varaiblen, aus xxx_Ver67 fuellen
5138 oder Flags setzen
5139 */
5140 if (bVer67)
5141 {
5142 pnChpFirst = pnChpFirst_Ver67;
5143 pnPapFirst = pnPapFirst_Ver67;
5144 cpnBteChp = cpnBteChp_Ver67;
5145 cpnBtePap = cpnBtePap_Ver67;
5146 }
5147 else if( bVer8 )
5148 {
5149 fMac = aVer8Bits1 & 0x01 ;
5150 fEmptySpecial = ( aVer8Bits1 & 0x02 ) >> 1;
5151 fLoadOverridePage = ( aVer8Bits1 & 0x04 ) >> 2;
5152 fFuturesavedUndo = ( aVer8Bits1 & 0x08 ) >> 3;
5153 fWord97Saved = ( aVer8Bits1 & 0x10 ) >> 4;
5154 fWord2000Saved = ( aVer8Bits1 & 0x20 ) >> 5;
5155
5156 /*
5157 speziell fuer WW8:
5158 ermittle die Werte fuer PLCF LST und PLF LFO
5159 und PLCF fuer TextBox-Break-Deskriptoren
5160 */
5161 long nOldPos = rSt.Tell();
5162 rSt.Seek( 0x02e2 );
5163 rSt >> fcPlcfLst;
5164 rSt >> lcbPlcfLst;
5165 rSt >> fcPlfLfo;
5166 rSt >> lcbPlfLfo;
5167 rSt >> fcPlcftxbxBkd;
5168 rSt >> lcbPlcftxbxBkd;
5169 rSt >> fcPlcfHdrtxbxBkd;
5170 rSt >> lcbPlcfHdrtxbxBkd;
5171 if( 0 != rSt.GetError() )
5172 {
5173 nFibError = ERR_SWG_READ_ERROR;
5174 }
5175
5176 rSt.Seek( 0x372 ); // fcSttbListNames
5177 rSt >> fcSttbListNames;
5178 rSt >> lcbSttbListNames;
5179 rSt.Seek( 0x382 ); // MagicTables
5180 rSt >> fcMagicTable;
5181 rSt >> lcbMagicTable;
5182 if( 0 != rSt.GetError() )
5183 nFibError = ERR_SWG_READ_ERROR;
5184
5185 rSt.Seek( nOldPos );
5186 }
5187 }
5188 else
5189 {
5190 nFibError = ERR_SWG_READ_ERROR; // Error melden
5191 }
5192 }
5193
5194
WW8Fib(sal_uInt8 nVer)5195 WW8Fib::WW8Fib(sal_uInt8 nVer)
5196 {
5197 memset(this, 0, sizeof(*this));
5198 nVersion = nVer;
5199 if (8 == nVer)
5200 {
5201 fcMin = 0x400;
5202 wIdent = 0xa5ec;
5203 nFib = 0xc2;
5204 nFibBack = 0xbf;
5205 nProduct = 0x204D;
5206
5207 csw = 0x0e; // muss das sein ???
5208 cfclcb = 0x6c; // -""-
5209 clw = 0x16; // -""-
5210 pnFbpChpFirst = pnFbpPapFirst = pnFbpLvcFirst = 0x000fffff;
5211 fExtChar = true;
5212 fWord97Saved = fWord2000Saved = true;
5213
5214 // diese Flags muessen nicht gesetzt werden; koennen aber.
5215 // wMagicCreated = wMagicRevised = 0x6a62;
5216 // wMagicCreatedPrivate = wMagicRevisedPrivate = 0xb3b2;
5217 //
5218
5219 wMagicCreated = 0x6143;
5220 wMagicRevised = 0x6C6F;
5221 wMagicCreatedPrivate = 0x6E61;
5222 wMagicRevisedPrivate = 0x3136;
5223 }
5224 else
5225 {
5226 fcMin = 0x300;
5227 wIdent = 0xa5dc;
5228 nFib = nFibBack = 0x65;
5229 nProduct = 0xc02d;
5230 }
5231
5232 lid = lidFE = 0x407;
5233 }
5234
Write(SvStream & rStrm)5235 bool WW8Fib::Write(SvStream& rStrm)
5236 {
5237 sal_uInt8 *pDataPtr = new sal_uInt8[ fcMin ];
5238 sal_uInt8 *pData = pDataPtr;
5239 memset( pData, 0, fcMin );
5240
5241 bool bVer8 = 8 == nVersion;
5242
5243 sal_uLong nPos = rStrm.Tell();
5244 cbMac = rStrm.Seek( STREAM_SEEK_TO_END );
5245 rStrm.Seek( nPos );
5246
5247 Set_UInt16( pData, wIdent );
5248 Set_UInt16( pData, nFib );
5249 Set_UInt16( pData, nProduct );
5250 Set_UInt16( pData, lid );
5251 Set_UInt16( pData, pnNext );
5252
5253 sal_uInt16 nBits16 = 0;
5254 if( fDot ) nBits16 |= 0x0001;
5255 if( fGlsy) nBits16 |= 0x0002;
5256 if( fComplex ) nBits16 |= 0x0004;
5257 if( fHasPic ) nBits16 |= 0x0008;
5258 nBits16 |= (0xf0 & ( cQuickSaves << 4 ));
5259 if( fEncrypted ) nBits16 |= 0x0100;
5260 if( fWhichTblStm ) nBits16 |= 0x0200;
5261 if( fExtChar ) nBits16 |= 0x1000;
5262 Set_UInt16( pData, nBits16 );
5263
5264 Set_UInt16( pData, nFibBack );
5265 Set_UInt16( pData, lKey1 );
5266 Set_UInt16( pData, lKey2 );
5267 Set_UInt8( pData, envr );
5268
5269 sal_uInt8 nBits8 = 0;
5270 if( bVer8 )
5271 {
5272 if( fMac ) nBits8 |= 0x0001;
5273 if( fEmptySpecial ) nBits8 |= 0x0002;
5274 if( fLoadOverridePage ) nBits8 |= 0x0004;
5275 if( fFuturesavedUndo ) nBits8 |= 0x0008;
5276 if( fWord97Saved ) nBits8 |= 0x0010;
5277 if( fWord2000Saved ) nBits8 |= 0x0020;
5278 }
5279 // unter Ver67 these are only reserved
5280 Set_UInt8( pData, nBits8 );
5281
5282 Set_UInt16( pData, chse );
5283 Set_UInt16( pData, chseTables );
5284 Set_UInt32( pData, fcMin );
5285 Set_UInt32( pData, fcMac );
5286
5287 // Einschub fuer WW8 *****************************************************
5288
5289 // Marke: "rgsw" Beginning of the array of shorts
5290 if( bVer8 )
5291 {
5292 Set_UInt16( pData, csw );
5293 Set_UInt16( pData, wMagicCreated );
5294 Set_UInt16( pData, wMagicRevised );
5295 Set_UInt16( pData, wMagicCreatedPrivate );
5296 Set_UInt16( pData, wMagicRevisedPrivate );
5297 pData += 9 * sizeof( sal_Int16 );
5298 Set_UInt16( pData, lidFE );
5299 Set_UInt16( pData, clw );
5300 }
5301
5302 // Ende des Einschubs fuer WW8 *******************************************
5303
5304 // Marke: "rglw" Beginning of the array of longs
5305 Set_UInt32( pData, cbMac );
5306
5307 // 2 Longs uebergehen, da unwichtiger Quatsch
5308 pData += 2 * sizeof( sal_Int32);
5309
5310 // weitere 2 Longs nur bei Ver67 ueberspringen
5311 if( !bVer8 )
5312 pData += 2 * sizeof( sal_Int32);
5313
5314 Set_UInt32( pData, ccpText );
5315 Set_UInt32( pData, ccpFtn );
5316 Set_UInt32( pData, ccpHdr );
5317 Set_UInt32( pData, ccpMcr );
5318 Set_UInt32( pData, ccpAtn );
5319 Set_UInt32( pData, ccpEdn );
5320 Set_UInt32( pData, ccpTxbx );
5321 Set_UInt32( pData, ccpHdrTxbx );
5322
5323 // weiteres Long nur bei Ver67 ueberspringen
5324 if( !bVer8 )
5325 pData += 1 * sizeof( sal_Int32);
5326
5327 // Einschub fuer WW8 *****************************************************
5328 if( bVer8 )
5329 {
5330 Set_UInt32( pData, pnFbpChpFirst );
5331 Set_UInt32( pData, pnChpFirst );
5332 Set_UInt32( pData, cpnBteChp );
5333 Set_UInt32( pData, pnFbpPapFirst );
5334 Set_UInt32( pData, pnPapFirst );
5335 Set_UInt32( pData, cpnBtePap );
5336 Set_UInt32( pData, pnFbpLvcFirst );
5337 Set_UInt32( pData, pnLvcFirst );
5338 Set_UInt32( pData, cpnBteLvc );
5339 Set_UInt32( pData, fcIslandFirst );
5340 Set_UInt32( pData, fcIslandLim );
5341 Set_UInt16( pData, cfclcb );
5342 }
5343 // Ende des Einschubs fuer WW8 *******************************************
5344
5345 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
5346 Set_UInt32( pData, fcStshfOrig );
5347 Set_UInt32( pData, lcbStshfOrig );
5348 Set_UInt32( pData, fcStshf );
5349 Set_UInt32( pData, lcbStshf );
5350 Set_UInt32( pData, fcPlcffndRef );
5351 Set_UInt32( pData, lcbPlcffndRef );
5352 Set_UInt32( pData, fcPlcffndTxt );
5353 Set_UInt32( pData, lcbPlcffndTxt );
5354 Set_UInt32( pData, fcPlcfandRef );
5355 Set_UInt32( pData, lcbPlcfandRef );
5356 Set_UInt32( pData, fcPlcfandTxt );
5357 Set_UInt32( pData, lcbPlcfandTxt );
5358 Set_UInt32( pData, fcPlcfsed );
5359 Set_UInt32( pData, lcbPlcfsed );
5360 Set_UInt32( pData, fcPlcfpad );
5361 Set_UInt32( pData, lcbPlcfpad );
5362 Set_UInt32( pData, fcPlcfphe );
5363 Set_UInt32( pData, lcbPlcfphe );
5364 Set_UInt32( pData, fcSttbfglsy );
5365 Set_UInt32( pData, lcbSttbfglsy );
5366 Set_UInt32( pData, fcPlcfglsy );
5367 Set_UInt32( pData, lcbPlcfglsy );
5368 Set_UInt32( pData, fcPlcfhdd );
5369 Set_UInt32( pData, lcbPlcfhdd );
5370 Set_UInt32( pData, fcPlcfbteChpx );
5371 Set_UInt32( pData, lcbPlcfbteChpx );
5372 Set_UInt32( pData, fcPlcfbtePapx );
5373 Set_UInt32( pData, lcbPlcfbtePapx );
5374 Set_UInt32( pData, fcPlcfsea );
5375 Set_UInt32( pData, lcbPlcfsea );
5376 Set_UInt32( pData, fcSttbfffn );
5377 Set_UInt32( pData, lcbSttbfffn );
5378 Set_UInt32( pData, fcPlcffldMom );
5379 Set_UInt32( pData, lcbPlcffldMom );
5380 Set_UInt32( pData, fcPlcffldHdr );
5381 Set_UInt32( pData, lcbPlcffldHdr );
5382 Set_UInt32( pData, fcPlcffldFtn );
5383 Set_UInt32( pData, lcbPlcffldFtn );
5384 Set_UInt32( pData, fcPlcffldAtn );
5385 Set_UInt32( pData, lcbPlcffldAtn );
5386 Set_UInt32( pData, fcPlcffldMcr );
5387 Set_UInt32( pData, lcbPlcffldMcr );
5388 Set_UInt32( pData, fcSttbfbkmk );
5389 Set_UInt32( pData, lcbSttbfbkmk );
5390 Set_UInt32( pData, fcPlcfbkf );
5391 Set_UInt32( pData, lcbPlcfbkf );
5392 Set_UInt32( pData, fcPlcfbkl );
5393 Set_UInt32( pData, lcbPlcfbkl );
5394 Set_UInt32( pData, fcCmds );
5395 Set_UInt32( pData, lcbCmds );
5396 Set_UInt32( pData, fcPlcfmcr );
5397 Set_UInt32( pData, lcbPlcfmcr );
5398 Set_UInt32( pData, fcSttbfmcr );
5399 Set_UInt32( pData, lcbSttbfmcr );
5400 Set_UInt32( pData, fcPrDrvr );
5401 Set_UInt32( pData, lcbPrDrvr );
5402 Set_UInt32( pData, fcPrEnvPort );
5403 Set_UInt32( pData, lcbPrEnvPort );
5404 Set_UInt32( pData, fcPrEnvLand );
5405 Set_UInt32( pData, lcbPrEnvLand );
5406 Set_UInt32( pData, fcWss );
5407 Set_UInt32( pData, lcbWss );
5408 Set_UInt32( pData, fcDop );
5409 Set_UInt32( pData, lcbDop );
5410 Set_UInt32( pData, fcSttbfAssoc );
5411 Set_UInt32( pData, cbSttbfAssoc );
5412 Set_UInt32( pData, fcClx );
5413 Set_UInt32( pData, lcbClx );
5414 Set_UInt32( pData, fcPlcfpgdFtn );
5415 Set_UInt32( pData, lcbPlcfpgdFtn );
5416 Set_UInt32( pData, fcAutosaveSource );
5417 Set_UInt32( pData, lcbAutosaveSource );
5418 Set_UInt32( pData, fcGrpStAtnOwners );
5419 Set_UInt32( pData, lcbGrpStAtnOwners );
5420 Set_UInt32( pData, fcSttbfAtnbkmk );
5421 Set_UInt32( pData, lcbSttbfAtnbkmk );
5422
5423 // weiteres short nur bei Ver67 ueberspringen
5424 if( !bVer8 )
5425 {
5426 pData += 1*sizeof( sal_Int16);
5427 Set_UInt16( pData, (sal_uInt16)pnChpFirst );
5428 Set_UInt16( pData, (sal_uInt16)pnPapFirst );
5429 Set_UInt16( pData, (sal_uInt16)cpnBteChp );
5430 Set_UInt16( pData, (sal_uInt16)cpnBtePap );
5431 }
5432
5433 Set_UInt32( pData, fcPlcfdoaMom ); // nur bei Ver67, in Ver8 unused
5434 Set_UInt32( pData, lcbPlcfdoaMom ); // nur bei Ver67, in Ver8 unused
5435 Set_UInt32( pData, fcPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused
5436 Set_UInt32( pData, lcbPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused
5437
5438 Set_UInt32( pData, fcPlcfspaMom ); // in Ver67 leere Reserve
5439 Set_UInt32( pData, lcbPlcfspaMom ); // in Ver67 leere Reserve
5440 Set_UInt32( pData, fcPlcfspaHdr ); // in Ver67 leere Reserve
5441 Set_UInt32( pData, lcbPlcfspaHdr ); // in Ver67 leere Reserve
5442
5443 Set_UInt32( pData, fcPlcfAtnbkf );
5444 Set_UInt32( pData, lcbPlcfAtnbkf );
5445 Set_UInt32( pData, fcPlcfAtnbkl );
5446 Set_UInt32( pData, lcbPlcfAtnbkl );
5447 Set_UInt32( pData, fcPms );
5448 Set_UInt32( pData, lcbPMS );
5449 Set_UInt32( pData, fcFormFldSttbf );
5450 Set_UInt32( pData, lcbFormFldSttbf );
5451 Set_UInt32( pData, fcPlcfendRef );
5452 Set_UInt32( pData, lcbPlcfendRef );
5453 Set_UInt32( pData, fcPlcfendTxt );
5454 Set_UInt32( pData, lcbPlcfendTxt );
5455 Set_UInt32( pData, fcPlcffldEdn );
5456 Set_UInt32( pData, lcbPlcffldEdn );
5457 Set_UInt32( pData, fcPlcfpgdEdn );
5458 Set_UInt32( pData, lcbPlcfpgdEdn );
5459 Set_UInt32( pData, fcDggInfo ); // in Ver67 leere Reserve
5460 Set_UInt32( pData, lcbDggInfo ); // in Ver67 leere Reserve
5461 Set_UInt32( pData, fcSttbfRMark );
5462 Set_UInt32( pData, lcbSttbfRMark );
5463 Set_UInt32( pData, fcSttbfCaption );
5464 Set_UInt32( pData, lcbSttbfCaption );
5465 Set_UInt32( pData, fcSttbAutoCaption );
5466 Set_UInt32( pData, lcbSttbAutoCaption );
5467 Set_UInt32( pData, fcPlcfwkb );
5468 Set_UInt32( pData, lcbPlcfwkb );
5469 Set_UInt32( pData, fcPlcfspl ); // in Ver67 leere Reserve
5470 Set_UInt32( pData, lcbPlcfspl ); // in Ver67 leere Reserve
5471 Set_UInt32( pData, fcPlcftxbxTxt );
5472 Set_UInt32( pData, lcbPlcftxbxTxt );
5473 Set_UInt32( pData, fcPlcffldTxbx );
5474 Set_UInt32( pData, lcbPlcffldTxbx );
5475 Set_UInt32( pData, fcPlcfHdrtxbxTxt );
5476 Set_UInt32( pData, lcbPlcfHdrtxbxTxt );
5477 Set_UInt32( pData, fcPlcffldHdrTxbx );
5478 Set_UInt32( pData, lcbPlcffldHdrTxbx );
5479
5480 if( bVer8 )
5481 {
5482 pData += 0x2e2 - 0x27a; // Pos + Offset (fcPlcfLst - fcStwUser)
5483 Set_UInt32( pData, fcPlcfLst );
5484 Set_UInt32( pData, lcbPlcfLst );
5485 Set_UInt32( pData, fcPlfLfo );
5486 Set_UInt32( pData, lcbPlfLfo );
5487 Set_UInt32( pData, fcPlcftxbxBkd );
5488 Set_UInt32( pData, lcbPlcftxbxBkd );
5489 Set_UInt32( pData, fcPlcfHdrtxbxBkd );
5490 Set_UInt32( pData, lcbPlcfHdrtxbxBkd );
5491
5492 pData += 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo)
5493 Set_UInt32( pData, fcSttbListNames );
5494 Set_UInt32( pData, lcbSttbListNames );
5495
5496 pData += 0x382 - 0x37A;
5497 Set_UInt32( pData, fcMagicTable );
5498 Set_UInt32( pData, lcbMagicTable );
5499
5500 pData += 0x3FA - 0x38A;
5501 Set_UInt16( pData, (sal_uInt16)0x0002);
5502 Set_UInt16( pData, (sal_uInt16)0x00D9);
5503 }
5504
5505 rStrm.Write( pDataPtr, fcMin );
5506 delete[] pDataPtr;
5507 return 0 == rStrm.GetError();
5508 }
5509
GetFIBCharset(sal_uInt16 chs)5510 rtl_TextEncoding WW8Fib::GetFIBCharset(sal_uInt16 chs)
5511 {
5512 ASSERT(chs <= 0x100, "overflowed winword charset set");
5513 rtl_TextEncoding eCharSet =
5514 (0x0100 == chs)
5515 ? RTL_TEXTENCODING_APPLE_ROMAN
5516 : rtl_getTextEncodingFromWindowsCharset( static_cast<sal_uInt8>(chs) );
5517 return eCharSet;
5518 }
5519
WW8Style(SvStream & rStream,WW8Fib & rFibPara)5520 WW8Style::WW8Style(SvStream& rStream, WW8Fib& rFibPara)
5521 : rFib(rFibPara), rSt(rStream), cstd(0), cbSTDBaseInFile(0),
5522 stiMaxWhenSaved(0), istdMaxFixedWhenSaved(0), nVerBuiltInNamesWhenSaved(0),
5523 ftcStandardChpStsh(0), ftcStandardChpCJKStsh(0), ftcStandardChpCTLStsh(0)
5524 {
5525 nStyleStart = rFib.fcStshf;
5526 nStyleLen = rFib.lcbStshf;
5527
5528 rSt.Seek(nStyleStart);
5529
5530 sal_uInt16 cbStshi = 0; // 2 bytes size of the following STSHI structure
5531
5532 // alte Version ?
5533 if (rFib.nFib < 67)
5534 cbStshi = 4; // -> Laengenfeld fehlt
5535 else // neue Version:
5536 // lies die Laenge der in der Datei gespeicherten Struktur
5537 rSt >> cbStshi;
5538
5539 sal_uInt16 nRead = cbStshi;
5540 do
5541 {
5542 sal_uInt16 a16Bit;
5543
5544 if( 2 > nRead ) break;
5545 rSt >> cstd;
5546
5547 if( 4 > nRead ) break;
5548 rSt >> cbSTDBaseInFile;
5549
5550 if( 6 > nRead ) break;
5551 rSt >> a16Bit;
5552 fStdStylenamesWritten = a16Bit & 0x0001;
5553
5554 if( 8 > nRead ) break;
5555 rSt >> stiMaxWhenSaved;
5556
5557 if( 10 > nRead ) break;
5558 rSt >> istdMaxFixedWhenSaved;
5559
5560 if( 12 > nRead ) break;
5561 rSt >> nVerBuiltInNamesWhenSaved;
5562
5563 if( 14 > nRead ) break;
5564 rSt >> ftcStandardChpStsh;
5565
5566 if( 16 > nRead ) break;
5567 rSt >> ftcStandardChpCJKStsh;
5568
5569 if ( 18 > nRead ) break;
5570 rSt >> ftcStandardChpCTLStsh;
5571
5572 // ggfs. den Rest ueberlesen
5573 if( 18 < nRead )
5574 rSt.SeekRel( nRead-18 );
5575 }
5576 while( !this ); // Trick: obiger Block wird genau einmal durchlaufen
5577 // und kann vorzeitig per "break" verlassen werden.
5578
5579 if( 0 != rSt.GetError() )
5580 {
5581 // wie denn nun den Error melden?
5582 }
5583 }
5584
5585 // Read1STDFixed() liest ein Style ein. Wenn der Style vollstaendig vorhanden
5586 // ist, d.h. kein leerer Slot, dann wird Speicher alloziert und ein Pointer auf
5587 // die ( evtl. mit Nullen aufgefuellten ) STD geliefert. Ist es ein leerer
5588 // Slot, dann wird ein Nullpointer zurueckgeliefert.
Read1STDFixed(short & rSkip,short * pcbStd)5589 WW8_STD* WW8Style::Read1STDFixed( short& rSkip, short* pcbStd )
5590 {
5591 WW8_STD* pStd = 0;
5592
5593 sal_uInt16 cbStd;
5594 rSt >> cbStd; // lies Laenge
5595
5596 sal_uInt16 nRead = cbSTDBaseInFile;
5597 if( cbStd >= cbSTDBaseInFile )
5598 {
5599 // Fixed part vollst. vorhanden
5600
5601 // read fixed part of STD
5602 pStd = new WW8_STD;
5603 memset( pStd, 0, sizeof( *pStd ) );
5604
5605 do
5606 {
5607 sal_uInt16 a16Bit;
5608
5609 if( 2 > nRead ) break;
5610 rSt >> a16Bit;
5611 pStd->sti = a16Bit & 0x0fff ;
5612 pStd->fScratch = 0 != ( a16Bit & 0x1000 );
5613 pStd->fInvalHeight = 0 != ( a16Bit & 0x2000 );
5614 pStd->fHasUpe = 0 != ( a16Bit & 0x4000 );
5615 pStd->fMassCopy = 0 != ( a16Bit & 0x8000 );
5616
5617 if( 4 > nRead ) break;
5618 rSt >> a16Bit;
5619 pStd->sgc = a16Bit & 0x000f ;
5620 pStd->istdBase = ( a16Bit & 0xfff0 ) >> 4;
5621
5622 if( 6 > nRead ) break;
5623 rSt >> a16Bit;
5624 pStd->cupx = a16Bit & 0x000f ;
5625 pStd->istdNext = ( a16Bit & 0xfff0 ) >> 4;
5626
5627 if( 8 > nRead ) break;
5628 rSt >> pStd->bchUpe;
5629
5630 // ab Ver8 sollten diese beiden Felder dazukommen:
5631 if(10 > nRead ) break;
5632 rSt >> a16Bit;
5633 pStd->fAutoRedef = a16Bit & 0x0001 ;
5634 pStd->fHidden = ( a16Bit & 0x0002 ) >> 2;
5635
5636 // man kann nie wissen: vorsichtshalber ueberlesen
5637 // wir eventuelle Fuellsel, die noch zum BASE-Part gehoeren...
5638 if( 10 < nRead )
5639 rSt.SeekRel( nRead-10 );
5640 }
5641 while( !this ); // Trick: obiger Block wird genau einmal durchlaufen
5642 // und kann vorzeitig per "break" verlassen werden.
5643
5644 if( (0 != rSt.GetError()) || !nRead )
5645 DELETEZ( pStd ); // per NULL den Error melden
5646
5647 rSkip = cbStd - cbSTDBaseInFile;
5648 }
5649 else
5650 { // Fixed part zu kurz
5651 if( cbStd )
5652 rSt.SeekRel( cbStd ); // ueberlies Reste
5653 rSkip = 0;
5654 }
5655 if( pcbStd )
5656 *pcbStd = cbStd;
5657 return pStd;
5658 }
5659
Read1Style(short & rSkip,String * pString,short * pcbStd)5660 WW8_STD* WW8Style::Read1Style( short& rSkip, String* pString, short* pcbStd )
5661 {
5662 // Attention: MacWord-Documents have their Stylenames
5663 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
5664
5665 WW8_STD* pStd = Read1STDFixed( rSkip, pcbStd ); // lese STD
5666
5667 // String gewuenscht ?
5668 if( pString )
5669 { // echter Style ?
5670 if ( pStd )
5671 {
5672 switch( rFib.nVersion )
5673 {
5674 case 6:
5675 case 7:
5676 // lies Pascal-String
5677 *pString = WW8ReadPString( rSt, RTL_TEXTENCODING_MS_1252 );
5678 // leading len and trailing zero --> 2
5679 rSkip -= 2+ pString->Len();
5680 break;
5681 case 8:
5682 // handle Unicode-String with leading length short and
5683 // trailing zero
5684 if (ww8String::TestBeltAndBraces(rSt))
5685 {
5686 *pString = WW8Read_xstz(rSt, 0, true);
5687 rSkip -= (pString->Len() + 2) * 2;
5688 }
5689 else
5690 {
5691 /*
5692 #i8114#
5693 This is supposed to be impossible, its just supposed
5694 to be 16 bit count followed by the string and ending
5695 in a 0 short. But "Lotus SmartSuite Product: Word Pro"
5696 is creating invalid style names in ww7- format. So we
5697 use the belt and braces of the ms strings to see if
5698 they are not corrupt. If they are then we try them as
5699 8bit ones
5700 */
5701 *pString = WW8ReadPString(rSt,RTL_TEXTENCODING_MS_1252);
5702 // leading len and trailing zero --> 2
5703 rSkip -= 2+ pString->Len();
5704 }
5705 break;
5706 default:
5707 ASSERT(!this, "Es wurde vergessen, nVersion zu kodieren!");
5708 break;
5709 }
5710 }
5711 else
5712 *pString = aEmptyStr; // Kann keinen Namen liefern
5713 }
5714 return pStd;
5715 }
5716
5717
5718 //-----------------------------------------
5719
5720
5721 struct WW8_FFN_Ver6 : public WW8_FFN_BASE
5722 {
5723 // ab Ver6
5724 sal_Char szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
5725 // records name of font.
5726 // Maximal size of szFfn is 65 characters.
5727 // Vorsicht: Dieses Array kann auch kleiner sein!!!
5728 // Possibly followed by a second sz which records the
5729 // name of an alternate font to use if the first named
5730 // font does not exist on this system.
5731 };
5732 struct WW8_FFN_Ver8 : public WW8_FFN_BASE
5733 {
5734 // ab Ver8 sind folgende beiden Felder eingeschoben,
5735 // werden von uns ignoriert.
5736 sal_Char panose[ 10 ]; // 0x6 PANOSE
5737 sal_Char fs[ 24 ]; // 0x10 FONTSIGNATURE
5738
5739 // ab Ver8 als Unicode
5740 sal_uInt16 szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
5741 // records name of font.
5742 // Maximal size of szFfn is 65 characters.
5743 // Vorsicht: Dieses Array kann auch kleiner sein!!!
5744 // Possibly followed by a second sz which records the
5745 // name of an alternate font to use if the first named
5746 // font does not exist on this system.
5747 };
5748
WW8Fonts(SvStream & rSt,WW8Fib & rFib)5749 WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
5750 {
5751 // Attention: MacWord-Documents have their Fontnames
5752 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
5753 if( rFib.lcbSttbfffn <= 2 )
5754 {
5755 ASSERT( !this, "Fonttabelle kaputt! (rFib.lcbSttbfffn < 2)" );
5756 pFontA = 0;
5757 nMax = 0;
5758 return;
5759 }
5760
5761 bool bVer67 = (8 > rFib.nVersion);
5762
5763 rSt.Seek( rFib.fcSttbfffn );
5764
5765 // allocate Font Array
5766 sal_uInt8* pA = new sal_uInt8[ rFib.lcbSttbfffn - 2 ];
5767 WW8_FFN* p = (WW8_FFN*)pA;
5768
5769 if( !bVer67 )
5770 {
5771 // bVer8: read the count of strings in nMax
5772 rSt >> nMax;
5773 }
5774
5775 // Ver8: skip undefined uint16
5776 // Ver67: skip the herein stored total byte of structure
5777 // - we already got that information in rFib.lcbSttbfffn
5778 rSt.SeekRel( 2 );
5779
5780 // read all font information
5781 rSt.Read( pA, rFib.lcbSttbfffn - 2 );
5782
5783 if( bVer67 )
5784 {
5785 // try to figure out how many fonts are defined here
5786 nMax = 0;
5787 long nLeft = rFib.lcbSttbfffn - 2;
5788 for(;;)
5789 {
5790 short nNextSiz;
5791
5792 nNextSiz = p->cbFfnM1 + 1;
5793 if( nNextSiz > nLeft )
5794 break;
5795 nMax++;
5796 nLeft -= nNextSiz;
5797 if( nLeft < 1 ) // can we read the given amount of bytes ?
5798 break;
5799 // increase p by nNextSiz Bytes
5800 p = (WW8_FFN *)( ( (sal_uInt8*)p ) + nNextSiz );
5801 }
5802 }
5803
5804 if( nMax )
5805 {
5806 // allocate Index Array
5807 pFontA = new WW8_FFN[ nMax ];
5808 p = pFontA;
5809
5810 if( bVer67 )
5811 {
5812 WW8_FFN_Ver6* pVer6 = (WW8_FFN_Ver6*)pA;
5813 sal_uInt8 c2;
5814 for(sal_uInt16 i=0; i<nMax; ++i, ++p)
5815 {
5816 p->cbFfnM1 = pVer6->cbFfnM1;
5817 c2 = *(((sal_uInt8*)pVer6) + 1);
5818
5819 p->prg = c2 & 0x02;
5820 p->fTrueType = (c2 & 0x04) >> 2;
5821 // ein Reserve-Bit ueberspringen
5822 p->ff = (c2 & 0x70) >> 4;
5823
5824 p->wWeight = SVBT16ToShort( *(SVBT16*)&pVer6->wWeight );
5825 p->chs = pVer6->chs;
5826 p->ibszAlt = pVer6->ibszAlt;
5827 /*
5828 #i8726# 7- seems to encode the name in the same encoding as
5829 the font, e.g load the doc in 97 and save to see the unicode
5830 ver of the asian fontnames in that example to confirm.
5831 */
5832 rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->chs);
5833 if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW))
5834 eEnc = RTL_TEXTENCODING_MS_1252;
5835 p->sFontname = String(pVer6->szFfn, eEnc);
5836 // p->sFontname = String(pVer6->szFfn, RTL_TEXTENCODING_MS_1252);
5837 if (p->ibszAlt)
5838 {
5839 p->sFontname.Append(';');
5840 p->sFontname += String(pVer6->szFfn+p->ibszAlt, eEnc);
5841 // RTL_TEXTENCODING_MS_1252 );
5842 }
5843 pVer6 = (WW8_FFN_Ver6*)( ((sal_uInt8*)pVer6) + pVer6->cbFfnM1 + 1 );
5844 }
5845 }
5846 else
5847 {
5848 WW8_FFN_Ver8* pVer8 = (WW8_FFN_Ver8*)pA;
5849 sal_uInt8 c2;
5850 for(sal_uInt16 i=0; i<nMax; ++i, ++p)
5851 {
5852 p->cbFfnM1 = pVer8->cbFfnM1;
5853 c2 = *(((sal_uInt8*)pVer8) + 1);
5854
5855 p->prg = c2 & 0x02;
5856 p->fTrueType = (c2 & 0x04) >> 2;
5857 // ein Reserve-Bit ueberspringen
5858 p->ff = (c2 & 0x70) >> 4;
5859
5860 p->wWeight = SVBT16ToShort( *(SVBT16*)&pVer8->wWeight );
5861 p->chs = pVer8->chs;
5862 p->ibszAlt = pVer8->ibszAlt;
5863
5864 #ifdef __WW8_NEEDS_COPY
5865 {
5866 sal_uInt8 nLen = 0x28;
5867 for( sal_uInt16* pTmp = pVer8->szFfn;
5868 nLen < pVer8->cbFfnM1 + 1 ; ++pTmp, nLen+=2 )
5869 {
5870 *pTmp = SVBT16ToShort( *(SVBT16*)pTmp );
5871 }
5872 }
5873 #endif // defined __WW8_NEEDS_COPY
5874
5875 p->sFontname = pVer8->szFfn;
5876 if (p->ibszAlt)
5877 {
5878 p->sFontname.Append(';');
5879 p->sFontname.Append(pVer8->szFfn+p->ibszAlt);
5880 }
5881
5882 // Zeiger auf Ursprungsarray einen Font nach hinten setzen
5883 pVer8 = (WW8_FFN_Ver8*)( ((sal_uInt8*)pVer8) + pVer8->cbFfnM1 + 1 );
5884 }
5885 }
5886 }
5887 delete[] pA;
5888 }
5889
GetFont(sal_uInt16 nNum) const5890 const WW8_FFN* WW8Fonts::GetFont( sal_uInt16 nNum ) const
5891 {
5892 if( !pFontA || nNum >= nMax )
5893 return 0;
5894
5895 return &pFontA[ nNum ];
5896 }
5897
5898
5899
5900 //-----------------------------------------
5901
5902
5903 // Suche zu einem Header / Footer den Index in der WW-Liste von Headern / Footern
5904 //
5905 // Pferdefuesse bei WinWord6 und -7:
5906 // 1) Am Anfang des Einlesens muss WWPLCF_HdFt mit Fib und Dop konstruiert werden
5907 // 2) Der Haupttext muss sequentiell ueber alle Sections gelesen werden
5908 // 3) Fuer jedes vorkommende Header / Footer - Attribut des Haupttextes
5909 // ( Darf pro Section maximal eins sein ) muss UpdateIndex() genau einmal
5910 // mit dem Parameter des Attributes gerufen werden. Dieser Aufruf muss *nach*
5911 // dem letzten Aufruf von GetTextPos() passieren.
5912 // 4) GetTextPos() darf mit genau einem der obenstehen WW_... aufgerufen werden
5913 // ( nicht verodern ! )
5914 // -> dann liefert GetTextPos() vielleicht auch ein richtiges Ergebnis
5915
WW8PLCF_HdFt(SvStream * pSt,WW8Fib & rFib,WW8Dop & rDop)5916 WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream* pSt, WW8Fib& rFib, WW8Dop& rDop )
5917 : aPLCF( pSt, rFib.fcPlcfhdd , rFib.lcbPlcfhdd , 0 )
5918 {
5919 nIdxOffset = 0;
5920
5921 /*
5922 cmc 23/02/2000: This dop.grpfIhdt has a bit set for each special
5923 footnote *and endnote!!* seperator,continuation seperator, and
5924 continuation notice entry, the documentation does not mention the
5925 endnote seperators, the documentation also gets the index numbers
5926 backwards when specifying which bits to test. The bottom six bits
5927 of this value must be tested and skipped over. Each section's
5928 grpfIhdt is then tested for the existence of the appropriate headers
5929 and footers, at the end of each section the nIdxOffset must be updated
5930 to point to the beginning of the next section's group of headers and
5931 footers in this PLCF, UpdateIndex does that task.
5932 */
5933 for( sal_uInt8 nI = 0x1; nI <= 0x20; nI <<= 1 )
5934 if( nI & rDop.grpfIhdt ) // Bit gesetzt ?
5935 nIdxOffset++;
5936
5937 nTextOfs = rFib.ccpText + rFib.ccpFtn; // Groesse des Haupttextes
5938 // und der Fussnoten
5939 }
5940
GetTextPos(sal_uInt8 grpfIhdt,sal_uInt8 nWhich,WW8_CP & rStart,long & rLen)5941 bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart,
5942 long& rLen)
5943 {
5944 sal_uInt8 nI = 0x01;
5945 short nIdx = nIdxOffset;
5946 while (true)
5947 {
5948 if( nI & nWhich )
5949 break; // found
5950 if( grpfIhdt & nI )
5951 nIdx++; // uninteresting Header / Footer
5952 nI <<= 1; // text next bit
5953 if( nI > 0x20 )
5954 return false; // not found
5955 }
5956 // nIdx ist HdFt-Index
5957 WW8_CP nEnd;
5958 void* pData;
5959
5960 aPLCF.SetIdx( nIdx ); // Lookup suitable CP
5961 aPLCF.Get( rStart, nEnd, pData );
5962 rLen = nEnd - rStart;
5963 aPLCF++;
5964
5965 return true;
5966 }
5967
GetTextPosExact(short nIdx,WW8_CP & rStart,long & rLen)5968 bool WW8PLCF_HdFt::GetTextPosExact(short nIdx, WW8_CP& rStart, long& rLen)
5969 {
5970 WW8_CP nEnd;
5971 void* pData;
5972
5973 aPLCF.SetIdx( nIdx ); // Lookup suitable CP
5974 aPLCF.Get( rStart, nEnd, pData );
5975 rLen = nEnd - rStart;
5976 return true;
5977 }
5978
UpdateIndex(sal_uInt8 grpfIhdt)5979 void WW8PLCF_HdFt::UpdateIndex( sal_uInt8 grpfIhdt )
5980 {
5981 // Caution: Description is not correct
5982 for( sal_uInt8 nI = 0x01; nI <= 0x20; nI <<= 1 )
5983 if( nI & grpfIhdt )
5984 nIdxOffset++;
5985 }
5986
5987 //-----------------------------------------
5988 // WW8Dop
5989 //-----------------------------------------
5990
WW8Dop(SvStream & rSt,sal_Int16 nFib,sal_Int32 nPos,sal_Int32 nSize)5991 WW8Dop::WW8Dop( SvStream& rSt, sal_Int16 nFib, sal_Int32 nPos, sal_Int32 nSize )
5992 {
5993 sal_uInt8* pDataPtr = new sal_uInt8[ 500 ];
5994 sal_uInt8* pData = pDataPtr;
5995
5996 sal_uInt32 nRead = 500 < nSize ? 500 : nSize;
5997 rSt.Seek( nPos );
5998 if( 2 > nSize || nRead != rSt.Read( pData, nRead ))
5999 {
6000 memset( &nDataStart, 0, (&nDataEnd - &nDataStart) );
6001 nDopError = ERR_SWG_READ_ERROR; // Error melden
6002 }
6003 else
6004 {
6005 if( 500 > nRead )
6006 memset( pData + nRead, 0, 500 - nRead );
6007
6008 // dann mal die Daten auswerten
6009 sal_uInt32 a32Bit;
6010 sal_uInt16 a16Bit;
6011 sal_uInt8 a8Bit;
6012
6013 a16Bit = Get_UShort( pData );
6014 fFacingPages = 0 != ( a16Bit & 0x0001 ) ;
6015 fWidowControl = 0 != ( a16Bit & 0x0002 ) ;
6016 fPMHMainDoc = 0 != ( a16Bit & 0x0004 ) ;
6017 grfSuppression = ( a16Bit & 0x0018 ) >> 3;
6018 fpc = ( a16Bit & 0x0060 ) >> 5;
6019 grpfIhdt = ( a16Bit & 0xff00 ) >> 8;
6020
6021 a16Bit = Get_UShort( pData );
6022 rncFtn = a16Bit & 0x0003 ;
6023 nFtn = ( a16Bit & ~0x0003 ) >> 2 ;
6024
6025 a8Bit = Get_Byte( pData );
6026 fOutlineDirtySave = 0 != ( a8Bit & 0x01 );
6027
6028 a8Bit = Get_Byte( pData );
6029 fOnlyMacPics = 0 != ( a8Bit & 0x01 );
6030 fOnlyWinPics = 0 != ( a8Bit & 0x02 );
6031 fLabelDoc = 0 != ( a8Bit & 0x04 );
6032 fHyphCapitals = 0 != ( a8Bit & 0x08 );
6033 fAutoHyphen = 0 != ( a8Bit & 0x10 );
6034 fFormNoFields = 0 != ( a8Bit & 0x20 );
6035 fLinkStyles = 0 != ( a8Bit & 0x40 );
6036 fRevMarking = 0 != ( a8Bit & 0x80 );
6037
6038 a8Bit = Get_Byte( pData );
6039 fBackup = 0 != ( a8Bit & 0x01 );
6040 fExactCWords = 0 != ( a8Bit & 0x02 );
6041 fPagHidden = 0 != ( a8Bit & 0x04 );
6042 fPagResults = 0 != ( a8Bit & 0x08 );
6043 fLockAtn = 0 != ( a8Bit & 0x10 );
6044 fMirrorMargins = 0 != ( a8Bit & 0x20 );
6045 fReadOnlyRecommended = 0 != ( a8Bit & 0x40 );
6046 fDfltTrueType = 0 != ( a8Bit & 0x80 );
6047
6048 a8Bit = Get_Byte( pData );
6049 fPagSuppressTopSpacing = 0 != ( a8Bit & 0x01 );
6050 fProtEnabled = 0 != ( a8Bit & 0x02 );
6051 fDispFormFldSel = 0 != ( a8Bit & 0x04 );
6052 fRMView = 0 != ( a8Bit & 0x08 );
6053 fRMPrint = 0 != ( a8Bit & 0x10 );
6054 fWriteReservation = 0 != ( a8Bit & 0x20 );
6055 fLockRev = 0 != ( a8Bit & 0x40 );
6056 fEmbedFonts = 0 != ( a8Bit & 0x80 );
6057
6058
6059 a8Bit = Get_Byte( pData );
6060 copts_fNoTabForInd = 0 != ( a8Bit & 0x01 );
6061 copts_fNoSpaceRaiseLower = 0 != ( a8Bit & 0x02 );
6062 copts_fSupressSpbfAfterPgBrk = 0 != ( a8Bit & 0x04 );
6063 copts_fWrapTrailSpaces = 0 != ( a8Bit & 0x08 );
6064 copts_fMapPrintTextColor = 0 != ( a8Bit & 0x10 );
6065 copts_fNoColumnBalance = 0 != ( a8Bit & 0x20 );
6066 copts_fConvMailMergeEsc = 0 != ( a8Bit & 0x40 );
6067 copts_fSupressTopSpacing = 0 != ( a8Bit & 0x80 );
6068
6069 a8Bit = Get_Byte( pData );
6070 copts_fOrigWordTableRules = 0 != ( a8Bit & 0x01 );
6071 copts_fTransparentMetafiles = 0 != ( a8Bit & 0x02 );
6072 copts_fShowBreaksInFrames = 0 != ( a8Bit & 0x04 );
6073 copts_fSwapBordersFacingPgs = 0 != ( a8Bit & 0x08 );
6074
6075 dxaTab = Get_Short( pData );
6076 wSpare = Get_UShort( pData );
6077 dxaHotZ = Get_UShort( pData );
6078 cConsecHypLim = Get_UShort( pData );
6079 wSpare2 = Get_UShort( pData );
6080 dttmCreated = Get_Long( pData );
6081 dttmRevised = Get_Long( pData );
6082 dttmLastPrint = Get_Long( pData );
6083 nRevision = Get_Short( pData );
6084 tmEdited = Get_Long( pData );
6085 cWords = Get_Long( pData );
6086 cCh = Get_Long( pData );
6087 cPg = Get_Short( pData );
6088 cParas = Get_Long( pData );
6089
6090 a16Bit = Get_UShort( pData );
6091 rncEdn = a16Bit & 0x0003 ;
6092 nEdn = ( a16Bit & ~0x0003 ) >> 2;
6093
6094 a16Bit = Get_UShort( pData );
6095 epc = a16Bit & 0x0003 ;
6096 nfcFtnRef = ( a16Bit & 0x003c ) >> 2;
6097 nfcEdnRef = ( a16Bit & 0x03c0 ) >> 6;
6098 fPrintFormData = 0 != ( a16Bit & 0x0400 );
6099 fSaveFormData = 0 != ( a16Bit & 0x0800 );
6100 fShadeFormData = 0 != ( a16Bit & 0x1000 );
6101 fWCFtnEdn = 0 != ( a16Bit & 0x8000 );
6102
6103 cLines = Get_Long( pData );
6104 cWordsFtnEnd = Get_Long( pData );
6105 cChFtnEdn = Get_Long( pData );
6106 cPgFtnEdn = Get_Short( pData );
6107 cParasFtnEdn = Get_Long( pData );
6108 cLinesFtnEdn = Get_Long( pData );
6109 lKeyProtDoc = Get_Long( pData );
6110
6111 a16Bit = Get_UShort( pData );
6112 wvkSaved = a16Bit & 0x0007 ;
6113 wScaleSaved = ( a16Bit & 0x0ff8 ) >> 3 ;
6114 zkSaved = ( a16Bit & 0x3000 ) >> 12;
6115 fRotateFontW6 = ( a16Bit & 0x4000 ) >> 14;
6116 iGutterPos = ( a16Bit & 0x8000 ) >> 15;
6117 /*
6118 bei nFib >= 103 gehts weiter:
6119 */
6120 if( nFib >= 103 )
6121 {
6122 a32Bit = Get_ULong( pData );
6123 fNoTabForInd = ( a32Bit & 0x00000001 ) ;
6124 fNoSpaceRaiseLower = ( a32Bit & 0x00000002 ) >> 1 ;
6125 fSupressSpbfAfterPageBreak = ( a32Bit & 0x00000004 ) >> 2 ;
6126 fWrapTrailSpaces = ( a32Bit & 0x00000008 ) >> 3 ;
6127 fMapPrintTextColor = ( a32Bit & 0x00000010 ) >> 4 ;
6128 fNoColumnBalance = ( a32Bit & 0x00000020 ) >> 5 ;
6129 fConvMailMergeEsc = ( a32Bit & 0x00000040 ) >> 6 ;
6130 fSupressTopSpacing = ( a32Bit & 0x00000080 ) >> 7 ;
6131 fOrigWordTableRules = ( a32Bit & 0x00000100 ) >> 8 ;
6132 fTransparentMetafiles = ( a32Bit & 0x00000200 ) >> 9 ;
6133 fShowBreaksInFrames = ( a32Bit & 0x00000400 ) >> 10 ;
6134 fSwapBordersFacingPgs = ( a32Bit & 0x00000800 ) >> 11 ;
6135 fSuppressTopSpacingMac5 = ( a32Bit & 0x00010000 ) >> 16 ;
6136 fTruncDxaExpand = ( a32Bit & 0x00020000 ) >> 17 ;
6137 fPrintBodyBeforeHdr = ( a32Bit & 0x00040000 ) >> 18 ;
6138 fNoLeading = ( a32Bit & 0x00080000 ) >> 19 ;
6139 fMWSmallCaps = ( a32Bit & 0x00200000 ) >> 21 ;
6140
6141 fUsePrinterMetrics = ( a32Bit & 0x80000000 ) >> 31 ;
6142 }
6143
6144 /*
6145 bei nFib > 105 gehts weiter:
6146 */
6147 if( nFib > 105 )
6148 {
6149 adt = Get_Short( pData );
6150
6151 doptypography.ReadFromMem(pData);
6152
6153 memcpy( &dogrid, pData, sizeof( WW8_DOGRID ));
6154 pData += sizeof( WW8_DOGRID );
6155
6156 a16Bit = Get_UShort( pData );
6157 // die untersten 9 Bit sind uninteressant
6158 fHtmlDoc = ( a16Bit & 0x0200 ) >> 9 ;
6159 fSnapBorder = ( a16Bit & 0x0800 ) >> 11 ;
6160 fIncludeHeader = ( a16Bit & 0x1000 ) >> 12 ;
6161 fIncludeFooter = ( a16Bit & 0x2000 ) >> 13 ;
6162 fForcePageSizePag = ( a16Bit & 0x4000 ) >> 14 ;
6163 fMinFontSizePag = ( a16Bit & 0x8000 ) >> 15 ;
6164
6165 a16Bit = Get_UShort( pData );
6166 fHaveVersions = 0 != ( a16Bit & 0x0001 );
6167 fAutoVersion = 0 != ( a16Bit & 0x0002 );
6168
6169 pData += 12;
6170
6171 cChWS = Get_Long( pData );
6172 cChWSFtnEdn = Get_Long( pData );
6173 grfDocEvents = Get_Long( pData );
6174
6175 pData += 4+30+8;
6176
6177 cDBC = Get_Long( pData );
6178 cDBCFtnEdn = Get_Long( pData );
6179
6180 pData += 1 * sizeof( long );
6181
6182 nfcFtnRef = Get_Short( pData );
6183 nfcEdnRef = Get_Short( pData );
6184 hpsZoonFontPag = Get_Short( pData );
6185 dywDispPag = Get_Short( pData );
6186 }
6187 }
6188 delete[] pDataPtr;
6189 }
6190
WW8Dop()6191 WW8Dop::WW8Dop()
6192 {
6193 // first set everything to a default of 0
6194 memset( &nDataStart, 0, (&nDataEnd - &nDataStart) );
6195
6196 fWidowControl = 1;
6197 fpc = 1;
6198 nFtn = 1;
6199 fOutlineDirtySave = 1;
6200 fHyphCapitals = 1;
6201 fBackup = 1;
6202 fPagHidden = 1;
6203 fPagResults = 1;
6204 fDfltTrueType = 1;
6205
6206 /*
6207 Writer acts like this all the time at the moment, ideally we need an
6208 option for these two as well to import word docs that are not like
6209 this by default
6210 */
6211 fNoLeading = 1;
6212 fUsePrinterMetrics = 1;
6213
6214 fRMView = 1;
6215 fRMPrint = 1;
6216 dxaTab = 0x2d0;
6217 dxaHotZ = 0x168;
6218 dttmCreated = 0x45FBAC69;
6219 dttmRevised = 0x45FBAC69;
6220 nRevision = 1;
6221 nEdn = 1;
6222
6223 epc = 3;
6224 nfcEdnRef = 2;
6225 fShadeFormData = 1;
6226
6227 wvkSaved = 2;
6228 wScaleSaved = 100;
6229 zkSaved = 0;
6230
6231 lvl = 9;
6232 fIncludeHeader = 1;
6233 fIncludeFooter = 1;
6234
6235 cChWS = /**!!**/ 0;
6236 cChWSFtnEdn = /**!!**/ 0;
6237
6238 cDBC = /**!!**/ 0;
6239 cDBCFtnEdn = /**!!**/ 0;
6240 }
6241
GetCompatabilityOptions() const6242 sal_uInt32 WW8Dop::GetCompatabilityOptions() const
6243 {
6244 sal_uInt32 a32Bit = 0;
6245 if (fNoTabForInd) a32Bit |= 0x00000001;
6246 if (fNoSpaceRaiseLower) a32Bit |= 0x00000002;
6247 if (fSupressSpbfAfterPageBreak) a32Bit |= 0x00000004;
6248 if (fWrapTrailSpaces) a32Bit |= 0x00000008;
6249 if (fMapPrintTextColor) a32Bit |= 0x00000010;
6250 if (fNoColumnBalance) a32Bit |= 0x00000020;
6251 if (fConvMailMergeEsc) a32Bit |= 0x00000040;
6252 if (fSupressTopSpacing) a32Bit |= 0x00000080;
6253 if (fOrigWordTableRules) a32Bit |= 0x00000100;
6254 if (fTransparentMetafiles) a32Bit |= 0x00000200;
6255 if (fShowBreaksInFrames) a32Bit |= 0x00000400;
6256 if (fSwapBordersFacingPgs) a32Bit |= 0x00000800;
6257 if (fSuppressTopSpacingMac5) a32Bit |= 0x00010000;
6258 if (fTruncDxaExpand) a32Bit |= 0x00020000;
6259 if (fPrintBodyBeforeHdr) a32Bit |= 0x00040000;
6260 if (fNoLeading) a32Bit |= 0x00080000;
6261 if (fMWSmallCaps) a32Bit |= 0x00200000;
6262 if (fUsePrinterMetrics) a32Bit |= 0x80000000;
6263 return a32Bit;
6264 }
6265
Write(SvStream & rStrm,WW8Fib & rFib) const6266 bool WW8Dop::Write(SvStream& rStrm, WW8Fib& rFib) const
6267 {
6268 sal_Int32 nLen = 8 == rFib.nVersion ? 0x220 : 84;
6269 rFib.fcDop = rStrm.Tell();
6270 rFib.lcbDop = nLen;
6271
6272 sal_uInt8 aData[ 0x220 ];
6273 memset( aData, 0, 0x220 );
6274 sal_uInt8* pData = aData;
6275
6276 // dann mal die Daten auswerten
6277 sal_uInt16 a16Bit;
6278 sal_uInt8 a8Bit;
6279
6280 a16Bit = 0;
6281 if (fFacingPages)
6282 a16Bit |= 0x0001;
6283 if (fWidowControl)
6284 a16Bit |= 0x0002;
6285 if (fPMHMainDoc)
6286 a16Bit |= 0x0004;
6287 a16Bit |= ( 0x0018 & (grfSuppression << 3));
6288 a16Bit |= ( 0x0060 & (fpc << 5));
6289 a16Bit |= ( 0xff00 & (grpfIhdt << 8));
6290 Set_UInt16( pData, a16Bit );
6291
6292 a16Bit = 0;
6293 a16Bit |= ( 0x0003 & rncFtn );
6294 a16Bit |= ( ~0x0003 & (nFtn << 2));
6295 Set_UInt16( pData, a16Bit );
6296
6297 a8Bit = 0;
6298 if( fOutlineDirtySave ) a8Bit |= 0x01;
6299 Set_UInt8( pData, a8Bit );
6300
6301 a8Bit = 0;
6302 if( fOnlyMacPics ) a8Bit |= 0x01;
6303 if( fOnlyWinPics ) a8Bit |= 0x02;
6304 if( fLabelDoc ) a8Bit |= 0x04;
6305 if( fHyphCapitals ) a8Bit |= 0x08;
6306 if( fAutoHyphen ) a8Bit |= 0x10;
6307 if( fFormNoFields ) a8Bit |= 0x20;
6308 if( fLinkStyles ) a8Bit |= 0x40;
6309 if( fRevMarking ) a8Bit |= 0x80;
6310 Set_UInt8( pData, a8Bit );
6311
6312 a8Bit = 0;
6313 if( fBackup ) a8Bit |= 0x01;
6314 if( fExactCWords ) a8Bit |= 0x02;
6315 if( fPagHidden ) a8Bit |= 0x04;
6316 if( fPagResults ) a8Bit |= 0x08;
6317 if( fLockAtn ) a8Bit |= 0x10;
6318 if( fMirrorMargins ) a8Bit |= 0x20;
6319 if( fReadOnlyRecommended ) a8Bit |= 0x40;
6320 if( fDfltTrueType ) a8Bit |= 0x80;
6321 Set_UInt8( pData, a8Bit );
6322
6323 a8Bit = 0;
6324 if( fPagSuppressTopSpacing ) a8Bit |= 0x01;
6325 if( fProtEnabled ) a8Bit |= 0x02;
6326 if( fDispFormFldSel ) a8Bit |= 0x04;
6327 if( fRMView ) a8Bit |= 0x08;
6328 if( fRMPrint ) a8Bit |= 0x10;
6329 if( fWriteReservation ) a8Bit |= 0x20;
6330 if( fLockRev ) a8Bit |= 0x40;
6331 if( fEmbedFonts ) a8Bit |= 0x80;
6332 Set_UInt8( pData, a8Bit );
6333
6334
6335 a8Bit = 0;
6336 if( copts_fNoTabForInd ) a8Bit |= 0x01;
6337 if( copts_fNoSpaceRaiseLower ) a8Bit |= 0x02;
6338 if( copts_fSupressSpbfAfterPgBrk ) a8Bit |= 0x04;
6339 if( copts_fWrapTrailSpaces ) a8Bit |= 0x08;
6340 if( copts_fMapPrintTextColor ) a8Bit |= 0x10;
6341 if( copts_fNoColumnBalance ) a8Bit |= 0x20;
6342 if( copts_fConvMailMergeEsc ) a8Bit |= 0x40;
6343 if( copts_fSupressTopSpacing ) a8Bit |= 0x80;
6344 Set_UInt8( pData, a8Bit );
6345
6346 a8Bit = 0;
6347 if( copts_fOrigWordTableRules ) a8Bit |= 0x01;
6348 if( copts_fTransparentMetafiles ) a8Bit |= 0x02;
6349 if( copts_fShowBreaksInFrames ) a8Bit |= 0x04;
6350 if( copts_fSwapBordersFacingPgs ) a8Bit |= 0x08;
6351 Set_UInt8( pData, a8Bit );
6352
6353 Set_UInt16( pData, dxaTab );
6354 Set_UInt16( pData, wSpare );
6355 Set_UInt16( pData, dxaHotZ );
6356 Set_UInt16( pData, cConsecHypLim );
6357 Set_UInt16( pData, wSpare2 );
6358 Set_UInt32( pData, dttmCreated );
6359 Set_UInt32( pData, dttmRevised );
6360 Set_UInt32( pData, dttmLastPrint );
6361 Set_UInt16( pData, nRevision );
6362 Set_UInt32( pData, tmEdited );
6363 Set_UInt32( pData, cWords );
6364 Set_UInt32( pData, cCh );
6365 Set_UInt16( pData, cPg );
6366 Set_UInt32( pData, cParas );
6367
6368 a16Bit = 0;
6369 a16Bit |= ( 0x0003 & rncEdn );
6370 a16Bit |= (~0x0003 & ( nEdn << 2));
6371 Set_UInt16( pData, a16Bit );
6372
6373 a16Bit = 0;
6374 a16Bit |= (0x0003 & epc );
6375 a16Bit |= (0x003c & (nfcFtnRef << 2));
6376 a16Bit |= (0x03c0 & (nfcEdnRef << 6));
6377 if( fPrintFormData ) a16Bit |= 0x0400;
6378 if( fSaveFormData ) a16Bit |= 0x0800;
6379 if( fShadeFormData ) a16Bit |= 0x1000;
6380 if( fWCFtnEdn ) a16Bit |= 0x8000;
6381 Set_UInt16( pData, a16Bit );
6382
6383 Set_UInt32( pData, cLines );
6384 Set_UInt32( pData, cWordsFtnEnd );
6385 Set_UInt32( pData, cChFtnEdn );
6386 Set_UInt16( pData, cPgFtnEdn );
6387 Set_UInt32( pData, cParasFtnEdn );
6388 Set_UInt32( pData, cLinesFtnEdn );
6389 Set_UInt32( pData, lKeyProtDoc );
6390
6391 a16Bit = 0;
6392 if (wvkSaved)
6393 a16Bit |= 0x0007;
6394 a16Bit |= (0x0ff8 & (wScaleSaved << 3));
6395 a16Bit |= (0x3000 & (zkSaved << 12));
6396 Set_UInt16( pData, a16Bit );
6397
6398 if( 8 == rFib.nVersion )
6399 {
6400 Set_UInt32(pData, GetCompatabilityOptions());
6401
6402 Set_UInt16( pData, adt );
6403
6404 doptypography.WriteToMem(pData);
6405
6406 memcpy( pData, &dogrid, sizeof( WW8_DOGRID ));
6407 pData += sizeof( WW8_DOGRID );
6408
6409 a16Bit = 0x12; // lvl auf 9 setzen
6410 if( fHtmlDoc ) a16Bit |= 0x0200;
6411 if( fSnapBorder ) a16Bit |= 0x0800;
6412 if( fIncludeHeader ) a16Bit |= 0x1000;
6413 if( fIncludeFooter ) a16Bit |= 0x2000;
6414 if( fForcePageSizePag ) a16Bit |= 0x4000;
6415 if( fMinFontSizePag ) a16Bit |= 0x8000;
6416 Set_UInt16( pData, a16Bit );
6417
6418 a16Bit = 0;
6419 if( fHaveVersions ) a16Bit |= 0x0001;
6420 if( fAutoVersion ) a16Bit |= 0x0002;
6421 Set_UInt16( pData, a16Bit );
6422
6423 pData += 12;
6424
6425 Set_UInt32( pData, cChWS );
6426 Set_UInt32( pData, cChWSFtnEdn );
6427 Set_UInt32( pData, grfDocEvents );
6428
6429 pData += 4+30+8;
6430
6431 Set_UInt32( pData, cDBC );
6432 Set_UInt32( pData, cDBCFtnEdn );
6433
6434 pData += 1 * sizeof( long );
6435
6436 Set_UInt16( pData, nfcFtnRef );
6437 Set_UInt16( pData, nfcEdnRef );
6438 Set_UInt16( pData, hpsZoonFontPag );
6439 Set_UInt16( pData, dywDispPag );
6440
6441 //500 -> 508, Appear to be repeated here in 2000+
6442 pData += 8;
6443 Set_UInt32(pData, GetCompatabilityOptions());
6444 }
6445 rStrm.Write( aData, nLen );
6446 return 0 == rStrm.GetError();
6447 }
6448
ReadFromMem(sal_uInt8 * & pData)6449 void WW8DopTypography::ReadFromMem(sal_uInt8 *&pData)
6450 {
6451 sal_uInt16 a16Bit = Get_UShort(pData);
6452 fKerningPunct = (a16Bit & 0x0001);
6453 iJustification = (a16Bit & 0x0006) >> 1;
6454 iLevelOfKinsoku = (a16Bit & 0x0018) >> 3;
6455 f2on1 = (a16Bit & 0x0020) >> 5;
6456 reserved1 = (a16Bit & 0x03C0) >> 6;
6457 reserved2 = (a16Bit & 0xFC00) >> 10;
6458
6459 cchFollowingPunct = Get_Short(pData);
6460 cchLeadingPunct = Get_Short(pData);
6461
6462 sal_Int16 i;
6463 for (i=0; i < nMaxFollowing; ++i)
6464 rgxchFPunct[i] = Get_Short(pData);
6465 for (i=0; i < nMaxLeading; ++i)
6466 rgxchLPunct[i] = Get_Short(pData);
6467
6468 rgxchFPunct[cchFollowingPunct]=0;
6469 rgxchLPunct[cchLeadingPunct]=0;
6470 }
6471
WriteToMem(sal_uInt8 * & pData) const6472 void WW8DopTypography::WriteToMem(sal_uInt8 *&pData) const
6473 {
6474 sal_uInt16 a16Bit = fKerningPunct;
6475 a16Bit |= (iJustification << 1) & 0x0006;
6476 a16Bit |= (iLevelOfKinsoku << 3) & 0x0018;
6477 a16Bit |= (f2on1 << 5) & 0x002;
6478 a16Bit |= (reserved1 << 6) & 0x03C0;
6479 a16Bit |= (reserved2 << 10) & 0xFC00;
6480 Set_UInt16(pData,a16Bit);
6481
6482 Set_UInt16(pData,cchFollowingPunct);
6483 Set_UInt16(pData,cchLeadingPunct);
6484
6485 sal_Int16 i;
6486 for (i=0; i < nMaxFollowing; ++i)
6487 Set_UInt16(pData,rgxchFPunct[i]);
6488 for (i=0; i < nMaxLeading; ++i)
6489 Set_UInt16(pData,rgxchLPunct[i]);
6490 }
6491
GetConvertedLang() const6492 sal_uInt16 WW8DopTypography::GetConvertedLang() const
6493 {
6494 sal_uInt16 nLang;
6495 //I have assumed peoples republic/taiwan == simplified/traditional
6496
6497 //This isn't a documented issue, so we might have it all wrong,
6498 //i.e. i.e. whats with the powers of two ?
6499
6500 /*
6501 #84082#
6502 One example of 3 for reserved1 which was really Japanese, perhaps last bit
6503 is for some other use ?, or redundant. If more examples trigger the assert
6504 we might be able to figure it out.
6505 */
6506 switch(reserved1 & 0xE)
6507 {
6508 case 2: //Japan
6509 nLang = LANGUAGE_JAPANESE;
6510 break;
6511 case 4: //Chinese (Peoples Republic)
6512 nLang = LANGUAGE_CHINESE_SIMPLIFIED;
6513 break;
6514 case 6: //Korean
6515 nLang = LANGUAGE_KOREAN;
6516 break;
6517 case 8: //Chinese (Taiwan)
6518 nLang = LANGUAGE_CHINESE_TRADITIONAL;
6519 break;
6520 default:
6521 ASSERT(!this, "Unknown MS Asian Typography language, report");
6522 nLang = LANGUAGE_CHINESE;
6523 break;
6524 case 0:
6525 //And here we have the possibility that it says 2, but its really
6526 //a bug and only japanese level 2 has been selected after a custom
6527 //version was chosen on last save!
6528 nLang = LANGUAGE_JAPANESE;
6529 break;
6530 }
6531 return nLang;
6532 }
6533
6534 //-----------------------------------------
6535 // Sprms
6536 //-----------------------------------------
GetSprmTailLen(sal_uInt16 nId,const sal_uInt8 * pSprm) const6537 sal_uInt16 wwSprmParser::GetSprmTailLen(sal_uInt16 nId, const sal_uInt8* pSprm)
6538 const
6539 {
6540 SprmInfo aSprm = GetSprmInfo(nId);
6541 sal_uInt16 nL = 0; // number of Bytes to read
6542
6543 //sprmPChgTabs
6544 switch( nId )
6545 {
6546 case 23:
6547 case 0xC615:
6548 if( pSprm[1 + mnDelta] != 255 )
6549 nL = pSprm[1 + mnDelta] + aSprm.nLen;
6550 else
6551 {
6552 sal_uInt8 nDel = pSprm[2 + mnDelta];
6553 sal_uInt8 nIns = pSprm[3 + mnDelta + 4 * nDel];
6554
6555 nL = 2 + 4 * nDel + 3 * nIns;
6556 }
6557 break;
6558 case 0xD608:
6559 nL = SVBT16ToShort( &pSprm[1 + mnDelta] );
6560 break;
6561 default:
6562 switch (aSprm.nVari)
6563 {
6564 case L_FIX:
6565 nL = aSprm.nLen; // Excl. Token
6566 break;
6567 case L_VAR:
6568 // Variable 1-Byte Length?
6569 // Excl. Token + Var-Lengthbyte
6570 nL = pSprm[1 + mnDelta] + aSprm.nLen;
6571 break;
6572 case L_VAR2:
6573 // Variable 2-Byte Length?
6574 // Excl. Token + Var-Lengthbyte
6575 nL = SVBT16ToShort( &pSprm[1 + mnDelta] ) + aSprm.nLen - 1;
6576 break;
6577 default:
6578 ASSERT(!this, "Unknown sprm variant");
6579 break;
6580 }
6581 break;
6582 }
6583 return nL;
6584 }
6585
CountSprms(const sal_uInt8 * pSp,long nSprmSiz,const wwSprmSequence * pIgnoreSprms) const6586 int wwSprmParser::CountSprms(const sal_uInt8* pSp, long nSprmSiz,
6587 const wwSprmSequence* pIgnoreSprms) const
6588 {
6589 sal_uInt16 nMySprms = 0;
6590 sal_uInt16 i=0;
6591 while (i+1+mnDelta < nSprmSiz)
6592 {
6593 sal_uInt16 nSpId = GetSprmId(pSp);
6594
6595 if( !nSpId )
6596 break;
6597
6598 sal_uInt16 nSpLen = GetSprmSize(nSpId, pSp);
6599 // increase pointers so to point to next sprm
6600 i += nSpLen;
6601 pSp += nSpLen;
6602
6603 if (!pIgnoreSprms || !pIgnoreSprms->search(nSpId))
6604 ++nMySprms;
6605 }
6606 return nMySprms;
6607 }
6608
6609 // one or two bytes at the beginning at the sprm id
GetSprmId(const sal_uInt8 * pSp) const6610 sal_uInt16 wwSprmParser::GetSprmId(const sal_uInt8* pSp) const
6611 {
6612 ASSERT_RET_ON_FAIL(pSp, "Why GetSprmId with pSp of 0", 0);
6613
6614 sal_uInt16 nId = 0;
6615 switch (mnVersion) // 6 stands for "6 OR 7", 7 stands for "ONLY 7"
6616 {
6617 case 6:
6618 case 7:
6619 nId = *pSp;
6620 if (0x0100 < nId)
6621 nId = 0;
6622 break;
6623 default:
6624 case 8:
6625 nId = SVBT16ToShort(pSp);
6626 if (0x0800 > nId)
6627 nId = 0;
6628 break;
6629 }
6630 return nId;
6631 }
6632
6633 // with tokens and length byte
GetSprmSize(sal_uInt16 nId,const sal_uInt8 * pSprm) const6634 sal_uInt16 wwSprmParser::GetSprmSize(sal_uInt16 nId, const sal_uInt8* pSprm) const
6635 {
6636 return GetSprmTailLen(nId, pSprm) + 1 + mnDelta + SprmDataOfs(nId);
6637 }
6638
SprmDataOfs(sal_uInt16 nId) const6639 sal_uInt8 wwSprmParser::SprmDataOfs(sal_uInt16 nId) const
6640 {
6641 return GetSprmInfo(nId).nVari;
6642 }
6643
DistanceToData(sal_uInt16 nId) const6644 sal_uInt16 wwSprmParser::DistanceToData(sal_uInt16 nId) const
6645 {
6646 return 1 + mnDelta + SprmDataOfs(nId);
6647 }
6648
SEPr()6649 SEPr::SEPr() :
6650 bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0),
6651 fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0),
6652 dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0),
6653 dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0),
6654 dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0),
6655 dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0),
6656 reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0),
6657 xaPage(12242), yaPage(15842), xaPageNUp(12242), yaPageNUp(15842),
6658 dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0),
6659 dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1),
6660 reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0),
6661 dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0),
6662 reserved4(0)
6663 {
6664 memset(rgdxaColumnWidthSpacing, 0, sizeof(rgdxaColumnWidthSpacing));
6665 }
6666
6667 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
6668