xref: /trunk/main/sw/source/filter/ww1/w1class.cxx (revision efeef26f)
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 #include <string.h>
29 #include <tools/stream.hxx>
30 
31 #ifndef _W1CLASS_HXX
32 #include <w1class.hxx>
33 #endif
34 
35 
36 #ifdef DUMP
37 static const sal_Char* pUnknown = "?";
38 #define DUMPNAME(s) s
39 #else
40 #define DUMPNAME(s) 0
41 #endif
42 
43 Ww1SingleSprm* Ww1Sprm::aTab[ 256 ];
44 Ww1SingleSprm* Ww1Sprm::pSingleSprm = 0;
45 
46 
47 
48 /////////////////////////////////////////////////////////////////// Fib
Ww1Fib(SvStream & _rStream)49 Ww1Fib::Ww1Fib( SvStream& _rStream )
50 	: rStream(_rStream)
51 {
52 	bOK = 0 == rStream.Seek(0) &&
53 		  rStream.Read( &aFib, sizeof( aFib )) == sizeof( aFib );
54 }
55 
56 ///////////////////////////////////////////////////////////// PlainText
57 
Ww1PlainText(Ww1Fib & rWwFib,sal_uLong nFilePos,sal_uLong nCountBytes)58 Ww1PlainText::Ww1PlainText(Ww1Fib& rWwFib, sal_uLong nFilePos, sal_uLong nCountBytes)
59     : rFib(rWwFib), ulFilePos(nFilePos), ulCountBytes(nCountBytes),
60     ulSeek(0), bOK(true)
61 {
62 }
63 
operator [](sal_uLong ulOffset)64 sal_Unicode Ww1PlainText::operator [] ( sal_uLong ulOffset )
65 {
66 	DBG_ASSERT( ulOffset<Count(), "Ww1PlainText" );
67 	sal_Unicode cRet;
68 	sal_Char cRead;
69 	if( rFib.GetStream().Seek( ulFilePos + ulOffset ) == ulFilePos+ulOffset &&
70 		rFib.GetStream().Read( &cRead, sizeof( cRead ) ) == sizeof( cRead ) )
71 	{
72 		cRet = ByteString::ConvertToUnicode( cRead, RTL_TEXTENCODING_MS_1252 );
73 	}
74 	else
75 		cRet = ' ';
76 	return cRet;
77 }
78 
GetText(sal_uLong ulOffset,sal_uLong nLen) const79 String Ww1PlainText::GetText( sal_uLong ulOffset, sal_uLong nLen ) const
80 {
81 	String sRet;
82 	ByteString aStr;
83 	DBG_ASSERT(ulOffset+nLen<Count(), "Ww1PlainText");
84 	if( rFib.GetStream().Seek(ulFilePos+ulOffset) == ulFilePos+ulOffset &&
85         rFib.GetStream().Read( aStr.AllocBuffer( static_cast< xub_StrLen >(nLen) ), nLen ) == nLen )
86 		sRet = String( aStr, RTL_TEXTENCODING_MS_1252 );
87 	return sRet;
88 }
89 
90 ///////////////////////////////////////////////////////////////// Style
Ww1Style()91 Ww1Style::Ww1Style()
92 	: pPapx(0), pParent(0), stcBase(0), stcNext(0), bUsed(false)
93 {
94 }
95 
~Ww1Style()96 Ww1Style::~Ww1Style()
97 {
98 	delete pPapx;
99 }
100 
SetDefaults(sal_uInt8 stc)101 void Ww1Style::SetDefaults(sal_uInt8 stc)
102 {
103 	if( 222 == stc )
104 	{
105 		stcBase = 222;
106 		stcNext = 222;
107 		aChpx.hpsSet(20);
108 	}
109 }
110 
ReadName(sal_uInt8 * & p,sal_uInt16 & rnCountBytes,sal_uInt16 stc)111 sal_uInt16 Ww1Style::ReadName( sal_uInt8*&p, sal_uInt16& rnCountBytes, sal_uInt16 stc )
112 {
113 	sal_uInt8 nCountBytes = SVBT8ToByte(p);
114 	p++;
115 	rnCountBytes--;
116 	if( !nCountBytes ) // default
117 	{
118 		static const sal_Char* __READONLY_DATA names[] =
119 		{
120 			"W1 Null",  //222
121 			"W1 Annotation reference",  //223
122 			"W1 Annotation text",  //224
123 			"W1 Table of contents 8",  //225
124 			"W1 Table of contents 7",  //226
125 			"W1 Table of contents 6",  //227
126 			"W1 Table of contents 5",  //228
127 			"W1 Table of contents 4",  //229
128 			"W1 Table of contents 3",  //230
129 			"W1 Table of contents 2",  //231
130 			"W1 Table of contents 1",  //232
131 			"W1 Index 7",  //233
132 			"W1 Index 6",  //234
133 			"W1 Index 5",  //235
134 			"W1 Index 4",  //236
135 			"W1 Index 3",  //237
136 			"W1 Index 2",  //238
137 			"W1 Index 1",  //239
138 			"W1 Line number",  //240
139 			"W1 Index heading",  //241
140 			"W1 Footer",  //242
141 			"W1 Header",  //243
142 			"W1 Footnote reference",  //244
143 			"W1 Footnote text",  //245
144 			"W1 Heading 9",  //246
145 			"W1 Heading 8",  //247
146 			"W1 Heading 7",  //248
147 			"W1 Heading 6",  //249
148 			"W1 Heading 5",  //250
149 			"W1 Heading 4",  //251
150 			"W1 Heading 3",  //252
151 			"W1 Heading 2",  //253
152 			"W1 Heading 1",  //254
153 			"W1 Normal indent"  //255
154 			};//256
155 
156 		const sal_Char* pStr;
157 		size_t nSize(stc);
158 		if (!nSize)
159 			pStr = "W1 Normal";
160 		else if (nSize - 222 >= sizeof(names) / sizeof(*names))
161 			pStr = "?";
162 		else
163 			pStr = names[nSize-222];
164 		SetName(String(pStr, RTL_TEXTENCODING_MS_1252));
165 	}
166 	else if( 255 > nCountBytes ) // unused
167 	{
168 		SetName( String( (sal_Char*)p, nCountBytes, RTL_TEXTENCODING_MS_1252 ));
169 		p += nCountBytes;
170 		DBG_ASSERT(rnCountBytes>=nCountBytes, "Ww1Style");
171         rnCountBytes = rnCountBytes - nCountBytes;
172 	}
173 	return 0;
174 }
175 
ReadChpx(sal_uInt8 * & p,sal_uInt16 & rnCountBytes)176 sal_uInt16 Ww1Style::ReadChpx( sal_uInt8*&p, sal_uInt16& rnCountBytes )
177 {
178 	sal_uInt16 nCountBytes = SVBT8ToByte(p);
179 	p++;
180 	rnCountBytes--;
181 	if (nCountBytes != 255 // unused
182 	 && nCountBytes != 0) // default
183 	{
184 		if (nCountBytes > sizeof(aChpx))
185 			nCountBytes = sizeof(aChpx);
186 		memcpy( &aChpx, p, nCountBytes );
187 		p += nCountBytes;
188 		DBG_ASSERT(rnCountBytes>=nCountBytes, "Ww1Style");
189         rnCountBytes = rnCountBytes - nCountBytes;
190 	}
191 	return 0;
192 }
193 
ReadPapx(sal_uInt8 * & p,sal_uInt16 & rnCountBytes)194 sal_uInt16 Ww1Style::ReadPapx(sal_uInt8*&p, sal_uInt16& rnCountBytes)
195 {
196 	sal_uInt16 nCountBytes = SVBT8ToByte(p);
197 	p++;
198 	rnCountBytes--;
199 	if (nCountBytes != 255)
200 	{
201 		pPapx = new Ww1SprmPapx(p, nCountBytes);
202 		p += nCountBytes;
203 		DBG_ASSERT(rnCountBytes>=nCountBytes, "Ww1Style");
204         rnCountBytes = rnCountBytes - nCountBytes;
205 	}
206 	else
207 		pPapx = new Ww1SprmPapx(p, 0);
208 	return 0;
209 }
210 
ReadEstcp(sal_uInt8 * & p,sal_uInt16 & rnCountBytes)211 sal_uInt16 Ww1Style::ReadEstcp(sal_uInt8*&p, sal_uInt16& rnCountBytes)
212 {
213 	stcNext = SVBT8ToByte(p);
214 	p++;
215 	rnCountBytes--;
216 	stcBase = SVBT8ToByte(p);
217 	p++;
218 	DBG_ASSERT(rnCountBytes>0, "Ww1Style");
219 	rnCountBytes--;
220 	return 0;
221 }
222 
223 //////////////////////////////////////////////////////////// StyleSheet
Ww1StyleSheet(Ww1Fib & _rFib)224 Ww1StyleSheet::Ww1StyleSheet(Ww1Fib& _rFib)
225 	: cstcStd(0),
226 	rFib(_rFib),
227 	bOK(sal_False)
228 {
229 	sal_uInt16 cbStshf = rFib.GetFIB().cbStshfGet();
230 	DBG_ASSERT(cbStshf>=17, "Ww1StyleSheet");
231 	for (sal_uInt16 stc=0;stc<Count();stc++)
232 	{
233 		aStyles[stc].SetParent(this);
234 		aStyles[stc].SetDefaults((sal_uInt8)stc);
235 	}
236 	sal_uInt8* del = NULL;
237 	if (rFib.GetStream().Seek(rFib.GetFIB().fcStshfGet())
238 	  == (sal_uLong)rFib.GetFIB().fcStshfGet()
239 	 && (del = new sal_uInt8[cbStshf]) != NULL
240 	 && rFib.GetStream().Read(del, cbStshf) == (sal_uLong)cbStshf)
241 		{
242 		sal_uInt8* p = del;
243 			cstcStd = SVBT16ToShort(p);
244 			p += sizeof(SVBT16);
245 			cbStshf -= sizeof(SVBT16);
246 			ReadNames(p, cbStshf);
247 			ReadChpx(p, cbStshf);
248 			ReadPapx(p, cbStshf);
249 			ReadEstcp(p, cbStshf);
250 			DBG_ASSERT(cbStshf==0, "Ww1StyleSheet");
251 			bOK = cbStshf == 0;
252 		}
253 	delete [] del;
254 }
255 
ReadNames(sal_uInt8 * & p,sal_uInt16 & rnCountBytes)256 sal_uInt16 Ww1StyleSheet::ReadNames( sal_uInt8*& p, sal_uInt16& rnCountBytes )
257 {
258 	sal_uInt16 nCountBytes = SVBT16ToShort(p);
259 	p += sizeof(SVBT16);
260 	DBG_ASSERT(rnCountBytes>=nCountBytes, "Ww1StyleSheet");
261     rnCountBytes = rnCountBytes - nCountBytes;
262     nCountBytes = nCountBytes - sizeof(SVBT16);
263 	sal_uInt16 stcp = 0;
264 	while (nCountBytes > 0)
265 	{
266 		sal_uInt16 stc = (stcp - cstcStd) & 255;
267 		aStyles[stc].ReadName(p, nCountBytes, stc);
268 		stcp++;
269 	}
270 	DBG_ASSERT(nCountBytes==0, "Ww1StyleSheet");
271 	return 0;
272 }
273 
ReadChpx(sal_uInt8 * & p,sal_uInt16 & rnCountBytes)274 sal_uInt16 Ww1StyleSheet::ReadChpx(sal_uInt8*& p, sal_uInt16& rnCountBytes)
275 {
276 	sal_uInt16 nCountBytes = SVBT16ToShort(p);
277 	p += sizeof(SVBT16);
278 	DBG_ASSERT(rnCountBytes>=nCountBytes, "Ww1StyleSheet");
279     rnCountBytes = rnCountBytes - nCountBytes;
280     nCountBytes = nCountBytes - sizeof(SVBT16);
281 	sal_uInt16 stcp = 0;
282 	while (nCountBytes > 0)
283 	{
284 		sal_uInt16 stc = (stcp - cstcStd) & 255;
285 		aStyles[stc].ReadChpx(p, nCountBytes);
286 		stcp++;
287 	}
288 	DBG_ASSERT(nCountBytes == 0, "Ww1StyleSheet");
289 	return 0;
290 }
291 
ReadPapx(sal_uInt8 * & p,sal_uInt16 & rnCountBytes)292 sal_uInt16 Ww1StyleSheet::ReadPapx(sal_uInt8*& p, sal_uInt16& rnCountBytes)
293 {
294 	sal_uInt16 nCountBytes = SVBT16ToShort(p);
295 	p += sizeof(SVBT16);
296 	DBG_ASSERT(rnCountBytes>=nCountBytes, "Ww1StyleSheet");
297     rnCountBytes = rnCountBytes - nCountBytes;
298     nCountBytes = nCountBytes - sizeof(SVBT16);
299 	sal_uInt16 stcp = 0;
300 	while (nCountBytes > 0)
301 	{
302 		sal_uInt16 stc = (stcp - cstcStd) & 255;
303 		aStyles[stc].ReadPapx(p, nCountBytes);
304 		stcp++;
305 	}
306 	DBG_ASSERT(nCountBytes == 0, "Ww1StyleSheet");
307 	return 0;
308 }
309 
ReadEstcp(sal_uInt8 * & p,sal_uInt16 & rnCountBytes)310 sal_uInt16 Ww1StyleSheet::ReadEstcp(sal_uInt8*& p, sal_uInt16& rnCountBytes)
311 {
312 	sal_uInt16 iMac = SVBT16ToShort(p);
313 	p += sizeof(SVBT16);
314 	DBG_ASSERT(rnCountBytes>=sizeof(SVBT16), "Ww1StyleSheet");
315 	rnCountBytes -= sizeof(SVBT16);
316 	for (sal_uInt16 stcp=0;stcp<iMac;stcp++)
317 	{
318 		sal_uInt16 stc = (stcp - cstcStd) & 255;
319 		aStyles[stc].ReadEstcp(p, rnCountBytes);
320 	}
321 	DBG_ASSERT(rnCountBytes==0, "Ww1StyleSheet");
322 	return 0;
323 }
324 
325 ///////////////////////////////////////////////////////////////// Fonts
326 
Ww1Fonts(Ww1Fib & rInFib,sal_uLong nFieldFlgs)327 Ww1Fonts::Ww1Fonts(Ww1Fib& rInFib, sal_uLong nFieldFlgs)
328 	: pFontA(0), rFib(rInFib), nFieldFlags(nFieldFlgs), nMax(0), bOK(false)
329 {
330 	if(rFib.GetFIB().cbSttbfffnGet() > 2 ) // ueberhaupt fonts?
331 	{
332 		SVBT16 nCountBytes;
333 		DBG_ASSERT(rFib.GetFIB().cbSttbfffnGet() > sizeof(nCountBytes), "Ww1Fonts");
334 		if (rFib.GetStream().Seek(rFib.GetFIB().fcSttbfffnGet())
335 		 == (sal_uLong)rFib.GetFIB().fcSttbfffnGet())
336 			if (rFib.GetStream().Read(nCountBytes, sizeof(nCountBytes))
337 			 == sizeof(nCountBytes)) // Laenge steht hier nochmal
338 			{
339 				DBG_ASSERT(SVBT16ToShort(nCountBytes)
340 				 == rFib.GetFIB().cbSttbfffnGet(), "redundant-size missmatch");
341 				 // hoffentlich sind sie immer gleich
342 				W1_FFN* pA = (W1_FFN*)new char[rFib.GetFIB().cbSttbfffnGet()
343 				 - sizeof(nCountBytes)]; // Alloziere Font-Array
344 				//~ Ww1: new-NULL
345 				if (rFib.GetStream().Read(pA, rFib.GetFIB().cbSttbfffnGet()
346 				 - sizeof(nCountBytes)) == (sal_uLong)rFib.GetFIB().cbSttbfffnGet()
347 				 - sizeof(nCountBytes))	// lese alle Fonts
348 				{} //nothing
349 
350 				long nLeft = rFib.GetFIB().cbSttbfffnGet()
351 				 - sizeof(nCountBytes); // Zaehle, wieviele Fonts enthalten
352 				W1_FFN* p = pA;
353 				while (1)
354 				{
355 					sal_uInt16 nNextSiz;
356 					nNextSiz = p->cbFfnM1Get() + 1;
357 					if(nNextSiz > nLeft)
358 						break;
359 					nMax++;
360 					nLeft -= nNextSiz;
361 					if(nLeft < 1)			// naechste Laenge muss gelesen werden koennen
362 						break;
363 					p = (W1_FFN *)(((char*)p) + nNextSiz);
364 				}
365 				if (nMax)
366 				{
367 					pFontA = new W1_FFN*[nMax];			// alloziere Index-Array
368 					//~ Ww1: new-NULL
369 					pFontA[0] = pA;						// fuelle Index-Array
370 					sal_uInt16 i;
371 					for(i=1, p=pA; i<nMax; i++)
372 					{
373 						p = (W1_FFN*)(((char*)p) + p->cbFfnM1Get() + 1);
374 						pFontA[i] = p;
375 					}
376 				}
377 				else
378 					pFontA = 0;	// Keine Eintraege -> kein Array
379 			}
380 	}
381 	bOK = sal_True;
382 }
383 
GetFFN(sal_uInt16 nNum)384 W1_FFN* Ww1Fonts::GetFFN(sal_uInt16 nNum)
385 {
386 	W1_FFN* pRet = NULL;
387 	if (pFontA)
388 		if (nNum < nMax)
389 			pRet = pFontA[nNum];
390 	return pRet;
391 }
392 
393 /////////////////////////////////////////////////////////////////// DOP
Ww1Dop(Ww1Fib & _rFib)394 Ww1Dop::Ww1Dop(Ww1Fib& _rFib)
395 	: rFib(_rFib)
396 {
397 	long nRead;
398 	memset(&aDop, 0, sizeof(aDop)); // set defaults
399 	if(rFib.GetFIB().cbDopGet() >= sizeof(aDop))
400 		nRead = sizeof(aDop);
401 	else
402 		nRead = rFib.GetFIB().cbDopGet();
403 	bOK = rFib.GetStream().Seek(rFib.GetFIB().fcDopGet()) ==
404 				(sal_uLong)rFib.GetFIB().fcDopGet() &&
405 			rFib.GetStream().Read(&aDop, nRead) == (sal_uLong)nRead;
406 }
407 
408 /////////////////////////////////////////////////////////////// Picture
Ww1Picture(SvStream & rStream,sal_uLong ulFilePos)409 Ww1Picture::Ww1Picture(SvStream& rStream, sal_uLong ulFilePos)
410 	: bOK(false), pPic(0)
411 {
412 	ulFilePos &= 0xffffff; //~ ww1: warum auch immer - im highbyte steht eine 5?!?!
413 	SVBT32 lcb;
414 	if (rStream.Seek(ulFilePos) == (sal_uLong)ulFilePos)
415 		if (rStream.Read(&lcb, sizeof(lcb)) == (sal_uLong)sizeof(lcb))
416 			if (sizeof(int)>=4 || SVBT32ToUInt32(lcb) < 0x8000) //~ mdt: 64K & 16bit
417 				if ((pPic = (W1_PIC*)(new sal_uInt8[SVBT32ToUInt32(lcb)])) != NULL)
418 					if (rStream.Seek(ulFilePos) == (sal_uLong)ulFilePos)
419 						if (rStream.Read(pPic, SVBT32ToUInt32(lcb)) == (sal_uLong)SVBT32ToUInt32(lcb))
420 						{
421 							DBG_ASSERT(pPic->cbHeaderGet()==sizeof(*pPic)-sizeof(pPic->rgb), "Ww1Picture");
422 							bOK = true;
423 						}
424 }
425 
426 ////////////////////////////////////////////////////////////////// Sprm
Ww1Sprm(sal_uInt8 * x,sal_uInt16 _nCountBytes)427 Ww1Sprm::Ww1Sprm(sal_uInt8* x, sal_uInt16 _nCountBytes)
428 	: p(NULL),
429 	nCountBytes(_nCountBytes),
430 	bOK(sal_False),
431 	pArr(NULL),
432 	count(0)
433 {
434 	if (nCountBytes == 0)
435 		bOK = sal_True;
436 	else
437 		if ((p = new sal_uInt8[nCountBytes]) != NULL)
438 		{
439 			memcpy(p, x, nCountBytes);
440 			if (ReCalc())
441 				bOK = sal_True;
442 		}
443 }
444 
Ww1Sprm(SvStream & rStream,sal_uLong ulFilePos)445 Ww1Sprm::Ww1Sprm(SvStream& rStream, sal_uLong ulFilePos)
446 	: p(NULL),
447 	nCountBytes(0),
448 	bOK(sal_False),
449 	pArr(NULL),
450 	count(0)
451 {
452 	SVBT8 x;
453 	ByteToSVBT8(0, x);
454 	if (rStream.Seek(ulFilePos) == (sal_uLong)ulFilePos)
455 		if (rStream.Read(&x, sizeof(x)) == (sal_uLong)sizeof(x))
456 			if ((nCountBytes = SVBT8ToByte(x)) == 255
457 			 || !nCountBytes
458 			 || (p = new sal_uInt8[nCountBytes]) != NULL)
459 				if (nCountBytes == 255
460 				 || !nCountBytes
461 				 || rStream.Read(p, nCountBytes) == (sal_uLong)nCountBytes)
462 					if (ReCalc())
463 						bOK = sal_True;
464 }
465 
~Ww1Sprm()466 Ww1Sprm::~Ww1Sprm()
467 {
468 	delete pArr;
469 	delete p;
470 }
471 
Size(sal_uInt8 *)472 sal_uInt16 Ww1SingleSprm::Size(sal_uInt8* /*pSprm*/)
473 {
474 	return nCountBytes;
475 }
476 
Size(sal_uInt8 * pSprm)477 sal_uInt16 Ww1SingleSprmTab::Size(sal_uInt8* pSprm) // Doc 24/25, Fastsave-Sprm
478 {
479 	DBG_ASSERT(nCountBytes==0, "Ww1SingleSprmTab");
480 	sal_uInt16 nRet = sizeof(SVBT8);
481 	sal_uInt16 nSize = SVBT8ToByte(pSprm);
482 	if (nSize != 255)
483         nRet = nRet + nSize;
484 	else
485 	{
486 		sal_uInt16 nDel = SVBT8ToByte(pSprm+1) * 4;
487 		sal_uInt16 nIns = SVBT8ToByte(pSprm + 3 + nDel) * 3;
488 		nRet += nDel + nIns;
489 	}
490 	DBG_ASSERT(nRet <= 354, "Ww1SingleSprmTab");
491 	if (nRet > 354)
492 		nRet = 0;
493 	return nRet;
494 }
495 
Size(sal_uInt8 * pSprm)496 sal_uInt16 Ww1SingleSprmByteSized::Size(sal_uInt8* pSprm)
497 {
498 	sal_uInt16 nRet;
499 	nRet = SVBT8ToByte(pSprm);
500 	nRet += sizeof(SVBT8);	// var. l. byte-size
501 //	pSprm += sizeof(SVBT8); // var. l. byte-size
502     nRet = nRet + nCountBytes;
503 	return nRet;
504 }
505 
Size(sal_uInt8 * pSprm)506 sal_uInt16 Ww1SingleSprmWordSized::Size(sal_uInt8* pSprm)
507 {
508 	sal_uInt16 nRet;
509 	nRet = SVBT16ToShort(pSprm);
510 	nRet += sizeof(SVBT16);  // var. l. word-size
511 //	pSprm += sizeof(SVBT16); // var. l. word-size
512     nRet = nRet + nCountBytes;
513 	return nRet;
514 }
515 
516 static sal_uInt8 nLast = 0;
517 static sal_uInt8 nCurrent = 0;
GetSize(sal_uInt8 nId,sal_uInt8 * pSprm)518 sal_uInt16 Ww1Sprm::GetSize(sal_uInt8 nId, sal_uInt8* pSprm)
519 {
520 	//DBG_ASSERT( nId < sizeof(aTab) / sizeof(*aTab), "Ww1Sprm" );
521 	sal_uInt16 nL = 0;
522 	nL = GetTab(nId).Size(pSprm);
523 	nLast = nCurrent;
524 	nCurrent = nId;
525 	return nL;
526 }
527 
Fill(sal_uInt16 index,sal_uInt8 & nId,sal_uInt16 & nL,sal_uInt8 * & pSprm)528 sal_Bool Ww1Sprm::Fill(sal_uInt16 index, sal_uInt8& nId, sal_uInt16& nL, sal_uInt8*& pSprm)
529 {
530 	//DBG_ASSERT( nId < sizeof(aTab) / sizeof(*aTab), "Ww1Sprm");
531 	DBG_ASSERT(index < Count(), "Ww1Sprm");
532 	pSprm = p + pArr[index];
533 	nId = SVBT8ToByte(pSprm);
534 	pSprm++;
535 	nL = GetTab(nId).Size(pSprm);
536 	return sal_True;
537 }
538 
ReCalc()539 sal_Bool Ww1Sprm::ReCalc()
540 {
541 	sal_Bool bRet = sal_True;
542 	delete pArr;
543 	pArr = NULL;
544 	count = 0;
545 	if (nCountBytes != 255) // not unused?
546 	{
547 		sal_uInt16 cbsik = nCountBytes;
548 		sal_uInt8* psik = p;
549 		while (cbsik > 0)
550 		{
551 			sal_uInt16 iLen = GetSizeBrutto(psik);
552 			DBG_ASSERT(iLen<=cbsik, "Ww1Sprm");
553 			if (iLen > cbsik)
554 				cbsik = 0; // ignore the rest: we are wrong...
555 			else
556 			{
557 				psik += iLen;
558                 cbsik = cbsik - iLen;
559 				count++;
560 			}
561 		}
562 		if (bRet
563 		 && (pArr = new sal_uInt16[count]) != NULL)
564 		{
565 			cbsik = nCountBytes;
566 			sal_uInt16 offset = 0;
567 			sal_uInt16 current = 0;
568 			psik = p;
569 			while (current<count)
570 			{
571 				pArr[current++] = offset;
572 				sal_uInt16 iLen = GetSizeBrutto(psik);
573 				psik += iLen;
574 				if (iLen > cbsik)
575 					cbsik = 0;
576 				else
577                     cbsik = cbsik - iLen;
578                 offset = offset + iLen;
579 			}
580 
581 		}
582 		else
583 			count = 0;
584 	}
585 	return bRet;
586 }
587 
DeinitTab()588 void Ww1Sprm::DeinitTab()
589 {
590 	for (size_t i=0; i < sizeof(aTab)/sizeof(*aTab); ++i)
591 		delete aTab[i];
592 	memset(aTab, 0, sizeof(aTab)/sizeof(*aTab));
593 	delete pSingleSprm;
594 }
595 
InitTab()596 void Ww1Sprm::InitTab()
597 {
598 	memset(aTab, 0, sizeof(aTab)/sizeof(*aTab));
599 	pSingleSprm = new Ww1SingleSprm( 0, DUMPNAME(pUnknown));
600 
601 	aTab[  2] = new Ww1SingleSprmByte(DUMPNAME("sprmPStc")); //   2 pap.istd (style code)
602 	aTab[  3] = new Ww1SingleSprmByteSized(0, DUMPNAME("sprmPIstdPermute")); //   3 pap.istd	permutation
603 	aTab[  4] = new Ww1SingleSprmByte(DUMPNAME("sprmPIncLevel")); //   4 pap.istddifference
604 	aTab[  5] = new Ww1SingleSprmPJc(DUMPNAME("sprmPJc")); //   5 pap.jc (justification)
605 	aTab[  6] = new Ww1SingleSprmBool(DUMPNAME("sprmPFSideBySide")); //   6 pap.fSideBySide
606 	aTab[  7] = new Ww1SingleSprmPFKeep(DUMPNAME("sprmPFKeep")); //   7 pap.fKeep
607 	aTab[  8] = new Ww1SingleSprmPFKeepFollow(DUMPNAME("sprmPFKeepFollow")); //   8 pap.fKeepFollow
608 	aTab[  9] = new Ww1SingleSprmPPageBreakBefore(DUMPNAME("sprmPPageBreakBefore")); //   9 pap.fPageBreakBefore
609 	aTab[ 10] = new Ww1SingleSprmByte(DUMPNAME("sprmPBrcl")); //  10 pap.brcl
610 	aTab[ 11] = new Ww1SingleSprmByte(DUMPNAME("sprmPBrcp")); //  11 pap.brcp
611 	aTab[ 12] = new Ww1SingleSprmByteSized(0, DUMPNAME("sprmPAnld")); //  12 pap.anld (ANLD structure)
612 	aTab[ 13] = new Ww1SingleSprmByte(DUMPNAME("sprmPNLvlAnm")); //  13 pap.nLvlAnm nn
613 	aTab[ 14] = new Ww1SingleSprmBool(DUMPNAME("sprmPFNoLineNumb")); //  14 ap.fNoLnn
614 	aTab[ 15] = new Ww1SingleSprmPChgTabsPapx(DUMPNAME("sprmPChgTabsPapx")); //  15 pap.itbdMac, ...
615 	aTab[ 16] = new Ww1SingleSprmPDxaRight(DUMPNAME("sprmPDxaRight")); //  16 pap.dxaRight
616 	aTab[ 17] = new Ww1SingleSprmPDxaLeft(DUMPNAME("sprmPDxaLeft")); //  17 pap.dxaLeft
617 	aTab[ 18] = new Ww1SingleSprmWord(DUMPNAME("sprmPNest")); //  18 pap.dxaNest
618 	aTab[ 19] = new Ww1SingleSprmPDxaLeft1(DUMPNAME("sprmPDxaLeft1")); //  19 pap.dxaLeft1
619 	aTab[ 20] = new Ww1SingleSprmPDyaLine(DUMPNAME("sprmPDyaLine")); //  20 pap.lspd	an LSPD
620 	aTab[ 21] = new Ww1SingleSprmPDyaBefore(DUMPNAME("sprmPDyaBefore")); //  21 pap.dyaBefore
621 	aTab[ 22] = new Ww1SingleSprmPDyaAfter(DUMPNAME("sprmPDyaAfter")); //  22 pap.dyaAfter
622 	aTab[ 23] = new Ww1SingleSprmTab(0, DUMPNAME(pUnknown)); // 23 pap.itbdMac, pap.rgdxaTab
623 	aTab[ 24] = new Ww1SingleSprmPFInTable(DUMPNAME("sprmPFInTable")); //  24 pap.fInTable
624 	aTab[ 25] = new Ww1SingleSprmPTtp(DUMPNAME("sprmPTtp")); //  25 pap.fTtp
625 	aTab[ 26] = new Ww1SingleSprmPDxaAbs(DUMPNAME("sprmPDxaAbs")); //  26 pap.dxaAbs
626 	aTab[ 27] = new Ww1SingleSprmPDyaAbs(DUMPNAME("sprmPDyaAbs")); //  27 pap.dyaAbs
627 	aTab[ 28] = new Ww1SingleSprmPDxaWidth(DUMPNAME("sprmPDxaWidth")); //  28 pap.dxaWidth
628 	aTab[ 29] = new Ww1SingleSprmPpc(DUMPNAME("sprmPPc")); //  29 pap.pcHorz, pap.pcVert
629 	aTab[ 30] = new Ww1SingleSprmPBrc10(BRC_TOP, DUMPNAME("sprmPBrcTop10")); //  30 pap.brcTop BRC10
630 	aTab[ 31] = new Ww1SingleSprmPBrc10(BRC_LEFT, DUMPNAME("sprmPBrcLeft10")); //  31 pap.brcLeft BRC10
631 	aTab[ 32] = new Ww1SingleSprmPBrc10(BRC_BOTTOM, DUMPNAME("sprmPBrcBottom10")); //  32 pap.brcBottom BRC10
632 	aTab[ 33] = new Ww1SingleSprmPBrc10(BRC_RIGHT, DUMPNAME("sprmPBrcRight10")); //  33 pap.brcRight BRC10
633 	aTab[ 34] = new Ww1SingleSprmWord(DUMPNAME("sprmPBrcBetween10")); //  34 pap.brcBetween BRC10
634 	aTab[ 35] = new Ww1SingleSprmPBrc10(BRC_LEFT, DUMPNAME("sprmPBrcBar10")); //  35 pap.brcBar BRC10
635 	aTab[ 36] = new Ww1SingleSprmPFromText(DUMPNAME("sprmPFromText10")); //  36 pap.dxaFromText dxa
636 	aTab[ 37] = new Ww1SingleSprmByte(DUMPNAME("sprmPWr")); //  37 pap.wr wr
637 	aTab[ 38] = new Ww1SingleSprmWord(DUMPNAME("sprmPBrcTop")); //  38 pap.brcTop BRC
638 	aTab[ 39] = new Ww1SingleSprmWord(DUMPNAME("sprmPBrcLeft")); //  39 pap.brcLeft BRC
639 	aTab[ 40] = new Ww1SingleSprmWord(DUMPNAME("sprmPBrcBottom")); //  40 pap.brcBottom BRC
640 	aTab[ 41] = new Ww1SingleSprmWord(DUMPNAME("sprmPBrcRight")); //  41 pap.brcRight BRC
641 	aTab[ 42] = new Ww1SingleSprmWord(DUMPNAME("sprmPBrcBetween")); //  42 pap.brcBetween BRC
642 	aTab[ 43] = new Ww1SingleSprmWord(DUMPNAME("sprmPBrcBar")); //  43 pap.brcBar BRC word
643 	aTab[ 44] = new Ww1SingleSprmBool(DUMPNAME("sprmPFNoAutoHyph")); //  44 pap.fNoAutoHyph
644 	aTab[ 45] = new Ww1SingleSprmWord(DUMPNAME("sprmPWHeightAbs")); //  45 pap.wHeightAbs w
645 	aTab[ 46] = new Ww1SingleSprmWord(DUMPNAME("sprmPDcs")); //  46 pap.dcs DCS
646 	aTab[ 47] = new Ww1SingleSprmWord(DUMPNAME("sprmPShd")); //  47 pap.shd SHD
647 	aTab[ 48] = new Ww1SingleSprmWord(DUMPNAME("sprmPDyaFromText")); //  48 pap.dyaFromText dya
648 	aTab[ 49] = new Ww1SingleSprmWord(DUMPNAME("sprmPDxaFromText")); //  49 pap.dxaFromText dxa
649 	aTab[ 50] = new Ww1SingleSprmBool(DUMPNAME("sprmPFLocked")); //  50 pap.fLocked 0 or 1 byte
650 	aTab[ 51] = new Ww1SingleSprmBool(DUMPNAME("sprmPFWidowControl")); //  51 pap.fWidowControl 0 or 1 byte
651 
652 	aTab[ 57] = new Ww1SingleSprmByteSized(0, DUMPNAME("sprmCDefault")); //  57 whole CHP (see below) none variable length
653 	aTab[ 58] = new Ww1SingleSprm(0, DUMPNAME("sprmCPlain")); //  58 whole CHP (see below) none 0
654 
655 	aTab[ 60] = new Ww1SingleSprm4State(DUMPNAME("sprmCFBold")); //  60 chp.fBold 0,1, 128, or 129 (see below) byte
656 	aTab[ 61] = new Ww1SingleSprm4State(DUMPNAME("sprmCFItalic")); //  61 chp.fItalic 0,1, 128, or 129 (see below) byte
657 	aTab[ 62] = new Ww1SingleSprm4State(DUMPNAME("sprmCFStrike")); //  62 chp.fStrike 0,1, 128, or 129 (see below) byte
658 	aTab[ 63] = new Ww1SingleSprm4State(DUMPNAME("sprmCFOutline")); //  63 chp.fOutline 0,1, 128, or 129 (see below) byte
659 	aTab[ 64] = new Ww1SingleSprm4State(DUMPNAME("sprmCFShadow")); //  64 chp.fShadow 0,1, 128, or 129 (see below) byte
660 	aTab[ 65] = new Ww1SingleSprm4State(DUMPNAME("sprmCFSmallCaps")); //  65 chp.fSmallCaps 0,1, 128, or 129 (see below) byte
661 	aTab[ 66] = new Ww1SingleSprm4State(DUMPNAME("sprmCFCaps")); //  66 chp.fCaps 0,1, 128, or 129 (see below) byte
662 	aTab[ 67] = new Ww1SingleSprm4State(DUMPNAME("sprmCFVanish")); //  67 chp.fVanish 0,1, 128, or 129 (see below) byte
663 	aTab[ 68] = new Ww1SingleSprmWord(DUMPNAME("sprmCFtc")); //  68 chp.ftc ftc word
664 	aTab[ 69] = new Ww1SingleSprmByte(DUMPNAME("sprmCKul")); //  69 chp.kul kul byte
665 	aTab[ 70] = new Ww1SingleSprm(3, DUMPNAME("sprmCSizePos")); //  70 chp.hps, chp.hpsPos (see below) 3 bytes
666 	aTab[ 71] = new Ww1SingleSprmWord(DUMPNAME("sprmCDxaSpace")); //  71 chp.dxaSpace dxa word
667 	aTab[ 72] = new Ww1SingleSprmWord(DUMPNAME("//")); //  72 //
668 	aTab[ 73] = new Ww1SingleSprmByte(DUMPNAME("sprmCIco")); //  73 chp.ico ico byte
669 	aTab[ 74] = new Ww1SingleSprmByte(DUMPNAME("sprmCHps")); //  74 chp.hps hps !byte!
670 	aTab[ 75] = new Ww1SingleSprmByte(DUMPNAME("sprmCHpsInc")); //  75 chp.hps (see below) byte
671 	aTab[ 76] = new Ww1SingleSprmWord(DUMPNAME("sprmCHpsPos")); //  76 chp.hpsPos hps !word!
672 	aTab[ 77] = new Ww1SingleSprmByte(DUMPNAME("sprmCHpsPosAdj")); //  77 chp.hpsPos hps (see below) byte
673 	aTab[ 78] = new Ww1SingleSprmByteSized(0, DUMPNAME(pUnknown)); //  78 ?chp.fBold, chp.fItalic, chp.fSmallCaps, ...
674 
675 	aTab[ 94] = new Ww1SingleSprmByte(DUMPNAME("sprmPicBrcl")); //  94 pic.brcl brcl (see PIC structure definition) byte
676 	aTab[ 95] = new Ww1SingleSprmByteSized(0, DUMPNAME("sprmPicScale")); //  95 pic.mx, pic.my, pic.dxaCropleft,
677 
678 	aTab[117] = new Ww1SingleSprmByte(DUMPNAME("sprmSBkc")); // 117 sep.bkc bkc byte
679 	aTab[118] = new Ww1SingleSprmBool(DUMPNAME("sprmSFTitlePage")); // 118 sep.fTitlePage 0 or 1 byte
680 	aTab[119] = new Ww1SingleSprmSColumns(DUMPNAME("sprmSCcolumns")); // 119 sep.ccolM1 # of cols - 1 word
681 	aTab[120] = new Ww1SingleSprmWord(DUMPNAME("sprmSDxaColumns")); // 120 sep.dxaColumns dxa word
682 
683 	aTab[122] = new Ww1SingleSprmByte(DUMPNAME("sprmSNfcPgn")); // 122 sep.nfcPgn nfc byte
684 
685 	aTab[125] = new Ww1SingleSprmBool(DUMPNAME("sprmSFPgnRestart")); // 125 sep.fPgnRestart 0 or 1 byte
686 	aTab[126] = new Ww1SingleSprmBool(DUMPNAME("sprmSFEndnote")); // 126 sep.fEndnote 0 or 1 byte
687 	aTab[127] = new Ww1SingleSprmByte(DUMPNAME("sprmSLnc")); // 127 sep.lnc lnc byte
688 	aTab[128] = new Ww1SingleSprmSGprfIhdt(DUMPNAME("sprmSGprfIhdt")); // 128 sep.grpfIhdt grpfihdt (see Headers and Footers topic) byte
689 	aTab[129] = new Ww1SingleSprmWord(DUMPNAME("sprmSNLnnMod")); // 129 sep.nLnnMod non-neg int. word
690 	aTab[130] = new Ww1SingleSprmWord(DUMPNAME("sprmSDxaLnn")); // 130 sep.dxaLnn dxa word
691 	aTab[131] = new Ww1SingleSprmWord(DUMPNAME("sprmSDyaHdrTop")); // 131 sep.dyaHdrTop dya word
692 	aTab[132] = new Ww1SingleSprmWord(DUMPNAME("sprmSDyaHdrBottom")); // 132 sep.dyaHdrBottom dya word
693 	aTab[133] = new Ww1SingleSprmBool(DUMPNAME("sprmSLBetween")); // 133 sep.fLBetween 0 or 1 byte
694 	aTab[134] = new Ww1SingleSprmByte(DUMPNAME("sprmSVjc")); // 134 sep.vjc vjc byte
695 	aTab[135] = new Ww1SingleSprmWord(DUMPNAME("sprmSLnnMin")); // 135 sep.lnnMin lnn word
696 	aTab[136] = new Ww1SingleSprmWord(DUMPNAME("sprmSPgnStart")); // 136 sep.pgnStart pgn word
697 
698 	aTab[146] = new Ww1SingleSprmWord(DUMPNAME("sprmTJc")); // 146 tap.jc jc word (low order byte is significant)
699 	aTab[147] = new Ww1SingleSprmWord(DUMPNAME("sprmTDxaLeft")); // 147 tap.rgdxaCenter (see below) dxa word
700 	aTab[148] = new Ww1SingleSprmWord(DUMPNAME("sprmTDxaGapHalf")); // 148 tap.dxaGapHalf, tap.rgdxaCenter (see below) dxa word
701 
702 	aTab[152] = new Ww1SingleSprmTDefTable10(DUMPNAME("sprmTDefTable10")); // 152 tap.rgdxaCenter, tap.rgtc complex (see below) variable length
703 	aTab[153] = new Ww1SingleSprmWord(DUMPNAME("sprmTDyaRowHeight")); // 153 tap.dyaRowHeight dya word
704 
705 	aTab[158] = new Ww1SingleSprm(4, DUMPNAME("sprmTInsert")); // 158 tap.rgdxaCenter,tap.rgtc complex (see below) 4 bytes
706 	aTab[159] = new Ww1SingleSprmWord(DUMPNAME("sprmTDelete")); // 159 tap.rgdxaCenter, tap.rgtc complex (see below) word
707 	aTab[160] = new Ww1SingleSprm(4, DUMPNAME("sprmTDxaCol")); // 160 tap.rgdxaCenter complex (see below) 4 bytes
708 	aTab[161] = new Ww1SingleSprmWord(DUMPNAME("sprmTMerge")); // 161 tap.fFirstMerged, tap.fMerged complex (see below) word
709 	aTab[162] = new Ww1SingleSprmWord(DUMPNAME("sprmTSplit")); // 162 tap.fFirstMerged, tap.fMerged complex (see below) word
710 	aTab[163] = new Ww1SingleSprm(5, DUMPNAME("sprmTSetBrc10")); // 163 tap.rgtc[].rgbrc complex (see below) 5 bytes
711 }
712 
713 ////////////////////////////////////////////////////////////// SprmPapx
Ww1SprmPapx(sal_uInt8 * pByte,sal_uInt16 nSize)714 Ww1SprmPapx::Ww1SprmPapx(sal_uInt8* pByte, sal_uInt16 nSize) :
715 	Ww1Sprm(Sprm(pByte, nSize), SprmSize(pByte, nSize))
716 {
717 	memset(&aPapx, 0, sizeof(aPapx));
718 	memcpy(&aPapx, pByte, nSize<sizeof(aPapx)?nSize:sizeof(aPapx));
719 }
720 
SprmSize(sal_uInt8 *,sal_uInt16 nSize)721 sal_uInt16 Ww1SprmPapx::SprmSize(sal_uInt8*, sal_uInt16 nSize)
722 {
723 	sal_uInt16 nRet = 0;
724 	if (nSize >= sizeof(W1_PAPX))
725 		nRet = nSize - ( sizeof(W1_PAPX) - 1 ); // im W1_PAPX ist das
726 												// 1. SprmByte enthalten
727 	return nRet;
728 }
729 
Sprm(sal_uInt8 * pByte,sal_uInt16 nSize)730 sal_uInt8* Ww1SprmPapx::Sprm(sal_uInt8* pByte, sal_uInt16 nSize)
731 {
732 	sal_uInt8* pRet = NULL;
733 	if (nSize >= sizeof(W1_PAPX))
734 		pRet = ((W1_PAPX*)(pByte))->grpprlGet();
735 	return pRet;
736 }
737 
738 /////////////////////////////////////////////////////////////////// Plc
Ww1Plc(Ww1Fib & rInFib,sal_uLong ulFilePos,sal_uInt16 nInCountBytes,sal_uInt16 nInItemSize)739 Ww1Plc::Ww1Plc(Ww1Fib& rInFib, sal_uLong ulFilePos, sal_uInt16 nInCountBytes,
740 	sal_uInt16 nInItemSize)
741 	: p(0), nCountBytes(nInCountBytes), iMac(0), nItemSize(nInItemSize),
742 	bOK(false), rFib(rInFib)
743 {
744 	if (!nCountBytes)
745 		bOK = true;
746 	else
747 	{
748 		if (rFib.GetStream().Seek(ulFilePos) == (sal_uLong)ulFilePos)
749 		{
750 			if ((p = new sal_uInt8[nCountBytes]) != NULL)
751 			{
752 				if (rFib.GetStream().Read(p, nCountBytes) == (sal_uLong)nCountBytes)
753 				{
754 					bOK = true;
755 					iMac = (nCountBytes -
756 						sizeof(SVBT32)) / (sizeof(SVBT32) + nItemSize);
757 					DBG_ASSERT(iMac * ((sal_uInt16)sizeof(sal_uLong) + nItemSize) +
758 					 (sal_uInt16)sizeof(SVBT32) == nCountBytes, "Ww1Plc");
759 				}
760 			}
761 		}
762 	}
763 }
764 
~Ww1Plc()765 Ww1Plc::~Ww1Plc()
766 {
767 	delete p;
768 }
769 
Seek(sal_uLong ulSeek,sal_uInt16 & nIndex)770 void Ww1Plc::Seek(sal_uLong ulSeek, sal_uInt16& nIndex)
771 {
772 	if (iMac)
773 		for (;nIndex <= iMac && Where(nIndex) < ulSeek;nIndex++)
774 			;
775 }
776 
Where(sal_uInt16 nIndex)777 sal_uLong Ww1Plc::Where(sal_uInt16 nIndex)
778 {
779 	sal_uLong ulRet = 0xffffffff;
780 	DBG_ASSERT(nIndex <= iMac, "index out of bounds");
781 	if (iMac && nIndex <= iMac)
782 		ulRet = SVBT32ToUInt32(p + sizeof(SVBT32) * nIndex);
783 	return ulRet;
784 }
785 
GetData(sal_uInt16 nIndex)786 sal_uInt8* Ww1Plc::GetData(sal_uInt16 nIndex)
787 {
788 	sal_uInt8* pRet = NULL;
789 	DBG_ASSERT(nIndex < iMac, "index out of bounds");
790 	if (nIndex < iMac)
791 		pRet = p + (iMac + 1) * sizeof(SVBT32) +
792 		 nIndex * nItemSize; // Pointer auf Inhalts-Array
793 	return pRet;
794 }
795 
796 /////////////////////////////////////////////////////////////////// Sep
797 
798 //////////////////////////////////////////////////////////////// PlcSep
799 
800 //////////////////////////////////////////////////////////////// PlcPap
801 
802 //////////////////////////////////////////////////////////////// PlcChp
803 
804 //////////////////////////////////////////////////////////////// PlcFnr
805 
806 ///////////////////////////////////////////////////////////// PlcFnText
807 
808 ///////////////////////////////////////////////////////////// PlcFields
809 
810 ///////////////////////////////////////////////////////////// PlcBookmarks
811 // class Ww1StringList liest im Ctor eine Anzahl von P-Strings aus dem Stream
812 // in den Speicher und patcht sie zu C-Strings um.
813 // Die Anzahl wird in nMax zurueckgeliefert.
814 // im Index 0 stehen alle Strings nacheinander, ab Index 1 werden
815 // die einzelnen Strings referenziert.
Ww1StringList(SvStream & rSt,sal_uLong nFc,sal_uInt16 nCb)816 Ww1StringList::Ww1StringList( SvStream& rSt, sal_uLong nFc, sal_uInt16 nCb )
817 	: pIdxA(0), nMax(0)
818 {
819 	if( nCb > 2 )			 // ueberhaupt Eintraege ?
820 	{
821 		SVBT16 nCountBytes;
822 		DBG_ASSERT(nCb > sizeof(nCountBytes), "Ww1StringList");
823 		if (rSt.Seek(nFc) == (sal_uLong)nFc)
824 			if (rSt.Read(nCountBytes, sizeof(nCountBytes))
825 			 		== sizeof(nCountBytes)) // Laenge steht hier nochmal
826 			{
827 				DBG_ASSERT(SVBT16ToShort(nCountBytes)
828 				 		== nCb, "redundant-size missmatch");
829 									// hoffentlich sind sie immer gleich
830 				sal_Char* pA = new sal_Char[nCb - sizeof(nCountBytes) + 1];
831 									// Alloziere PString-Array
832 				//~ Ww1: new-NULL
833 				if (rSt.Read(pA, nCb - sizeof(nCountBytes))
834 						== (sal_uLong)nCb - sizeof(nCountBytes))	// lese alle
835 				{}// do nothing
836 									// Zaehle, wieviele Fonts enthalten
837 				long nLeft = nCb - sizeof(nCountBytes);
838 				sal_Char* p = pA;
839 				while (1)
840 				{
841 					sal_uInt16 nNextSiz;
842 					nNextSiz = *p + 1;
843 					if(nNextSiz > nLeft)
844 						break;
845 					nMax++;
846 					nLeft -= nNextSiz;
847 					if(nLeft < 1)			// naechste Laenge muss gelesen werden koennen
848 						break;
849 					p = p + nNextSiz;
850 				}
851 				if (nMax)
852 				{
853 					pIdxA = new sal_Char*[nMax+1];		// alloziere Index-Array
854 					pIdxA[0] = pA;						// Index 0 : alles
855 														// ab Index 1 C-Strings
856 					pIdxA[1] = pA + 1;					// fuelle Index-Array
857 					sal_uInt16 i = 2;
858 					p = pA;
859 					sal_uInt8 nL = *p;
860 					while(1)
861 					{
862 						p += nL + 1;					// Neues Laengen-Byte
863 						nL = *p;						// merke Laenge
864 						*p = '\0';						// mach C-String draus
865 						if( i > nMax )
866 							break;
867 						pIdxA[i] = p + 1;				// Ptr auf C-String
868 						i++;
869 					}
870 				}
871 				else
872 					pIdxA = 0;	// Keine Eintraege -> kein Array
873 			}
874 	}
875 }
GetStr(sal_uInt16 nNum) const876 const String Ww1StringList::GetStr( sal_uInt16 nNum ) const
877 {
878 	String sRet;
879 	if( nNum <= nMax )
880 		sRet = String( pIdxA[ nNum+1 ], RTL_TEXTENCODING_MS_1252 );
881 	return sRet;
882 }
883 
Ww1Bookmarks(Ww1Fib & rInFib)884 Ww1Bookmarks::Ww1Bookmarks(Ww1Fib& rInFib)
885 	: aNames(rInFib), rFib(rInFib), nIsEnd(0)
886 {
887 	pPos[0] = new Ww1PlcBookmarkPos(rFib, rFib.GetFIB().fcPlcfbkfGet(),
888 									rFib.GetFIB().cbPlcfbkfGet(), sal_False);
889 	nPlcIdx[0] = 0;
890 	pPos[1] = new Ww1PlcBookmarkPos(rFib, rFib.GetFIB().fcPlcfbklGet(),
891 									rFib.GetFIB().cbPlcfbklGet(), sal_True);
892 	nPlcIdx[1] = 0;
893 	bOK = !aNames.GetError() && !pPos[0]->GetError() && !pPos[1]->GetError();
894 }
895 
896 // Der Operator ++ hat eine Tuecke: Wenn 2 Bookmarks aneinandergrenzen, dann
897 // sollte erst das Ende des ersten und dann der Anfang des 2. erreicht werden.
898 // Liegen jedoch 2 Bookmarks der Laenge 0 aufeinander, *muss* von jedem Bookmark
899 // erst der Anfang und dann das Ende gefunden werden.
900 // Der Fall: ][
901 //            [...]
902 //           ][
903 // ist noch nicht geloest, dabei muesste ich in den Anfangs- und Endindices
904 // vor- und zurueckspringen, wobei ein weiterer Index oder ein Bitfeld
905 // oder etwas aehnliches zum Merken der bereits abgearbeiteten Bookmarks
906 // noetig wird.
operator ++(int)907 void Ww1Bookmarks::operator ++( int )
908 {
909 	if( bOK )
910 	{
911 		nPlcIdx[nIsEnd]++;
912 
913 		sal_uLong l0 = pPos[0]->Where(nPlcIdx[0]);
914 		sal_uLong l1 = pPos[1]->Where(nPlcIdx[1]);
915 		if( l0 < l1 )
916 			nIsEnd = 0;
917 		else if( l1 < l0 )
918 			nIsEnd = 1;
919 		else
920 			nIsEnd = ( nIsEnd ) ? 0 : 1;
921 	}
922 }
923 
GetHandle() const924 long Ww1Bookmarks::GetHandle() const
925 {
926 	if( bOK )
927 	{
928 		if( nIsEnd )
929 			return nPlcIdx[1];
930 
931 		const sal_uInt8* p = pPos[0]->GetData( nPlcIdx[0] );
932 		if( p )
933 			return SVBT16ToShort( p );
934 	}
935 	return LONG_MAX;
936 }
937 
Len() const938 long Ww1Bookmarks::Len() const
939 {
940 	if( nIsEnd )
941 	{
942 		DBG_ASSERT( sal_False, "Falscher Aufruf (1) von Ww1Bookmarks::Len()" );
943 		return 0;
944 	}
945 	sal_uInt16 nEndIdx = SVBT16ToShort(pPos[0]->GetData(nPlcIdx[0]));
946 	return pPos[1]->Where(nEndIdx) - pPos[0]->Where(nPlcIdx[0]);
947 }
948 
GetName() const949 const String Ww1Bookmarks::GetName() const
950 {
951 	if( nIsEnd )
952 		return String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "???" ));
953 	return aNames.GetStr( nPlcIdx[0] );
954 }
955 
956 /////////////////////////////////////////////////////////////////// Fkp
Ww1Fkp(SvStream & rStream,sal_uLong ulFilePos,sal_uInt16 _nItemSize)957 Ww1Fkp::Ww1Fkp(SvStream& rStream, sal_uLong ulFilePos, sal_uInt16 _nItemSize) :
958 	nItemSize(_nItemSize),
959 	bOK(sal_False)
960 {
961 	if (rStream.Seek(ulFilePos) == (sal_uLong)ulFilePos)
962 		if (rStream.Read(aFkp, sizeof(aFkp)) == sizeof(aFkp))
963 			bOK = sal_True;
964 }
965 
Where(sal_uInt16 nIndex)966 sal_uLong Ww1Fkp::Where(sal_uInt16 nIndex)
967 {
968 	sal_uLong lRet = 0xffffffff;
969 	DBG_ASSERT(nIndex<=Count(), "index out of bounds");
970 	if (nIndex<=Count())
971 		lRet = SVBT32ToUInt32(aFkp+nIndex*sizeof(SVBT32));
972 	return lRet;
973 }
974 
GetData(sal_uInt16 nIndex)975 sal_uInt8* Ww1Fkp::GetData(sal_uInt16 nIndex)
976 {
977 	sal_uInt8* pRet = NULL;
978 	DBG_ASSERT(nIndex<=Count(), "index out of bounds");
979 	if (nIndex<=Count())
980 		pRet = aFkp + (Count()+1) * sizeof(SVBT32) +
981 		 nIndex * nItemSize; // beginn der strukturen
982 	return pRet;
983 }
984 
985 //////////////////////////////////////////////////////////////// FkpPap
Fill(sal_uInt16 nIndex,sal_uInt8 * & p,sal_uInt16 & rnCountBytes)986 sal_Bool Ww1FkpPap::Fill(sal_uInt16 nIndex, sal_uInt8*& p, sal_uInt16& rnCountBytes)
987 {
988 	DBG_ASSERT( nIndex < Count(), "Ww1FkpPap::Fill() Index out of Range" );
989 	sal_uInt16 nOffset = SVBT8ToByte(GetData(nIndex)) * 2;
990 	if (nOffset)
991 	{
992 		DBG_ASSERT(nOffset>(sal_uInt16)(Count()*sizeof(SVBT32)), "calc error");
993 //		rnCountBytes = SVBT8ToByte(aFkp+nOffset) * 2 + 1;  // SH: +1 ?????
994 		rnCountBytes = SVBT8ToByte(aFkp+nOffset) * 2;
995 		nOffset += sizeof(SVBT8);
996 		if( nOffset + rnCountBytes < 511 )	// SH: Assert schlug 1 zu frueh zu
997 			rnCountBytes++;                 // SH: Ich weiss nicht genau,
998 											// ob das letzte Byte des PAPX
999 											// genutzt wird, aber so vergessen
1000 											// wir keins und sind trotzdem
1001 											// auf der sicheren Seite
1002 		DBG_ASSERT(nOffset+rnCountBytes <= 511, "calc error");
1003 		p = aFkp + nOffset;
1004 	}
1005 	else
1006 	{
1007 		p = NULL;
1008 		rnCountBytes = 0;
1009 	}
1010 	return sal_True;
1011 }
1012 
1013 //////////////////////////////////////////////////////////////// FkpChp
Fill(sal_uInt16 nIndex,W1_CHP & aChp)1014 sal_Bool Ww1FkpChp::Fill(sal_uInt16 nIndex, W1_CHP& aChp)
1015 {
1016 	DBG_ASSERT( nIndex < Count(), "Ww1FkpChp::Fill() Index out of Range" );
1017 	memset(&aChp, 0, sizeof(aChp));	// Default, da verkuerzt gespeichert
1018 	sal_uInt16 nOffset = GetData(nIndex)[0] * 2;
1019 	if (nOffset)
1020 	{
1021 		DBG_ASSERT(nOffset>(sal_uInt16)(Count()*sizeof(SVBT32)), "calc error");
1022 		sal_uInt16 nCountBytes = aFkp[nOffset];
1023 		nOffset += sizeof(SVBT8);
1024 		DBG_ASSERT(nCountBytes <= 511-nOffset, "calc error");
1025 		DBG_ASSERT(nCountBytes <= sizeof(aChp), "calc error");
1026 		memcpy(&aChp, aFkp+nOffset, nCountBytes);
1027 	}
1028 	return sal_True;
1029 }
1030 
1031 ///////////////////////////////////////////////////////////////// Assoc
Ww1Assoc(Ww1Fib & _rFib)1032 Ww1Assoc::Ww1Assoc(Ww1Fib& _rFib)
1033 	: rFib(_rFib), pBuffer(NULL), bOK(sal_False)
1034 {
1035 	sal_uInt16 cb = rFib.GetFIB().cbSttbfAssocGet();
1036 	sal_uInt16 i;
1037 
1038 	for ( i = 0; i < MaxFields; i++ )
1039 		pStrTbl[i] = NULL;
1040 	if ((pBuffer = new sal_Char[cb]) != NULL
1041 	 && rFib.GetStream().Seek(rFib.GetFIB().fcSttbfAssocGet()) ==
1042 		rFib.GetFIB().fcSttbfAssocGet()
1043 	 && rFib.GetStream().Read(pBuffer, cb) == cb)
1044 	{
1045 		sal_uInt16 j;
1046 		DBG_ASSERT( cb == SVBT16ToShort( *(SVBT16*)pBuffer ), "size missmatch");
1047 		for (i=0,j=sizeof(SVBT16);j<cb && i<Criteria1;i++)
1048 		{
1049 			pStrTbl[i] = pBuffer+j;
1050 			j += (*pBuffer + j) + 1;
1051 		}
1052 		bOK = sal_True;
1053 	}
1054 }
1055 
GetStr(sal_uInt16 code)1056 String Ww1Assoc::GetStr(sal_uInt16 code)
1057 {
1058 	String sRet;
1059 	DBG_ASSERT(code<MaxFields, "out of range");
1060 	if (pStrTbl[code] != NULL)
1061 		for( sal_uInt16 i=0;i<pStrTbl[code][0];i++ )
1062 			sRet += String( pStrTbl[code][i+1], RTL_TEXTENCODING_MS_1252 );
1063 	return sRet;
1064 }
1065 
1066 /////////////////////////////////////////////////////////////////// Pap
Ww1Pap(Ww1Fib & _rFib)1067 Ww1Pap::Ww1Pap(Ww1Fib& _rFib)
1068 	: Ww1PlcPap(_rFib), nPlcIndex(0), nPushedPlcIndex(0xffff), nFkpIndex(0),
1069 	nPushedFkpIndex(0xffff), ulOffset(0), pPap(0)
1070 {
1071 }
1072 
Seek(sal_uLong ulSeek)1073 void Ww1Pap::Seek(sal_uLong ulSeek)
1074 {
1075 	while (ulSeek > Where())
1076 		(*this)++;
1077 }
1078 
1079 // SH: Where hat einen Parameter mitbekommen, der sagt, ob bei Neuanlegen eines
1080 // Fkps der zugehoerige Index auf 0 gesetzt werden soll
1081 // ( darf fuer Push/Pop nicht passieren )
1082 // Ein eleganterer Weg faellt mir auf die Schnelle nicht ein
Where(sal_Bool bSetIndex)1083 sal_uLong Ww1Pap::Where( sal_Bool bSetIndex )
1084 {
1085 	sal_uLong ulRet = 0xffffffff;
1086 	if (pPap == NULL)
1087 		if (nPlcIndex < Count())
1088 		{
1089 			pPap = new Ww1FkpPap(rFib.GetStream(),
1090 						SVBT16ToShort(GetData(nPlcIndex)) << 9);
1091 			if( bSetIndex )
1092 				nFkpIndex = 0;
1093 		}
1094 	if (pPap != NULL)
1095 //		if (nFkpIndex < pPap->Count())
1096 		if (nFkpIndex <= pPap->Count())
1097 			ulRet = pPap->Where(nFkpIndex) - rFib.GetFIB().fcMinGet();
1098 	return ulRet;
1099 }
1100 
operator ++(int)1101 void Ww1Pap::operator++(int)
1102 {
1103 	if (pPap != NULL)
1104 //		if (++nFkpIndex >= pPap->Count())
1105 		if (++nFkpIndex > pPap->Count())
1106 		{
1107 			delete pPap;
1108 			pPap = NULL;
1109 			nPlcIndex++;
1110 		}
1111 }
1112 
1113 // SH: FindSprm sucht in grpprl nach Sprm nId
1114 // Rueckgabe: Pointer oder 0
FindSprm(sal_uInt16 nId,sal_uInt8 * pStart,sal_uInt8 * pEnd)1115 sal_Bool Ww1Pap::FindSprm(sal_uInt16 nId, sal_uInt8* pStart, sal_uInt8* pEnd)
1116 {
1117     Ww1Sprm aSprm( pStart, static_cast< sal_uInt16 >(pEnd-pStart) );
1118 	sal_uInt16 nC = aSprm.Count();
1119     sal_uInt16 i;
1120 	sal_uInt8 nI;
1121 	sal_uInt16 nLen;
1122 	sal_uInt8 *pData;
1123 	for( i = 0; i < nC; i++ ){
1124 		aSprm.Fill( i, nI, nLen, pData );
1125 		if( nI == nId )
1126 			return sal_True;
1127 	}
1128 	return sal_False;
1129 }
1130 
HasId0(sal_uInt16 nId)1131 sal_Bool Ww1Pap::HasId0(sal_uInt16 nId)
1132 {
1133 	sal_Bool bRet = sal_False;
1134 	UpdateIdx();
1135 
1136 	if( !pPap ){
1137 		DBG_ASSERT( sal_False, "Ww1Pap::HasId():: kann kein pPap erzeugen" );
1138 		return sal_False;
1139 	}
1140 
1141 	sal_uInt8* pByte;
1142 	sal_uInt16 n;
1143 	if( pPap->Fill(nFkpIndex, pByte, n) ){
1144 		sal_uInt8* p2 = ((W1_PAPX*)(pByte))->grpprlGet(); // SH: Offset fehlte
1145 		bRet = FindSprm( nId, p2, pByte + n );
1146 	}
1147 	return bRet;
1148 }
1149 
HasId(sal_uInt16 nId)1150 sal_Bool Ww1Pap::HasId(sal_uInt16 nId)
1151 {
1152 	sal_Bool bRet = sal_False;
1153 	sal_uInt16 nPushedPlcIndex2 = nPlcIndex;
1154 	sal_uInt16 nPushedFkpIndex2 = nFkpIndex;
1155 	bRet = HasId0( nId );
1156 	if (nPlcIndex != nPushedPlcIndex2)
1157 	{
1158 		delete pPap;
1159 		pPap = NULL;
1160 	}
1161 	nPlcIndex = nPushedPlcIndex2;
1162 	nFkpIndex = nPushedFkpIndex2;
1163 	Where( sal_False );
1164 	return bRet;
1165 }
1166 
1167 /////////////////////////////////////////////////////////////////// Chp
Ww1Chp(Ww1Fib & _rFib)1168 Ww1Chp::Ww1Chp(Ww1Fib& _rFib)
1169 	: Ww1PlcChp(_rFib), nPlcIndex(0), nPushedPlcIndex(0xffff), nFkpIndex(0),
1170 	nPushedFkpIndex(0xffff), ulOffset(0), pChp(0)
1171 {
1172 }
1173 
Seek(sal_uLong ulSeek)1174 void Ww1Chp::Seek(sal_uLong ulSeek)
1175 {
1176 	while (ulSeek > Where())
1177 		(*this)++;
1178 }
1179 
1180 // SH: Where hat einen Parameter mitbekommen, der sagt, ob bei Neuanlegen eines
1181 // Fkps der zugehoerige Index auf 0 gesetzt werden soll
1182 // ( darf fuer Push/Pop nicht passieren )
1183 // Ein eleganterer Weg faellt mir auf die Schnelle nicht ein
Where(sal_Bool bSetIndex)1184 sal_uLong Ww1Chp::Where( sal_Bool bSetIndex )
1185 {
1186 	sal_uLong ulRet = 0xffffffff;
1187 	if (pChp == NULL)
1188 		if (nPlcIndex < Count())
1189 		{
1190 			pChp = new Ww1FkpChp(rFib.GetStream(),
1191 						SVBT16ToShort(GetData(nPlcIndex)) << 9);
1192 			if( bSetIndex )
1193 				nFkpIndex = 0;
1194 		}
1195 	if (pChp != NULL)
1196 //		if (nFkpIndex < pChp->Count())
1197 		if (nFkpIndex <= pChp->Count())
1198 			ulRet = pChp->Where(nFkpIndex) -
1199 					 rFib.GetFIB().fcMinGet() - ulOffset;
1200 	return ulRet;
1201 }
1202 
operator ++(int)1203 void Ww1Chp::operator++(int)
1204 {
1205 	if (pChp != NULL)
1206 //		if (++nFkpIndex >= pChp->Count())
1207 		if (++nFkpIndex > pChp->Count())
1208 		{
1209 			delete pChp;
1210 			pChp = NULL;
1211 			nPlcIndex++;
1212 		}
1213 }
1214 
1215 ////////////////////////////////////////////////////////////// Manager
Ww1Manager(SvStream & rStrm,sal_uLong nFieldFlgs)1216 Ww1Manager::Ww1Manager(SvStream& rStrm, sal_uLong nFieldFlgs)
1217 	: bOK(sal_False), bInTtp(sal_False), bInStyle(sal_False), bStopAll(sal_False), aFib(rStrm),
1218 	aDop(aFib), aFonts(aFib, nFieldFlgs), aDoc(aFib), pDoc(&aDoc),
1219 	ulDocSeek(0), pSeek(&ulDocSeek), aFld(aFib), pFld(&aFld), aChp(aFib),
1220 	aPap(aFib), aFtn(aFib), aBooks(aFib),
1221 	aSep(aFib, aDop.GetDOP().grpfIhdtGet())
1222 {
1223 	bOK =  !aFib.GetError()
1224 		&& !aFib.GetFIB().fComplexGet()
1225 		&& !aDoc.GetError()
1226 		&& !aSep.GetError()
1227 		&& !aPap.GetError()
1228 		&& !aChp.GetError()
1229 		&& !aFld.GetError()
1230 		&& !aFtn.GetError()
1231 		&& !aBooks.GetError();
1232 }
1233 
HasInTable()1234 sal_Bool Ww1Manager::HasInTable()
1235 {
1236 	return aPap.HasId(24); // Ww1SingleSprmPFInTable
1237 }
1238 
HasTtp()1239 sal_Bool Ww1Manager::HasTtp()
1240 {
1241 	return aPap.HasId(25); // Ww1SingleSprmPTtp
1242 }
1243 
HasPPc()1244 sal_Bool Ww1Manager::HasPPc()
1245 {
1246 	return aPap.HasId(29); // Ww1SingleSprmPPc
1247 }
1248 
HasPDxaAbs()1249 sal_Bool Ww1Manager::HasPDxaAbs()
1250 {
1251 	return aPap.HasId(26); // Ww1SingleSprmPDxaAbs
1252 }
1253