📄 out2window.c
字号:
/* * 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 voidvString2Diagram(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 */voidvSetLeftIndentation(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 longlComputeNetWidth(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 intiComputeHoles(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 */voidvAlign2Window(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 */voidvJustify2Window(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 */voidvResetStyles(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_ttStyle2Window(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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -