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
 * fonts.c
3
 * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
4
 *
5
 * Description:
6
 * Functions to deal with fonts (generic)
7
 */
8
 
9
#include <ctype.h>
10
#include <string.h>
11
#include "antiword.h"
12
 
13
/* Maximum line length in the font file */
14
#define FONT_LINE_LENGTH	81
15
 
16
/* Pitch */
17
#define PITCH_UNKNOWN		0
18
#define PITCH_FIXED		1
19
#define PITCH_VARIABLE		2
20
 
21
/* Font Family */
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
28
 
29
/* Font Translation Table */
30
static size_t		tFontTableRecords = 0;
31
static font_table_type	*pFontTable = NULL;
32
 
33
/*
34
 * Find the given font in the font table
35
 *
36
 * returns the index into the FontTable, -1 if not found
37
 */
38
int
39
iGetFontByNumber(UCHAR ucWordFontNumber, USHORT usFontStyle)
40
{
41
	int	iIndex;
42
 
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') {
47
			return iIndex;
48
		}
49
	}
50
	DBG_DEC(ucWordFontNumber);
51
	DBG_HEX(usFontStyle);
52
	return -1;
53
} /* end of iGetFontByNumber */
54
 
55
/*
56
 * szGetOurFontname - Get our font name
57
 *
58
 * return our font name from the given index, NULL if not found
59
 */
60
const char *
61
szGetOurFontname(int iIndex)
62
{
63
	if (iIndex < 0 || iIndex >= (int)tFontTableRecords) {
64
		return NULL;
65
	}
66
	return pFontTable[iIndex].szOurFontname;
67
} /* end of szGetOurFontname */
68
 
69
/*
70
 * Find the given font in the font table
71
 *
72
 * returns the Word font number, -1 if not found
73
 */
74
int
75
iFontname2Fontnumber(const char *szOurFontname, USHORT usFontStyle)
76
{
77
	int	iIndex;
78
 
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;
83
		}
84
	}
85
	return -1;
86
} /* end of iFontname2Fontnumber */
87
 
88
/*
89
 * szGetDefaultFont - get the default font that matches the parameters
90
 */
91
static const char *
92
szGetDefaultFont(UCHAR ucFFN, int iEmphasis)
93
{
94
	UCHAR	ucPrq, ucFf;
95
 
96
	fail(iEmphasis < 0 || iEmphasis > 3);
97
 
98
	ucPrq = ucFFN & 0x03;
99
	ucFf = (ucFFN & 0x70) >> 4;
100
	NO_DBG_DEC(ucPrq);
101
	NO_DBG_DEC(ucFf);
102
	if (ucPrq == PITCH_FIXED) {
103
		/* Set to the default monospaced font */
104
		switch (iEmphasis) {
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;
109
		}
110
	} else if (ucFf == FAMILY_ROMAN) {
111
		/* Set to the default serif font */
112
		switch (iEmphasis) {
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;
117
		}
118
	} else if (ucFf == FAMILY_SWISS) {
119
		/* Set to the default sans serif font */
120
		switch (iEmphasis) {
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;
125
		}
126
	} else {
127
		/* Set to the default default font */
128
		switch (iEmphasis) {
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;
133
		}
134
	}
135
} /* end of szGetDefaultFont */
136
 
137
/*
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).
142
 */
143
static BOOL
144
bFontEqual(const UCHAR *aucWord, const char *szTable, int iBytesPerChar)
145
{
146
	const UCHAR	*pucTmp;
147
	const char	*pcTmp;
148
 
149
	fail(aucWord == NULL || szTable == NULL);
150
	fail(iBytesPerChar != 1 && iBytesPerChar != 2);
151
 
152
	for (pucTmp = aucWord, pcTmp = szTable;
153
	     *pucTmp != 0;
154
	     pucTmp += iBytesPerChar, pcTmp++) {
155
		if (ulToUpper((ULONG)*pucTmp) !=
156
		    ulToUpper((ULONG)(UCHAR)*pcTmp)) {
157
			return FALSE;
158
		}
159
	}
160
	return *pcTmp == '\0';
161
} /* end of bFontEqual */
162
 
163
/*
164
 * vFontname2Table - add fontnames to the font table
165
 */
166
static void
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)
171
{
172
	BOOL	bMatchFound;
173
 
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);
181
 
182
	bMatchFound = bFontEqual(aucFont, szWordFont, iBytesPerChar);
183
 
184
	if (!bMatchFound && aucAltFont != NULL) {
185
		bMatchFound = bFontEqual(aucAltFont, szWordFont, iBytesPerChar);
186
	}
187
 
188
	if (!bMatchFound &&
189
	    pFontTableRecord->szWordFontname[0] == '\0' &&
190
	    szWordFont[0] == '*' &&
191
	    szWordFont[1] == '\0') {
192
		/*
193
		 * szWordFont contains a "*", so szOurFont will contain the
194
		 * "default default" font. See if we can do better than that.
195
		 */
196
		szOurFont = szGetDefaultFont(ucFFN, iEmphasis);
197
		bMatchFound = TRUE;
198
	}
199
 
200
	if (bMatchFound) {
201
		switch (iBytesPerChar) {
202
		case 1:
203
			(void)strncpy(pFontTableRecord->szWordFontname,
204
				(const char *)aucFont,
205
				sizeof(pFontTableRecord->szWordFontname) - 1);
206
			break;
207
		case 2:
208
			(void)unincpy(pFontTableRecord->szWordFontname,
209
				aucFont,
210
				sizeof(pFontTableRecord->szWordFontname) - 1);
211
			break;
212
		default:
213
			DBG_FIXME();
214
			pFontTableRecord->szWordFontname[0] = '\0';
215
			break;
216
		}
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;
227
	}
228
} /* end of vFontname2Table */
229
 
230
/*
231
 * vCreateFontTable - Create and initialize the internal font table
232
 */
233
static void
234
vCreateFontTable(void)
235
{
236
	font_table_type	*pTmp;
237
	int	iNbr;
238
 
239
	if (tFontTableRecords == 0) {
240
		pFontTable = xfree(pFontTable);
241
		return;
242
	}
243
 
244
	/* Create the font table */
245
	pFontTable = xcalloc(tFontTableRecords, sizeof(*pFontTable));
246
 
247
	/* Initialize the font table */
248
	for (iNbr = 0, pTmp = pFontTable;
249
	     pTmp < pFontTable + tFontTableRecords;
250
	     iNbr++, pTmp++) {
251
		pTmp->ucWordFontNumber = (UCHAR)(iNbr / 4);
252
		switch (iNbr % 4) {
253
		case 0:
254
			pTmp->usFontStyle = FONT_REGULAR;
255
			break;
256
		case 1:
257
			pTmp->usFontStyle = FONT_BOLD;
258
			break;
259
		case 2:
260
			pTmp->usFontStyle = FONT_ITALIC;
261
			break;
262
		case 3:
263
			pTmp->usFontStyle = FONT_BOLD|FONT_ITALIC;
264
			break;
265
		default:
266
			DBG_DEC(iNbr);
267
			break;
268
		}
269
	}
270
} /* end of vCreateFontTable */
271
 
272
/*
273
 * vMinimizeFontTable - make the font table as small as possible
274
 */
275
static void
276
vMinimizeFontTable(void)
277
{
278
	font_block_type		tFontNext;
279
	const style_block_type	*pStyle;
280
	const font_block_type	*pFont;
281
	font_table_type		*pTmp;
282
	int	iUnUsed;
283
	BOOL	bMustAddTableFont;
284
 
285
	NO_DBG_MSG("vMinimizeFontTable");
286
 
287
	if (tFontTableRecords == 0) {
288
		pFontTable = xfree(pFontTable);
289
		return;
290
	}
291
 
292
	/* See if we must add a font for our tables */
293
	bMustAddTableFont = TRUE;
294
 
295
#if 0
296
	DBG_MSG("Before");
297
	DBG_DEC(tFontTableRecords);
298
	for (pTmp = pFontTable;
299
	     pTmp < pFontTable + tFontTableRecords;
300
	     pTmp++) {
301
		DBG_DEC(pTmp->ucWordFontNumber);
302
		DBG_HEX(pTmp->usFontStyle);
303
		DBG_MSG(pTmp->szWordFontname);
304
		DBG_MSG(pTmp->szOurFontname);
305
	}
306
#endif /* DEBUG */
307
 
308
	/* See which fonts/styles we really need */
309
 
310
	/* Default font/style is by definition in use */
311
	pFontTable[0].ucInUse = 1;
312
 
313
	/* Make InUse 1 for all the fonts/styles that WILL be used */
314
	pFont = NULL;
315
	while((pFont = pGetNextFontInfoListItem(pFont)) != NULL) {
316
		pTmp = pFontTable + 4 * (int)pFont->ucFontNumber;
317
		if (bIsBold(pFont->usFontStyle)) {
318
			pTmp++;
319
		}
320
		if (bIsItalic(pFont->usFontStyle)) {
321
			pTmp += 2;
322
		}
323
		if (pTmp >= pFontTable + tFontTableRecords) {
324
			continue;
325
		}
326
		if (STREQ(pTmp->szOurFontname, TABLE_FONT)) {
327
			/* The table font is already present */
328
			bMustAddTableFont = FALSE;
329
		}
330
		pTmp->ucInUse = 1;
331
	}
332
 
333
	/* Make InUse 1 for all the fonts/styles that MIGHT be used */
334
	pStyle = NULL;
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)) {
340
			pTmp++;
341
		}
