diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /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-x | sys/src/cmd/aux/antiword/out2window.c | 768 |
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 */ |