examples/PIPS/antiword/src/out2window.c

00001 /*
00002  * out2window.c
00003  * Copyright (C) 1998-2005 A.J. van Os; Released under GPL
00004  *
00005  * Description:
00006  * Output to a text window
00007  */
00008 
00009 #include <string.h>
00010 #include <stdlib.h>
00011 #include <ctype.h>
00012 #include "antiword.h"
00013 
00014 /* Used for numbering the chapters */
00015 static unsigned int     auiHdrCounter[9];
00016 
00017 
00018 /*
00019  * vString2Diagram - put a string into a diagram
00020  */
00021 static void
00022 vString2Diagram(diagram_type *pDiag, output_type *pAnchor)
00023 {
00024         output_type     *pOutput;
00025         long            lWidth;
00026         USHORT          usMaxFontSize;
00027 
00028         TRACE_MSG("vString2Diagram");
00029 
00030         fail(pDiag == NULL);
00031         fail(pAnchor == NULL);
00032 
00033         /* Compute the maximum fontsize in this string */
00034         usMaxFontSize = MIN_FONT_SIZE;
00035         for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
00036                 if (pOutput->usFontSize > usMaxFontSize) {
00037                         usMaxFontSize = pOutput->usFontSize;
00038                 }
00039         }
00040 
00041         /* Goto the next line */
00042         vMove2NextLine(pDiag, pAnchor->tFontRef, usMaxFontSize);
00043 
00044         /* Output all substrings */
00045         for (pOutput = pAnchor; pOutput != NULL; pOutput = pOutput->pNext) {
00046                 lWidth = lMilliPoints2DrawUnits(pOutput->lStringWidth);
00047                 vSubstring2Diagram(pDiag, pOutput->szStorage,
00048                         pOutput->tNextFree, lWidth, pOutput->ucFontColor,
00049                         pOutput->usFontStyle, pOutput->tFontRef,
00050                         pOutput->usFontSize, usMaxFontSize);
00051         }
00052 
00053         /* Goto the start of the line */
00054         pDiag->lXleft = 0;
00055         TRACE_MSG("leaving vString2Diagram");
00056 } /* end of vString2Diagram */
00057 
00058 /*
00059  * vSetLeftIndentation - set the left indentation of the specified diagram
00060  */
00061 void
00062 vSetLeftIndentation(diagram_type *pDiag, long lLeftIndentation)
00063 {
00064         long    lX;
00065 
00066         TRACE_MSG("vSetLeftIndentation");
00067 
00068         fail(pDiag == NULL);
00069         fail(lLeftIndentation < 0);
00070 
00071         lX = lMilliPoints2DrawUnits(lLeftIndentation);
00072         if (lX > 0) {
00073                 pDiag->lXleft = lX;
00074         } else {
00075                 pDiag->lXleft = 0;
00076         }
00077 } /* end of vSetLeftIndentation */
00078 
00079 /*
00080  * lComputeNetWidth - compute the net string width
00081  */
00082 static long
00083 lComputeNetWidth(output_type *pAnchor)
00084 {
00085         output_type     *pTmp;
00086         long            lNetWidth;
00087 
00088         TRACE_MSG("lComputeNetWidth");
00089 
00090         fail(pAnchor == NULL);
00091 
00092         /* Step 1: Count all but the last sub-string */
00093         lNetWidth = 0;
00094         for (pTmp = pAnchor; pTmp->pNext != NULL; pTmp = pTmp->pNext) {
00095                 fail(pTmp->lStringWidth < 0);
00096                 lNetWidth += pTmp->lStringWidth;
00097         }
00098         fail(pTmp == NULL);
00099         fail(pTmp->pNext != NULL);
00100 
00101         /* Step 2: remove the white-space from the end of the string */
00102         while (pTmp->tNextFree != 0 &&
00103                isspace((int)(UCHAR)pTmp->szStorage[pTmp->tNextFree - 1])) {
00104                 pTmp->szStorage[pTmp->tNextFree - 1] = '\0';
00105                 pTmp->tNextFree--;
00106                 NO_DBG_DEC(pTmp->lStringWidth);
00107                 pTmp->lStringWidth = lComputeStringWidth(
00108                                                 pTmp->szStorage,
00109                                                 pTmp->tNextFree,
00110                                                 pTmp->tFontRef,
00111                                                 pTmp->usFontSize);
00112                 NO_DBG_DEC(pTmp->lStringWidth);
00113         }
00114 
00115         /* Step 3: Count the last sub-string */
00116         lNetWidth += pTmp->lStringWidth;
00117         return lNetWidth;
00118 } /* end of lComputeNetWidth */
00119 
00120 /*
00121  * iComputeHoles - compute number of holes
00122  * (A hole is a number of whitespace characters followed by a
00123  *  non-whitespace character)
00124  */
00125 static int
00126 iComputeHoles(output_type *pAnchor)
00127 {
00128         output_type     *pTmp;
00129         size_t  tIndex;
00130         int     iCounter;
00131         BOOL    bWasSpace, bIsSpace;
00132 
00133         TRACE_MSG("iComputeHoles");
00134 
00135         fail(pAnchor == NULL);
00136 
00137         iCounter = 0;
00138         bIsSpace = FALSE;
00139         /* Count the holes */
00140         for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
00141                 fail(pTmp->tNextFree != strlen(pTmp->szStorage));
00142                 for (tIndex = 0; tIndex <= pTmp->tNextFree; tIndex++) {
00143                         bWasSpace = bIsSpace;
00144                         bIsSpace = isspace((int)(UCHAR)pTmp->szStorage[tIndex]);
00145                         if (bWasSpace && !bIsSpace) {
00146                                 iCounter++;
00147                         }
00148                 }
00149         }
00150         return iCounter;
00151 } /* end of iComputeHoles */
00152 
00153 /*
00154  * vAlign2Window - Align a string and insert it into the text
00155  */
00156 void
00157 vAlign2Window(diagram_type *pDiag, output_type *pAnchor,
00158         long lScreenWidth, UCHAR ucAlignment)
00159 {
00160         long    lNetWidth, lLeftIndentation;
00161 
00162         TRACE_MSG("vAlign2Window");
00163 
00164         fail(pDiag == NULL || pAnchor == NULL);
00165         fail(lScreenWidth < lChar2MilliPoints(MIN_SCREEN_WIDTH));
00166 
00167         lNetWidth = lComputeNetWidth(pAnchor);
00168 
00169         if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
00170             lNetWidth <= 0) {
00171                 /*
00172                  * Screenwidth is "infinite", so no alignment is possible
00173                  * Don't bother to align an empty line
00174                  */
00175                 vString2Diagram(pDiag, pAnchor);
00176                 TRACE_MSG("leaving vAlign2Window #1");
00177                 return;
00178         }
00179 
00180         switch (ucAlignment) {
00181         case ALIGNMENT_CENTER:
00182                 lLeftIndentation = (lScreenWidth - lNetWidth) / 2;
00183                 DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
00184                 if (lLeftIndentation > 0) {
00185                         vSetLeftIndentation(pDiag, lLeftIndentation);
00186                 }
00187                 break;
00188         case ALIGNMENT_RIGHT:
00189                 lLeftIndentation = lScreenWidth - lNetWidth;
00190                 DBG_DEC_C(lLeftIndentation < 0, lLeftIndentation);
00191                 if (lLeftIndentation > 0) {
00192                         vSetLeftIndentation(pDiag, lLeftIndentation);
00193                 }
00194                 break;
00195         case ALIGNMENT_JUSTIFY:
00196         case ALIGNMENT_LEFT:
00197         default:
00198                 break;
00199         }
00200         vString2Diagram(pDiag, pAnchor);
00201         TRACE_MSG("leaving vAlign2Window #2");
00202 } /* end of vAlign2Window */
00203 
00204 /*
00205  * vJustify2Window - Justify a string and insert it into the text
00206  */
00207 void
00208 vJustify2Window(diagram_type *pDiag, output_type *pAnchor,
00209         long lScreenWidth, long lRightIndentation, UCHAR ucAlignment)
00210 {
00211         output_type     *pTmp;
00212         char    *pcNew, *pcOld, *szStorage;
00213         long    lNetWidth, lSpaceWidth, lToAdd;
00214         int     iFillerLen, iHoles;
00215 
00216         TRACE_MSG("vJustify2Window");
00217 
00218         fail(pDiag == NULL || pAnchor == NULL);
00219         fail(lScreenWidth < MIN_SCREEN_WIDTH);
00220         fail(lRightIndentation > 0);
00221 
00222         if (ucAlignment != ALIGNMENT_JUSTIFY) {
00223                 vAlign2Window(pDiag, pAnchor, lScreenWidth, ucAlignment);
00224                 return;
00225         }
00226 
00227         lNetWidth = lComputeNetWidth(pAnchor);
00228 
00229         if (lScreenWidth > lChar2MilliPoints(MAX_SCREEN_WIDTH) ||
00230             lNetWidth <= 0) {
00231                 /*
00232                  * Screenwidth is "infinite", so justify is not possible
00233                  * Don't bother to justify an empty line
00234                  */
00235                 vString2Diagram(pDiag, pAnchor);
00236                 TRACE_MSG("leaving vJustify2Window #1");
00237                 return;
00238         }
00239 
00240         /* Justify */
00241         fail(ucAlignment != ALIGNMENT_JUSTIFY);
00242         lSpaceWidth = lComputeStringWidth(" ", 1,
00243                                 pAnchor->tFontRef, pAnchor->usFontSize);
00244         lToAdd = lScreenWidth -
00245                         lNetWidth -
00246                         lDrawUnits2MilliPoints(pDiag->lXleft) +
00247                         lRightIndentation;
00248 #if defined(DEBUG)
00249         if (lToAdd / lSpaceWidth < -1) {
00250                 DBG_DEC(lSpaceWidth);
00251                 DBG_DEC(lToAdd);
00252                 DBG_DEC(lScreenWidth);
00253                 DBG_DEC(lNetWidth);
00254                 DBG_DEC(lDrawUnits2MilliPoints(pDiag->lXleft));
00255                 DBG_DEC(pDiag->lXleft);
00256                 DBG_DEC(lRightIndentation);
00257         }
00258 #endif /* DEBUG */
00259         lToAdd /= lSpaceWidth;
00260         DBG_DEC_C(lToAdd < 0, lToAdd);
00261         if (lToAdd <= 0) {
00262                 vString2Diagram(pDiag, pAnchor);
00263                 TRACE_MSG("leaving vJustify2Window #2");
00264                 return;
00265         }
00266 
00267         /* Justify by adding spaces */
00268         iHoles = iComputeHoles(pAnchor);
00269         for (pTmp = pAnchor; pTmp != NULL; pTmp = pTmp->pNext) {
00270                 fail(pTmp->tNextFree != strlen(pTmp->szStorage));
00271                 fail(lToAdd < 0);
00272                 szStorage = xmalloc(pTmp->tNextFree + (size_t)lToAdd + 1);
00273                 pcNew = szStorage;
00274                 for (pcOld = pTmp->szStorage; *pcOld != '\0'; pcOld++) {
00275                         *pcNew++ = *pcOld;
00276                         if (*pcOld == ' ' &&
00277                             *(pcOld + 1) != ' ' &&
00278                             iHoles > 0) {
00279                                 iFillerLen = (int)(lToAdd / iHoles);
00280                                 lToAdd -= iFillerLen;
00281                                 iHoles--;
00282                                 for (; iFillerLen > 0; iFillerLen--) {
00283                                         *pcNew++ = ' ';
00284                                 }
00285                         }
00286                 }
00287                 *pcNew = '\0';
00288                 pTmp->szStorage = xfree(pTmp->szStorage);
00289                 pTmp->szStorage = szStorage;
00290                 pTmp->tStorageSize = pTmp->tNextFree + (size_t)lToAdd + 1;
00291                 pTmp->lStringWidth +=
00292                         (pcNew - szStorage - (long)pTmp->tNextFree) *
00293                         lSpaceWidth;
00294                 fail(pcNew < szStorage);
00295                 pTmp->tNextFree = (size_t)(pcNew - szStorage);
00296                 fail(pTmp->tNextFree != strlen(pTmp->szStorage));
00297         }
00298         DBG_DEC_C(lToAdd != 0, lToAdd);
00299         vString2Diagram(pDiag, pAnchor);
00300         TRACE_MSG("leaving vJustify2Window #3");
00301 } /* end of vJustify2Window */
00302 
00303 /*
00304  * vResetStyles - reset the style information variables
00305  */
00306 void
00307 vResetStyles(void)
00308 {
00309         TRACE_MSG("vResetStyles");
00310 
00311         (void)memset(auiHdrCounter, 0, sizeof(auiHdrCounter));
00312 } /* end of vResetStyles */
00313 
00314 /*
00315  * tStyle2Window - Add the style characters to the line
00316  *
00317  * Returns the length of the resulting string
00318  */
00319 size_t
00320 tStyle2Window(char *szLine, size_t tLineSize, const style_block_type *pStyle,
00321         const section_block_type *pSection)
00322 {
00323         char    *pcTxt;
00324         size_t  tIndex, tStyleIndex;
00325         BOOL    bNeedPrevLvl;
00326         level_type_enum eNumType;
00327         UCHAR   ucNFC;
00328 
00329         TRACE_MSG("tStyle2Window");
00330 
00331         fail(szLine == NULL || pStyle == NULL || pSection == NULL);
00332 
00333         if (pStyle->usIstd == 0 || pStyle->usIstd > 9) {
00334                 szLine[0] = '\0';
00335                 return 0;
00336         }
00337 
00338         /* Set the numbers */
00339         tStyleIndex = (size_t)pStyle->usIstd - 1;
00340         for (tIndex = 0; tIndex < 9; tIndex++) {
00341                 if (tIndex == tStyleIndex) {
00342                         auiHdrCounter[tIndex]++;
00343                 } else if (tIndex > tStyleIndex) {
00344                         auiHdrCounter[tIndex] = 0;
00345                 } else if (auiHdrCounter[tIndex] == 0) {
00346                         auiHdrCounter[tIndex] = 1;
00347                 }
00348         }
00349 
00350         eNumType = eGetNumType(pStyle->ucNumLevel);
00351         if (eNumType != level_type_outline) {
00352                 szLine[0] = '\0';
00353                 return 0;
00354         }
00355 
00356         /* Print the numbers */
00357         pcTxt = szLine;
00358         bNeedPrevLvl = (pSection->usNeedPrevLvl & BIT(tStyleIndex)) != 0;
00359         for (tIndex = 0; tIndex <= tStyleIndex; tIndex++) {
00360                 if (tIndex == tStyleIndex ||
00361                     (bNeedPrevLvl && tIndex < tStyleIndex)) {
00362                         if (pcTxt - szLine >= tLineSize - 25) {
00363                                 /* Prevent a possible buffer overflow */
00364                                 DBG_DEC(pcTxt - szLine);
00365                                 DBG_DEC(tLineSize - 25);
00366                                 DBG_FIXME();
00367                                 szLine[0] = '\0';
00368                                 return 0;
00369                         }
00370                         ucNFC = pSection->aucNFC[tIndex];
00371                         switch(ucNFC) {
00372                         case LIST_ARABIC_NUM:
00373                         case LIST_NUMBER_TXT:
00374                         case LIST_ORDINAL_TXT:
00375                                 pcTxt += sprintf(pcTxt, "%u",
00376                                         auiHdrCounter[tIndex]);
00377                                 break;
00378                         case LIST_UPPER_ROMAN:
00379                         case LIST_LOWER_ROMAN:
00380                                 pcTxt += tNumber2Roman(
00381                                         auiHdrCounter[tIndex],
00382                                         ucNFC == LIST_UPPER_ROMAN,
00383                                         pcTxt);
00384                                 break;
00385                         case LIST_UPPER_ALPHA:
00386                         case LIST_LOWER_ALPHA:
00387                                 pcTxt += tNumber2Alpha(
00388                                         auiHdrCounter[tIndex],
00389                                         ucNFC == LIST_UPPER_ALPHA,
00390                                         pcTxt);
00391                                 break;
00392                         case LIST_OUTLINE_NUM:
00393                                 pcTxt += sprintf(pcTxt, "%02u",
00394                                         auiHdrCounter[tIndex]);
00395                                 break;
00396                         default:
00397                                 DBG_DEC(ucNFC);
00398                                 DBG_FIXME();
00399                                 pcTxt += sprintf(pcTxt, "%u",
00400                                         auiHdrCounter[tIndex]);
00401                                 break;
00402                         }
00403                         if (tIndex < tStyleIndex) {
00404                                 *pcTxt++ = '.';
00405                         } else if (tIndex == tStyleIndex) {
00406                                 *pcTxt++ = ' ';
00407                         }
00408                 }
00409         }
00410         *pcTxt = '\0';
00411         NO_DBG_MSG_C((int)pStyle->usIstd >= 1 &&
00412                 (int)pStyle->usIstd <= 9 &&
00413                 eNumType != level_type_none &&
00414                 eNumType != level_type_outline, szLine);
00415         NO_DBG_MSG_C(szLine[0] != '\0', szLine);
00416         fail(pcTxt < szLine);
00417         return (size_t)(pcTxt - szLine);
00418 } /* end of tStyle2Window */
00419 
00420 /*
00421  * vRemoveRowEnd - remove the end of table row indicator
00422  *
00423  * Remove the double TABLE_SEPARATOR characters from the end of the string.
00424  * Special: remove the TABLE_SEPARATOR, 0x0a sequence
00425  */
00426 static void
00427 vRemoveRowEnd(char *szRowTxt)
00428 {
00429         int     iLastIndex;
00430 
00431         TRACE_MSG("vRemoveRowEnd");
00432 
00433         fail(szRowTxt == NULL || szRowTxt[0] == '\0');
00434 
00435         iLastIndex = (int)strlen(szRowTxt) - 1;
00436 
00437         if (szRowTxt[iLastIndex] == TABLE_SEPARATOR ||
00438             szRowTxt[iLastIndex] == (char)0x0a) {
00439                 szRowTxt[iLastIndex] = '\0';
00440                 iLastIndex--;
00441         } else {
00442                 DBG_HEX(szRowTxt[iLastIndex]);
00443         }
00444 
00445         if (iLastIndex >= 0 && szRowTxt[iLastIndex] == (char)0x0a) {
00446                 szRowTxt[iLastIndex] = '\0';
00447                 iLastIndex--;
00448         }
00449 
00450         if (iLastIndex >= 0 && szRowTxt[iLastIndex] == TABLE_SEPARATOR) {
00451                 szRowTxt[iLastIndex] = '\0';
00452                 return;
00453         }
00454 
00455         DBG_DEC(iLastIndex);
00456         DBG_HEX(szRowTxt[iLastIndex]);
00457         DBG_MSG(szRowTxt);
00458 } /* end of vRemoveRowEnd */
00459 
00460 /*
00461  * tComputeStringLengthMax - max string length in relation to max column width
00462  *
00463  * Return the maximum string length
00464  */
00465 static size_t
00466 tComputeStringLengthMax(const char *szString, size_t tColumnWidthMax)
00467 {
00468         const char      *pcTmp;
00469         size_t  tLengthMax, tLenPrev, tLen, tWidth;
00470 
00471         TRACE_MSG("tComputeStringLengthMax");
00472 
00473         fail(szString == NULL);
00474         fail(tColumnWidthMax == 0);
00475 
00476         pcTmp = strchr(szString, '\n');
00477         if (pcTmp != NULL) {
00478                 tLengthMax = (size_t)(pcTmp - szString + 1);
00479         } else {
00480                 tLengthMax = strlen(szString);
00481         }
00482         if (tLengthMax == 0) {
00483                 return 0;
00484         }
00485 
00486         tLen = 0;
00487         tWidth = 0;
00488         for (;;) {
00489                 tLenPrev = tLen;
00490                 tLen += tGetCharacterLength(szString + tLen);
00491                 DBG_DEC_C(tLen > tLengthMax, tLen);
00492                 DBG_DEC_C(tLen > tLengthMax, tLengthMax);
00493                 fail(tLen > tLengthMax);
00494                 tWidth = tCountColumns(szString, tLen);
00495                 if (tWidth > tColumnWidthMax) {
00496                         return tLenPrev;
00497                 }
00498                 if (tLen >= tLengthMax) {
00499                         return tLengthMax;
00500                 }
00501         }
00502 } /* end of tComputeStringLengthMax */
00503 
00504 /*
00505  * tGetBreakingPoint - get the number of bytes that fit the column
00506  *
00507  * Returns the number of bytes that fit the column
00508  */
00509 static size_t
00510 tGetBreakingPoint(const char *szString,
00511         size_t tLen, size_t tWidth, size_t tColumnWidthMax)
00512 {
00513         int     iIndex;
00514 
00515         TRACE_MSG("tGetBreakingPoint");
00516 
00517         fail(szString == NULL);
00518         fail(tLen > strlen(szString));
00519         fail(tWidth > tColumnWidthMax);
00520 
00521         if (tWidth < tColumnWidthMax ||
00522             (tWidth == tColumnWidthMax &&
00523              (szString[tLen] == ' ' ||
00524               szString[tLen] == '\n' ||
00525               szString[tLen] == '\0'))) {
00526                 /* The string already fits, do nothing */
00527                 return tLen;
00528         }
00529         /* Search for a breaking point */
00530         for (iIndex = (int)tLen - 1; iIndex >= 0; iIndex--) {
00531                 if (szString[iIndex] == ' ') {
00532                         return (size_t)iIndex;
00533                 }
00534         }
00535         /* No breaking point found, just fill the column */
00536         return tLen;
00537 } /* end of tGetBreakingPoint */
00538 
00539 /*
00540  * tComputeColumnWidthMax - compute the maximum column width
00541  */
00542 static size_t
00543 tComputeColumnWidthMax(short sWidth, long lCharWidth, double dFactor)
00544 {
00545         size_t  tColumnWidthMax;
00546 
00547         TRACE_MSG("tComputeColumnWidthMax");
00548 
00549         fail(sWidth < 0);
00550         fail(lCharWidth <= 0);
00551         fail(dFactor <= 0.0);
00552 
00553         tColumnWidthMax = (size_t)(
00554                 (lTwips2MilliPoints(sWidth) * dFactor + lCharWidth / 2.0) /
00555                  lCharWidth);
00556         if (tColumnWidthMax == 0) {
00557                 /* Minimum column width */
00558                 return 1;
00559         }
00560         if (tColumnWidthMax > 1) {
00561                 /* Make room for the TABLE_SEPARATOR_CHAR */
00562                 tColumnWidthMax--;
00563         }
00564         NO_DBG_DEC(tColumnWidthMax);
00565         return tColumnWidthMax;
00566 } /* end of tComputeColumnWidthMax */
00567 
00568 /*
00569  * vTableRow2Window - put a table row into a diagram
00570  */
00571 void
00572 vTableRow2Window(diagram_type *pDiag, output_type *pOutput,
00573         const row_block_type *pRowInfo,
00574         conversion_type eConversionType, int iParagraphBreak)
00575 {
00576         output_type     tRow;
00577         char    *aszColTxt[TABLE_COLUMN_MAX];
00578         char    *szLine, *pcTxt;
00579         double  dMagnify;
00580         long    lCharWidthLarge, lCharWidthSmall;
00581         size_t  tColumnWidthTotal, atColumnWidthMax[TABLE_COLUMN_MAX];
00582         size_t  tSize, tColumnWidthMax, tWidth, tLen;
00583         int     iIndex, iNbrOfColumns, iTmp;
00584         BOOL    bNotReady;
00585 
00586         TRACE_MSG("vTableRow2Window");
00587 
00588         fail(pDiag == NULL || pOutput == NULL || pRowInfo == NULL);
00589         fail(pOutput->szStorage == NULL);
00590         fail(pOutput->pNext != NULL);
00591         fail(iParagraphBreak < 0);
00592 
00593         /* Character sizes */
00594         lCharWidthLarge = lComputeStringWidth("W", 1,
00595                                 pOutput->tFontRef, pOutput->usFontSize);
00596         NO_DBG_DEC(lCharWidthLarge);
00597         lCharWidthSmall = lComputeStringWidth("i", 1,
00598                                 pOutput->tFontRef, pOutput->usFontSize);
00599         NO_DBG_DEC(lCharWidthSmall);
00600         /* For the time being: use a fixed width font */
00601         fail(lCharWidthLarge != lCharWidthSmall);
00602 
00603         vRemoveRowEnd(pOutput->szStorage);
00604 
00605         /* Split the row text into a set of column texts */
00606         aszColTxt[0] = pOutput->szStorage;
00607         for (iNbrOfColumns = 1;
00608              iNbrOfColumns < TABLE_COLUMN_MAX;
00609              iNbrOfColumns++) {
00610                 aszColTxt[iNbrOfColumns] =
00611                                 strchr(aszColTxt[iNbrOfColumns - 1],
00612                                         TABLE_SEPARATOR);
00613                 if (aszColTxt[iNbrOfColumns] == NULL) {
00614                         break;
00615                 }
00616                 *aszColTxt[iNbrOfColumns] = '\0';
00617                 aszColTxt[iNbrOfColumns]++;
00618                 NO_DBG_DEC(iNbrOfColumns);
00619                 NO_DBG_MSG(aszColTxt[iNbrOfColumns]);
00620         }
00621 
00622         /* Work around a bug in Word */
00623         while (iNbrOfColumns > (int)pRowInfo->ucNumberOfColumns &&
00624                pRowInfo->asColumnWidth[iNbrOfColumns] == 0) {
00625                 iNbrOfColumns--;
00626         }
00627 
00628         DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
00629                 iNbrOfColumns);
00630         DBG_DEC_C(iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns,
00631                 pRowInfo->ucNumberOfColumns);
00632         if (iNbrOfColumns != (int)pRowInfo->ucNumberOfColumns) {
00633                 werr(0, "Skipping an unmatched table row");
00634                 return;
00635         }
00636 
00637 #if defined(__FULL_TEXT_SEARCH)
00638         /* No table formatting: use for full-text search (untested) */
00639         for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
00640                 fprintf(pDiag->pOutFile, "%s\n" , aszColTxt[iIndex]);
00641         }
00642 #else
00643         if (bAddTableRow(pDiag, aszColTxt, iNbrOfColumns,
00644                         pRowInfo->asColumnWidth, pRowInfo->ucBorderInfo)) {
00645                 /* All work has been done */
00646                 return;
00647         }
00648 
00649         /* Fill the table with maximum column widths */
00650         if (eConversionType == conversion_text ||
00651             eConversionType == conversion_fmt_text) {
00652                 if (iParagraphBreak == 0 ||
00653                     iParagraphBreak >= MAX_SCREEN_WIDTH) {
00654                         dMagnify = (double)MAX_SCREEN_WIDTH;
00655                 } else if (iParagraphBreak <= MIN_SCREEN_WIDTH) {
00656                         dMagnify = (double)MIN_SCREEN_WIDTH;
00657                 } else {
00658                         dMagnify = (double)iParagraphBreak;
00659                 }
00660                 dMagnify /= (double)DEFAULT_SCREEN_WIDTH;
00661                 DBG_FLT_C(dMagnify < 0.99 || dMagnify > 1.01, dMagnify);
00662         } else {
00663                 dMagnify = 1.0;
00664         }
00665         tColumnWidthTotal = 0;
00666         for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
00667                 atColumnWidthMax[iIndex] = tComputeColumnWidthMax(
00668                                         pRowInfo->asColumnWidth[iIndex],
00669                                         lCharWidthLarge,
00670                                         dMagnify);
00671                 tColumnWidthTotal += atColumnWidthMax[iIndex];
00672         }
00673 
00674         /*
00675          * Get enough space for the row.
00676          * Worst case: three bytes per UTF-8 character
00677          */
00678         tSize = 3 * (1 + tColumnWidthTotal + (size_t)iNbrOfColumns + 3);
00679         szLine = xmalloc(tSize);
00680 
00681         do {
00682                 /* Print one line of a table row */
00683                 bNotReady = FALSE;
00684                 pcTxt = szLine;
00685                 *pcTxt++ = TABLE_SEPARATOR_CHAR;
00686                 for (iIndex = 0; iIndex < iNbrOfColumns; iIndex++) {
00687                         tColumnWidthMax = atColumnWidthMax[iIndex];
00688                         if (aszColTxt[iIndex] == NULL) {
00689                                 /* Add an empty column */
00690                                 for (iTmp = 0;
00691                                      iTmp < (int)tColumnWidthMax;
00692                                      iTmp++) {
00693                                         *pcTxt++ = (char)FILLER_CHAR;
00694                                 }
00695                                 *pcTxt++ = TABLE_SEPARATOR_CHAR;
00696                                 *pcTxt = '\0';
00697                                 continue;
00698                         }
00699                         /* Compute the length and width of the column text */
00700                         tLen = tComputeStringLengthMax(
00701                                         aszColTxt[iIndex], tColumnWidthMax);
00702                         NO_DBG_DEC(tLen);
00703                         while (tLen != 0 &&
00704                                         (aszColTxt[iIndex][tLen - 1] == '\n' ||
00705                                          aszColTxt[iIndex][tLen - 1] == ' ')) {
00706                                 aszColTxt[iIndex][tLen - 1] = ' ';
00707                                 tLen--;
00708                         }
00709                         tWidth = tCountColumns(aszColTxt[iIndex], tLen);
00710                         fail(tWidth > tColumnWidthMax);
00711                         tLen = tGetBreakingPoint(aszColTxt[iIndex],
00712                                         tLen, tWidth, tColumnWidthMax);
00713                         tWidth = tCountColumns(aszColTxt[iIndex], tLen);
00714                         if (tLen == 0 && *aszColTxt[iIndex] == '\0') {
00715                                 /* No text at all */
00716                                 aszColTxt[iIndex] = NULL;
00717                         } else {
00718                                 /* Add the text */
00719                                 pcTxt += sprintf(pcTxt,
00720                                         "%.*s", (int)tLen, aszColTxt[iIndex]);
00721                                 if (tLen == 0 && *aszColTxt[iIndex] != ' ') {
00722                                         tLen = tGetCharacterLength(
00723                                                         aszColTxt[iIndex]);
00724                                         DBG_CHR(*aszColTxt[iIndex]);
00725                                         DBG_FIXME();
00726                                         fail(tLen == 0);
00727                                 }
00728                                 aszColTxt[iIndex] += tLen;
00729                                 while (*aszColTxt[iIndex] == ' ') {
00730                                         aszColTxt[iIndex]++;
00731                                 }
00732                                 if (*aszColTxt[iIndex] == '\0') {
00733                                         /* This row is now complete */
00734                                         aszColTxt[iIndex] = NULL;
00735                                 } else {
00736                                         /* This row needs more lines */
00737                                         bNotReady = TRUE;
00738                                 }
00739                         }
00740                         /* Fill up the rest */
00741                         for (iTmp = 0;
00742                              iTmp < (int)tColumnWidthMax - (int)tWidth;
00743                              iTmp++) {
00744                                 *pcTxt++ = (char)FILLER_CHAR;
00745                         }
00746                         /* End of column */
00747                         *pcTxt++ = TABLE_SEPARATOR_CHAR;
00748                         *pcTxt = '\0';
00749                 }
00750                 /* Output the table row line */
00751                 *pcTxt = '\0';
00752                 tRow = *pOutput;
00753                 tRow.szStorage = szLine;
00754                 fail(pcTxt < szLine);
00755                 tRow.tNextFree = (size_t)(pcTxt - szLine);
00756                 tRow.lStringWidth = lComputeStringWidth(
00757                                         tRow.szStorage,
00758                                         tRow.tNextFree,
00759                                         tRow.tFontRef,
00760                                         tRow.usFontSize);
00761                 vString2Diagram(pDiag, &tRow);
00762                 TRACE_MSG("after vString2Diagram in vTableRow2Window");
00763         } while (bNotReady);
00764         /* Clean up before you leave */
00765         szLine = xfree(szLine);
00766         TRACE_MSG("leaving vTableRow2Window");
00767 #endif /* __FULL_TEXT_SEARCH */
00768 } /* end of vTableRow2Window */

Generated by  doxygen 1.6.2