342
		if (bIsItalic(tFontNext.usFontStyle)) {
343
			pTmp += 2;
344
		}
345
		if (pTmp >= pFontTable + tFontTableRecords) {
346
			continue;
347
		}
348
		if (STREQ(pTmp->szOurFontname, TABLE_FONT)) {
349
			/* The table font is already present */
350
			bMustAddTableFont = FALSE;
351
		}
352
		pTmp->ucInUse = 1;
353
	}
354
 
355
	/* Remove the unused font entries from the font table */
356
	iUnUsed = 0;
357
	for (pTmp = pFontTable;
358
	     pTmp < pFontTable + tFontTableRecords;
359
	     pTmp++) {
360
		if (pTmp->ucInUse == 0) {
361
			iUnUsed++;
362
			continue;
363
		}
364
		if (iUnUsed > 0) {
365
			fail(pTmp - iUnUsed <= pFontTable);
366
			*(pTmp - iUnUsed) = *pTmp;
367
		}
368
	}
369
	fail(iUnUsed < 0);
370
	fail(tFontTableRecords <= (size_t)iUnUsed);
371
	tFontTableRecords -= (size_t)iUnUsed;
372
 
373
	if (bMustAddTableFont) {
374
		pTmp = pFontTable + tFontTableRecords;
375
		fail(pTmp <= pFontTable);
376
		pTmp->ucWordFontNumber = (pTmp - 1)->ucWordFontNumber + 1;
377
		pTmp->usFontStyle = FONT_REGULAR;
378
		pTmp->ucInUse = 1;
379
		strcpy(pTmp->szWordFontname, "Extra Table Font");
380
		strcpy(pTmp->szOurFontname, TABLE_FONT);
381
		tFontTableRecords++;
382
		iUnUsed--;
383
	}
384
	if (iUnUsed > 0) {
385
		/* Resize the font table */
386
		pFontTable = xrealloc(pFontTable,
387
				tFontTableRecords * sizeof(*pFontTable));
388
	}
389
#if defined(DEBUG)
390
	DBG_MSG("After");
391
	DBG_DEC(tFontTableRecords);
392
	for (pTmp = pFontTable;
393
	     pTmp < pFontTable + tFontTableRecords;
394
	     pTmp++) {
395
		DBG_DEC(pTmp->ucWordFontNumber);
396
		DBG_HEX(pTmp->usFontStyle);
397
		DBG_MSG(pTmp->szWordFontname);
398
		DBG_MSG(pTmp->szOurFontname);
399
	}
400
#endif /* DEBUG */
401
} /* end of vMinimizeFontTable */
402
 
403
/*
404
 * bReadFontFile - read and check a line from the font translation file
405
 *
406
 * returns TRUE when a correct line has been read, otherwise FALSE
407
 */
408
static BOOL
409
bReadFontFile(FILE *pFontTableFile, char *szWordFont,
410
	int *piItalic, int *piBold, char *szOurFont, int *piSpecial)
