Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * stylesheet.c
3
 * Copyright (C) 2001-2004 A.J. van Os; Released under GNU GPL
4
 *
5
 * Description:
6
 * Build, read and destroy a list of stylesheet information
7
 *
8
 */
9
 
10
#include <string.h>
11
#include "antiword.h"
12
 
13
 
14
#define SGC_PAP		1
15
#define SGC_CHP		2
16
 
17
/* Variables needed to describe the stylesheet list */
18
static style_block_type	*atStyleInfo = NULL;
19
static font_block_type	*atFontInfo = NULL;
20
static BOOL		*abFilled = NULL;
21
static size_t		tStdCount = 0;
22
 
23
 
24
/*
25
 * vDestroyStylesheetList - destroy the stylesheet list
26
 */
27
void
28
vDestroyStylesheetList(void)
29
{
30
	DBG_MSG("vDestroyStylesheetList");
31
 
32
	tStdCount = 0;
33
	atStyleInfo = xfree(atStyleInfo);
34
	atFontInfo = xfree(atFontInfo);
35
	abFilled = xfree(abFilled);
36
} /* end of vDestroyStylesheetList */
37
 
38
/*
39
 * vGetDefaultStyle - fill the style struct with default values
40
 */
41
static void
42
vGetDefaultStyle(style_block_type *pStyle)
43
{
44
	(void)memset(pStyle, 0, sizeof(*pStyle));
45
	pStyle->usIstd = ISTD_INVALID;
46
	pStyle->usIstdNext = ISTD_INVALID;
47
	pStyle->usStartAt = 1;
48
	pStyle->ucListLevel = 9;
49
} /* end of vGetDefaultStyle */
50
 
51
/*
52
 * vGetDefaultFont - fill the font struct with default values
53
 */
54
static void
55
vGetDefaultFont(font_block_type *pFont, USHORT usDefaultFontNumber)
56
{
57
	(void)memset(pFont, 0, sizeof(*pFont));
58
	pFont->usFontSize = DEFAULT_FONT_SIZE;
59
	if (usDefaultFontNumber <= (USHORT)UCHAR_MAX) {
60
		pFont->ucFontNumber = (UCHAR)usDefaultFontNumber;
61
	} else {
62
		DBG_DEC(usDefaultFontNumber);
63
		DBG_FIXME();
64
		pFont->ucFontNumber = 0;
65
	}
66
} /* end of vGetDefaultFont */
67
 
68
/*
69
 * iGetStyleIndex - get the index of the record with the specified istd
70
 *
71
 * returns the index when found, otherwise -1
72
 */
73
static int
74
iGetStyleIndex(USHORT usIstd)
75
{
76
	int	iIndex;
77
 
78
	fail(abFilled == NULL);
79
 
80
	if (usIstd == ISTD_INVALID || abFilled == NULL) {
81
		return -1;
82
	}
83
 
84
	for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
85
		if (abFilled[iIndex] && atStyleInfo[iIndex].usIstd == usIstd) {
86
			/* The record is filled and the istd matches */
87
			return iIndex;
88
		}
89
	}
90
	return -1;
91
} /* end of iGetStyleIndex */
92
 
93
/*
94
 * Get a build-in style for Winword 1/2
95
 */
96
static void
97
vGetBuildinStyle(UCHAR ucStc, style_block_type *pStyle)
98
{
99
	fail(pStyle == NULL);
100
 
101
	/* Start with de defaults */
102
	vGetDefaultStyle(pStyle);
103
 
104
	/* Add the build-in style info */
105
	switch (ucStc) {
106
	case 246:
107
	case 247:
108
	case 248:
109
	case 249:
110
	case 250:
111
	case 255:
112
		pStyle->sLeftIndent = 720;
113
		break;
114
	case 251:
115
	case 252:
116
		pStyle->sLeftIndent = 360;
117
		break;
118
	case 253:
119
		pStyle->usBeforeIndent = 120;
120
		break;
121
	case 254:
122
		pStyle->usBeforeIndent = 240;
123
		break;
124
	default:
125
		if (ucStc >= 233 && ucStc <= 239) {
126
			pStyle->sLeftIndent = (239 - (short)ucStc) * 360;
127
		}
128
		if (ucStc >= 225 && ucStc <= 232) {
129
			pStyle->sLeftIndent = (232 - (short)ucStc) * 720;
130
			pStyle->sRightIndent = 720;
131
		}
132
		break;
133
	}
134
} /* end of vGetBuildinStyle */
135
 
