123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768 |
- /*
- * 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 */
|