411
{
412
	char	*pcTmp;
413
	int	iFields;
414
	char	szLine[FONT_LINE_LENGTH];
415
 
416
	fail(szWordFont == NULL || szOurFont == NULL);
417
	fail(piItalic == NULL || piBold == NULL || piSpecial == NULL);
418
 
419
	while (fgets(szLine, (int)sizeof(szLine), pFontTableFile) != NULL) {
420
		if (szLine[0] == '#' ||
421
		    szLine[0] == '\n' ||
422
		    szLine[0] == '\r') {
423
			continue;
424
		}
425
		iFields = sscanf(szLine, "%[^,],%d,%d,%1s%[^,],%d",
426
			szWordFont, piItalic, piBold,
427
			&szOurFont[0], &szOurFont[1], piSpecial);
428
		if (iFields != 6) {
429
			pcTmp = strchr(szLine, '\r');
430
			if (pcTmp != NULL) {
431
				*pcTmp = '\0';
432
			}
433
			pcTmp = strchr(szLine, '\n');
434
			if (pcTmp != NULL) {
435
				*pcTmp = '\0';
436
			}
437
			DBG_DEC(iFields);
438
			werr(0, "Syntax error in: '%s'", szLine);
439
			continue;
440
		}
441
		if (strlen(szWordFont) >=
442
				sizeof(pFontTable[0].szWordFontname)) {
443
			werr(0, "Word fontname too long: '%s'", szWordFont);
444
			continue;
445
		}
446
		if (strlen(szOurFont) >=
447
				sizeof(pFontTable[0].szOurFontname)) {
448
			werr(0, "Local fontname too long: '%s'", szOurFont);
449
			continue;
450
		}
451
		/* The current line passed all the tests */
452
		return TRUE;
453
	}
454
	return FALSE;
455
} /* end of bReadFontFile */
456
 
457
/*
458
 * vCreate0FontTable - create a font table from Word for DOS
459
 */
460
void
461
vCreate0FontTable(void)
462
{
463
	FILE	*pFontTableFile;
464
	font_table_type	*pTmp;
465
	UCHAR	*aucFont;
466
	int	iBold, iItalic, iSpecial, iEmphasis, iFtc;
467
	UCHAR	ucPrq, ucFf, ucFFN;
468
	char	szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
469
 
470
	tFontTableRecords = 0;
471
	pFontTable = xfree(pFontTable);
472
 
473
	pFontTableFile = pOpenFontTableFile();
474
	if (pFontTableFile == NULL) {
475
		/* No translation table file, no translation table */
476
		return;
477
	}
478
 
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 */
483
	vCreateFontTable();
484
 
485
	/* Read the font translation file */
486
	iItalic = 0;
487
	iBold = 0;
488
	iSpecial = 0;
489
	while (bReadFontFile(pFontTableFile, szWordFont,
490
			&iItalic, &iBold, szOurFont, &iSpecial)) {
491
		iEmphasis = 0;
492
		if (iBold != 0) {
493
			iEmphasis++;
494
		}
495
		if (iItalic != 0) {
496
			iEmphasis += 2;
497
		}
498
		for (iFtc = 0, pTmp = pFontTable + iEmphasis;
499
		     pTmp < pFontTable + tFontTableRecords;
500
		     iFtc++, pTmp += 4) {
501
			if (iFtc >= 16 && iFtc <= 55) {
502
				ucPrq = PITCH_VARIABLE;
503
				ucFf = FAMILY_ROMAN;
504
				aucFont = (UCHAR *)"Times";
505
			} else {
506
				ucPrq = PITCH_FIXED;
507
				ucFf = FAMILY_MODERN;
508
				aucFont = (UCHAR *)"Courier";
509
			}
510
			ucFFN = (ucFf << 4) | ucPrq;
511
			vFontname2Table(aucFont, NULL, 1, iEmphasis,
512
					ucFFN, szWordFont, szOurFont, pTmp);
513
		}
514
	}
515
	(void)fclose(pFontTableFile);
516
	vMinimizeFontTable();
517
} /* end of vCreate0FontTable */
518
 
519
/*
520
 * vCreate2FontTable - create a font table from WinWord 1/2
521
 */
