3 * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
6 * Functions to deal with fonts (generic)
13 /* Maximum line length in the font file */
14 #define FONT_LINE_LENGTH 81
17 #define PITCH_UNKNOWN 0
19 #define PITCH_VARIABLE 2
22 #define FAMILY_UNKNOWN 0
23 #define FAMILY_ROMAN 1
24 #define FAMILY_SWISS 2
25 #define FAMILY_MODERN 3
26 #define FAMILY_SCRIPT 4
27 #define FAMILY_DECORATIVE 5
29 /* Font Translation Table */
30 static size_t tFontTableRecords
= 0;
31 static font_table_type
*pFontTable
= NULL
;
34 * Find the given font in the font table
36 * returns the index into the FontTable, -1 if not found
39 iGetFontByNumber(UCHAR ucWordFontNumber
, USHORT usFontStyle
)
43 for (iIndex
= 0; iIndex
< (int)tFontTableRecords
; iIndex
++) {
44 if (ucWordFontNumber
== pFontTable
[iIndex
].ucWordFontNumber
&&
45 usFontStyle
== pFontTable
[iIndex
].usFontStyle
&&
46 pFontTable
[iIndex
].szOurFontname
[0] != '\0') {
50 DBG_DEC(ucWordFontNumber
);
53 } /* end of iGetFontByNumber */
56 * szGetOurFontname - Get our font name
58 * return our font name from the given index, NULL if not found
61 szGetOurFontname(int iIndex
)
63 if (iIndex
< 0 || iIndex
>= (int)tFontTableRecords
) {
66 return pFontTable
[iIndex
].szOurFontname
;
67 } /* end of szGetOurFontname */
70 * Find the given font in the font table
72 * returns the Word font number, -1 if not found
75 iFontname2Fontnumber(const char *szOurFontname
, USHORT usFontStyle
)
79 for (iIndex
= 0; iIndex
< (int)tFontTableRecords
; iIndex
++) {
80 if (pFontTable
[iIndex
].usFontStyle
== usFontStyle
&&
81 STREQ(pFontTable
[iIndex
].szOurFontname
, szOurFontname
)) {
82 return (int)pFontTable
[iIndex
].ucWordFontNumber
;
86 } /* end of iFontname2Fontnumber */
89 * szGetDefaultFont - get the default font that matches the parameters
92 szGetDefaultFont(UCHAR ucFFN
, int iEmphasis
)
96 fail(iEmphasis
< 0 || iEmphasis
> 3);
99 ucFf
= (ucFFN
& 0x70) >> 4;
102 if (ucPrq
== PITCH_FIXED
) {
103 /* Set to the default monospaced font */
105 case 1: return FONT_MONOSPACED_BOLD
;
106 case 2: return FONT_MONOSPACED_ITALIC
;
107 case 3: return FONT_MONOSPACED_BOLDITALIC
;
108 default: return FONT_MONOSPACED_PLAIN
;
110 } else if (ucFf
== FAMILY_ROMAN
) {
111 /* Set to the default serif font */
113 case 1: return FONT_SERIF_BOLD
;
114 case 2: return FONT_SERIF_ITALIC
;
115 case 3: return FONT_SERIF_BOLDITALIC
;
116 default: return FONT_SERIF_PLAIN
;
118 } else if (ucFf
== FAMILY_SWISS
) {
119 /* Set to the default sans serif font */
121 case 1: return FONT_SANS_SERIF_BOLD
;
122 case 2: return FONT_SANS_SERIF_ITALIC
;
123 case 3: return FONT_SANS_SERIF_BOLDITALIC
;
124 default: return FONT_SANS_SERIF_PLAIN
;
127 /* Set to the default default font */
129 case 1: return FONT_SERIF_BOLD
;
130 case 2: return FONT_SERIF_ITALIC
;
131 case 3: return FONT_SERIF_BOLDITALIC
;
132 default: return FONT_SERIF_PLAIN
;
135 } /* end of szGetDefaultFont */
138 * See if the fontname from the Word file matches the fontname from the
139 * font translation file.
140 * If iBytesPerChar is one than aucWord is in ISO-8859-x (Word 2/6/7),
141 * if iBytesPerChar is two than aucWord is in Unicode (Word 8/9/10).
144 bFontEqual(const UCHAR
*aucWord
, const char *szTable
, int iBytesPerChar
)
149 fail(aucWord
== NULL
|| szTable
== NULL
);
150 fail(iBytesPerChar
!= 1 && iBytesPerChar
!= 2);
152 for (pucTmp
= aucWord
, pcTmp
= szTable
;
154 pucTmp
+= iBytesPerChar
, pcTmp
++) {
155 if (ulToUpper((ULONG
)*pucTmp
) !=
156 ulToUpper((ULONG
)(UCHAR
)*pcTmp
)) {
160 return *pcTmp
== '\0';
161 } /* end of bFontEqual */
164 * vFontname2Table - add fontnames to the font table
167 vFontname2Table(const UCHAR
*aucFont
, const UCHAR
*aucAltFont
,
168 int iBytesPerChar
, int iEmphasis
, UCHAR ucFFN
,
169 const char *szWordFont
, const char *szOurFont
,
170 font_table_type
*pFontTableRecord
)
174 fail(aucFont
== NULL
|| aucFont
[0] == 0);
175 fail(aucAltFont
!= NULL
&& aucAltFont
[0] == 0);
176 fail(iBytesPerChar
!= 1 && iBytesPerChar
!= 2);
177 fail(iEmphasis
< 0 || iEmphasis
> 3);
178 fail(szWordFont
== NULL
|| szWordFont
[0] == '\0');
179 fail(szOurFont
== NULL
|| szOurFont
[0] == '\0');
180 fail(pFontTableRecord
== NULL
);
182 bMatchFound
= bFontEqual(aucFont
, szWordFont
, iBytesPerChar
);
184 if (!bMatchFound
&& aucAltFont
!= NULL
) {
185 bMatchFound
= bFontEqual(aucAltFont
, szWordFont
, iBytesPerChar
);
189 pFontTableRecord
->szWordFontname
[0] == '\0' &&
190 szWordFont
[0] == '*' &&
191 szWordFont
[1] == '\0') {
193 * szWordFont contains a "*", so szOurFont will contain the
194 * "default default" font. See if we can do better than that.
196 szOurFont
= szGetDefaultFont(ucFFN
, iEmphasis
);
201 switch (iBytesPerChar
) {
203 (void)strncpy(pFontTableRecord
->szWordFontname
,
204 (const char *)aucFont
,
205 sizeof(pFontTableRecord
->szWordFontname
) - 1);
208 (void)unincpy(pFontTableRecord
->szWordFontname
,
210 sizeof(pFontTableRecord
->szWordFontname
) - 1);
214 pFontTableRecord
->szWordFontname
[0] = '\0';
217 pFontTableRecord
->szWordFontname
[
218 sizeof(pFontTableRecord
->szWordFontname
) - 1] = '\0';
219 (void)strncpy(pFontTableRecord
->szOurFontname
, szOurFont
,
220 sizeof(pFontTableRecord
->szOurFontname
) - 1);
221 pFontTableRecord
->szOurFontname
[
222 sizeof(pFontTableRecord
->szOurFontname
) - 1] = '\0';
223 NO_DBG_MSG(pFontTableRecord
->szWordFontname
);
224 NO_DBG_MSG(pFontTableRecord
->szOurFontname
);
225 pFontTableRecord
->ucFFN
= ucFFN
;
226 pFontTableRecord
->ucEmphasis
= (UCHAR
)iEmphasis
;
228 } /* end of vFontname2Table */
231 * vCreateFontTable - Create and initialize the internal font table
234 vCreateFontTable(void)
236 font_table_type
*pTmp
;
239 if (tFontTableRecords
== 0) {
240 pFontTable
= xfree(pFontTable
);
244 /* Create the font table */
245 pFontTable
= xcalloc(tFontTableRecords
, sizeof(*pFontTable
));
247 /* Initialize the font table */
248 for (iNbr
= 0, pTmp
= pFontTable
;
249 pTmp
< pFontTable
+ tFontTableRecords
;
251 pTmp
->ucWordFontNumber
= (UCHAR
)(iNbr
/ 4);
254 pTmp
->usFontStyle
= FONT_REGULAR
;
257 pTmp
->usFontStyle
= FONT_BOLD
;
260 pTmp
->usFontStyle
= FONT_ITALIC
;
263 pTmp
->usFontStyle
= FONT_BOLD
|FONT_ITALIC
;
270 } /* end of vCreateFontTable */
273 * vMinimizeFontTable - make the font table as small as possible
276 vMinimizeFontTable(void)
278 font_block_type tFontNext
;
279 const style_block_type
*pStyle
;
280 const font_block_type
*pFont
;
281 font_table_type
*pTmp
;
283 BOOL bMustAddTableFont
;
285 NO_DBG_MSG("vMinimizeFontTable");
287 if (tFontTableRecords
== 0) {
288 pFontTable
= xfree(pFontTable
);
292 /* See if we must add a font for our tables */
293 bMustAddTableFont
= TRUE
;
297 DBG_DEC(tFontTableRecords
);
298 for (pTmp
= pFontTable
;
299 pTmp
< pFontTable
+ tFontTableRecords
;
301 DBG_DEC(pTmp
->ucWordFontNumber
);
302 DBG_HEX(pTmp
->usFontStyle
);
303 DBG_MSG(pTmp
->szWordFontname
);
304 DBG_MSG(pTmp
->szOurFontname
);
308 /* See which fonts/styles we really need */
310 /* Default font/style is by definition in use */
311 pFontTable
[0].ucInUse
= 1;
313 /* Make InUse 1 for all the fonts/styles that WILL be used */
315 while((pFont
= pGetNextFontInfoListItem(pFont
)) != NULL
) {
316 pTmp
= pFontTable
+ 4 * (int)pFont
->ucFontNumber
;
317 if (bIsBold(pFont
->usFontStyle
)) {
320 if (bIsItalic(pFont
->usFontStyle
)) {
323 if (pTmp
>= pFontTable
+ tFontTableRecords
) {
326 if (STREQ(pTmp
->szOurFontname
, TABLE_FONT
)) {
327 /* The table font is already present */
328 bMustAddTableFont
= FALSE
;
333 /* Make InUse 1 for all the fonts/styles that MIGHT be used */
335 while((pStyle
= pGetNextStyleInfoListItem(pStyle
)) != NULL
) {
336 vFillFontFromStylesheet(pStyle
->usIstdNext
, &tFontNext
);
337 vCorrectFontValues(&tFontNext
);
338 pTmp
= pFontTable
+ 4 * (int)tFontNext
.ucFontNumber
;
339 if (bIsBold(tFontNext
.usFontStyle
)) {
342 if (bIsItalic(tFontNext
.usFontStyle
)) {
345 if (pTmp
>= pFontTable
+ tFontTableRecords
) {
348 if (STREQ(pTmp
->szOurFontname
, TABLE_FONT
)) {
349 /* The table font is already present */
350 bMustAddTableFont
= FALSE
;
355 /* Remove the unused font entries from the font table */
357 for (pTmp
= pFontTable
;
358 pTmp
< pFontTable
+ tFontTableRecords
;
360 if (pTmp
->ucInUse
== 0) {
365 fail(pTmp
- iUnUsed
<= pFontTable
);
366 *(pTmp
- iUnUsed
) = *pTmp
;
370 fail(tFontTableRecords
<= (size_t)iUnUsed
);
371 tFontTableRecords
-= (size_t)iUnUsed
;
373 if (bMustAddTableFont
) {
374 pTmp
= pFontTable
+ tFontTableRecords
;
375 fail(pTmp
<= pFontTable
);
376 pTmp
->ucWordFontNumber
= (pTmp
- 1)->ucWordFontNumber
+ 1;
377 pTmp
->usFontStyle
= FONT_REGULAR
;
379 strcpy(pTmp
->szWordFontname
, "Extra Table Font");
380 strcpy(pTmp
->szOurFontname
, TABLE_FONT
);
385 /* Resize the font table */
386 pFontTable
= xrealloc(pFontTable
,
387 tFontTableRecords
* sizeof(*pFontTable
));
391 DBG_DEC(tFontTableRecords
);
392 for (pTmp
= pFontTable
;
393 pTmp
< pFontTable
+ tFontTableRecords
;
395 DBG_DEC(pTmp
->ucWordFontNumber
);
396 DBG_HEX(pTmp
->usFontStyle
);
397 DBG_MSG(pTmp
->szWordFontname
);
398 DBG_MSG(pTmp
->szOurFontname
);
401 } /* end of vMinimizeFontTable */
404 * bReadFontFile - read and check a line from the font translation file
406 * returns TRUE when a correct line has been read, otherwise FALSE
409 bReadFontFile(FILE *pFontTableFile
, char *szWordFont
,
410 int *piItalic
, int *piBold
, char *szOurFont
, int *piSpecial
)
414 char szLine
[FONT_LINE_LENGTH
];
416 fail(szWordFont
== NULL
|| szOurFont
== NULL
);
417 fail(piItalic
== NULL
|| piBold
== NULL
|| piSpecial
== NULL
);
419 while (fgets(szLine
, (int)sizeof(szLine
), pFontTableFile
) != NULL
) {
420 if (szLine
[0] == '#' ||
425 iFields
= sscanf(szLine
, "%[^,],%d,%d,%1s%[^,],%d",
426 szWordFont
, piItalic
, piBold
,
427 &szOurFont
[0], &szOurFont
[1], piSpecial
);
429 pcTmp
= strchr(szLine
, '\r');
433 pcTmp
= strchr(szLine
, '\n');
438 werr(0, "Syntax error in: '%s'", szLine
);
441 if (strlen(szWordFont
) >=
442 sizeof(pFontTable
[0].szWordFontname
)) {
443 werr(0, "Word fontname too long: '%s'", szWordFont
);
446 if (strlen(szOurFont
) >=
447 sizeof(pFontTable
[0].szOurFontname
)) {
448 werr(0, "Local fontname too long: '%s'", szOurFont
);
451 /* The current line passed all the tests */
455 } /* end of bReadFontFile */
458 * vCreate0FontTable - create a font table from Word for DOS
461 vCreate0FontTable(void)
463 FILE *pFontTableFile
;
464 font_table_type
*pTmp
;
466 int iBold
, iItalic
, iSpecial
, iEmphasis
, iFtc
;
467 UCHAR ucPrq
, ucFf
, ucFFN
;
468 char szWordFont
[FONT_LINE_LENGTH
], szOurFont
[FONT_LINE_LENGTH
];
470 tFontTableRecords
= 0;
471 pFontTable
= xfree(pFontTable
);
473 pFontTableFile
= pOpenFontTableFile();
474 if (pFontTableFile
== NULL
) {
475 /* No translation table file, no translation table */
479 /* Get the maximum number of entries in the font table */
480 tFontTableRecords
= 64;
481 tFontTableRecords
*= 4; /* Plain, Bold, Italic and Bold/italic */
482 tFontTableRecords
++; /* One extra for the table-font */
485 /* Read the font translation file */
489 while (bReadFontFile(pFontTableFile
, szWordFont
,
490 &iItalic
, &iBold
, szOurFont
, &iSpecial
)) {
498 for (iFtc
= 0, pTmp
= pFontTable
+ iEmphasis
;
499 pTmp
< pFontTable
+ tFontTableRecords
;
501 if (iFtc
>= 16 && iFtc
<= 55) {
502 ucPrq
= PITCH_VARIABLE
;
504 aucFont
= (UCHAR
*)"Times";
507 ucFf
= FAMILY_MODERN
;
508 aucFont
= (UCHAR
*)"Courier";
510 ucFFN
= (ucFf
<< 4) | ucPrq
;
511 vFontname2Table(aucFont
, NULL
, 1, iEmphasis
,
512 ucFFN
, szWordFont
, szOurFont
, pTmp
);
515 (void)fclose(pFontTableFile
);
516 vMinimizeFontTable();
517 } /* end of vCreate0FontTable */
520 * vCreate2FontTable - create a font table from WinWord 1/2
523 vCreate2FontTable(FILE *pFile
, int iWordVersion
, const UCHAR
*aucHeader
)
525 FILE *pFontTableFile
;
526 font_table_type
*pTmp
;
529 ULONG ulBeginFontInfo
;
531 int iPos
, iOff
, iRecLen
;
532 int iBold
, iItalic
, iSpecial
, iEmphasis
;
534 char szWordFont
[FONT_LINE_LENGTH
], szOurFont
[FONT_LINE_LENGTH
];
536 fail(pFile
== NULL
|| aucHeader
== NULL
);
537 fail(iWordVersion
!= 1 && iWordVersion
!= 2);
539 tFontTableRecords
= 0;
540 pFontTable
= xfree(pFontTable
);
542 pFontTableFile
= pOpenFontTableFile();
543 if (pFontTableFile
== NULL
) {
544 /* No translation table file, no translation table */
548 ulBeginFontInfo
= ulGetLong(0xb2, aucHeader
); /* fcSttbfffn */
549 DBG_HEX(ulBeginFontInfo
);
550 tFontInfoLen
= (size_t)usGetWord(0xb6, aucHeader
); /* cbSttbfffn */
551 DBG_DEC(tFontInfoLen
);
553 if (ulBeginFontInfo
> (ULONG
)LONG_MAX
|| tFontInfoLen
== 0) {
554 /* Don't ask me why this is needed */
555 DBG_HEX_C(tFontInfoLen
!= 0, ulBeginFontInfo
);
556 (void)fclose(pFontTableFile
);
560 aucBuffer
= xmalloc(tFontInfoLen
);
561 if (!bReadBytes(aucBuffer
, tFontInfoLen
, ulBeginFontInfo
, pFile
)) {
562 aucBuffer
= xfree(aucBuffer
);
563 (void)fclose(pFontTableFile
);
566 NO_DBG_PRINT_BLOCK(aucBuffer
, tFontInfoLen
);
567 DBG_DEC(usGetWord(0, aucBuffer
));
569 /* Compute the maximum number of entries in the font table */
570 if (iWordVersion
== 1) {
571 fail(tFontInfoLen
< 2);
572 /* WinWord 1 has three implicit fonts */
573 tFontTableRecords
= 3;
576 fail(tFontInfoLen
< 6);
577 /* WinWord 2 and up have no implicit fonts */
578 tFontTableRecords
= 0;
582 while (iPos
+ iOff
< (int)tFontInfoLen
) {
583 iRecLen
= (int)ucGetByte(iPos
, aucBuffer
);
585 NO_DBG_MSG(aucBuffer
+ iPos
+ iOff
);
589 tFontTableRecords
*= 4; /* Plain, Bold, Italic and Bold/Italic */
590 tFontTableRecords
++; /* One extra for the table-font */
593 /* Add the tree implicit fonts (in four variations) */
594 if (iWordVersion
== 1) {
595 fail(tFontTableRecords
< 13);
596 vFontname2Table((UCHAR
*)"Tms Rmn", NULL
, 1, 0,
597 (UCHAR
)((FAMILY_ROMAN
<< 4) | PITCH_VARIABLE
),
598 "*", "Times-Roman", pFontTable
+ 0);
599 vFontname2Table((UCHAR
*)"Tms Rmn", NULL
, 1, 1,
600 (UCHAR
)((FAMILY_ROMAN
<< 4) | PITCH_VARIABLE
),
601 "*", "Times-Bold", pFontTable
+ 1);
602 vFontname2Table((UCHAR
*)"Tms Rmn", NULL
, 1, 2,
603 (UCHAR
)((FAMILY_ROMAN
<< 4) | PITCH_VARIABLE
),
604 "*", "Times-Italic", pFontTable
+ 2);
605 vFontname2Table((UCHAR
*)"Tms Rmn", NULL
, 1, 3,
606 (UCHAR
)((FAMILY_ROMAN
<< 4) | PITCH_VARIABLE
),
607 "*", "Times-BoldItalic", pFontTable
+ 3);
608 vFontname2Table((UCHAR
*)"Symbol", NULL
, 1, 0,
609 (UCHAR
)((FAMILY_ROMAN
<< 4) | PITCH_VARIABLE
),
610 "*", "Times-Roman", pFontTable
+ 4);
611 vFontname2Table((UCHAR
*)"Symbol", NULL
, 1, 1,
612 (UCHAR
)((FAMILY_ROMAN
<< 4) | PITCH_VARIABLE
),
613 "*", "Times-Bold", pFontTable
+ 5);
614 vFontname2Table((UCHAR
*)"Symbol", NULL
, 1, 2,
615 (UCHAR
)((FAMILY_ROMAN
<< 4) | PITCH_VARIABLE
),
616 "*", "Times-Italic", pFontTable
+ 6);
617 vFontname2Table((UCHAR
*)"Symbol", NULL
, 1, 3,
618 (UCHAR
)((FAMILY_ROMAN
<< 4) | PITCH_VARIABLE
),
619 "*", "Times-BoldItalic", pFontTable
+ 7);
620 vFontname2Table((UCHAR
*)"Helv", NULL
, 1, 0,
621 (UCHAR
)((FAMILY_SWISS
<< 4) | PITCH_VARIABLE
),
622 "*", "Helvetica", pFontTable
+ 8);
623 vFontname2Table((UCHAR
*)"Helv", NULL
, 1, 1,
624 (UCHAR
)((FAMILY_SWISS
<< 4) | PITCH_VARIABLE
),
625 "*", "Helvetica-Bold", pFontTable
+ 9);
626 vFontname2Table((UCHAR
*)"Helv", NULL
, 1, 2,
627 (UCHAR
)((FAMILY_SWISS
<< 4) | PITCH_VARIABLE
),
628 "*", "Helvetica-Oblique", pFontTable
+ 10);
629 vFontname2Table((UCHAR
*)"Helv", NULL
, 1, 3,
630 (UCHAR
)((FAMILY_SWISS
<< 4) | PITCH_VARIABLE
),
631 "*", "Helvetica-BoldOblique", pFontTable
+ 11);
634 /* Read the font translation file */
638 while (bReadFontFile(pFontTableFile
, szWordFont
,
639 &iItalic
, &iBold
, szOurFont
, &iSpecial
)) {
647 pTmp
= pFontTable
+ iEmphasis
;
649 while (iPos
+ iOff
< (int)tFontInfoLen
) {
650 iRecLen
= (int)ucGetByte(iPos
, aucBuffer
);
651 ucFFN
= ucGetByte(iPos
+ 1, aucBuffer
);
652 aucFont
= aucBuffer
+ iPos
+ iOff
;
653 vFontname2Table(aucFont
, NULL
, 1, iEmphasis
,
654 ucFFN
, szWordFont
, szOurFont
, pTmp
);
659 (void)fclose(pFontTableFile
);
660 aucBuffer
= xfree(aucBuffer
);
661 vMinimizeFontTable();
662 } /* end of vCreate2FontTable */
665 * vCreate6FontTable - create a font table from Word 6/7
668 vCreate6FontTable(FILE *pFile
, ULONG ulStartBlock
,
669 const ULONG
*aulBBD
, size_t tBBDLen
,
670 const UCHAR
*aucHeader
)
672 FILE *pFontTableFile
;
673 font_table_type
*pTmp
;
674 UCHAR
*aucFont
, *aucAltFont
;
676 ULONG ulBeginFontInfo
;
678 int iPos
, iRecLen
, iOffsetAltName
;
679 int iBold
, iItalic
, iSpecial
, iEmphasis
;
681 char szWordFont
[FONT_LINE_LENGTH
], szOurFont
[FONT_LINE_LENGTH
];
683 fail(pFile
== NULL
|| aucHeader
== NULL
);
684 fail(ulStartBlock
> MAX_BLOCKNUMBER
&& ulStartBlock
!= END_OF_CHAIN
);
685 fail(aulBBD
== NULL
);
687 tFontTableRecords
= 0;
688 pFontTable
= xfree(pFontTable
);
690 pFontTableFile
= pOpenFontTableFile();
691 if (pFontTableFile
== NULL
) {
692 /* No translation table file, no translation table */
696 ulBeginFontInfo
= ulGetLong(0xd0, aucHeader
); /* fcSttbfffn */
697 DBG_HEX(ulBeginFontInfo
);
698 tFontInfoLen
= (size_t)ulGetLong(0xd4, aucHeader
); /* lcbSttbfffn */
699 DBG_DEC(tFontInfoLen
);
700 fail(tFontInfoLen
< 9);
702 aucBuffer
= xmalloc(tFontInfoLen
);
703 if (!bReadBuffer(pFile
, ulStartBlock
,
704 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
705 aucBuffer
, ulBeginFontInfo
, tFontInfoLen
)) {
706 aucBuffer
= xfree(aucBuffer
);
707 (void)fclose(pFontTableFile
);
710 DBG_DEC(usGetWord(0, aucBuffer
));
712 /* Compute the maximum number of entries in the font table */
713 tFontTableRecords
= 0;
715 while (iPos
+ 6 < (int)tFontInfoLen
) {
716 iRecLen
= (int)ucGetByte(iPos
, aucBuffer
);
718 iOffsetAltName
= (int)ucGetByte(iPos
+ 5, aucBuffer
);
719 NO_DBG_MSG(aucBuffer
+ iPos
+ 6);
720 NO_DBG_MSG_C(iOffsetAltName
> 0,
721 aucBuffer
+ iPos
+ 6 + iOffsetAltName
);
725 tFontTableRecords
*= 4; /* Plain, Bold, Italic and Bold/italic */
726 tFontTableRecords
++; /* One extra for the table-font */
729 /* Read the font translation file */
733 while (bReadFontFile(pFontTableFile
, szWordFont
,
734 &iItalic
, &iBold
, szOurFont
, &iSpecial
)) {
742 pTmp
= pFontTable
+ iEmphasis
;
744 while (iPos
+ 6 < (int)tFontInfoLen
) {
745 iRecLen
= (int)ucGetByte(iPos
, aucBuffer
);
746 ucFFN
= ucGetByte(iPos
+ 1, aucBuffer
);
747 aucFont
= aucBuffer
+ iPos
+ 6;
748 iOffsetAltName
= (int)ucGetByte(iPos
+ 5, aucBuffer
);
749 if (iOffsetAltName
<= 0) {
752 aucAltFont
= aucFont
+ iOffsetAltName
;
754 NO_DBG_MSG(aucAltFont
);
756 vFontname2Table(aucFont
, aucAltFont
, 1, iEmphasis
,
757 ucFFN
, szWordFont
, szOurFont
, pTmp
);
762 (void)fclose(pFontTableFile
);
763 aucBuffer
= xfree(aucBuffer
);
764 vMinimizeFontTable();
765 } /* end of vCreate6FontTable */
768 * vCreate8FontTable - create a font table from Word 8/9/10
771 vCreate8FontTable(FILE *pFile
, const pps_info_type
*pPPS
,
772 const ULONG
*aulBBD
, size_t tBBDLen
,
773 const ULONG
*aulSBD
, size_t tSBDLen
,
774 const UCHAR
*aucHeader
)
776 FILE *pFontTableFile
;
777 font_table_type
*pTmp
;
778 const ULONG
*aulBlockDepot
;
779 UCHAR
*aucFont
, *aucAltFont
;
781 ULONG ulBeginFontInfo
;
782 size_t tFontInfoLen
, tBlockDepotLen
, tBlockSize
;
783 int iPos
, iRecLen
, iOffsetAltName
;
784 int iBold
, iItalic
, iSpecial
, iEmphasis
;
786 char szWordFont
[FONT_LINE_LENGTH
], szOurFont
[FONT_LINE_LENGTH
];
788 fail(pFile
== NULL
|| pPPS
== NULL
|| aucHeader
== NULL
);
789 fail(aulBBD
== NULL
|| aulSBD
== NULL
);
791 tFontTableRecords
= 0;
792 pFontTable
= xfree(pFontTable
);
794 pFontTableFile
= pOpenFontTableFile();
795 if (pFontTableFile
== NULL
) {
796 /* No translation table file, no translation table */
800 ulBeginFontInfo
= ulGetLong(0x112, aucHeader
); /* fcSttbfffn */
801 DBG_HEX(ulBeginFontInfo
);
802 tFontInfoLen
= (size_t)ulGetLong(0x116, aucHeader
); /* lcbSttbfffn */
803 DBG_DEC(tFontInfoLen
);
804 fail(tFontInfoLen
< 46);
806 DBG_DEC(pPPS
->tTable
.ulSB
);
807 DBG_HEX(pPPS
->tTable
.ulSize
);
808 if (pPPS
->tTable
.ulSize
== 0) {
809 DBG_MSG("No fontname table");
810 (void)fclose(pFontTableFile
);
814 if (pPPS
->tTable
.ulSize
< MIN_SIZE_FOR_BBD_USE
) {
815 /* Use the Small Block Depot */
816 aulBlockDepot
= aulSBD
;
817 tBlockDepotLen
= tSBDLen
;
818 tBlockSize
= SMALL_BLOCK_SIZE
;
820 /* Use the Big Block Depot */
821 aulBlockDepot
= aulBBD
;
822 tBlockDepotLen
= tBBDLen
;
823 tBlockSize
= BIG_BLOCK_SIZE
;
825 aucBuffer
= xmalloc(tFontInfoLen
);
826 if (!bReadBuffer(pFile
, pPPS
->tTable
.ulSB
,
827 aulBlockDepot
, tBlockDepotLen
, tBlockSize
,
828 aucBuffer
, ulBeginFontInfo
, tFontInfoLen
)) {
829 aucBuffer
= xfree(aucBuffer
);
830 (void)fclose(pFontTableFile
);
833 NO_DBG_PRINT_BLOCK(aucBuffer
, tFontInfoLen
);
835 /* Get the maximum number of entries in the font table */
836 tFontTableRecords
= (size_t)usGetWord(0, aucBuffer
);
837 tFontTableRecords
*= 4; /* Plain, Bold, Italic and Bold/italic */
838 tFontTableRecords
++; /* One extra for the table-font */
841 /* Read the font translation file */
845 while (bReadFontFile(pFontTableFile
, szWordFont
,
846 &iItalic
, &iBold
, szOurFont
, &iSpecial
)) {
854 pTmp
= pFontTable
+ iEmphasis
;
856 while (iPos
+ 40 < (int)tFontInfoLen
) {
857 iRecLen
= (int)ucGetByte(iPos
, aucBuffer
);
858 ucFFN
= ucGetByte(iPos
+ 1, aucBuffer
);
859 aucFont
= aucBuffer
+ iPos
+ 40;
860 iOffsetAltName
= (int)unilen(aucFont
);
861 if (iPos
+ 40 + iOffsetAltName
+ 4 >= iRecLen
) {
864 aucAltFont
= aucFont
+ iOffsetAltName
+ 2;
865 NO_DBG_UNICODE(aucFont
);
866 NO_DBG_UNICODE(aucAltFont
);
868 vFontname2Table(aucFont
, aucAltFont
, 2, iEmphasis
,
869 ucFFN
, szWordFont
, szOurFont
, pTmp
);
874 (void)fclose(pFontTableFile
);
875 aucBuffer
= xfree(aucBuffer
);
876 vMinimizeFontTable();
877 } /* end of vCreate8FontTable */
880 * Destroy the internal font table by freeing its memory
883 vDestroyFontTable(void)
885 DBG_MSG("vDestroyFontTable");
887 tFontTableRecords
= 0;
888 pFontTable
= xfree(pFontTable
);
889 } /* end of vDestroyFontTable */
892 * pGetNextFontTableRecord
894 * returns the next record in the table or NULL if there is no next record
896 const font_table_type
*
897 pGetNextFontTableRecord(const font_table_type
*pRecordCurr
)
901 if (pRecordCurr
== NULL
) {
902 /* No current record, so start with the first one */
903 return &pFontTable
[0];
906 if (pRecordCurr
< pFontTable
||
907 pRecordCurr
>= pFontTable
+ tFontTableRecords
) {
908 /* Not a pointer in the array */
909 DBG_HEX(pRecordCurr
);
914 tIndexCurr
= (size_t)(pRecordCurr
- pFontTable
);
915 if (tIndexCurr
+ 1 < tFontTableRecords
) {
916 /* There is a next record, so return it */
917 return &pFontTable
[tIndexCurr
+ 1];
919 /* There is no next record */
921 } /* end of pGetNextFontTableRecord */
924 * tGetFontTableLength
926 * returns the number of records in the internal font table
929 tGetFontTableLength(void)
931 return tFontTableRecords
;
932 } /* end of tGetFontTableLength */
934 #if !defined(__riscos)
936 * vCorrect4PDF - only include PDF default fonts
941 font_table_type
*pTmp
;
942 const char *szOurFont
;
944 for (pTmp
= pFontTable
; pTmp
< pFontTable
+ tFontTableRecords
; pTmp
++) {
945 if (STRCEQ(pTmp
->szOurFontname
, FONT_MONOSPACED_PLAIN
) ||
946 STRCEQ(pTmp
->szOurFontname
, FONT_MONOSPACED_BOLD
) ||
947 STRCEQ(pTmp
->szOurFontname
, FONT_MONOSPACED_ITALIC
) ||
948 STRCEQ(pTmp
->szOurFontname
, FONT_MONOSPACED_BOLDITALIC
) ||
949 STRCEQ(pTmp
->szOurFontname
, FONT_SERIF_PLAIN
) ||
950 STRCEQ(pTmp
->szOurFontname
, FONT_SERIF_BOLD
) ||
951 STRCEQ(pTmp
->szOurFontname
, FONT_SERIF_ITALIC
) ||
952 STRCEQ(pTmp
->szOurFontname
, FONT_SERIF_BOLDITALIC
) ||
953 STRCEQ(pTmp
->szOurFontname
, FONT_SANS_SERIF_PLAIN
) ||
954 STRCEQ(pTmp
->szOurFontname
, FONT_SANS_SERIF_BOLD
) ||
955 STRCEQ(pTmp
->szOurFontname
, FONT_SANS_SERIF_ITALIC
) ||
956 STRCEQ(pTmp
->szOurFontname
, FONT_SANS_SERIF_BOLDITALIC
)) {
957 /* Already a default font */
961 szGetDefaultFont(pTmp
->ucFFN
, (int)pTmp
->ucEmphasis
);
962 (void)strncpy(pTmp
->szOurFontname
, szOurFont
,
963 sizeof(pTmp
->szOurFontname
) - 1);
964 pTmp
->szOurFontname
[sizeof(pTmp
->szOurFontname
) - 1] = '\0';
966 } /* end of vCorrect4PDF */
969 * vCorrect4CyrPS - only include monospaced fonts
974 font_table_type
*pTmp
;
975 const char *szOurFont
;
978 ucFFN
= (FAMILY_UNKNOWN
<< 4) | PITCH_FIXED
;
979 for (pTmp
= pFontTable
; pTmp
< pFontTable
+ tFontTableRecords
; pTmp
++) {
980 szOurFont
= szGetDefaultFont(ucFFN
, (int)pTmp
->ucEmphasis
);
981 (void)strncpy(pTmp
->szOurFontname
, szOurFont
,
982 sizeof(pTmp
->szOurFontname
) - 1);
983 pTmp
->szOurFontname
[sizeof(pTmp
->szOurFontname
) - 1] = '\0';
985 } /* end of vCorrect4CyrPS */
986 #endif /* __riscos */
989 * vCorrectFontTable - correct the font table in special cases
992 vCorrectFontTable(conversion_type eConversionType
, encoding_type eEncoding
)
994 #if !defined(__riscos)
995 if (eConversionType
== conversion_pdf
) {
998 if (eConversionType
== conversion_ps
&&
999 eEncoding
== encoding_cyrillic
) {
1002 #endif /* __riscos */
1003 } /* end of vCorrectFontTable */
1006 * lComputeSpaceWidth - compute the width of a space character
1008 * Returns the space width in millipoints
1011 lComputeSpaceWidth(drawfile_fontref tFontRef
, USHORT usFontSize
)
1013 char szSpace
[] = " ";
1015 fail(usFontSize
< MIN_FONT_SIZE
|| usFontSize
> MAX_FONT_SIZE
);
1017 return lComputeStringWidth(szSpace
, 1, tFontRef
, usFontSize
);
1018 } /* end of lComputeSpaceWidth */