136
/*
137
 * Get a build-in fontstyle for Winword 1/2
138
 */
139
static void
140
vGetBuildinFont(UCHAR ucStc, font_block_type *pFont)
141
{
142
	fail(pFont == NULL);
143
 
144
	/* Start with de defaults */
145
	vGetDefaultFont(pFont, 0);
146
 
147
	/* Add the build-in fontstyle info */
148
	switch (ucStc) {
149
	case 223:
150
	case 244:
151
		pFont->usFontSize = 16;
152
		break;
153
	case 246:
154
	case 247:
155
	case 248:
156
		pFont->usFontStyle |= FONT_ITALIC;
157
		break;
158
	case 249:
159
		pFont->usFontStyle |= FONT_UNDERLINE;
160
		break;
161
	case 250:
162
		pFont->usFontStyle |= FONT_BOLD;
163
		break;
164
	case 251:
165
		pFont->usFontStyle |= FONT_UNDERLINE;
166
		pFont->usFontSize = 24;
167
		break;
168
	case 252:
169
		pFont->usFontStyle |= FONT_BOLD;
170
		pFont->usFontSize = 24;
171
		break;
172
	case 253:
173
		pFont->ucFontNumber = 2;
174
		pFont->usFontStyle |= FONT_BOLD;
175
		pFont->usFontSize = 24;
176
		break;
177
	case 254:
178
		pFont->ucFontNumber = 2;
179
		pFont->usFontStyle |= (FONT_BOLD|FONT_UNDERLINE);
180
		pFont->usFontSize = 24;
181
		break;
182
	default:
183
		break;
184
	}
185
} /* end of vGetBuildinFont */
186
 
187
/*
188
 * Convert a stylecode (stc) as used by WinWord 1/2 into a styleindex (istd)
189
 * as used by Word 6 and up
190
 */
191
USHORT
192
usStc2istd(UCHAR ucStc)
193
{
194
	/* Old nil style to new nil style */
195
	if (ucStc == 222) {
196
		return STI_NIL;
197
	}
198
 
199
	/* Heading 1 through 9 must become istd 1 through 9 */
200
	/* so 254 through 246 must become 1 through 9 and vice versa */
201
	if ((ucStc >= 1 && ucStc <= 9) ||
202
	    (ucStc >= 246 && ucStc <= 254)) {
203
		return 255 - (USHORT)ucStc;
204
	}
205
	return (USHORT)ucStc;
206
} /* end of usStd2istd */
207
 
208
/*
209
 * Build the lists with Stylesheet Information for WinWord 1/2 files
210
 */
