/***************************************************************************** * * * TABLE.C * * * * Copyright (C) Microsoft Corporation 1990. * * All Rights reserved. * * * ****************************************************************************** * * * Module Intent * * * * This module compiles tables into side by side paragraph structures. * * Eventually, it will also handle side by side paragraphs, and full * * table support. * * * *****************************************************************************/ #include "stdafx.h" #pragma hdrstop #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /*************************************************************************** * - Name: StartTable - * Purpose: * Starts table processing * * Arguments: * ptbl: Pointer to table information. * * Returns: * nothing. * * Globals: * This function uses the global wTextBufChCount to determine * whether or not to output the previous FCP. This way, tables * can occur at the very top of a topic (but only if they are * at the beginning of the RTF file.) * * +++ * * Notes: * ***************************************************************************/ void STDCALL StartTable(void) { if (tbl.tbs == tbsOff) { // Get rid of old FCP and start table processing if (wTextBufChCount) { // REVIEW (see Globals: comment above) VOutFCP(FALSE); pfInt = pfCur; VSaveTabTable(); } tbl.tbs = tbsOn; tbl.wParaCmdBegin = 0; tbl.wParaTextBegin = 0; tbl.wParaTextCompBegin = 0; tbl.wObjrgTotal = 0; tbl.iCell = 0; } } /*************************************************************************** * - Name: RcEndTable - * Purpose: * Finishes table processing on the given row, and outputs the entire * table FCP in side by side format. * * Arguments: * ptbl: Pointer to table information. * * Returns: * return code from RcCopyPbfQcb, or RC_Failure if tables were not * turned on from the \intbl command. * * Globals: * pbfCommand, all VOutFCP stuff. * * +++ * * Notes: * ***************************************************************************/ RC_TYPE STDCALL RcEndTable(void) { INT16 iT = iColumnNil; ASSERT(tbl.tbs == tbsOn); if (tbl.tbs != tbsOn) return RC_Failure; // Remove all text and commands since last valid FCP: pbfCommand->SetSize(tbl.wParaCmdBegin); pbfText->SetSize(tbl.wParaTextCompBegin); if (!pbfCommand->Add(&iT, sizeof(INT16))) OOM(); tbl.tbs = tbsFinish; VOutFCP(FALSE); tbl.tbs = tbsOff; return RC_Success; } /*************************************************************************** * - Name: RcAddFcpPtbl - * Purpose: * Puts a paragraph object into the command table for a table FCP. * * Arguments: * ptbl: Pointer to table information * * Returns: * General purpose return code. RC_Failure if tables were not turned on. * * Globals: * * +++ * * Notes: * ***************************************************************************/ RC_TYPE STDCALL RcAddFcpPtbl(void) { MOBJ mobj; MOPG mopg; ASSERT(tbl.tbs == tbsOn); if (tbl.tbs != tbsOn) return RC_Failure; // prepare object header mobj.bType = (BYTE) FCTYPE_PARAGROUP; #ifdef MAGIC mobj.bMagic = bMagicMOBJ; #endif // Fill the paragroup object and get the compressed size VSetParaGroupObject(&mopg); mopg.libText = tbl.wParaTextBegin; // do correction // compress the group object void* qcopgT = szScratchBuf + sizeof(INT16) + sizeof(MOBJ); int cbCOPG = CbPackMOPG(&mopg, qcopgT); int cbNewCommands = pbfCommand->GetSize() - tbl.wParaCmdBegin; mobj.lcbSize = cbCOPG + cbNewCommands; /* * Object regions in the current object equals total in this fcp minus * total already output in this fcp. */ mobj.wObjInfo = adrs.wObjrg - tbl.wObjrgTotal; tbl.wObjrgTotal = adrs.wObjrg; // pack the object header int cbCOBJ = CbPackMOBJ(&mobj, szScratchBuf + sizeof(INT16)); memmove(szScratchBuf + sizeof(INT16) + cbCOBJ, qcopgT, cbCOPG); *(INT16 *) szScratchBuf = tbl.iCell; int cbInsert = cbCOPG + cbCOBJ + sizeof(INT16); /* REVIEW: * We now need to insert the data in szScratchBuf before the new * commands that we have just been adding to the command buffer. What we * really need here is a side-by-side buffer to copy everything to. */ // Expand the buffer: if (pbfCommand->Add(szScratchBuf, cbInsert)) { PBYTE qbCmd = pbfCommand->pbMem; memmove(qbCmd + tbl.wParaCmdBegin + cbInsert, qbCmd + tbl.wParaCmdBegin, cbNewCommands); memcpy(qbCmd + tbl.wParaCmdBegin, szScratchBuf, cbInsert); tbl.wParaCmdBegin = pbfCommand->GetSize(); tbl.wParaTextCompBegin = pbfText->GetSize(); tbl.wParaTextBegin = wTextBufChCount; return RC_Success; } else return RC_OutOfMemory; } /*************************************************************************** * - Name: CbSetTableHeader - * Purpose: * Fills out a buffer with the header information for a table FCP. * * Arguments: * qv: A pointer to the buffer. * ptbl: Pointer to table information. * * Returns: * Number of bytes copied to the buffer. * * Globals: * * +++ * * Notes: * This function needs a better mechanism to avoid buffer overflow. * Currently, the buffer does not overflow because there is a limit * to the number of columns a table can have, and hence to the size * of the header information. * ***************************************************************************/ int STDCALL CbSetTableHeader(void* pv) { MCOL* pmcol; UINT iCell; HP hpTotal; WORD* pi; MSBS* pmsbs = (MSBS*) pv; pmsbs->bcCol = (BYTE) tbl.cCell; pmsbs -> fAbsolute = (BYTE) tbl.fAbsolute; ASSERT(tbl.cCell > 0); if (!tbl.fAbsolute) { pi = (WORD*) (pmsbs + 1); hpTotal = tbl.rghpCellx[tbl.cCell-1]; *pi = hpTotal; pmcol = (MCOL*) (pi + 1); } else pmcol = (MCOL*) (pmsbs + 1); pmcol->xWidthSpace = MAX(0, tbl.hpLeft + tbl.hpSpace); pmcol->xWidthColumn = MAX(1, tbl.rghpCellx[0] - pmcol->xWidthSpace - (tbl.hpSpace / 2)); ++pmcol; for (iCell = 1; iCell < tbl.cCell; ++iCell, ++pmcol) { pmcol->xWidthSpace = tbl.hpSpace; pmcol->xWidthColumn = MAX(1, tbl.rghpCellx[iCell] - tbl.rghpCellx[iCell - 1] - tbl.hpSpace); } if (!tbl.fAbsolute) { pi = (WORD*) (pmsbs + 1); pmcol = (MCOL*) (pi + 1); for (iCell = 0; iCell < tbl.cCell; ++iCell, ++pmcol) { int savewidth = pmcol->xWidthSpace; pmcol->xWidthSpace = (WORD) (DWORD) pmcol->xWidthSpace * 0x7FFF / hpTotal; pmcol->xWidthColumn = (WORD) (DWORD) pmcol->xWidthColumn * 0x7FFF / hpTotal; } } return ((PBYTE) pmcol - (PBYTE) pv); }