Imported from antiword-0.36.tar.gz.
[antiword.git] / stylesheet.c
blob0cb4cc336ca3433d527c9657b68ff7e4905edcff
1 /*
2 * stylesheet.c
3 * Copyright (C) 2001-2004 A.J. van Os; Released under GNU GPL
5 * Description:
6 * Build, read and destroy a list of stylesheet information
8 */
10 #include <string.h>
11 #include "antiword.h"
14 #define SGC_PAP 1
15 #define SGC_CHP 2
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;
25 * vDestroyStylesheetList - destroy the stylesheet list
27 void
28 vDestroyStylesheetList(void)
30 DBG_MSG("vDestroyStylesheetList");
32 tStdCount = 0;
33 atStyleInfo = xfree(atStyleInfo);
34 atFontInfo = xfree(atFontInfo);
35 abFilled = xfree(abFilled);
36 } /* end of vDestroyStylesheetList */
39 * vGetDefaultStyle - fill the style struct with default values
41 static void
42 vGetDefaultStyle(style_block_type *pStyle)
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 */
52 * vGetDefaultFont - fill the font struct with default values
54 static void
55 vGetDefaultFont(font_block_type *pFont, USHORT usDefaultFontNumber)
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;
66 } /* end of vGetDefaultFont */
69 * iGetStyleIndex - get the index of the record with the specified istd
71 * returns the index when found, otherwise -1
73 static int
74 iGetStyleIndex(USHORT usIstd)
76 int iIndex;
78 fail(abFilled == NULL);
80 if (usIstd == ISTD_INVALID || abFilled == NULL) {
81 return -1;
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;
90 return -1;
91 } /* end of iGetStyleIndex */
94 * Get a build-in style for Winword 1/2
96 static void
97 vGetBuildinStyle(UCHAR ucStc, style_block_type *pStyle)
99 fail(pStyle == NULL);
101 /* Start with de defaults */
102 vGetDefaultStyle(pStyle);
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;
128 if (ucStc >= 225 && ucStc <= 232) {
129 pStyle->sLeftIndent = (232 - (short)ucStc) * 720;
130 pStyle->sRightIndent = 720;
132 break;
134 } /* end of vGetBuildinStyle */
137 * Get a build-in fontstyle for Winword 1/2
139 static void
140 vGetBuildinFont(UCHAR ucStc, font_block_type *pFont)
142 fail(pFont == NULL);
144 /* Start with de defaults */
145 vGetDefaultFont(pFont, 0);
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;
185 } /* end of vGetBuildinFont */
188 * Convert a stylecode (stc) as used by WinWord 1/2 into a styleindex (istd)
189 * as used by Word 6 and up
191 USHORT
192 usStc2istd(UCHAR ucStc)
194 /* Old nil style to new nil style */
195 if (ucStc == 222) {
196 return STI_NIL;
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;
205 return (USHORT)ucStc;
206 } /* end of usStd2istd */
209 * Build the lists with Stylesheet Information for WinWord 1/2 files
211 void
212 vGet2Stylesheet(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
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;
224 fail(pFile == NULL || aucHeader == NULL);
225 fail(iWordVersion != 1 && iWordVersion != 2);
227 ulBeginStshInfo = ulGetLong(0x5e, aucHeader); /* fcStshf */
228 NO_DBG_HEX(ulBeginStshInfo);
229 tStshInfoLen = (size_t)usGetWord(0x62, aucHeader); /* cbStshf */
230 NO_DBG_DEC(tStshInfoLen);
232 aucBuffer = xmalloc(tStshInfoLen);
233 if (!bReadBytes(aucBuffer, tStshInfoLen, ulBeginStshInfo, pFile)) {
234 aucBuffer = xfree(aucBuffer);
235 return;
237 NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
239 fail(2 > tStshInfoLen);
240 iStd = (int)usGetWord(0, aucBuffer);
242 fail(2 + 2 > tStshInfoLen);
243 tName = (size_t)usGetWord(2, aucBuffer);
245 fail(2 + tName + 2 > tStshInfoLen);
246 tChpx = (size_t)usGetWord(2 + tName, aucBuffer);
248 fail(2 + tName + tChpx + 2 > tStshInfoLen);
249 tPapx = (size_t)usGetWord(2 + tName + tChpx, aucBuffer);
251 fail(2 + tName + tChpx + tPapx + 2 > tStshInfoLen);
252 tStdCount = (size_t)usGetWord(2 + tName + tChpx + tPapx, aucBuffer);
254 NO_DBG_HEX(tStdCount);
256 atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
257 atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
258 abFilled = xcalloc(tStdCount, sizeof(BOOL));
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;
289 continue;
292 NO_DBG_STRN(aucBuffer + iStIndex + 1, iSt);
293 iStIndex += iSt + 1;
295 ucStcNext = ucGetByte(tMaxIndex, aucBuffer);
296 ucStcBase = ucGetByte(tMaxIndex + 1, aucBuffer);
297 ucStc = (UCHAR)((iIndex - iStd) & 0xff);
298 NO_DBG_DEC(ucStc);
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;
315 continue;
318 if (abFilled[iIndex]) {
319 /* This record has already been filled */
320 iChpxIndex += iChpx + 1;
321 iPapxIndex += iPapx + 1;
322 tMaxIndex += 2;
323 continue;
326 usBaseStyle = usStc2istd(ucStcBase);
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;
342 fail(iBaseStyleIndex >= (int)tStdCount);
343 fail(!abFilled[iBaseStyleIndex]);
344 /* Based on the specified base style */
345 *pStyle = atStyleInfo[iBaseStyleIndex];
346 *pFont = atFontInfo[iBaseStyleIndex];
348 pStyle->usIstd = usStc2istd(ucStc);
349 pStyle->usIstdNext = usStc2istd(ucStcNext);
351 abFilled[iIndex] = TRUE;
352 iCounter++;
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);
372 iChpxIndex += iChpx + 1;
373 break;
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;
389 tMaxIndex += 2;
392 NO_DBG_DEC(iCounter);
393 } while (iCounter > 0);
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);
404 /* Clean up before you leave */
405 abFilled = xfree(abFilled);
406 aucBuffer = xfree(aucBuffer);
407 } /* end of vGet2Stylesheet */
410 * Build the lists with Stylesheet Information for Word 6/7 files
412 void
413 vGet6Stylesheet(FILE *pFile, ULONG ulStartBlock,
414 const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
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;
426 fail(pFile == NULL || aucHeader == NULL);
427 fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
428 fail(aulBBD == NULL);
430 ulBeginStshInfo = ulGetLong(0x60, aucHeader); /* fcStshf */
431 NO_DBG_HEX(ulBeginStshInfo);
432 tStshInfoLen = (size_t)ulGetLong(0x64, aucHeader); /* lcbStshf */
433 NO_DBG_DEC(tStshInfoLen);
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;
442 NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
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);
450 atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
451 atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
452 abFilled = xcalloc(tStdCount, sizeof(BOOL));
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;
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;
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;
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];
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++;
516 NO_DBG_DEC(tPos);
517 if (tPos >= tStdLen) {
518 continue;
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;
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);
544 tPos += 2 + tUpxLen;
545 if (odd(tPos)) {
546 tPos++;
548 NO_DBG_DEC(tPos);
549 tUpxLen = (size_t)usGetWord(
550 tOffset + tPos, aucBuffer);
551 NO_DBG_DEC(tUpxLen);
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;
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);
572 NO_DBG_DEC(iCounter);
573 } while (iCounter > 0);
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);
585 /* Clean up before you leave */
586 abFilled = xfree(abFilled);
587 aucBuffer = xfree(aucBuffer);
588 } /* end of vGet6Stylesheet */
591 * Build the lists with Stylesheet Information for Word 8/9/10 files
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)
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;
610 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
611 fail(aulBBD == NULL || aulSBD == NULL);
613 ulBeginStshInfo = ulGetLong(0xa2, aucHeader); /* fcStshf */
614 NO_DBG_HEX(ulBeginStshInfo);
615 tStshInfoLen = (size_t)ulGetLong(0xa6, aucHeader); /* lcbStshf */
616 NO_DBG_DEC(tStshInfoLen);
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;
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;
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;
643 NO_DBG_PRINT_BLOCK(aucBuffer, tStshInfoLen);
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);
651 atStyleInfo = xcalloc(tStdCount, sizeof(style_block_type));
652 atFontInfo = xcalloc(tStdCount, sizeof(font_block_type));
653 abFilled = xcalloc(tStdCount, sizeof(BOOL));
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;
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;
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;
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];
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++;
719 NO_DBG_DEC(tPos);
720 if (tPos >= tStdLen) {
721 continue;
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;
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);
747 tPos += 2 + tUpxLen;
748 if (odd(tPos)) {
749 tPos++;
751 NO_DBG_DEC(tPos);
752 tUpxLen = (size_t)usGetWord(
753 tOffset + tPos, aucBuffer);
754 NO_DBG_DEC(tUpxLen);
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;
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);
775 NO_DBG_DEC(iCounter);
776 } while (iCounter > 0);
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);
788 /* Clean up before you leave */
789 abFilled = xfree(abFilled);
790 aucBuffer = xfree(aucBuffer);
791 } /* end of vGet8Stylesheet */
794 * vFillStyleFromStylesheet - fill a style struct with stylesheet info
796 void
797 vFillStyleFromStylesheet(USHORT usIstd, style_block_type *pStyle)
799 int iIndex;
801 fail(pStyle == NULL);
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;
813 vGetDefaultStyle(pStyle);
814 pStyle->usIstd = usIstd;
815 } /* end of vFillStyleFromStylesheet */
818 * vFillFontFromStylesheet - fill a font struct with stylesheet info
820 void
821 vFillFontFromStylesheet(USHORT usIstd, font_block_type *pFont)
823 int iIndex;
825 fail(pFont == NULL);
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;
837 vGetDefaultFont(pFont, 0);
838 } /* end of vFillFontFromStylesheet */