211
void
212
vGet2Stylesheet(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
213
{
214
	style_block_type	*pStyle;
215
	font_block_type		*pFont;
216
	UCHAR	*aucBuffer;
217
	ULONG	ulBeginStshInfo;
218
	size_t	tStshInfoLen, tName, tChpx, tPapx, tMaxIndex;
219
	int	iStIndex, iChpxIndex, iPapxIndex, iSt, iChpx, iPapx;
220
	int	iStd, iIndex, iBaseStyleIndex, iCounter;
221
	USHORT	usBaseStyle;
222
	UCHAR	ucStc, ucStcNext, ucStcBase;
223
 
224
	fail(pFile == NULL || aucHeader == NULL);
225
	fail(iWordVersion != 1 && iWordVersion != 2);
226
 
227
	ulBeginStshInfo = ulGetLong(0x5e, aucHeader); /* fcStshf */
228
	NO_DBG_HEX(ulBeginStshInfo);
229
	tStshInfoLen = (size_t)usGetWord(0x62, aucHeader); /* cbStshf */
230
	NO_DBG_DEC(tStshInfoLen);
231
 
232
	aucBuffer = xmalloc(tStshInfoLen);
233
	if (!bReadBytes(aucBuffer, tStshInfoLen, ulBeginStshInfo, pFile)) {
234
		aucBuffer = xfree(aucBuffer);
235
		return;
236
	}
237
	NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
238
 
239
	fail(2 > tStshInfoLen);
240
	iStd = (int)usGetWord(0, aucBuffer);
241
 
242
	fail(2 + 2 > tStshInfoLen);
243
	tName = (size_t)usGetWord(2, aucBuffer);
244
 
245
	fail(2 + tName + 2 > tStshInfoLen);
246
	tChpx = (size_t)usGetWord(2 + tName, aucBuffer);
247
 
248
	fail(2 + tName + tChpx + 2 > tStshInfoLen);
249
	tPapx = (size_t)usGetWord(2 + tName + tChpx, aucBuffer);
250
 
251
	fail(2 + tName + tChpx + tPapx + 2 > tStshInfoLen);
252
	tStdCount = (size_t)usGetWord(2 + tName + tChpx + tPapx, aucBuffer);
253
 
254
	NO_DBG_HEX(tStdCount);
255
 
256
	atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
257
	atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
258
	abFilled = xcalloc(tStdCount, sizeof(BOOL));
259
 
260
	do {
261
		iCounter = 0;
262
		iStIndex = 2 + 2;
263
		iChpxIndex = 2 + (int)tName + 2;
264
		iPapxIndex = 2 + (int)tName + (int)tChpx + 2;
265
		tMaxIndex = 2 + tName + tChpx + tPapx + 2;
266
		/* Read the styles one-by-one */
267
		for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
268
			pStyle = &atStyleInfo[iIndex];
269
			pFont = &atFontInfo[iIndex];
270
			iSt = (int)ucGetByte(iStIndex, aucBuffer);
271
			iChpx = (int)ucGetByte(iChpxIndex, aucBuffer);
272
			iPapx = (int)ucGetByte(iPapxIndex, aucBuffer);
273
			NO_DBG_HEX(iSt);
274
			NO_DBG_HEX(iChpx);
275
			NO_DBG_HEX(iPapx);
276
			if (iSt == 0xff || tMaxIndex + 1 >= tStshInfoLen) {
277
				/* Undefined style or no information */
278
				iStIndex++;
279
				iChpxIndex++;
280
				iPapxIndex++;
281
				tMaxIndex += 2;
282
				if (!abFilled[iIndex]) {
283
					DBG_HEX_C(iChpx != 0xff, iChpx);
284
					DBG_HEX_C(iPapx != 0xff, iPapx);
285
					vGetDefaultStyle(pStyle);
286
					vGetDefaultFont(pFont, 0);
287
					abFilled[iIndex] = TRUE;
288
				}
289
				continue;
290
			}
291
 
292
			NO_DBG_STRN(aucBuffer + iStIndex + 1, iSt);
293
			iStIndex += iSt + 1;
294
 
295
			ucStcNext = ucGetByte(tMaxIndex, aucBuffer);
296
			ucStcBase = ucGetByte(tMaxIndex + 1, aucBuffer);
297
			ucStc = (UCHAR)((iIndex - iStd) & 0xff);
298
			NO_DBG_DEC(ucStc);
299
 
300
			if (iChpx == 0xff || iPapx == 0xff) {
301
				/* Use a build-in style */
302
				iChpxIndex++;
303
				iPapxIndex++;
304
				tMaxIndex += 2;
305
				if (!abFilled[iIndex]) {
306
					DBG_HEX_C(iChpx != 0xff, iChpx);
307
					DBG_HEX_C(iPapx != 0xff, iPapx);
308
					vGetBuildinStyle(ucStc, pStyle);
309
					pStyle->usIstd = usStc2istd(ucStc);
310
					pStyle->usIstdNext =
311
							usStc2istd(ucStcNext);
312
					vGetBuildinFont(ucStc, pFont);
313
					abFilled[iIndex] = TRUE;
314
				}
315
				continue;
316
			}
317
 
318
			if (abFilled[iIndex]) {
319
				/* This record has already been filled */
320
				iChpxIndex += iChpx + 1;
321
				iPapxIndex += iPapx + 1;
322
				tMaxIndex += 2;
323
				continue;
324
			}
325
 
326
			usBaseStyle = usStc2istd(ucStcBase);
327
 
328
			if (usBaseStyle == STI_NIL) {
329
				/* Based on the Nil style */
330
				vGetDefaultStyle(pStyle);
331
				vGetDefaultFont(pFont, 0);
332
			} else {
333
				iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
334
				NO_DBG_DEC(iBaseStyleIndex);
335
				if (iBaseStyleIndex < 0) {
336
					/* This style is not known yet */
337
					iChpxIndex += iChpx + 1;
338
					iPapxIndex += iPapx + 1;
339
					tMaxIndex += 2;
340
					continue;
341
				}
342
				fail(iBaseStyleIndex >= (int)tStdCount);
343
				fail(!abFilled[iBaseStyleIndex]);
344
				/* Based on the specified base style */
345
				*pStyle = atStyleInfo[iBaseStyleIndex];
346
				*pFont = atFontInfo[iBaseStyleIndex];
347
			}
348
			pStyle->usIstd = usStc2istd(ucStc);
349
			pStyle->usIstdNext = usStc2istd(ucStcNext);
350
 
351
			abFilled[iIndex] = TRUE;
352
			iCounter++;
353
 
354
			/* Add the changes if any */
355
			switch (iChpx) {
356
			case 0x00:
357
			case 0xff:
358
				iChpxIndex++;
359
				break;
360
			default:
361
				NO_DBG_PRINT_BLOCK(aucBuffer + iChpxIndex + 1,
362
						iChpx);
363
				if (iWordVersion == 1) {
364
					vGet1FontInfo(0,
365
						aucBuffer + iChpxIndex + 1,
366
						(size_t)iChpx, pFont);
367
				} else {
368
					vGet2FontInfo(0,
369
						aucBuffer + iChpxIndex + 1,
370
						(size_t)iChpx, pFont);
371
				}
372
				iChpxIndex += iChpx + 1;
373
				break;
374
			}
375
 
376
			switch (iPapx) {
377
			case 0x00:
378
			case 0xff:
379
				iPapxIndex++;
380
				break;
381
			default:
382
				NO_DBG_PRINT_BLOCK(aucBuffer + iPapxIndex + 8,
383
						iPapx - 7);
384
				vGet2StyleInfo(0, aucBuffer + iPapxIndex + 8,
385
						iPapx - 7, pStyle);
386
				iPapxIndex += iPapx + 1;
387
				break;
388
			}
389
			tMaxIndex += 2;
390
 
391
		}
392
		NO_DBG_DEC(iCounter);
393
	} while (iCounter > 0);
394
 
395
	/* Fill records that are still empty */
396
	for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
397
		if (!abFilled[iIndex]) {
398
			NO_DBG_DEC(iIndex);
399
			vGetDefaultStyle(&atStyleInfo[iIndex]);
400
			vGetDefaultFont(&atFontInfo[iIndex], 0);
401
		}
402
	}
403
 
404
	/* Clean up before you leave */
405
	abFilled = xfree(abFilled);
406
	aucBuffer = xfree(aucBuffer);
407
} /* end of vGet2Stylesheet */
408
 
409
/*
410
 * Build the lists with Stylesheet Information for Word 6/7 files
411
 */
412
void
413
vGet6Stylesheet(FILE *pFile, ULONG ulStartBlock,
414
	const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
415
{
416
	style_block_type	*pStyle;
417
	font_block_type		*pFont;
418
	UCHAR	*aucBuffer;
419
	ULONG	ulBeginStshInfo;
420
	size_t	tStshInfoLen, tOffset, tStdLen, tStdBaseInFile;
421
	size_t	tPos, tNameLen, tUpxLen;
422
	int	iIndex, iBaseStyleIndex, iCounter;
423
	USHORT	usTmp, usUpxCount, usStyleType, usBaseStyle;
424
	USHORT	usFtcStandardChpStsh;
425
 
426
	fail(pFile == NULL || aucHeader == NULL);
427
	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
428
	fail(aulBBD == NULL);
429
 
430
	ulBeginStshInfo = ulGetLong(0x60, aucHeader); /* fcStshf */
431
	NO_DBG_HEX(ulBeginStshInfo);
432
	tStshInfoLen = (size_t)ulGetLong(0x64, aucHeader); /* lcbStshf */
433
	NO_DBG_DEC(tStshInfoLen);
434
 
435
	aucBuffer = xmalloc(tStshInfoLen);
436
	if (!bReadBuffer(pFile, ulStartBlock,
437
			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
438
			aucBuffer, ulBeginStshInfo, tStshInfoLen)) {
439
		aucBuffer = xfree(aucBuffer);
440
		return;
441
	}
442
	NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
443
 
444
	tStdCount = (size_t)usGetWord(2, aucBuffer);
445
	NO_DBG_DEC(tStdCount);
446
	tStdBaseInFile = (size_t)usGetWord(4, aucBuffer);
447
	usFtcStandardChpStsh = usGetWord(14, aucBuffer);
448
	NO_DBG_DEC(usFtcStandardChpStsh);
449
 
450
	atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
451
	atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
452
	abFilled = xcalloc(tStdCount, sizeof(BOOL));
453
 
454
	do {
455
		iCounter = 0;
456
		/* Read the styles one-by-one */
457
		for (iIndex = 0, tOffset = 2 + (size_t)usGetWord(0, aucBuffer);
458
		     iIndex < (int)tStdCount;
459
		     iIndex++, tOffset += 2 + tStdLen) {
460
			NO_DBG_DEC(tOffset);
461
			tStdLen = (size_t)usGetWord(tOffset, aucBuffer);
462
			NO_DBG_DEC(tStdLen);
463
			if (abFilled[iIndex]) {
464
				/* This record has already been filled */
465
				continue;
466
			}
467
			pStyle = &atStyleInfo[iIndex];
468
			pFont = &atFontInfo[iIndex];
469
			if (tStdLen == 0) {
470
				/* Empty record */
471
				vGetDefaultStyle(pStyle);
472
				vGetDefaultFont(pFont, usFtcStandardChpStsh);
473
				abFilled[iIndex] = TRUE;
474
				continue;
475
			}
476
			usTmp = usGetWord(tOffset + 4, aucBuffer);
477
			usStyleType = usTmp % 16;
478
			usBaseStyle = usTmp / 16;
479
			NO_DBG_DEC(usStyleType);
480
			NO_DBG_DEC(usBaseStyle);
481
			if (usBaseStyle == STI_NIL || usBaseStyle == STI_USER) {
482
				/* Based on the Nil style */
483
				vGetDefaultStyle(pStyle);
484
				vGetDefaultFont(pFont, usFtcStandardChpStsh);
485
			} else {
486
				iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
487
				NO_DBG_DEC(iBaseStyleIndex);
488
				if (iBaseStyleIndex < 0) {
489
					/* This base style is not known yet */
490
					continue;
491
				}
492
				fail(iBaseStyleIndex >= (int)tStdCount);
493
				fail(!abFilled[iBaseStyleIndex]);
494
				/* Based on the specified base style */
495
				*pStyle = atStyleInfo[iBaseStyleIndex];
496
				pStyle->usIstd = ISTD_INVALID;
497
				*pFont = atFontInfo[iBaseStyleIndex];
498
			}
499
			abFilled[iIndex] = TRUE;
500
			iCounter++;
501
			/* STD */
502
			usTmp = usGetWord(tOffset + 6, aucBuffer);
503
			usUpxCount = usTmp % 16;
504
			pStyle->usIstdNext = usTmp / 16;;
505
			NO_DBG_DEC(usUpxCount);
506
			tPos = 2 + tStdBaseInFile;
507
			NO_DBG_DEC(tPos);
508
			tNameLen = (size_t)ucGetByte(tOffset + tPos, aucBuffer);
509
			NO_DBG_DEC(tNameLen);
510
			NO_DBG_STRN(aucBuffer + tOffset + tPos + 1, tNameLen);
511
			tNameLen++;	/* Include the ASCII NULL character */
512
			tPos += 1 + tNameLen;
513
			if (odd(tPos)) {
514
				tPos++;
515
			}
516
			NO_DBG_DEC(tPos);
517
			if (tPos >= tStdLen) {
518
				continue;
519
			}
520
			tUpxLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
521
			NO_DBG_DEC(tUpxLen);
522
			if (tPos + tUpxLen > tStdLen) {
523
				/* UPX length too large to be a record */
524
				DBG_DEC_C(tPos + tUpxLen > tStdLen,
525
						tPos + tUpxLen);
526
				continue;
527
			}
528
			if (usStyleType == SGC_PAP && usUpxCount >= 1) {
529
				if (tUpxLen >= 2) {
530
					NO_DBG_PRINT_BLOCK(
531
						aucBuffer + tOffset + tPos + 2,
532
						tUpxLen);
533
					pStyle->usIstd = usGetWord(
534
						tOffset + tPos + 2, aucBuffer);
535
					NO_DBG_DEC(pStyle->usIstd);
536
					NO_DBG_DEC(pStyle->usIstdNext);
537
					vGet6StyleInfo(0,
538
						aucBuffer + tOffset + tPos + 4,
539
						tUpxLen - 2, pStyle);
540
					NO_DBG_DEC(pStyle->sLeftIndent);
541
					NO_DBG_DEC(pStyle->sRightIndent);
542
					NO_DBG_HEX(pStyle->ucAlignment);
543
				}
544
				tPos += 2 + tUpxLen;
545
				if (odd(tPos)) {
546
					tPos++;
547
				}
548
				NO_DBG_DEC(tPos);
549
				tUpxLen = (size_t)usGetWord(
550
						tOffset + tPos, aucBuffer);
551
				NO_DBG_DEC(tUpxLen);
552
			}
553
			if (tUpxLen == 0 || tPos + tUpxLen > tStdLen) {
554
				/* Too small or too large to be a record */
555
				DBG_DEC_C(tPos + tUpxLen > tStdLen,
556
							tPos + tUpxLen);
557
				continue;
558
			}
559
			if ((usStyleType == SGC_PAP && usUpxCount >= 2) ||
560
			    (usStyleType == SGC_CHP && usUpxCount >= 1)) {
561
				NO_DBG_PRINT_BLOCK(
562
						aucBuffer + tOffset + tPos + 2,
563
						tUpxLen);
564
				vGet6FontInfo(0, ISTD_INVALID,
565
						aucBuffer + tOffset + tPos + 2,
566
						(int)tUpxLen, pFont);
567
				NO_DBG_DEC(pFont->usFontSize);
568
				NO_DBG_DEC(pFont->ucFontcolor);
569
				NO_DBG_HEX(pFont->usFontStyle);
570
			}
571
		}
572
		NO_DBG_DEC(iCounter);
573
	} while (iCounter > 0);
574
 
575
	/* Fill records that are still empty */
576
	for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
577
		if (!abFilled[iIndex]) {
578
			NO_DBG_DEC(iIndex);
579
			vGetDefaultStyle(&atStyleInfo[iIndex]);
580
			vGetDefaultFont(&atFontInfo[iIndex],
581
					usFtcStandardChpStsh);
582
		}
583
	}
584
 
585
	/* Clean up before you leave */
586
	abFilled = xfree(abFilled);
587
	aucBuffer = xfree(aucBuffer);
588
} /* end of vGet6Stylesheet */
589
 
