/*
* out2window.c
* Copyright (C) 1998-2005 A.J. van Os; Released under GPL
*
* Description:
* Output to a text window
*/
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "antiword.h"
/* Used for numbering the chapters */
static unsigned int auiHdrCounter[9];
/*
* vString2Diagram - put a string into a diagram
*/
static void
vString2Diagram(diagram_type *pDiag, output_type *pAnchor)
{
output_type *pOutput;
long lWidth;
USHORT usMaxFontSize;
TRACE_MSG("vString2Diagram");
fail(pDiag == NULL);
fail(pAnchor == NULL);
/* Compute the maximum fontsize in this string */
usMaxFontSize = MIN_FONT_SIZE;
for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
if (pOutput->usFontSize > usMaxFontSize) {
usMaxFontSize = pOutput->usFontSize;
}
}
/* Goto the next line */
vMove2NextLine(pDiag, pAnchor->tFontRef, usMaxFontSize);
/* Output all substrings */
for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
lWidth = lMilliPoints2DrawUnits(pOutput->lStringWidth);
vSubstring2Diagram(pDiag, pOutput->szStorage,
pOutput->tNextFree, lWidth, pOutput->ucFontColor,
pOutput->usFontStyle, pOutput->tFontRef,
pOutput->usFontSize, usMaxFontSize);
}
/* Goto the start of the line */
pDiag->lXleft = 0;
TRACE_MSG("leaving vString2Diagram");
} /* end of vString2Diagram */
/*
* vSetLeftIndentation - set the left indentation of the specified diagram
*/
void
vSetLeftIndentation(diagram_type *pDiag, long lLeftIndentation)
{
long lX;
TRACE_MSG("vSetLeftIndentation");
fail(pDiag == NULL);
fail(lLeftIndentation < 0);
lX = lMilliPoints2DrawUnits(lLeftIndentation);
if (lX > 0) {
pDiag->lXleft = lX;
} else {
pDiag->lXleft = 0;
}
} /* end of vSetLeftIndentation */
/*
* lComputeNetWidth - compute the net string width
*/
static long
lComputeNetWidth(output_type *pAnchor)
{
output_type *pTmp;
long lNetWidth;
TRACE_MSG("lComputeNetWidth");
fail(pAnchor == NULL);
/* Step 1: Count all but the last sub-string */
lNetWidth = 0;
for (pTmp = pAnchor; pTmp->pNext != NULL; pTmp = pTmp->pNext) {
fail(pTmp->lStringWidth < 0);
lNetWidth += pTmp->lStringWidth;
}
fail(pTmp == NULL);
fail(pTmp->pNext != NULL);
/* Step 2: remove the white-space from the end of the string */
while (pTmp->tNextFree != 0 &&
isspace((int)(UCHAR)pTmp->szStorage[pTmp->tNextFree - 1])) {
pTmp->szStorage[pTmp->tNextFree - 1] = '\0';
pTmp->tNextFree--;
NO_DBG_DEC(pTmp->lStringWidth);
pTmp->lStringWidth = lComputeStringWidth(
pTmp->szStorage,
pTmp->tNextFree,
pTmp->tFontRef,
pTmp->usFontSize);
NO_DBG_DEC(pTmp->lStringWidth);
}
/* Step 3: Count the last sub-string */
lNetWidth += pTmp->lStringWidth;
return lNetWidth;
} /* end of lComputeNetWidth */
/*
* iComputeHoles - compute number of holes
* (A hole is a number of whitespace characters followed by a
* non-whitespace character)
*/
static int
iComputeHoles(output_type *pAnchor)
{
output_type *pTmp;
size_t tIndex;
int iCounter;
BOOL bWasSpace, bIsSpace;
TRACE_MSG("iComputeHoles");
fail(pAnchor == NULL);
iCounter = 0;
bIsSpace = FALSE;
/* Count the holes */
for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
fail(pTmp->tNextFree != strlen(pTmp->szStorage));
for (tIndex = 0; tIndex <= pTmp->tNextFree; tIndex++) {
bWasSpace = bIsSpace;
bIsSpace = isspace((int)(UCHAR)pTmp->szStorage[tIndex]);
if (bWasSpace && !bIsSpace) {
iCounter++;
}
}
}
return iCounter;
} /* end of iComputeHoles */
/*
* vAlign2Window - Align a string and insert it into the text
*/
void
vAlign2Window(diagram_type *pDiag, output_type *pAnchor,
long lScreenWidth, UCHAR ucAlignment)
{
long lNetWidth, lLeftIndentation;
TRACE_MSG("vAlign2Window");
fail(pDiag == NULL || pAnchor == NULL);
fail(lScreenWidth < lChar2MilliPoints(MIN_SCREEN_WIDTH));
lNetWidth = lComputeNetWidth(pAnchor);
if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
lNetWidth <= 0) {
/*
* Screenwidth is "infinite", so no alignment is possible
* Don't bother to align an empty line
*/
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vAlign2Window #1");
return;
}
switch (ucAlignment) {
case ALIGNMENT_CENTER:
lLeftIndentation = (lScreenWidth - lNetWidth) / 2;
DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
if (lLeftIndentation > 0) {
vSetLeftIndentation(pDiag, lLeftIndentation);
}
break;
case ALIGNMENT_RIGHT:
lLeftIndentation = lScreenWidth - lNetWidth;
DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
if (lLeftIndentation > 0) {
vSetLeftIndentation(pDiag, lLeftIndentation);
}
break;
case ALIGNMENT_JUSTIFY:
case ALIGNMENT_LEFT:
default:
break;
}
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vAlign2Window #2");
} /* end of vAlign2Window */
/*
* vJustify2Window - Justify a string and insert it into the text
*/
void
vJustify2Window(diagram_type *pDiag, output_type *pAnchor,
long lScreenWidth, long lRightIndentation, UCHAR ucAlignment)
{
output_type *pTmp;
char *pcNew, *pcOld, *szStorage;
long lNetWidth, lSpaceWidth, lToAdd;
int iFillerLen, iHoles;
TRACE_MSG("vJustify2Window");
fail(pDiag == NULL || pAnchor == NULL);
fail(lScreenWidth < MIN_SCREEN_WIDTH);
fail(lRightIndentation > 0);
if (ucAlignment != ALIGNMENT_JUSTIFY) {
vAlign2Window(pDiag, pAnchor, lScreenWidth, ucAlignment);
return;
}
lNetWidth = lComputeNetWidth(pAnchor);
if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
lNetWidth <= 0) {
/*
* Screenwidth is "infinite", so justify is not possible
* Don't bother to justify an empty line
*/
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vJustify2Window #1");
return;
}
/* Justify */
fail(ucAlignment != ALIGNMENT_JUSTIFY);
lSpaceWidth = lComputeStringWidth(" ", 1,
pAnchor->tFontRef, pAnchor->usFontSize);
lToAdd = lScreenWidth -
lNetWidth -
lDrawUnits2MilliPoints(pDiag->lXleft) +
lRightIndentation;
#if defined(DEBUG)
if (lToAdd / lSpaceWidth < -1) {
DBG_DEC(lSpaceWidth);
DBG_DEC(lToAdd);
DBG_DEC(lScreenWidth);
DBG_DEC(lNetWidth);
DBG_DEC(lDrawUnits2MilliPoints(pDiag->lXleft));
DBG_DEC(pDiag->lXleft);
DBG_DEC(lRightIndentation);
}
#endif /* DEBUG */
lToAdd /= lSpaceWidth;
DBG_DEC_C(lToAdd < 0, lToAdd);
if (lToAdd <= 0) {
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vJustify2Window #2");
return;
}
/* Justify by adding spaces */
iHoles = iComputeHoles(pAnchor);
for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
fail(pTmp->tNextFree != strlen(pTmp->szStorage));
fail(lToAdd < 0);
szStorage = xmalloc(pTmp->tNextFree + (size_t)lToAdd + 1);
pcNew = szStorage;
for (pcOld = pTmp->szStorage; *pcOld != '\0'; pcOld++) {
*pcNew++ = *pcOld;
if (*pcOld == ' ' &&
*(pcOld + 1) != ' ' &&
iHoles > 0) {
iFillerLen = (int)(lToAdd / iHoles);
lToAdd -= iFillerLen;
iHoles--;
for (; iFillerLen > 0; iFillerLen--) {
*pcNew++ = ' ';
}
}
}
*pcNew = '\0';
pTmp->szStorage = xfree(pTmp->szStorage);
pTmp->szStorage = szStorage;
pTmp->tStorageSize = pTmp->tNextFree + (size_t)lToAdd + 1;
pTmp->lStringWidth +=
(pcNew - szStorage - (long)pTmp->tNextFree) *
lSpaceWidth;
fail(pcNew < szStorage);
pTmp->tNextFree = (size_t)(pcNew - szStorage);
fail(pTmp->tNextFree != strlen(pTmp->szStorage));
}
DBG_DEC_C(lToAdd != 0, lToAdd);
vString2Diagram(pDiag, pAnchor);
TRACE_MSG("leaving vJustify2Window #3");
} /* end of vJustify2Window */
/*
* vResetStyles - reset the style information variables
*/
void
vResetStyles(void)
{
TRACE_MSG("vResetStyles");
(void)memset(auiHdrCounter, 0, sizeof(auiHdrCounter));
} /* end of vResetStyles */
/*
* tStyle2Window - Add the style characters to the line
*
* Returns the length of the resulting string
*/
size_t
tStyle2Window(char *szLine, size_t tLineSize, const style_block_type *pStyle,
const section_block_type *pSection)
{
char *pcTxt;
size_t tIndex, tStyleIndex;
BOOL bNeedPrevLvl;
level_type_enum eNumType;
UCHAR ucNFC;
TRACE_MSG("tStyle2Window");
fail(szLine == NULL || pStyle == NULL || pSection == NULL);
if (pStyle->usIstd == 0 || pStyle->usIstd > 9) {
szLine[0] = '\0';
return 0;
}
/* Set the numbers */
tStyleIndex = (size_t)pStyle->usIstd - 1;
for (tIndex = 0; tIndex < 9; tIndex++) {
if (tIndex == tStyleIndex) {
auiHdrCounter[tIndex]++;
} else if (tIndex > tStyleIndex) {
auiHdrCounter[tIndex] = 0;
} else if (auiHdrCounter[tIndex] == 0) {
auiHdrCounter[tIndex] = 1;
}
}
eNumType = eGetNumType(pStyle->ucNumLevel);
if (eNumType != level_type_outline) {
szLine[0] = '\0';
return 0;
}
/* Print the numbers */
pcTxt = szLine;
bNeedPrevLvl = (pSection->usNeedPrevLvl & BIT(tStyleIndex)) != 0;
for (tIndex = 0; tIndex <= tStyleIndex; tIndex++) {
if (tIndex == tStyleIndex ||
(bNeedPrevLvl && tIndex < tStyleIndex)) {
if (pcTxt - szLine >= tLineSize - 25) {
/* Prevent a possible buffer overflow */
DBG_DEC(pcTxt - szLine);
DBG_DEC(tLineSize - 25);
DBG_FIXME();
szLine[0] = '\0';
return 0;
}
ucNFC = pSection->aucNFC[tIndex];
switch(ucNFC) {
case LIST_ARABIC_NUM:
case LIST_NUMBER_TXT:
case LIST_ORDINAL_TXT:
pcTxt += sprintf(pcTxt, "%u",
auiHdrCounter[tIndex]);
break;
case LIST_UPPER_ROMAN:
case LIST_LOWER_ROMAN:
pcTxt += tNumber2Roman(
auiHdrCounter[tIndex],
ucNFC == LIST_UPPER_ROMAN,
pcTxt);
break;
case LIST_UPPER_ALPHA:
case LIST_LOWER_ALPHA:
pcTxt += tNumber2Alpha(
auiHdrCounter[tIndex],
ucNFC == LIST_UPPER_ALPHA,
pcTxt);
break;
case LIST_OUTLINE_NUM:
pcTxt += sprintf(pcTxt, "%02u",
auiHdrCounter[tIndex]);
break;
default:
DBG_DEC(ucNFC);
DBG_FIXME();
pcTxt += sprintf(pcTxt, "%u",
auiHdrCounter[tIndex]);
break;
}
if (tIndex < tStyleIndex) {
*pcTxt++ = '.';
} else if (tIndex == tStyleIndex) {
*pcTxt++ = ' ';
}
}
}
*pcTxt = '\0';
NO_DBG_MSG_C((int)pStyle->usIstd >= 1 &&
(int)pStyle->usIstd <= 9 &&
eNumType != level_type_none &&
eNumType != level_type_outline, szLine);
NO_DBG_MSG_C(szLine[0] != '\0', szLine);
fail(pcTxt < szLine);
return (size_t)(pcTxt - szLine);
} /* end of tStyle2Window */
/*
* vRemoveRowEnd - remove the end of table row indicator
*
* Remove the double TABLE_SEPARATOR characters from the end of the string.
* Special: remove the TABLE_SEPARATOR, 0x0a sequence
*/
static void
vRemoveRowEnd(char *szRowTxt)
{
int iLastIndex;
TRACE_MSG("vRemoveRowEnd");
fail(szRowTxt == NULL || szRowTxt[0] == '\0');
iLastIndex = (int)strlen(szRowTxt) - 1;
if (szRowTxt[iLastIndex] == TABLE_SEPARATOR ||
szRowTxt[iLastIndex] == (char)0x0a) {
szRowTxt[iLastIndex] = '\0';
iLastIndex--;
} else {
DBG_HEX(szRowTxt[iLastIndex]);
}
if (iLastIndex >= 0 && szRowTxt[iLastIndex] == (char)0x0a) {
szRowTxt[iLastIndex] = '\0';
iLastIndex--;
}
if (iLastIndex >= 0 && szRowTxt[iLastIndex] == TABLE_SEPARATOR) {
szRowTxt[iLastIndex] = '\0';
return;
}
DBG_DEC(iLastIndex);
DBG_HEX(szRowTxt[iLastIndex]);
DBG_MSG(szRowTxt);
} /* end of vRemoveRowEnd */
/*
* tComputeStringLengthMax - max string length in relation to max column width
*
* Return the maximum string length
*/
static size_t
tComputeStringLengthMax(const char *szString, size_t tColumnWidthMax)
{
const char *pcTmp;
size_t tLengthMax, tLenPrev, tLen, tWidth;
TRACE_MSG("tComputeStringLengthMax");
fail(szString == NULL);
fail(tColumnWidthMax == 0);
pcTmp = strchr(szString, '\n');
if (pcTmp != NULL) {
tLengthMax = (size_t)(pcTmp - szString + 1);
} else {
tLengthMax = strlen(szString);
}
if (tLengthMax == 0) {
return 0;
}
tLen = 0;
tWidth = 0;
for (;;) {
tLenPrev = tLen;
tLen += tGetCharacterLength(szString + tLen);
DBG_DEC_C(tLen > tLengthMax, tLen);
DBG_DEC_C(tLen > tLengthMax, tLengthMax);
fail(tLen > tLengthMax);
tWidth = tCountColumns(szString, tLen);
if (tWidth > tColumnWidthMax) {
return tLenPrev;
}
if (tLen >= tLengthMax) {
return tLengthMax;
}
}
} /* end of tComputeStringLengthMax */
/*
* tGetBreakingPoint - get the number of bytes that fit the column
*
* Returns the number of bytes that fit the column
*/
static size_t
tGetBreakingPoint(const char *szString,
size_t tLen, size_t tWidth, size_t tColumnWidthMax)
{
int iIndex;
TRACE_MSG("tGetBreakingPoint");
fail(szString == NULL);
fail(tLen > strlen(szString));
fail(tWidth > tColumnWidthMax);
if (tWidth < tColumnWidthMax ||
(tWidth == tColumnWidthMax &&
(szString[tLen] == ' ' ||
szString[tLen] == '\n' ||
szString[tLen] == '\0'))) {
/* The string already fits, do nothing */
return tLen;
}
/* Search for a breaking point */
for (iIndex = (int)tLen - 1; iIndex >= 0; iIndex--) {
if (szString[iIndex] == ' ') {
return (size_t)iIndex;
}
}
/* No breaking point found, just fill the column */
return tLen;
} /* end of tGetBreakingPoint */
/*
* tComputeColumnWidthMax - compute the maximum column width
*/
static size_t
tComputeColumnWidthMax(short sWidth, long lCharWidth, double dFactor)
{
size_t tColumnWidthMax;
TRACE_MSG("tComputeColumnWidthMax");
fail(sWidth < 0);
fail(lCharWidth <= 0);
fail(dFactor <= 0.0);
tColumnWidthMax = (size_t)(
(lTwips2MilliPoints(sWidth) * dFactor + lCharWidth / 2.0) /
lCharWidth);
if (tColumnWidthMax == 0) {
/* Minimum column width */
return 1;
}
if (tColumnWidthMax > 1) {
/* Make room for the TABLE_SEPARATOR_CHAR */
tColumnWidthMax--;
}
NO_DBG_DEC(tColumnWidthMax);
return tColumnWidthMax;
} /* end of tComputeColumnWidthMax */
/*
* vTableRow2Window - put a table row into a diagram
*/
void
vTableRow2Window(diagram_type *pDiag, output_type *pOutput,
const row_block_type *pRowInfo,
conversion_type eConversionType, int iParagraphBreak)
{
output_type tRow;
char *aszColTxt[TABLE_COLUMN_MAX];
char *szLine, *pcTxt;
double dMagnify;
long lCharWidthLarge, lCharWidthSmall;
size_t tColumnWidthTotal, atColumnWidthMax[TABLE_COLUMN_MAX];
size_t tSize, tColumnWidthMax, tWidth, tLen;
int iIndex, iNbrOfColumns, iTmp;
BOOL bNotReady;
TRACE_MSG("vTableRow2Window");
fail(pDiag == NULL || pOutput == NULL || pRowInfo == NULL);
fail(pOutput->szStorage == NULL);
fail(pOutput->pNext != NULL);
fail(iParagraphBreak < 0);
/* Character sizes */
lCharWidthLarge = lComputeStringWidth("W", 1,
pOutput->tFontRef, pOutput->usFontSize);
NO_DBG_DEC(lCharWidthLarge);
lCharWidthSmall = lComputeStringWidth("i", 1,
pOutput->tFontRef, pOutput->usFontSize);
NO_DBG_DEC(lCharWidthSmall);
/* For the time being: use a fixed width font */
fail(lCharWidthLarge != lCharWidthSmall);
vRemoveRowEnd(pOutput->szStorage);
/* Split the row text into a set of column texts */
aszColTxt[0] = pOutput->szStorage;
for (iNbrOfColumns = 1;
iNbrOfColumns < TABLE_COLUMN_MAX;
iNbrOfColumns++) {
aszColTxt[iNbrOfColumns] =
strchr(aszColTxt[iNbrOfColumns - 1],
TABLE_SEPARATOR);
if (aszColTxt[iNbrOfColumns] == NULL) {
break;
}
*aszColTxt[iNbrOfColumns] = '\0';
aszColTxt[iNbrOfColumns]++;
NO_DBG_DEC(iNbrOfColumns);
NO_DBG_MSG(aszColTxt[iNbrOfColumns]);
}
/* Work around a bug in Word */
while (iNbrOfColumns > (int)pRowInfo->ucNumberOfColumns &&
pRowInfo->asColumnWidth[iNbrOfColumns] == 0) {
iNbrOfColumns--;
}
DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
iNbrOfColumns);
DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
pRowInfo->ucNumberOfColumns);
if (iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns) {
werr(0, "Skipping an unmatched table row");
return;
}
#if defined(__FULL_TEXT_SEARCH)
/* No table formatting: use for full-text search (untested) */
for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
fprintf(pDiag->pOutFile, "%s\n" , aszColTxt[iIndex]);
}
#else
if (bAddTableRow(pDiag, aszColTxt, iNbrOfColumns,
pRowInfo->asColumnWidth, pRowInfo->ucBorderInfo)) {
/* All work has been done */
return;
}
/* Fill the table with maximum column widths */
if (eConversionType == conversion_text ||
eConversionType == conversion_fmt_text) {
if (iParagraphBreak == 0 ||
iParagraphBreak >= MAX_SCREEN_WIDTH) {
dMagnify = (double)MAX_SCREEN_WIDTH;
} else if (iParagraphBreak <= MIN_SCREEN_WIDTH) {
dMagnify = (double)MIN_SCREEN_WIDTH;
} else {
dMagnify = (double)iParagraphBreak;
}
dMagnify /= (double)DEFAULT_SCREEN_WIDTH;
DBG_FLT_C(dMagnify < 0.99 || dMagnify > 1.01, dMagnify);
} else {
dMagnify = 1.0;
}
tColumnWidthTotal = 0;
for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
atColumnWidthMax[iIndex] = tComputeColumnWidthMax(
pRowInfo->asColumnWidth[iIndex],
lCharWidthLarge,
dMagnify);
tColumnWidthTotal += atColumnWidthMax[iIndex];
}
/*
* Get enough space for the row.
* Worst case: three bytes per UTF-8 character
*/
tSize = 3 * (1 + tColumnWidthTotal + (size_t)iNbrOfColumns + 3);
szLine = xmalloc(tSize);
do {
/* Print one line of a table row */
bNotReady = FALSE;
pcTxt = szLine;
*pcTxt++ = TABLE_SEPARATOR_CHAR;
for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
tColumnWidthMax = atColumnWidthMax[iIndex];
if (aszColTxt[iIndex] == NULL) {
/* Add an empty column */
for (iTmp = 0;
iTmp < (int)tColumnWidthMax;
iTmp++) {
*pcTxt++ = (char)FILLER_CHAR;
}
*pcTxt++ = TABLE_SEPARATOR_CHAR;
*pcTxt = '\0';
continue;
}
/* Compute the length and width of the column text */
tLen = tComputeStringLengthMax(
aszColTxt[iIndex], tColumnWidthMax);
NO_DBG_DEC(tLen);
while (tLen != 0 &&
(aszColTxt[iIndex][tLen - 1] == '\n' ||
aszColTxt[iIndex][tLen - 1] == ' ')) {
aszColTxt[iIndex][tLen - 1] = ' ';
tLen--;
}
tWidth = tCountColumns(aszColTxt[iIndex], tLen);
fail(tWidth > tColumnWidthMax);
tLen = tGetBreakingPoint(aszColTxt[iIndex],
tLen, tWidth, tColumnWidthMax);
tWidth = tCountColumns(aszColTxt[iIndex], tLen);
if (tLen == 0 && *aszColTxt[iIndex] == '\0') {
/* No text at all */
aszColTxt[iIndex] = NULL;
} else {
/* Add the text */
pcTxt += sprintf(pcTxt,
"%.*s", (int)tLen, aszColTxt[iIndex]);
if (tLen == 0 && *aszColTxt[iIndex] != ' ') {
tLen = tGetCharacterLength(
aszColTxt[iIndex]);
DBG_CHR(*aszColTxt[iIndex]);
DBG_FIXME();
fail(tLen == 0);
}
aszColTxt[iIndex] += tLen;
while (*aszColTxt[iIndex] == ' ') {
aszColTxt[iIndex]++;
}
if (*aszColTxt[iIndex] == '\0') {
/* This row is now complete */
aszColTxt[iIndex] = NULL;
} else {
/* This row needs more lines */
bNotReady = TRUE;
}
}
/* Fill up the rest */
for (iTmp = 0;
iTmp < (int)tColumnWidthMax - (int)tWidth;
iTmp++) {
*pcTxt++ = (char)FILLER_CHAR;
}
/* End of column */
*pcTxt++ = TABLE_SEPARATOR_CHAR;
*pcTxt = '\0';
}
/* Output the table row line */
*pcTxt = '\0';
tRow = *pOutput;
tRow.szStorage = szLine;
fail(pcTxt < szLine);
tRow.tNextFree = (size_t)(pcTxt - szLine);
tRow.lStringWidth = lComputeStringWidth(
tRow.szStorage,
tRow.tNextFree,
tRow.tFontRef,
tRow.usFontSize);
vString2Diagram(pDiag, &tRow);
TRACE_MSG("after vString2Diagram in vTableRow2Window");
} while (bNotReady);
/* Clean up before you leave */
szLine = xfree(szLine);
TRACE_MSG("leaving vTableRow2Window");
#endif /* __FULL_TEXT_SEARCH */
} /* end of vTableRow2Window */
|