summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/antiword/out2window.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/antiword/out2window.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/antiword/out2window.c')
-rwxr-xr-xsys/src/cmd/aux/antiword/out2window.c768
1 files changed, 768 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/antiword/out2window.c b/sys/src/cmd/aux/antiword/out2window.c
new file mode 100755
index 000000000..9bdacc314
--- /dev/null
+++ b/sys/src/cmd/aux/antiword/out2window.c
@@ -0,0 +1,768 @@
+/*
+ * 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 */