590
/*
591
 * Build the lists with Stylesheet Information for Word 8/9/10 files
592
 */
593
void
594
vGet8Stylesheet(FILE *pFile, const pps_info_type *pPPS,
595
	const ULONG *aulBBD, size_t tBBDLen,
596
	const ULONG *aulSBD, size_t tSBDLen,
597
	const UCHAR *aucHeader)
598
{
599
	style_block_type	*pStyle;
600
	font_block_type		*pFont;
601
	const ULONG	*aulBlockDepot;
602
	UCHAR	*aucBuffer;
603
	ULONG	ulBeginStshInfo;
604
	size_t	tStshInfoLen, tBlockDepotLen, tOffset, tStdLen, tStdBaseInFile;
605
	size_t	tBlockSize, tPos, tNameLen, tUpxLen;
606
	int	iIndex, iBaseStyleIndex, iCounter;
607
	USHORT	usTmp, usUpxCount, usStyleType, usBaseStyle;
608
	USHORT	usFtcStandardChpStsh;
609
 
610
	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
611
	fail(aulBBD == NULL || aulSBD == NULL);
612
 
613
	ulBeginStshInfo = ulGetLong(0xa2, aucHeader); /* fcStshf */
614
	NO_DBG_HEX(ulBeginStshInfo);
615
	tStshInfoLen = (size_t)ulGetLong(0xa6, aucHeader); /* lcbStshf */
616
	NO_DBG_DEC(tStshInfoLen);
617
 
618
	NO_DBG_DEC(pPPS->tTable.ulSB);
619
	NO_DBG_HEX(pPPS->tTable.ulSize);
620
	if (pPPS->tTable.ulSize == 0) {
621
		DBG_MSG("No stylesheet information");
622
		return;
623
	}
624
 
625
	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
626
		/* Use the Small Block Depot */
627
		aulBlockDepot = aulSBD;
628
		tBlockDepotLen = tSBDLen;
629
		tBlockSize = SMALL_BLOCK_SIZE;
630
	} else {
631
		/* Use the Big Block Depot */
632
		aulBlockDepot = aulBBD;
633
		tBlockDepotLen = tBBDLen;
634
		tBlockSize = BIG_BLOCK_SIZE;
635
	}
