home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
anwor032.zip
/
antiword.0.32
/
blocklist.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-11
|
28KB
|
1,048 lines
/*
* blocklist.c
* Copyright (C) 1998-2001 A.J. van Os; Released under GPL
*
* Description:
* Build, read and destroy a list of Word text blocks
*/
#include <stdlib.h>
#include "antiword.h"
/*
* Private structure to hide the way the information
* is stored from the rest of the program
*/
typedef struct list_mem_tag {
text_block_type tInfo;
struct list_mem_tag *pNext;
} list_mem_type;
/* Variables to describe the start of the five block lists */
static list_mem_type *pTextAnchor = NULL;
static list_mem_type *pFootAnchor = NULL;
static list_mem_type *pUnused1Anchor = NULL;
static list_mem_type *pEndAnchor = NULL;
static list_mem_type *pUnused2Anchor = NULL;
/* Variable needed to build the block list */
static list_mem_type *pBlockLast = NULL;
/* Variable needed to read the text block list */
static list_mem_type *pTextBlockCurrent = NULL;
/* Variable needed to read the footnote block list */
static list_mem_type *pFootBlockCurrent = NULL;
/* Variable needed to read the endnote block list */
static list_mem_type *pEndBlockCurrent = NULL;
/* Last block read */
static unsigned char aucBlock[BIG_BLOCK_SIZE];
/*
* vDestroyTextBlockList - destroy the text block list
*/
void
vDestroyTextBlockList(void)
{
list_mem_type *apAnchor[5];
list_mem_type *pCurr, *pNext;
int iIndex;
DBG_MSG("vDestroyTextBlockList");
apAnchor[0] = pTextAnchor;
apAnchor[1] = pFootAnchor;
apAnchor[2] = pUnused1Anchor;
apAnchor[3] = pEndAnchor;
apAnchor[4] = pUnused2Anchor;
for (iIndex = 0; iIndex < 5; iIndex++) {
pCurr = apAnchor[iIndex];
while (pCurr != NULL) {
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
}
/* Show that there are no lists any more */
pTextAnchor = NULL;
pFootAnchor = NULL;
pUnused1Anchor = NULL;
pEndAnchor = NULL;
pUnused2Anchor = NULL;
/* Reset all the controle variables */
pBlockLast = NULL;
pTextBlockCurrent = NULL;
pFootBlockCurrent = NULL;
pEndBlockCurrent = NULL;
} /* end of vDestroyTextBlockList */
/*
* bAdd2TextBlockList - add an element to the text block list
*
* returns: TRUE when successful, otherwise FALSE
*/
BOOL
bAdd2TextBlockList(text_block_type *pTextBlock)
{
list_mem_type *pListMember;
fail(pTextBlock == NULL);
fail(pTextBlock->lFileOffset < 0);
fail(pTextBlock->lTextOffset < 0);
fail(pTextBlock->lLength <= 0);
fail(pTextBlock->bUsesUnicode && odd(pTextBlock->lLength));
NO_DBG_MSG("bAdd2TextBlockList");
NO_DBG_HEX(pTextBlock->lFileOffset);
NO_DBG_HEX(pTextBlock->lTextOffset);
NO_DBG_HEX(pTextBlock->lLength);
NO_DBG_DEC(pTextBlock->bUsesUnicode);
NO_DBG_DEC(pTextBlock->usPropMod);
if (pTextBlock->lFileOffset < 0 ||
pTextBlock->lTextOffset < 0 ||
pTextBlock->lLength <= 0 ||
(pTextBlock->bUsesUnicode && odd(pTextBlock->lLength))) {
werr(0, "Software (textblock) error");
return FALSE;
}
/*
* Check for continuous blocks of the same character size and
* the same properties modifier
*/
if (pBlockLast != NULL &&
pBlockLast->tInfo.lFileOffset +
pBlockLast->tInfo.lLength == pTextBlock->lFileOffset &&
pBlockLast->tInfo.lTextOffset +
pBlockLast->tInfo.lLength == pTextBlock->lTextOffset &&
pBlockLast->tInfo.bUsesUnicode == pTextBlock->bUsesUnicode &&
pBlockLast->tInfo.usPropMod == pTextBlock->usPropMod) {
/* These are continous blocks */
pBlockLast->tInfo.lLength += pTextBlock->lLength;
return TRUE;
}
/* Make a new block */
pListMember = xmalloc(sizeof(list_mem_type));
/* Add the block to the list */
pListMember->tInfo = *pTextBlock;
pListMember->pNext = NULL;
if (pTextAnchor == NULL) {
pTextAnchor = pListMember;
} else {
fail(pBlockLast == NULL);
pBlockLast->pNext = pListMember;
}
pBlockLast = pListMember;
return TRUE;
} /* end of bAdd2TextBlockList */
/*
* vSplitBlockList - split the block list in five parts
*
* Split the blocklist in a Text block list, a Footnote block list, a
* Endnote block list and two Unused lists.
*
* NOTE:
* The various l*Len input parameters are given in characters, but the
* length of the blocks are in bytes.
*/
void
vSplitBlockList(long lTextLen, long lFootnoteLen, long lUnused1Len,
long lEndnoteLen, long lUnused2Len, BOOL bMustExtend)
{
list_mem_type *apAnchors[5];
list_mem_type *pGarbageAnchor, *pCurr, *pNext;
long lCharsToGo, lBytesTooFar;
int iIndex;
#if defined(DEBUG)
long lTotal;
#endif /* DEBUG */
DBG_MSG("vSplitBlockList");
/* Text block list */
pCurr = NULL;
lCharsToGo = lTextLen;
lBytesTooFar = -1;
if (lTextLen > 0) {
DBG_MSG("Text block list");
DBG_DEC(lTextLen);
for (pCurr = pTextAnchor;
pCurr != NULL;
pCurr = pCurr->pNext) {
NO_DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lCharsToGo -= pCurr->tInfo.lLength / 2;
if (lCharsToGo < 0) {
lBytesTooFar = -2 * lCharsToGo;
}
} else {
lCharsToGo -= pCurr->tInfo.lLength;
if (lCharsToGo < 0) {
lBytesTooFar = -lCharsToGo;
}
}
if (lCharsToGo <= 0) {
break;
}
}
}
/* Split the list */
if (lTextLen <= 0) {
/* Empty text blocks list */
pFootAnchor = pTextAnchor;
pTextAnchor = NULL;
} else if (pCurr == NULL) {
/* No footnote blocks */
pFootAnchor = NULL;
} else if (lCharsToGo == 0) {
/* Move the integral number of footnote blocks */
pFootAnchor = pCurr->pNext;
pCurr->pNext = NULL;
} else {
/* Split the part-text block, part-footnote block */
DBG_DEC(lBytesTooFar);
fail(lBytesTooFar <= 0);
pFootAnchor = xmalloc(sizeof(list_mem_type));
DBG_HEX(pCurr->tInfo.lFileOffset);
pFootAnchor->tInfo.lFileOffset =
pCurr->tInfo.lFileOffset +
pCurr->tInfo.lLength -
lBytesTooFar;
DBG_HEX(pFootAnchor->tInfo.lFileOffset);
DBG_HEX(pCurr->tInfo.lTextOffset);
pFootAnchor->tInfo.lTextOffset =
pCurr->tInfo.lTextOffset +
pCurr->tInfo.lLength -
lBytesTooFar;
DBG_HEX(pFootAnchor->tInfo.lTextOffset);
pFootAnchor->tInfo.lLength = lBytesTooFar;
pCurr->tInfo.lLength -= lBytesTooFar;
pFootAnchor->tInfo.bUsesUnicode = pCurr->tInfo.bUsesUnicode;
/* Move the integral number of footnote blocks */
pFootAnchor->pNext = pCurr->pNext;
pCurr->pNext = NULL;
}
/* Footnote block list */
pCurr = NULL;
lCharsToGo = lFootnoteLen;
lBytesTooFar = -1;
if (lFootnoteLen > 0) {
DBG_MSG("Footnote block list");
DBG_DEC(lFootnoteLen);
for (pCurr = pFootAnchor;
pCurr != NULL;
pCurr = pCurr->pNext) {
DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lCharsToGo -= pCurr->tInfo.lLength / 2;
if (lCharsToGo < 0) {
lBytesTooFar = -2 * lCharsToGo;
}
} else {
lCharsToGo -= pCurr->tInfo.lLength;
if (lCharsToGo < 0) {
lBytesTooFar = -lCharsToGo;
}
}
if (lCharsToGo <= 0) {
break;
}
}
}
/* Split the list */
if (lFootnoteLen <= 0) {
/* Empty footnote list */
pUnused1Anchor = pFootAnchor;
pFootAnchor = NULL;
} else if (pCurr == NULL) {
/* No unused1 blocks */
pUnused1Anchor = NULL;
} else if (lCharsToGo == 0) {
/* Move the integral number of unused1-list blocks */
pUnused1Anchor = pCurr->pNext;
pCurr->pNext = NULL;
} else {
/* Split the part-footnote block, part-unused1 block */
DBG_DEC(lBytesTooFar);
fail(lBytesTooFar <= 0);
pUnused1Anchor = xmalloc(sizeof(list_mem_type));
DBG_HEX(pCurr->tInfo.lFileOffset);
pUnused1Anchor->tInfo.lFileOffset =
pCurr->tInfo.lFileOffset +
pCurr->tInfo.lLength -
lBytesTooFar;
DBG_HEX(pUnused1Anchor->tInfo.lFileOffset);
DBG_HEX(pCurr->tInfo.lTextOffset);
pUnused1Anchor->tInfo.lTextOffset =
pCurr->tInfo.lTextOffset +
pCurr->tInfo.lLength -
lBytesTooFar;
DBG_HEX(pUnused1Anchor->tInfo.lTextOffset);
pUnused1Anchor->tInfo.lLength = lBytesTooFar;
pCurr->tInfo.lLength -= lBytesTooFar;
pUnused1Anchor->tInfo.bUsesUnicode =
pCurr->tInfo.bUsesUnicode;
/* Move the integral number of unused1 blocks */
pUnused1Anchor->pNext = pCurr->pNext;
pCurr->pNext = NULL;
}
/* Unused1 block list */
pCurr = NULL;
lCharsToGo = lUnused1Len;
lBytesTooFar = -1;
if (lUnused1Len > 0) {
DBG_MSG("Unused1 block list");
DBG_DEC(lUnused1Len);
for (pCurr = pUnused1Anchor;
pCurr != NULL;
pCurr = pCurr->pNext) {
DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lCharsToGo -= pCurr->tInfo.lLength / 2;
if (lCharsToGo < 0) {
lBytesTooFar = -2 * lCharsToGo;
}
} else {
lCharsToGo -= pCurr->tInfo.lLength;
if (lCharsToGo < 0) {
lBytesTooFar = -lCharsToGo;
}
}
if (lCharsToGo <= 0) {
break;
}
}
}
/* Split the list */
if (lUnused1Len <= 0) {
/* Empty unused1 list */
pEndAnchor = pUnused1Anchor;
pUnused1Anchor = NULL;
} else if (pCurr == NULL) {
/* No endnote blocks */
pEndAnchor = NULL;
} else if (lCharsToGo == 0) {
/* Move the intergral number of endnote blocks */
pEndAnchor = pCurr->pNext;
pCurr->pNext = NULL;
} else {
/* Split the part-unused1-list block, part-endnote block */
DBG_DEC(lBytesTooFar);
fail(lBytesTooFar <= 0);
pEndAnchor = xmalloc(sizeof(list_mem_type));
DBG_HEX(pCurr->tInfo.lFileOffset);
pEndAnchor->tInfo.lFileOffset =
pCurr->tInfo.lFileOffset +
pCurr->tInfo.lLength -
lBytesTooFar;
DBG_HEX(pEndAnchor->tInfo.lFileOffset);
DBG_HEX(pCurr->tInfo.lTextOffset);
pEndAnchor->tInfo.lTextOffset =
pCurr->tInfo.lTextOffset +
pCurr->tInfo.lLength -
lBytesTooFar;
DBG_HEX(pEndAnchor->tInfo.lTextOffset);
pEndAnchor->tInfo.lLength = lBytesTooFar;
pCurr->tInfo.lLength -= lBytesTooFar;
pEndAnchor->tInfo.bUsesUnicode = pCurr->tInfo.bUsesUnicode;
/* Move the integral number of endnote blocks */
pEndAnchor->pNext = pCurr->pNext;
pCurr->pNext = NULL;
}
/* Endnote block list */
pCurr = NULL;
lCharsToGo = lEndnoteLen;
lBytesTooFar = -1;
if (lEndnoteLen > 0) {
DBG_MSG("Endnote block list");
DBG_DEC(lEndnoteLen);
for (pCurr = pEndAnchor;
pCurr != NULL;
pCurr = pCurr->pNext) {
DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lCharsToGo -= pCurr->tInfo.lLength / 2;
if (lCharsToGo <= 0) {
lBytesTooFar = -2 * lCharsToGo;
}
} else {
lCharsToGo -= pCurr->tInfo.lLength;
if (lCharsToGo <= 0) {
lBytesTooFar = -lCharsToGo;
}
}
if (lCharsToGo <= 0) {
break;
}
}
}
/* Split the list */
if (lEndnoteLen <= 0) {
/* Empty endnote list */
pUnused2Anchor = pEndAnchor;
pEndAnchor = NULL;
} else if (pCurr == NULL) {
/* No unused2 blocks */
pUnused2Anchor = NULL;
} else if (lCharsToGo == 0) {
/* Move the intergral number of unused2 blocks */
pUnused2Anchor = pCurr->pNext;
pCurr->pNext = NULL;
} else {
/* Split the part-endnote block, part-unused2 block */
DBG_DEC(lBytesTooFar);
fail(lBytesTooFar <= 0);
pUnused2Anchor = xmalloc(sizeof(list_mem_type));
DBG_HEX(pCurr->tInfo.lFileOffset);
pUnused2Anchor->tInfo.lFileOffset =
pCurr->tInfo.lFileOffset +
pCurr->tInfo.lLength -
lBytesTooFar;
DBG_HEX(pUnused2Anchor->tInfo.lFileOffset);
DBG_HEX(pCurr->tInfo.lTextOffset);
pUnused2Anchor->tInfo.lTextOffset =
pCurr->tInfo.lTextOffset +
pCurr->tInfo.lLength -
lBytesTooFar;
DBG_HEX(pUnused2Anchor->tInfo.lTextOffset);
pUnused2Anchor->tInfo.lLength = lBytesTooFar;
pCurr->tInfo.lLength -= lBytesTooFar;
pUnused2Anchor->tInfo.bUsesUnicode =
pCurr->tInfo.bUsesUnicode;
/* Move the integral number of unused2 blocks */
pUnused2Anchor->pNext = pCurr->pNext;
pCurr->pNext = NULL;
}
/* Unused2 block list */
pCurr = NULL;
lCharsToGo = lUnused2Len;
lBytesTooFar = -1;
if (lUnused2Len > 0) {
DBG_MSG("Unused2 block list");
DBG_DEC(lUnused2Len);
for (pCurr = pUnused2Anchor;
pCurr != NULL;
pCurr = pCurr->pNext) {
DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lCharsToGo -= pCurr->tInfo.lLength / 2;
if (lCharsToGo < 0) {
lBytesTooFar = -2 * lCharsToGo;
}
} else {
lCharsToGo -= pCurr->tInfo.lLength;
if (lCharsToGo < 0) {
lBytesTooFar = -lCharsToGo;
}
}
if (lCharsToGo <= 0) {
break;
}
}
}
/* Split the list */
if (lUnused2Len <= 0) {
/* Empty unused2 list */
pGarbageAnchor = pUnused2Anchor;
pUnused2Anchor = NULL;
} else if (pCurr == NULL) {
/* No garbage block list */
pGarbageAnchor = NULL;
} else if (lCharsToGo == 0) {
/* Move the intergral number of garbage blocks */
pGarbageAnchor = pCurr->pNext;
pCurr->pNext = NULL;
} else {
/* Reduce the part-unused2 block */
DBG_DEC(lBytesTooFar);
fail(lBytesTooFar <= 0);
pCurr->tInfo.lLength -= lBytesTooFar;
/* Move the integral number of garbage blocks */
pGarbageAnchor = pCurr->pNext;
pCurr->pNext = NULL;
}
/* Free the garbage block list, this should never be needed */
pCurr = pGarbageAnchor;
while (pCurr != NULL) {
DBG_FIXME();
DBG_HEX(pCurr->tInfo.lFileOffset);
DBG_DEC(pCurr->tInfo.lLength);
pNext = pCurr->pNext;
pCurr = xfree(pCurr);
pCurr = pNext;
}
#if defined(DEBUG)
/* Check the number of bytes in the block lists */
lTotal = 0;
for (pCurr = pTextAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
NO_DBG_HEX(pCurr->tInfo.lFileOffset);
NO_DBG_HEX(pCurr->tInfo.lTextOffset);
NO_DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lTotal += pCurr->tInfo.lLength / 2;
} else {
lTotal += pCurr->tInfo.lLength;
}
}
DBG_DEC(lTotal);
if (lTotal != lTextLen) {
DBG_DEC(lTextLen);
werr(1, "Software error (Text)");
}
lTotal = 0;
for (pCurr = pFootAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
DBG_HEX(pCurr->tInfo.lFileOffset);
NO_DBG_HEX(pCurr->tInfo.lTextOffset);
DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lTotal += pCurr->tInfo.lLength / 2;
} else {
lTotal += pCurr->tInfo.lLength;
}
}
DBG_DEC(lTotal);
if (lTotal != lFootnoteLen) {
DBG_DEC(lFootnoteLen);
werr(1, "Software error (Footnotes)");
}
lTotal = 0;
for (pCurr = pUnused1Anchor; pCurr != NULL; pCurr = pCurr->pNext) {
DBG_HEX(pCurr->tInfo.lFileOffset);
NO_DBG_HEX(pCurr->tInfo.lTextOffset);
DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lTotal += pCurr->tInfo.lLength / 2;
} else {
lTotal += pCurr->tInfo.lLength;
}
}
DBG_DEC(lTotal);
if (lTotal != lUnused1Len) {
DBG_DEC(lUnused1Len);
werr(1, "Software error (Unused1-list)");
}
lTotal = 0;
for (pCurr = pEndAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
DBG_HEX(pCurr->tInfo.lFileOffset);
NO_DBG_HEX(pCurr->tInfo.lTextOffset);
DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lTotal += pCurr->tInfo.lLength / 2;
} else {
lTotal += pCurr->tInfo.lLength;
}
}
DBG_DEC(lTotal);
if (lTotal != lEndnoteLen) {
DBG_DEC(lEndnoteLen);
werr(1, "Software error (Endnotes)");
}
lTotal = 0;
for (pCurr = pUnused2Anchor; pCurr != NULL; pCurr = pCurr->pNext) {
DBG_HEX(pCurr->tInfo.lFileOffset);
NO_DBG_HEX(pCurr->tInfo.lTextOffset);
DBG_DEC(pCurr->tInfo.lLength);
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lTotal += pCurr->tInfo.lLength / 2;
} else {
lTotal += pCurr->tInfo.lLength;
}
}
DBG_DEC(lTotal);
if (lTotal != lUnused2Len) {
DBG_DEC(lUnused2Len);
werr(1, "Software error (Unused2-list)");
}
#endif /* DEBUG */
if (!bMustExtend) {
return;
}
/*
* All blocks (except the last one) must have a length that
* is a multiple of the Big Block Size
*/
apAnchors[0] = pTextAnchor;
apAnchors[1] = pFootAnchor;
apAnchors[2] = pUnused1Anchor;
apAnchors[3] = pEndAnchor;
apAnchors[4] = pUnused2Anchor;
for (iIndex = 0; iIndex < 5; iIndex++) {
for (pCurr = apAnchors[iIndex];
pCurr != NULL;
pCurr = pCurr->pNext) {
if (pCurr->pNext != NULL &&
pCurr->tInfo.lLength % BIG_BLOCK_SIZE != 0) {
DBG_HEX(pCurr->tInfo.lFileOffset);
DBG_HEX(pCurr->tInfo.lTextOffset);
DBG_DEC(pCurr->tInfo.lLength);
pCurr->tInfo.lLength /= BIG_BLOCK_SIZE;
pCurr->tInfo.lLength++;
pCurr->tInfo.lLength *= BIG_BLOCK_SIZE;
DBG_DEC(pCurr->tInfo.lLength);
}
}
}
} /* end of vSplitBlockList */
#if defined(__riscos)
/*
* lGetDocumentLength - get the combined character length of the three lists
*
* returns: The total number of characters
*/
long
lGetDocumentLength(void)
{
list_mem_type *apAnchors[3];
list_mem_type *pCurr;
long lTotal;
int iIndex;
DBG_MSG("uiGetDocumentLength");
apAnchors[0] = pTextAnchor;
apAnchors[1] = pFootAnchor;
apAnchors[2] = pEndAnchor;
lTotal = 0;
for (iIndex = 0; iIndex < 3; iIndex++) {
for (pCurr = apAnchors[iIndex];
pCurr != NULL;
pCurr = pCurr->pNext) {
fail(pCurr->tInfo.lLength <= 0);
if (pCurr->tInfo.bUsesUnicode) {
fail(odd(pCurr->tInfo.lLength));
lTotal += pCurr->tInfo.lLength / 2;
} else {
lTotal += pCurr->tInfo.lLength;
}
}
}
DBG_DEC(lTotal);
return lTotal;
} /* end of tGetDocumentLength */
#endif /* __riscos */
/*
* usNextTextByte - get the next byte from the text block list
*/
static unsigned short
usNextTextByte(FILE *pFile,
long *plFileOffset, long *plTextOffset, unsigned short *pusPropMod)
{
static long lBlockOffset = 0;
static size_t tByteNext = 0;
long lReadOff;
size_t tReadLen;
if (pTextBlockCurrent == NULL ||
tByteNext >= sizeof(aucBlock) ||
lBlockOffset + (long)tByteNext >= pTextBlockCurrent->tInfo.lLength) {
if (pTextBlockCurrent == NULL) {
/* First block, first part */
pTextBlockCurrent = pTextAnchor;
lBlockOffset = 0;
} else if (lBlockOffset + (long)sizeof(aucBlock) <
pTextBlockCurrent->tInfo.lLength) {
/* Same block, next part */
lBlockOffset += (long)sizeof(aucBlock);
} else {
/* Next block, first part */
pTextBlockCurrent = pTextBlockCurrent->pNext;
lBlockOffset = 0;
}
if (pTextBlockCurrent == NULL) {
/* Past the last part of the last block */
return (unsigned short)EOF;
}
tReadLen = (size_t)
(pTextBlockCurrent->tInfo.lLength - lBlockOffset);
if (tReadLen > sizeof(aucBlock)) {
tReadLen = sizeof(aucBlock);
}
lReadOff = pTextBlockCurrent->tInfo.lFileOffset +
lBlockOffset;
if (!bReadBytes(aucBlock, tReadLen, lReadOff, pFile)) {
return (unsigned short)EOF;
}
tByteNext = 0;
}
if (plFileOffset != NULL) {
*plFileOffset = pTextBlockCurrent->tInfo.lFileOffset +
lBlockOffset + (long)tByteNext;
}
if (plTextOffset != NULL) {
*plTextOffset = pTextBlockCurrent->tInfo.lTextOffset +
lBlockOffset + (long)tByteNext;
}
if (pusPropMod != NULL) {
*pusPropMod = pTextBlockCurrent->tInfo.usPropMod;
}
return aucBlock[tByteNext++];
} /* end of usNextTextByte */
/*
* usNextFootByte - get the next byte from the footnote block list
*/
static unsigned short
usNextFootByte(FILE *pFile,
long *plFileOffset, long *plTextOffset, unsigned short *pusPropMod)
{
static long lBlockOffset = 0;
static size_t tByteNext = 0;
long lReadOff;
size_t tReadLen;
if (pFootBlockCurrent == NULL ||
tByteNext >= sizeof(aucBlock) ||
lBlockOffset + (long)tByteNext >= pFootBlockCurrent->tInfo.lLength) {
if (pFootBlockCurrent == NULL) {
/* First block, first part */
pFootBlockCurrent = pFootAnchor;
lBlockOffset = 0;
} else if (lBlockOffset + (long)sizeof(aucBlock) <
pFootBlockCurrent->tInfo.lLength) {
/* Same block, next part */
lBlockOffset += (long)sizeof(aucBlock);
} else {
/* Next block, first part */
pFootBlockCurrent = pFootBlockCurrent->pNext;
lBlockOffset = 0;
}
if (pFootBlockCurrent == NULL) {
/* Past the last part of the last block */
return (unsigned short)EOF;
}
tReadLen = (size_t)
(pFootBlockCurrent->tInfo.lLength - lBlockOffset);
if (tReadLen > sizeof(aucBlock)) {
tReadLen = sizeof(aucBlock);
}
lReadOff = pFootBlockCurrent->tInfo.lFileOffset +
lBlockOffset;
if (!bReadBytes(aucBlock, tReadLen, lReadOff, pFile)) {
return (unsigned short)EOF;
}
tByteNext = 0;
}
if (plFileOffset != NULL) {
*plFileOffset = pFootBlockCurrent->tInfo.lFileOffset +
lBlockOffset + (long)tByteNext;
}
if (plTextOffset != NULL) {
*plTextOffset = pFootBlockCurrent->tInfo.lTextOffset +
lBlockOffset + (long)tByteNext;
}
if (pusPropMod != NULL) {
*pusPropMod = pFootBlockCurrent->tInfo.usPropMod;
}
return aucBlock[tByteNext++];
} /* end of usNextFootByte */
/*
* usNextEndByte - get the next byte from the endnote block list
*/
static unsigned short
usNextEndByte(FILE *pFile,
long *plFileOffset, long *plTextOffset, unsigned short *pusPropMod)
{
static long lBlockOffset = 0;
static size_t tByteNext = 0;
long lReadOff;
size_t tReadLen;
if (pEndBlockCurrent == NULL ||
tByteNext >= sizeof(aucBlock) ||
lBlockOffset + (long)tByteNext >= pEndBlockCurrent->tInfo.lLength) {
if (pEndBlockCurrent == NULL) {
/* First block, first part */
pEndBlockCurrent = pEndAnchor;
lBlockOffset = 0;
} else if (lBlockOffset + (long)sizeof(aucBlock) <
pEndBlockCurrent->tInfo.lLength) {
/* Same block, next part */
lBlockOffset += sizeof(aucBlock);
} else {
/* Next block, first part */
pEndBlockCurrent = pEndBlockCurrent->pNext;
lBlockOffset = 0;
}
if (pEndBlockCurrent == NULL) {
/* Past the last part of the last block */
return (unsigned short)EOF;
}
tReadLen = (size_t)
(pEndBlockCurrent->tInfo.lLength - lBlockOffset);
if (tReadLen > sizeof(aucBlock)) {
tReadLen = sizeof(aucBlock);
}
lReadOff = pEndBlockCurrent->tInfo.lFileOffset +
lBlockOffset;
if (!bReadBytes(aucBlock, tReadLen, lReadOff, pFile)) {
return (unsigned short)EOF;
}
tByteNext = 0;
}
if (plFileOffset != NULL) {
*plFileOffset = pEndBlockCurrent->tInfo.lFileOffset +
lBlockOffset + (long)tByteNext;
}
if (plTextOffset != NULL) {
*plTextOffset = pEndBlockCurrent->tInfo.lTextOffset +
lBlockOffset + (long)tByteNext;
}
if (pusPropMod != NULL) {
*pusPropMod = pEndBlockCurrent->tInfo.usPropMod;
}
return aucBlock[tByteNext++];
} /* end of usNextEndByte */
/*
* usNextTextChar - get the next character from the text block list
*/
static unsigned short
usNextTextChar(FILE *pFile,
long *plFileOffset, long *plTextOffset, unsigned short *pusPropMod)
{
unsigned short usLSB, usMSB;
usLSB = usNextTextByte(pFile, plFileOffset, plTextOffset, pusPropMod);
if (usLSB == (unsigned short)EOF) {
return (unsigned short)EOF;
}
if (pTextBlockCurrent->tInfo.bUsesUnicode) {
usMSB = usNextTextByte(pFile, NULL, NULL, NULL);
} else {
usMSB = 0x00;
}
if (usMSB == (unsigned short)EOF) {
DBG_MSG("usNextTextChar: Unexpected EOF");
DBG_HEX_C(plFileOffset != NULL, *plFileOffset);
DBG_HEX_C(plTextOffset != NULL, *plTextOffset);
return (unsigned short)EOF;
}
return (usMSB << 8) | usLSB;
} /* end of usNextTextChar */
/*
* usNextFootChar - get the next character from the footnote block list
*/
static unsigned short
usNextFootChar(FILE *pFile,
long *plFileOffset, long *plTextOffset, unsigned short *pusPropMod)
{
unsigned short usLSB, usMSB;
usLSB = usNextFootByte(pFile, plFileOffset, plTextOffset, pusPropMod);
if (usLSB == (unsigned short)EOF) {
return (unsigned short)EOF;
}
if (pFootBlockCurrent->tInfo.bUsesUnicode) {
usMSB = usNextFootByte(pFile, NULL, NULL, NULL);
} else {
usMSB = 0x00;
}
if (usMSB == (unsigned short)EOF) {
DBG_MSG("usNextFootChar: Unexpected EOF");
DBG_HEX_C(plFileOffset != NULL, *plFileOffset);
DBG_HEX_C(plTextOffset != NULL, *plTextOffset);
return (unsigned short)EOF;
}
return (usMSB << 8) | usLSB;
} /* end of usNextFootChar */
/*
* usNextEndChar - get the next character from the endnote block list
*/
static unsigned short
usNextEndChar(FILE *pFile,
long *plFileOffset, long *plTextOffset, unsigned short *pusPropMod)
{
unsigned short usLSB, usMSB;
usLSB = usNextEndByte(pFile, plFileOffset, plTextOffset, pusPropMod);
if (usLSB == (unsigned short)EOF) {
return (unsigned short)EOF;
}
if (pEndBlockCurrent->tInfo.bUsesUnicode) {
usMSB = usNextEndByte(pFile, NULL, NULL, NULL);
} else {
usMSB = 0x00;
}
if (usMSB == (unsigned short)EOF) {
DBG_MSG("usNextEndChar: Unexpected EOF");
DBG_HEX_C(plFileOffset != NULL, *plFileOffset);
DBG_HEX_C(plTextOffset != NULL, *plTextOffset);
return (unsigned short)EOF;
}
return (usMSB << 8) | usLSB;
} /* end of usNextEndChar */
/*
* usNextChar - get the next character from the given block list
*/
unsigned short
usNextChar(FILE *pFile, list_id_enum eListID,
long *plFileOffset, long *plTextOffset, unsigned short *pusPropMod)
{
fail(pFile == NULL);
switch (eListID) {
case text_list:
return usNextTextChar(pFile,
plFileOffset, plTextOffset, pusPropMod);
case footnote_list:
return usNextFootChar(pFile,
plFileOffset, plTextOffset, pusPropMod);
case endnote_list:
return usNextEndChar(pFile,
plFileOffset, plTextOffset, pusPropMod);
default:
if (plFileOffset != NULL) {
*plFileOffset = -1;
}
if (plTextOffset != NULL) {
*plTextOffset = -1;
}
if (pusPropMod != NULL) {
*pusPropMod = IGNORE_PROPMOD;
}
return (unsigned short)EOF;
}
} /* end of usNextChar */
#if 0
/*
* Translate the start from the begin of the text to the block that contains
* this offset.
* Logical offset to block pointer.
*
* Returns: block pointer or NULL
*/
static text_block_type *
pTextOffset2Block(long lTextOffset)
{
list_mem_type *apAnchors[3];
list_mem_type *pCurr;
int iIndex;
apAnchors[0] = pTextAnchor;
apAnchors[1] = pFootAnchor;
apAnchors[2] = pEndAnchor;
for (iIndex = 0; iIndex < 3; iIndex++) {
for (pCurr = apAnchors[iIndex];
pCurr != NULL;
pCurr = pCurr->pNext) {
if (lTextOffset >= pCurr->tInfo.lTextOffset &&
lTextOffset < pCurr->tInfo.lTextOffset +
pCurr->tInfo.lLength) {
/* The textoffset is in the current block */
return &pCurr->tInfo;
}
}
}
/* Passed beyond the end of the last list */
return NULL;
} /* end of pTextOffset2Block */
#endif
/*
* Translate the start from the begin of the text to an offset in the file.
* Logical to physical offset.
*
* Returns: -1: in case of error
* >=0: the computed file offset
*/
long
lTextOffset2FileOffset(long lTextOffset)
{
list_mem_type *apAnchors[3];
list_mem_type *pCurr;
long lBestGuess;
int iIndex;
apAnchors[0] = pTextAnchor;
apAnchors[1] = pFootAnchor;
apAnchors[2] = pEndAnchor;
lBestGuess = -1; /* Best guess is "fileoffset not found" */
for (iIndex = 0; iIndex < 3; iIndex++) {
for (pCurr = apAnchors[iIndex];
pCurr != NULL;
pCurr = pCurr->pNext) {
if (lTextOffset == pCurr->tInfo.lTextOffset +
pCurr->tInfo.lLength &&
pCurr->pNext != NULL) {
/*
* The textoffset is one beyond this block,
* so we guess it's the first byte of the next
* block (if there is a next block)
*/
lBestGuess = pCurr->pNext->tInfo.lFileOffset;
}
if (lTextOffset < pCurr->tInfo.lTextOffset ||
lTextOffset >= pCurr->tInfo.lTextOffset +
pCurr->tInfo.lLength) {
/* The textoffset is not in this block */
continue;
}
/* The textoffset is in the current block */
return pCurr->tInfo.lFileOffset +
lTextOffset - pCurr->tInfo.lTextOffset;
}
}
/* Passed beyond the end of the last list */
NO_DBG_HEX(lTextOffset);
NO_DBG_HEX(lBestGuess);
return lBestGuess;
} /* end of lTextOffset2FileOffset */
#if 0
/*
* Get the properties modifier for the given logical offset
*
* Returns: the properties modifier or IGNORE_PROPMOD
*/
unsigned short
pTextOffset2PropMod(long lTextOffset)
{
text_block_type *pTextBlock;
pTextBlock = pTextOffset2Block(lTextOffset);
if (pTextBlock == NULL) {
return IGNORE_PROPMOD;
}
return pTextBlock->usPropMod;
} /* end of pTextOffset2PropMod */
#endif