522
void
523
vCreate2FontTable(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
524
{
525
	FILE	*pFontTableFile;
526
	font_table_type	*pTmp;
527
	UCHAR	*aucFont;
528
	UCHAR	*aucBuffer;
529
	ULONG	ulBeginFontInfo;
530
	size_t	tFontInfoLen;
531
	int	iPos, iOff, iRecLen;
532
	int	iBold, iItalic, iSpecial, iEmphasis;
533
	UCHAR	ucFFN;
534
	char	szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
535
 
536
	fail(pFile == NULL || aucHeader == NULL);
537
	fail(iWordVersion != 1 && iWordVersion != 2);
538
 
539
	tFontTableRecords = 0;
540
	pFontTable = xfree(pFontTable);
541
 
542
	pFontTableFile = pOpenFontTableFile();
543
	if (pFontTableFile == NULL) {
544
		/* No translation table file, no translation table */
545
		return;
546
	}
547
 
548
	ulBeginFontInfo = ulGetLong(0xb2, aucHeader); /* fcSttbfffn */
549
	DBG_HEX(ulBeginFontInfo);
550
	tFontInfoLen = (size_t)usGetWord(0xb6, aucHeader); /* cbSttbfffn */
551
	DBG_DEC(tFontInfoLen);
552
 
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);
557
		return;
558
	}
559
 
560
	aucBuffer = xmalloc(tFontInfoLen);
561
	if (!bReadBytes(aucBuffer, tFontInfoLen, ulBeginFontInfo, pFile)) {
562
		aucBuffer = xfree(aucBuffer);
563
		(void)fclose(pFontTableFile);
564
		return;
565
	}
566
	NO_DBG_PRINT_BLOCK(aucBuffer, tFontInfoLen);
567
	DBG_DEC(usGetWord(0, aucBuffer));
568
 
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;
574
		iOff = 2;
575
	} else {
576
		fail(tFontInfoLen < 6);
577
		/* WinWord 2 and up have no implicit fonts */
578
		tFontTableRecords = 0;
579
		iOff = 3;
580
	}
581
	iPos = 2;
582
	while (iPos + iOff < (int)tFontInfoLen) {
583
		iRecLen = (int)ucGetByte(iPos, aucBuffer);
584
		NO_DBG_DEC(iRecLen);
585
		NO_DBG_MSG(aucBuffer + iPos + iOff);
586
		iPos += iRecLen + 1;
587
		tFontTableRecords++;
588
	}
589
	tFontTableRecords *= 4;	/* Plain, Bold, Italic and Bold/Italic */
590
	tFontTableRecords++;	/* One extra for the table-font */
591
	vCreateFontTable();
592
 
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);
632
	}
633
 
634
	/* Read the font translation file */
635
	iItalic = 0;
636
	iBold = 0;
637
	iSpecial = 0;
638
	while (bReadFontFile(pFontTableFile, szWordFont,
639
			&iItalic, &iBold, szOurFont, &iSpecial)) {
640
		iEmphasis = 0;
641
		if (iBold != 0) {
642
			iEmphasis++;
643
		}
644
		if (iItalic != 0) {
645
			iEmphasis += 2;
646
		}
647
		pTmp = pFontTable + iEmphasis;
648
		iPos = 2;
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);
655
			pTmp += 4;
656
			iPos += iRecLen + 1;
657
		}
658
	}
659
	(void)fclose(pFontTableFile);
660
	aucBuffer = xfree(aucBuffer);
661
	vMinimizeFontTable();
662
} /* end of vCreate2FontTable */
663
 
664
/*
665
 * vCreate6FontTable - create a font table from Word 6/7
666
 */
667
void
668
vCreate6FontTable(FILE *pFile, ULONG ulStartBlock,
669
	const ULONG *aulBBD, size_t tBBDLen,
670
	const UCHAR *aucHeader)
671
{
672
	FILE	*pFontTableFile;
673
	font_table_type	*pTmp;
674
	UCHAR	*aucFont, *aucAltFont;
675
	UCHAR	*aucBuffer;
676
	ULONG	ulBeginFontInfo;
677
	size_t	tFontInfoLen;
678
	int	iPos, iRecLen, iOffsetAltName;
679
	int	iBold, iItalic, iSpecial, iEmphasis;
680
	UCHAR	ucFFN;
681
	char	szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
682
 
683
	fail(pFile == NULL || aucHeader == NULL);
684
	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
685
	fail(aulBBD == NULL);
686
 
687
	tFontTableRecords = 0;
688
	pFontTable = xfree(pFontTable);
689
 
690
	pFontTableFile = pOpenFontTableFile();
691
	if (pFontTableFile == NULL) {
692
		/* No translation table file, no translation table */
693
		return;
694
	}
695
 
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);
701
 
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);
708
		return;