636
	aucBuffer = xmalloc(tStshInfoLen);
637
	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
638
			aulBlockDepot, tBlockDepotLen, tBlockSize,
639
			aucBuffer, ulBeginStshInfo, tStshInfoLen)) {
640
		aucBuffer = xfree(aucBuffer);
641
		return;
642
	}
643
	NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
644
 
645
	tStdCount = (size_t)usGetWord(2, aucBuffer);
646
	NO_DBG_DEC(tStdCount);
647
	tStdBaseInFile = (size_t)usGetWord(4, aucBuffer);
648
	usFtcStandardChpStsh = usGetWord(14, aucBuffer);
649
	NO_DBG_DEC(usFtcStandardChpStsh);
650
 
651
	atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
652
	atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
653
	abFilled = xcalloc(tStdCount, sizeof(BOOL));
654
 
655
	do {
656
		iCounter = 0;
657
		/* Read the styles one-by-one */
658
		for (iIndex = 0, tOffset = 2 + (size_t)usGetWord(0, aucBuffer);
659
		     iIndex < (int)tStdCount;
660
		     iIndex++, tOffset += 2 + tStdLen) {
661
			NO_DBG_DEC(tOffset);
662
			tStdLen = (size_t)usGetWord(tOffset, aucBuffer);
663
			NO_DBG_DEC(tStdLen);
664
			if (abFilled[iIndex]) {
665
				/* This record has already been filled */
666
				continue;
667
			}
668
			pStyle = &atStyleInfo[iIndex];
669
			pFont = &atFontInfo[iIndex];
670
			if (tStdLen == 0) {
671
				/* Empty record */
672
				vGetDefaultStyle(pStyle);
673
				vGetDefaultFont(pFont, usFtcStandardChpStsh);
674
				abFilled[iIndex] = TRUE;
675
				continue;
676
			}
677
			usTmp = usGetWord(tOffset + 4, aucBuffer);
678
			usStyleType = usTmp % 16;
679
			usBaseStyle = usTmp / 16;
680
			NO_DBG_DEC(usStyleType);
681
			NO_DBG_DEC(usBaseStyle);
682
			if (usBaseStyle == STI_NIL || usBaseStyle == STI_USER) {
683
				/* Based on the Nil style */
684
				vGetDefaultStyle(pStyle);
685
				vGetDefaultFont(pFont, usFtcStandardChpStsh);
686
			} else {
687
				iBaseStyleIndex = iGetStyleIndex(usBaseStyle);
688
				NO_DBG_DEC(iBaseStyleIndex);
689
				if (iBaseStyleIndex < 0) {
690
					/* This base style is not known yet */
691
					continue;
692
				}
693
				fail(iBaseStyleIndex >= (int)tStdCount);
694
				fail(!abFilled[iBaseStyleIndex]);
695
				/* Based on the specified base style */
696
				*pStyle = atStyleInfo[iBaseStyleIndex];
697
				pStyle->usIstd = ISTD_INVALID;
698
				*pFont = atFontInfo[iBaseStyleIndex];
699
			}
700
			abFilled[iIndex] = TRUE;
701
			iCounter++;
702
			/* STD */
703
			usTmp = usGetWord(tOffset + 6, aucBuffer);
704
			usUpxCount = usTmp % 16;
705
			pStyle->usIstdNext = usTmp / 16;
706
			NO_DBG_DEC(usUpxCount);
707
			tPos = 2 + tStdBaseInFile;
708
			NO_DBG_DEC(tPos);
709
			tNameLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
710
			NO_DBG_DEC(tNameLen);
711
			tNameLen *= 2;	/* From Unicode characters to bytes */
712
			NO_DBG_UNICODE_N(aucBuffer + tOffset + tPos + 2,
713
					tNameLen);
714
			tNameLen += 2;	/* Include the Unicode NULL character */
715
			tPos += 2 + tNameLen;
716
			if (odd(tPos)) {
717
				tPos++;
718
			}
719
			NO_DBG_DEC(tPos);
720
			if (tPos >= tStdLen) {
721
				continue;
722
			}
723
			tUpxLen = (size_t)usGetWord(tOffset + tPos, aucBuffer);
724
			NO_DBG_DEC(tUpxLen);
725
			if (tPos + tUpxLen > tStdLen) {
726
				/* UPX length too large to be a record */
727
				DBG_DEC_C(tPos + tUpxLen > tStdLen,
728
						tPos + tUpxLen);
729
				continue;
730
			}
731
			if (usStyleType == SGC_PAP && usUpxCount >= 1) {
732
				if (tUpxLen >= 2) {
733
					NO_DBG_PRINT_BLOCK(
734
						aucBuffer + tOffset + tPos + 2,
735
						tUpxLen);
736
					pStyle->usIstd = usGetWord(
737
						tOffset + tPos + 2, aucBuffer);
738
					NO_DBG_DEC(pStyle->usIstd);
739
					NO_DBG_DEC(pStyle->usIstdNext);
740
					vGet8StyleInfo(0,
741
						aucBuffer + tOffset + tPos + 4,
742
						tUpxLen - 2, pStyle);
743
					NO_DBG_DEC(pStyle->sLeftIndent);
744
					NO_DBG_DEC(pStyle->sRightIndent);
745
					NO_DBG_HEX(pStyle->ucAlignment);
746
				}
747
				tPos += 2 + tUpxLen;
748
				if (odd(tPos)) {
749
					tPos++;
750
				}
751
				NO_DBG_DEC(tPos);
752
				tUpxLen = (size_t)usGetWord(
753
						tOffset + tPos, aucBuffer);
754
				NO_DBG_DEC(tUpxLen);
755
			}
756
			if (tUpxLen == 0 || tPos + tUpxLen > tStdLen) {
757
				/* Too small or too large to be a record */
758
				DBG_DEC_C(tPos + tUpxLen > tStdLen,
759
							tPos + tUpxLen);
760
				continue;
761
			}
762
			if ((usStyleType == SGC_PAP && usUpxCount >= 2) ||
763
			    (usStyleType == SGC_CHP && usUpxCount >= 1)) {
764
				NO_DBG_PRINT_BLOCK(
765
						aucBuffer + tOffset + tPos + 2,
766
						tUpxLen);
767
				vGet8FontInfo(0, ISTD_INVALID,
768
						aucBuffer + tOffset + tPos + 2,
769
						(int)tUpxLen, pFont);
770
				NO_DBG_DEC(pFont->usFontSize);
771
				NO_DBG_DEC(pFont->ucFontcolor);
772
				NO_DBG_HEX(pFont->usFontStyle);
773
			}
774
		}
775
		NO_DBG_DEC(iCounter);
776
	} while (iCounter > 0);
