diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/out2window_8c_source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/out2window_8c_source.html Tue Mar 30 16:16:55 2010 +0100 @@ -0,0 +1,784 @@ + + +
+ +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 */ +