709
	}
710
	DBG_DEC(usGetWord(0, aucBuffer));
711
 
712
	/* Compute the maximum number of entries in the font table */
713
	tFontTableRecords = 0;
714
	iPos = 2;
715
	while (iPos + 6 < (int)tFontInfoLen) {
716
		iRecLen = (int)ucGetByte(iPos, aucBuffer);
717
		NO_DBG_DEC(iRecLen);
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);
722
		iPos += iRecLen + 1;
723
		tFontTableRecords++;
724
	}
725
	tFontTableRecords *= 4;	/* Plain, Bold, Italic and Bold/italic */
726
	tFontTableRecords++;	/* One extra for the table-font */
727
	vCreateFontTable();
728
 
729
	/* Read the font translation file */
730
	iItalic = 0;
731
	iBold = 0;
732
	iSpecial = 0;
733
	while (bReadFontFile(pFontTableFile, szWordFont,
734
			&iItalic, &iBold, szOurFont, &iSpecial)) {
735
		iEmphasis = 0;
736
		if (iBold != 0) {
737
			iEmphasis++;
738
		}
739
		if (iItalic != 0) {
740
			iEmphasis += 2;
741
		}
742
		pTmp = pFontTable + iEmphasis;
743
		iPos = 2;
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) {
750
				aucAltFont = NULL;
751
			} else {
752
				aucAltFont = aucFont + iOffsetAltName;
753
				NO_DBG_MSG(aucFont);
754
				NO_DBG_MSG(aucAltFont);
755
			}
756
			vFontname2Table(aucFont, aucAltFont, 1, iEmphasis,
757
					ucFFN, szWordFont, szOurFont, pTmp);
758
			pTmp += 4;
759
			iPos += iRecLen + 1;
760
		}
761
	}
762
	(void)fclose(pFontTableFile);
763
	aucBuffer = xfree(aucBuffer);
764
	vMinimizeFontTable();
765
} /* end of vCreate6FontTable */
766
 
767
/*
768
 * vCreate8FontTable - create a font table from Word 8/9/10
769
 */
770
void
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)
775
{
776
	FILE	*pFontTableFile;
777
	font_table_type	*pTmp;
778
	const ULONG	*aulBlockDepot;
779
	UCHAR	*aucFont, *aucAltFont;
780
	UCHAR	*aucBuffer;
781
	ULONG	ulBeginFontInfo;
782
	size_t	tFontInfoLen, tBlockDepotLen, tBlockSize;
783
	int	iPos, iRecLen, iOffsetAltName;
784
	int	iBold, iItalic, iSpecial, iEmphasis;
785
	UCHAR	ucFFN;
786
	char	szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
787
 
788
	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
789
	fail(aulBBD == NULL || aulSBD == NULL);
790
 
791
	tFontTableRecords = 0;
792
	pFontTable = xfree(pFontTable);
793
 
794
	pFontTableFile = pOpenFontTableFile();
795
	if (pFontTableFile == NULL) {
796
		/* No translation table file, no translation table */
797
		return;
798
	}
799
 
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);
805
 
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);
811
		return;
812
	}
813
 
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;
819
	} else {
820
		/* Use the Big Block Depot */
821
		aulBlockDepot = aulBBD;
822
		tBlockDepotLen = tBBDLen;
823
		tBlockSize = BIG_BLOCK_SIZE;
824
	}
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);
831
		return;
832
	}
833
	NO_DBG_PRINT_BLOCK(aucBuffer, tFontInfoLen);
834
 
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 */
839
	vCreateFontTable();
840
 
841
	/* Read the font translation file */
842
	iItalic = 0;
843
	iBold = 0;
844
	iSpecial = 0;
