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