777
 
778
	/* Fill records that are still empty */
779
	for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
780
		if (!abFilled[iIndex]) {
781
			NO_DBG_DEC(iIndex);
782
			vGetDefaultStyle(&atStyleInfo[iIndex]);
783
			vGetDefaultFont(&atFontInfo[iIndex],
784
					usFtcStandardChpStsh);
785
		}
786
	}
787
 
788
	/* Clean up before you leave */
789
	abFilled = xfree(abFilled);
790
	aucBuffer = xfree(aucBuffer);
791
} /* end of vGet8Stylesheet */
792
 
793
/*
794
 * vFillStyleFromStylesheet - fill a style struct with stylesheet info
795
 */
796
void
797
vFillStyleFromStylesheet(USHORT usIstd, style_block_type *pStyle)
798
{
799
	int	iIndex;
800
 
801
	fail(pStyle == NULL);
802
 
803
	if (usIstd != ISTD_INVALID && usIstd != STI_NIL && usIstd != STI_USER) {
804
		for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
805
			if (atStyleInfo[iIndex].usIstd == usIstd) {
806
				/* Right index found; return style */
807
				*pStyle = atStyleInfo[iIndex];
808
				return;
809
			}
810
		}
811
	}
812
 
813
	vGetDefaultStyle(pStyle);
814
	pStyle->usIstd = usIstd;
815
} /* end of vFillStyleFromStylesheet */
816
 
817
/*
818
 * vFillFontFromStylesheet - fill a font struct with stylesheet info
819
 */
820
void
821
vFillFontFromStylesheet(USHORT usIstd, font_block_type *pFont)
822
{
823
	int	iIndex;
824
 
825
	fail(pFont == NULL);
826
 
827
	if (usIstd != ISTD_INVALID && usIstd != STI_NIL && usIstd != STI_USER) {
828
		for (iIndex = 0; iIndex < (int)tStdCount; iIndex++) {
829
			if (atStyleInfo[iIndex].usIstd == usIstd) {
830
				/* Right index found; return font */
831
				*pFont = atFontInfo[iIndex];
832
				return;
833
			}
834
		}
835
	}
836
 
837
	vGetDefaultFont(pFont, 0);
838
} /* end of vFillFontFromStylesheet */