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