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 ColombiervDestroyFontInfoList(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 ColombiervCorrectFontValues(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 ColombiervAdd2FontInfoList(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 ColombierpGetNextFontInfoListItem(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