xref: /plan9/sys/src/cmd/aux/antiword/fontlist.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * fontlist.c
3*25b329d5SDavid du Colombier  * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Build, read and destroy a list of Word font information
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include <stdlib.h>
10f5736e95SDavid du Colombier #include <stddef.h>
11f5736e95SDavid du Colombier #include "antiword.h"
12f5736e95SDavid du Colombier 
13f5736e95SDavid du Colombier 
14*25b329d5SDavid du Colombier /*
15*25b329d5SDavid du Colombier  * Private structure to hide the way the information
16*25b329d5SDavid du Colombier  * is stored from the rest of the program
17*25b329d5SDavid du Colombier  */
18*25b329d5SDavid du Colombier typedef struct font_desc_tag {
19*25b329d5SDavid du Colombier 	font_block_type tInfo;
20*25b329d5SDavid du Colombier 	struct font_desc_tag    *pNext;
21*25b329d5SDavid du Colombier } font_mem_type;
22*25b329d5SDavid du Colombier 
23f5736e95SDavid du Colombier /* Variables needed to write the Font Information List */
24*25b329d5SDavid du Colombier static font_mem_type	*pAnchor = NULL;
25*25b329d5SDavid du Colombier static font_mem_type	*pFontLast = NULL;
26f5736e95SDavid du Colombier 
27f5736e95SDavid du Colombier 
28f5736e95SDavid du Colombier /*
29f5736e95SDavid du Colombier  * vDestroyFontInfoList - destroy the Font Information List
30f5736e95SDavid du Colombier  */
31f5736e95SDavid du Colombier void
vDestroyFontInfoList(void)32f5736e95SDavid du Colombier vDestroyFontInfoList(void)
33f5736e95SDavid du Colombier {
34*25b329d5SDavid du Colombier 	font_mem_type	*pCurr, *pNext;
35f5736e95SDavid du Colombier 
36f5736e95SDavid du Colombier 	DBG_MSG("vDestroyFontInfoList");
37f5736e95SDavid du Colombier 
38f5736e95SDavid du Colombier 	/* Free the Font Information List */
39f5736e95SDavid du Colombier 	pCurr = pAnchor;
40f5736e95SDavid du Colombier 	while (pCurr != NULL) {
41f5736e95SDavid du Colombier 		pNext = pCurr->pNext;
42f5736e95SDavid du Colombier 		pCurr = xfree(pCurr);
43f5736e95SDavid du Colombier 		pCurr = pNext;
44f5736e95SDavid du Colombier 	}
45f5736e95SDavid du Colombier 	pAnchor = NULL;
46f5736e95SDavid du Colombier 	/* Reset all control variables */
47f5736e95SDavid du Colombier 	pFontLast = NULL;
48f5736e95SDavid du Colombier } /* end of vDestroyFontInfoList */
49f5736e95SDavid du Colombier 
50f5736e95SDavid du Colombier /*
51f5736e95SDavid du Colombier  * vCorrectFontValues - correct font values to values Antiword can use
52f5736e95SDavid du Colombier  */
53f5736e95SDavid du Colombier void
vCorrectFontValues(font_block_type * pFontBlock)54f5736e95SDavid du Colombier vCorrectFontValues(font_block_type *pFontBlock)
55f5736e95SDavid du Colombier {
56f5736e95SDavid du Colombier 	UINT	uiRealSize;
57f5736e95SDavid du Colombier 	USHORT	usRealStyle;
58f5736e95SDavid du Colombier 
59f5736e95SDavid du Colombier 	uiRealSize = pFontBlock->usFontSize;
60f5736e95SDavid du Colombier 	usRealStyle = pFontBlock->usFontStyle;
61f5736e95SDavid du Colombier 	if (bIsSmallCapitals(pFontBlock->usFontStyle)) {
62f5736e95SDavid du Colombier 		/* Small capitals become normal capitals in a smaller font */
63f5736e95SDavid du Colombier 		uiRealSize = (uiRealSize * 4 + 2) / 5;
64f5736e95SDavid du Colombier 		usRealStyle &= ~FONT_SMALL_CAPITALS;
65f5736e95SDavid du Colombier 		usRealStyle |= FONT_CAPITALS;
66f5736e95SDavid du Colombier 	}
67f5736e95SDavid du Colombier 	if (bIsSuperscript(pFontBlock->usFontStyle) ||
68f5736e95SDavid du Colombier 	    bIsSubscript(pFontBlock->usFontStyle)) {
69f5736e95SDavid du Colombier 		/* Superscript and subscript use a smaller fontsize */
70f5736e95SDavid du Colombier 		uiRealSize = (uiRealSize * 2 + 1) / 3;
71f5736e95SDavid du Colombier 	}
72f5736e95SDavid du Colombier 
73f5736e95SDavid du Colombier 	if (uiRealSize < MIN_FONT_SIZE) {
74f5736e95SDavid du Colombier 		DBG_DEC(uiRealSize);
75f5736e95SDavid du Colombier 		uiRealSize = MIN_FONT_SIZE;
76f5736e95SDavid du Colombier 	} else if (uiRealSize > MAX_FONT_SIZE) {
77f5736e95SDavid du Colombier 		DBG_DEC(uiRealSize);
78f5736e95SDavid du Colombier 		uiRealSize = MAX_FONT_SIZE;
79f5736e95SDavid du Colombier 	}
80f5736e95SDavid du Colombier 
81f5736e95SDavid du Colombier 	pFontBlock->usFontSize = (USHORT)uiRealSize;
82f5736e95SDavid du Colombier 	if (pFontBlock->ucFontColor == 8) {
83f5736e95SDavid du Colombier 		/* White text to light gray text */
84f5736e95SDavid du Colombier 		pFontBlock->ucFontColor = 16;
85f5736e95SDavid du Colombier 	}
86f5736e95SDavid du Colombier 	pFontBlock->usFontStyle = usRealStyle;
87f5736e95SDavid du Colombier } /* end of vCorrectFontValues */
88f5736e95SDavid du Colombier 
89f5736e95SDavid du Colombier /*
90f5736e95SDavid du Colombier  * vAdd2FontInfoList - Add an element to the Font Information List
91f5736e95SDavid du Colombier  */
92f5736e95SDavid du Colombier void
vAdd2FontInfoList(const font_block_type * pFontBlock)93f5736e95SDavid du Colombier vAdd2FontInfoList(const font_block_type *pFontBlock)
94f5736e95SDavid du Colombier {
95*25b329d5SDavid du Colombier 	font_mem_type	*pListMember;
96f5736e95SDavid du Colombier 
97f5736e95SDavid du Colombier 	fail(pFontBlock == NULL);
98f5736e95SDavid du Colombier 
99f5736e95SDavid du Colombier 	NO_DBG_MSG("bAdd2FontInfoList");
100f5736e95SDavid du Colombier 
101f5736e95SDavid du Colombier 	if (pFontBlock->ulFileOffset == FC_INVALID) {
102f5736e95SDavid du Colombier 		/*
103f5736e95SDavid du Colombier 		 * This offset is really past the end of the file,
104f5736e95SDavid du Colombier 		 * so don't waste any memory by storing it.
105f5736e95SDavid du Colombier 		 */
106f5736e95SDavid du Colombier 		return;
107f5736e95SDavid du Colombier 	}
108f5736e95SDavid du Colombier 
109f5736e95SDavid du Colombier 	NO_DBG_HEX(pFontBlock->ulFileOffset);
110f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pFontBlock->ucFontNumber != 0,
111f5736e95SDavid du Colombier 					pFontBlock->ucFontNumber);
112f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pFontBlock->usFontSize != DEFAULT_FONT_SIZE,
113f5736e95SDavid du Colombier 					pFontBlock->usFontSize);
114f5736e95SDavid du Colombier 	NO_DBG_DEC_C(pFontBlock->ucFontColor != 0,
115f5736e95SDavid du Colombier 					pFontBlock->ucFontColor);
116f5736e95SDavid du Colombier 	NO_DBG_HEX_C(pFontBlock->usFontStyle != 0x00,
117f5736e95SDavid du Colombier 					pFontBlock->usFontStyle);
118f5736e95SDavid du Colombier 
119f5736e95SDavid du Colombier 	if (pFontLast != NULL &&
120f5736e95SDavid du Colombier 	    pFontLast->tInfo.ulFileOffset == pFontBlock->ulFileOffset) {
121f5736e95SDavid du Colombier 		/*
122f5736e95SDavid du Colombier 		 * If two consecutive fonts share the same
123f5736e95SDavid du Colombier 		 * offset, remember only the last font
124f5736e95SDavid du Colombier 		 */
125f5736e95SDavid du Colombier 		fail(pFontLast->pNext != NULL);
126f5736e95SDavid du Colombier 		pFontLast->tInfo = *pFontBlock;
127f5736e95SDavid du Colombier 		return;
128f5736e95SDavid du Colombier 	}
129f5736e95SDavid du Colombier 
130f5736e95SDavid du Colombier 	/* Create list member */
131*25b329d5SDavid du Colombier 	pListMember = xmalloc(sizeof(font_mem_type));
132f5736e95SDavid du Colombier 	/* Fill the list member */
133f5736e95SDavid du Colombier 	pListMember->tInfo = *pFontBlock;
134f5736e95SDavid du Colombier 	pListMember->pNext = NULL;
135f5736e95SDavid du Colombier 	/* Correct the values where needed */
136f5736e95SDavid du Colombier 	vCorrectFontValues(&pListMember->tInfo);
137f5736e95SDavid du Colombier 	/* Add the new member to the list */
138f5736e95SDavid du Colombier 	if (pAnchor == NULL) {
139f5736e95SDavid du Colombier 		pAnchor = pListMember;
140f5736e95SDavid du Colombier 	} else {
141f5736e95SDavid du Colombier 		fail(pFontLast == NULL);
142f5736e95SDavid du Colombier 		pFontLast->pNext = pListMember;
143f5736e95SDavid du Colombier 	}
144f5736e95SDavid du Colombier 	pFontLast = pListMember;
145f5736e95SDavid du Colombier } /* end of vAdd2FontInfoList */
146f5736e95SDavid du Colombier 
147f5736e95SDavid du Colombier /*
148f5736e95SDavid du Colombier  * Get the record that follows the given recored in the Font Information List
149f5736e95SDavid du Colombier  */
150f5736e95SDavid du Colombier const font_block_type *
pGetNextFontInfoListItem(const font_block_type * pCurr)151f5736e95SDavid du Colombier pGetNextFontInfoListItem(const font_block_type *pCurr)
152f5736e95SDavid du Colombier {
153*25b329d5SDavid du Colombier 	const font_mem_type	*pRecord;
154f5736e95SDavid du Colombier 	size_t	tOffset;
155f5736e95SDavid du Colombier 
156f5736e95SDavid du Colombier 	if (pCurr == NULL) {
157f5736e95SDavid du Colombier 		if (pAnchor == NULL) {
158f5736e95SDavid du Colombier 			/* There are no records */
159f5736e95SDavid du Colombier 			return NULL;
160f5736e95SDavid du Colombier 		}
161f5736e95SDavid du Colombier 		/* The first record is the only one without a predecessor */
162f5736e95SDavid du Colombier 		return &pAnchor->tInfo;
163f5736e95SDavid du Colombier 	}
164*25b329d5SDavid du Colombier 	tOffset = offsetof(font_mem_type, tInfo);
165f5736e95SDavid du Colombier 	/* Many casts to prevent alignment warnings */
166*25b329d5SDavid du Colombier 	pRecord = (font_mem_type *)(void *)((char *)pCurr - tOffset);
167f5736e95SDavid du Colombier 	fail(pCurr != &pRecord->tInfo);
168f5736e95SDavid du Colombier 	if (pRecord->pNext == NULL) {
169f5736e95SDavid du Colombier 		/* The last record has no successor */
170f5736e95SDavid du Colombier 		return NULL;
171f5736e95SDavid du Colombier 	}
172f5736e95SDavid du Colombier 	return &pRecord->pNext->tInfo;
173f5736e95SDavid du Colombier } /* end of pGetNextFontInfoListItem */
174