mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
6.7 KiB
280 lines
6.7 KiB
/*****************************************************************************
|
|
* *
|
|
* 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);
|
|
}
|