845
	while (bReadFontFile(pFontTableFile, szWordFont,
846
			&iItalic, &iBold, szOurFont, &iSpecial)) {
847
		iEmphasis = 0;
848
		if (iBold != 0) {
849
			iEmphasis++;
850
		}
851
		if (iItalic != 0) {
852
			iEmphasis += 2;
853
		}
854
		pTmp = pFontTable + iEmphasis;
855
		iPos = 4;
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) {
862
				aucAltFont = NULL;
863
			} else {
864
				aucAltFont = aucFont + iOffsetAltName + 2;
865
				NO_DBG_UNICODE(aucFont);
866
				NO_DBG_UNICODE(aucAltFont);
867
			}
868
			vFontname2Table(aucFont, aucAltFont, 2, iEmphasis,
869
					ucFFN, szWordFont, szOurFont, pTmp);
870
			pTmp += 4;
871
			iPos += iRecLen + 1;
872
		}
873
	}
874
	(void)fclose(pFontTableFile);
875
	aucBuffer = xfree(aucBuffer);
876
	vMinimizeFontTable();
877
} /* end of vCreate8FontTable */
878
 
879
/*
880
 * Destroy the internal font table by freeing its memory
881
 */
882
void
883
vDestroyFontTable(void)
884
{
885
	DBG_MSG("vDestroyFontTable");
886
 
887
	tFontTableRecords = 0;
888
	pFontTable = xfree(pFontTable);
889
} /* end of vDestroyFontTable */
890
 
891
/*
892
 * pGetNextFontTableRecord
893
 *
894
 * returns the next record in the table or NULL if there is no next record
895
 */
896
const font_table_type *
897
pGetNextFontTableRecord(const font_table_type *pRecordCurr)
898
{
899
	size_t	tIndexCurr;
900
 
901
	if (pRecordCurr == NULL) {
902
		/* No current record, so start with the first one */
903
		return &pFontTable[0];
904
	}
905
 
906
	if (pRecordCurr < pFontTable ||
907
	    pRecordCurr >= pFontTable + tFontTableRecords) {
908
		/* Not a pointer in the array */
909
		DBG_HEX(pRecordCurr);
910
		DBG_HEX(pFontTable);
911
		return NULL;
912
	}
913
 
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];
918
	}
919
	/* There is no next record */
920
	return NULL;
921
} /* end of pGetNextFontTableRecord */
922
 
923
/*
924
 * tGetFontTableLength
925
 *
926
 * returns the number of records in the internal font table
927
 */
928
size_t
929
tGetFontTableLength(void)
930
{
931
	return tFontTableRecords;
932
} /* end of tGetFontTableLength */
933
 
934
#if !defined(__riscos)
935
/*
936
 * vCorrect4PDF - only include PDF default fonts
937
 */
938
static void
939
vCorrect4PDF(void)
940
{
941
	font_table_type	*pTmp;
942
	const char	*szOurFont;
943
 
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 */
958
			continue;
959
		}
960
		szOurFont =
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';
965
	}
966
} /* end of vCorrect4PDF */
967
 
968
/*
969
 * vCorrect4CyrPS - only include monospaced fonts
970
 */
971
static void
972
vCorrect4CyrPS(void)
973
{
974
	font_table_type	*pTmp;
975
	const char	*szOurFont;
976
	UCHAR	ucFFN;
977
 
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';
984
	}
985
} /* end of vCorrect4CyrPS */
986
#endif /* __riscos */
987
 
988
/*
989
 * vCorrectFontTable - correct the font table in special cases
990
 */
991
void
992
vCorrectFontTable(conversion_type eConversionType, encoding_type eEncoding)
993
{
994
#if !defined(__riscos)
995
	if (eConversionType == conversion_pdf) {
996
		vCorrect4PDF();
997
	}
998
	if (eConversionType == conversion_ps &&
999
	    eEncoding == encoding_cyrillic) {
1000
		vCorrect4CyrPS();
1001
	}
1002
#endif /* __riscos */
1003
} /* end of vCorrectFontTable */
1004
 
1005
/*
1006
 * lComputeSpaceWidth - compute the width of a space character
1007
 *
1008
 * Returns the space width in millipoints
1009
 */
1010
long
1011
lComputeSpaceWidth(drawfile_fontref tFontRef, USHORT usFontSize)
1012
{
1013
	char	szSpace[] = " ";
1014
 
1015
	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
1016
 
1017
        return lComputeStringWidth(szSpace, 1, tFontRef, usFontSize);
1018
} /* end of lComputeSpaceWidth */