477 lines
14 KiB
C
477 lines
14 KiB
C
|
#include "lsidefs.h"
|
||
|
#include "pilsobj.h"
|
||
|
#include "plsline.h"
|
||
|
#include "lstext.h"
|
||
|
#include "lscbk.h"
|
||
|
#include "lsc.h"
|
||
|
#include "lscontxt.h"
|
||
|
#include "limqmem.h"
|
||
|
#include "qheap.h"
|
||
|
#include "lsline.h"
|
||
|
#include "lsdnode.h"
|
||
|
#include "iobj.h"
|
||
|
#include "chnutils.h"
|
||
|
#include "autonum.h"
|
||
|
|
||
|
#include "lsmem.h" /* memset() */
|
||
|
|
||
|
|
||
|
|
||
|
static LSERR CannotCreateLsContext(PLSC, LSERR);
|
||
|
static LSERR InitObject(PLSC plsc, DWORD iobj, const LSIMETHODS* plsim);
|
||
|
static LSERR RemoveContextObjects(PLSC plsc);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
#ifdef LSTEST_ASSERTSTOP
|
||
|
|
||
|
/* We use it to run debug LS with ship build of WORD */
|
||
|
|
||
|
int nZero = 0;
|
||
|
|
||
|
void AssertFailedStop (char* pzstrMsg, char* pzstrFile, int nLine)
|
||
|
{
|
||
|
Unreferenced (pzstrMsg);
|
||
|
Unreferenced (pzstrFile);
|
||
|
Unreferenced (nLine);
|
||
|
|
||
|
nZero = nZero / nZero;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/* L S C R E A T E C O N T E X T */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: LsCreateContext
|
||
|
%%Contact: igorzv
|
||
|
|
||
|
Parameters:
|
||
|
plsci - (IN) structure which contains clients setings
|
||
|
pplsc - (OUT) pointer to created contexts (opaque to clients)
|
||
|
|
||
|
Creates a Line Services context.
|
||
|
Typically called once, at the beginning of time.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
LSERR WINAPI LsCreateContext(const LSCONTEXTINFO* plsci, PLSC* pplsc)
|
||
|
{
|
||
|
static LSIMETHODS const lsimText =
|
||
|
{
|
||
|
CreateILSObjText,
|
||
|
DestroyILSObjText,
|
||
|
SetDocText,
|
||
|
CreateLNObjText,
|
||
|
DestroyLNObjText,
|
||
|
FmtText,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
TruncateText,
|
||
|
FindPrevBreakText,
|
||
|
FindNextBreakText,
|
||
|
ForceBreakText,
|
||
|
SetBreakText,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
CalcPresentationText,
|
||
|
QueryPointPcpText,
|
||
|
QueryCpPpointText,
|
||
|
EnumObjText,
|
||
|
DisplayText,
|
||
|
DestroyDObjText,
|
||
|
};
|
||
|
|
||
|
static LSIMETHODS const lsimAutonum =
|
||
|
{
|
||
|
AutonumCreateILSObj,
|
||
|
AutonumDestroyILSObj,
|
||
|
AutonumSetDoc,
|
||
|
AutonumCreateLNObj,
|
||
|
AutonumDestroyLNObj,
|
||
|
AutonumFmt,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
AutonumTruncateChunk,
|
||
|
AutonumFindPrevBreakChunk,
|
||
|
AutonumFindNextBreakChunk,
|
||
|
AutonumForceBreakChunk,
|
||
|
AutonumSetBreak,
|
||
|
AutonumGetSpecialEffectsInside,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
AutonumCalcPresentation,
|
||
|
AutonumQueryPointPcp,
|
||
|
AutonumQueryCpPpoint,
|
||
|
AutonumEnumerate,
|
||
|
AutonumDisplay,
|
||
|
AutonumDestroyDobj,
|
||
|
};
|
||
|
|
||
|
DWORD const iobjText = plsci->cInstalledHandlers;
|
||
|
DWORD const iobjAutonum = plsci->cInstalledHandlers + 1;
|
||
|
DWORD const iobjMac = iobjText + 2;
|
||
|
POLS const pols = plsci->pols;
|
||
|
const LSIMETHODS* const plsim = plsci->pInstalledHandlers;
|
||
|
|
||
|
DWORD iobj;
|
||
|
PLSC plsc;
|
||
|
LSERR lserr;
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
#ifdef LSTEST_ASSERTSTOP
|
||
|
|
||
|
/* We use this option when run debug LS with ship WORD */
|
||
|
|
||
|
pfnAssertFailed = AssertFailedStop;
|
||
|
|
||
|
#else
|
||
|
|
||
|
pfnAssertFailed = plsci->lscbk.pfnAssertFailed;
|
||
|
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
if (pplsc == NULL)
|
||
|
return lserrNullOutputParameter;
|
||
|
|
||
|
*pplsc = NULL;
|
||
|
|
||
|
/* Allocate memory for the context and clean it
|
||
|
*/
|
||
|
plsc = plsci->lscbk.pfnNewPtr(pols, cbRep(struct lscontext, lsiobjcontext.rgobj, iobjMac));
|
||
|
if (plsc == NULL)
|
||
|
return lserrOutOfMemory;
|
||
|
memset(plsc, 0, cbRep(struct lscontext, lsiobjcontext.rgobj, iobjMac));
|
||
|
|
||
|
/* Initialize the fixed-size part of the context
|
||
|
*/
|
||
|
plsc->tag = tagLSC;
|
||
|
plsc->pols = pols;
|
||
|
plsc->lscbk = plsci->lscbk;
|
||
|
plsc->fDontReleaseRuns = plsci->fDontReleaseRuns;
|
||
|
|
||
|
|
||
|
plsc->cLinesActive = 0;
|
||
|
plsc->plslineCur = NULL;
|
||
|
|
||
|
plsc->lsstate = LsStateCreatingContext;
|
||
|
|
||
|
plsc->pqhLines = CreateQuickHeap(plsc, limLines,
|
||
|
cbRep(struct lsline, rgplnobj, iobjMac), fFalse);
|
||
|
plsc->pqhAllDNodesRecycled = CreateQuickHeap(plsc, limAllDNodes,
|
||
|
sizeof (struct lsdnode), fTrue);
|
||
|
if (plsc->pqhLines == NULL || plsc->pqhAllDNodesRecycled == NULL )
|
||
|
{
|
||
|
return CannotCreateLsContext(plsc, lserrOutOfMemory);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* create arrays for chunks */
|
||
|
lserr = AllocChunkArrays(&plsc->lschunkcontextStorage, &plsc->lscbk, plsc->pols,
|
||
|
&plsc->lsiobjcontext);
|
||
|
if (lserr != lserrNone)
|
||
|
return CannotCreateLsContext(plsc, lserr);
|
||
|
|
||
|
|
||
|
/* create array for tabs */
|
||
|
plsc->lstabscontext.pcaltbd = plsci->lscbk.pfnNewPtr(pols,
|
||
|
sizeof(LSCALTBD)*limCaltbd);
|
||
|
|
||
|
plsc->lstabscontext.ccaltbdMax = limCaltbd;
|
||
|
|
||
|
if (plsc->lstabscontext.pcaltbd == NULL )
|
||
|
{
|
||
|
return CannotCreateLsContext(plsc, lserrOutOfMemory);
|
||
|
}
|
||
|
|
||
|
/* set links in lstabscontext */
|
||
|
plsc->lstabscontext.plscbk = &plsc->lscbk;
|
||
|
plsc->lstabscontext.pols = plsc->pols;
|
||
|
plsc->lstabscontext.plsdocinf = &plsc->lsdocinf;
|
||
|
|
||
|
|
||
|
/* ****************************************************************** */
|
||
|
/* Initialize the "static" array part of the context
|
||
|
* "Text" is the last element of the array
|
||
|
*/
|
||
|
plsc->lsiobjcontext.iobjMac = iobjMac;
|
||
|
for (iobj = 0; iobj < iobjText; iobj++)
|
||
|
{
|
||
|
lserr = InitObject(plsc, iobj, &plsim[iobj]);
|
||
|
if (lserr != lserrNone)
|
||
|
return CannotCreateLsContext(plsc, lserr);
|
||
|
}
|
||
|
|
||
|
lserr = InitObject(plsc, iobjText, &lsimText);
|
||
|
if (lserr != lserrNone)
|
||
|
return CannotCreateLsContext(plsc, lserr);
|
||
|
|
||
|
/* Set text Config */
|
||
|
lserr = SetTextConfig(PilsobjFromLsc(&plsc->lsiobjcontext, iobjText), &(plsci->lstxtcfg));
|
||
|
if (lserr != lserrNone)
|
||
|
return CannotCreateLsContext(plsc, lserr);
|
||
|
|
||
|
lserr = InitObject(plsc, iobjAutonum, &lsimAutonum);
|
||
|
if (lserr != lserrNone)
|
||
|
return CannotCreateLsContext(plsc, lserr);
|
||
|
|
||
|
/* Set text Config */
|
||
|
lserr = SetAutonumConfig(PilsobjFromLsc(&plsc->lsiobjcontext, iobjAutonum),
|
||
|
&(plsci->lstxtcfg));
|
||
|
if (lserr != lserrNone)
|
||
|
return CannotCreateLsContext(plsc, lserr);
|
||
|
|
||
|
|
||
|
plsc->lsstate = LsStateNotReady; /* nobody can use context before LsSetDoc */
|
||
|
|
||
|
|
||
|
/* we set other variavles by memset, bellow we check that we get what we want */
|
||
|
Assert(plsc->cLinesActive == 0);
|
||
|
Assert(plsc->plslineCur == NULL);
|
||
|
Assert(plsc->fIgnoreSplatBreak == 0);
|
||
|
Assert(plsc->fLimSplat == fFalse);
|
||
|
Assert(plsc->fHyphenated == fFalse);
|
||
|
Assert(plsc->fAdvanceBack == fFalse);
|
||
|
Assert(plsc->grpfManager == 0);
|
||
|
Assert(plsc->urRightMarginBreak == 0);
|
||
|
Assert(plsc->lMarginIncreaseCoefficient == 0);
|
||
|
|
||
|
|
||
|
Assert(plsc->lsdocinf.fDisplay == fFalse);
|
||
|
Assert(plsc->lsdocinf.fPresEqualRef == fFalse);
|
||
|
Assert(plsc->lsdocinf.lsdevres.dxpInch == 0);
|
||
|
Assert(plsc->lsdocinf.lsdevres.dxrInch == 0);
|
||
|
Assert(plsc->lsdocinf.lsdevres.dypInch == 0);
|
||
|
Assert(plsc->lsdocinf.lsdevres.dyrInch == 0);
|
||
|
|
||
|
Assert(plsc->lstabscontext.fTabsInitialized == fFalse);
|
||
|
Assert(plsc->lstabscontext.durIncrementalTab == 0);
|
||
|
Assert(plsc->lstabscontext.urBeforePendingTab == 0);
|
||
|
Assert(plsc->lstabscontext.plsdnPendingTab == NULL);
|
||
|
Assert(plsc->lstabscontext.icaltbdMac == 0);
|
||
|
Assert(plsc->lstabscontext.urColumnMax == 0);
|
||
|
Assert(plsc->lstabscontext.fResolveTabsAsWord97 == fFalse);
|
||
|
|
||
|
Assert(plsc->lsadjustcontext.fLineCompressed == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fLineContainsAutoNumber == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fUnderlineTrailSpacesRM == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fForgetLastTabAlignment == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fNominalToIdealEncounted == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fForeignObjectEncounted == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fTabEncounted == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fNonLeftTabEncounted == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fSubmittedSublineEncounted == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.fAutodecimalTabPresent == fFalse);
|
||
|
Assert(plsc->lsadjustcontext.lskj == lskjNone);
|
||
|
Assert(plsc->lsadjustcontext.lskalign == lskalLeft);
|
||
|
Assert(plsc->lsadjustcontext.lsbrj == lsbrjBreakJustify);
|
||
|
Assert(plsc->lsadjustcontext.urLeftIndent == 0);
|
||
|
Assert(plsc->lsadjustcontext.urStartAutonumberingText == 0);
|
||
|
Assert(plsc->lsadjustcontext.urStartMainText == 0);
|
||
|
Assert(plsc->lsadjustcontext.urRightMarginJustify == 0);
|
||
|
|
||
|
Assert(plsc->lschunkcontextStorage.FChunkValid == fFalse);
|
||
|
Assert(plsc->lschunkcontextStorage.FLocationValid == fFalse);
|
||
|
Assert(plsc->lschunkcontextStorage.FGroupChunk == fFalse);
|
||
|
Assert(plsc->lschunkcontextStorage.FBorderInside == fFalse);
|
||
|
Assert(plsc->lschunkcontextStorage.grpfTnti == 0);
|
||
|
Assert(plsc->lschunkcontextStorage.fNTIAppliedToLastChunk == fFalse);
|
||
|
Assert(plsc->lschunkcontextStorage.locchnkCurrent.clschnk == 0);
|
||
|
Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.fFirstOnLine == fFalse);
|
||
|
Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.cpFirst == fFalse);
|
||
|
Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.urPen == 0);
|
||
|
Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.vrPen == 0);
|
||
|
Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.urColumnMax == 0);
|
||
|
Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.lstflow == 0);
|
||
|
|
||
|
|
||
|
Assert(plsc->lslistcontext.plsdnToFinish == NULL);
|
||
|
Assert(plsc->lslistcontext.plssublCurrent == NULL);
|
||
|
Assert(plsc->lslistcontext.nDepthFormatLineCurrent == 0);
|
||
|
|
||
|
/* Everything worked, so set the output parameter and return success
|
||
|
*/
|
||
|
*pplsc = plsc;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* C A N N O T C R E A T E L S C O N T E X T */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CannotCreateLsContext
|
||
|
%%Contact: igorzv
|
||
|
|
||
|
Parameters:
|
||
|
plsc - partually created context
|
||
|
lseReturn - error code
|
||
|
|
||
|
Utility function called when an error occurs when an LSC is
|
||
|
partially created.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
static LSERR CannotCreateLsContext(PLSC plsc, LSERR lseReturn)
|
||
|
{
|
||
|
plsc->lsstate = LsStateFree; /* otherwise destroy will not work */
|
||
|
(void) LsDestroyContext(plsc);
|
||
|
return lseReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* L S D E S T R O Y C O N T E X T */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: LsDestroyContext
|
||
|
%%Contact: igorzv
|
||
|
|
||
|
Parameters:
|
||
|
plsc - (IN) ptr to line services context
|
||
|
|
||
|
Frees all resources associated with a Line Services context,
|
||
|
which was created by CreateLsContext.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
|
||
|
LSERR WINAPI LsDestroyContext(PLSC plsc)
|
||
|
{
|
||
|
LSERR lserr = lserrNone;
|
||
|
|
||
|
if (plsc != NULL)
|
||
|
{
|
||
|
if (!FIsLSC(plsc))
|
||
|
return lserrInvalidContext;
|
||
|
|
||
|
if (plsc->cLinesActive != 0 || FIsLSCBusy(plsc))
|
||
|
return lserrContextInUse;
|
||
|
|
||
|
plsc->lsstate = LsStateDestroyingContext;
|
||
|
|
||
|
DestroyQuickHeap(plsc->pqhLines);
|
||
|
Assert(plsc->pqhAllDNodesRecycled != NULL);
|
||
|
DestroyQuickHeap(plsc->pqhAllDNodesRecycled);
|
||
|
|
||
|
DisposeChunkArrays(&plsc->lschunkcontextStorage);
|
||
|
|
||
|
plsc->lscbk.pfnDisposePtr(plsc->pols, plsc->lstabscontext.pcaltbd);
|
||
|
|
||
|
|
||
|
lserr = RemoveContextObjects(plsc);
|
||
|
|
||
|
|
||
|
plsc->tag = tagInvalid;
|
||
|
plsc->lscbk.pfnDisposePtr(plsc->pols, plsc);
|
||
|
}
|
||
|
|
||
|
return lserr;
|
||
|
}
|
||
|
|
||
|
static LSERR InitObject(PLSC plsc, DWORD iobj, const LSIMETHODS* plsim)
|
||
|
{
|
||
|
struct OBJ *pobj;
|
||
|
LSERR lserr;
|
||
|
|
||
|
Assert(FIsLSC(plsc));
|
||
|
Assert(plsc->lsstate == LsStateCreatingContext);
|
||
|
Assert(iobj < plsc->lsiobjcontext.iobjMac);
|
||
|
|
||
|
pobj = &(plsc->lsiobjcontext.rgobj[iobj]);
|
||
|
pobj->lsim = *plsim;
|
||
|
Assert(pobj->pilsobj == NULL);
|
||
|
|
||
|
lserr = pobj->lsim.pfnCreateILSObj(plsc->pols, plsc, &(plsc->lscbk), iobj, &(pobj->pilsobj));
|
||
|
if (lserr != lserrNone)
|
||
|
{
|
||
|
if (pobj->pilsobj != NULL)
|
||
|
{
|
||
|
pobj->lsim.pfnDestroyILSObj(pobj->pilsobj);
|
||
|
pobj->pilsobj = NULL;
|
||
|
}
|
||
|
return lserr;
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
|
||
|
}
|
||
|
/* R E M O V E C O N T E X T O B J E C T S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: RemoveContextObjects
|
||
|
%%Contact: igorzv
|
||
|
Parameter:
|
||
|
plsc - (IN) ptr to line services context
|
||
|
|
||
|
Removes a set of installed objects from an LSC.
|
||
|
Destroy all ilsobj
|
||
|
----------------------------------------------------------------------------*/
|
||
|
LSERR RemoveContextObjects(PLSC plsc)
|
||
|
{
|
||
|
DWORD iobjMac;
|
||
|
LSERR lserr, lserrFinal = lserrNone;
|
||
|
DWORD iobj;
|
||
|
PILSOBJ pilsobj;
|
||
|
|
||
|
Assert(FIsLSC(plsc));
|
||
|
Assert(plsc->lsstate == LsStateDestroyingContext);
|
||
|
|
||
|
iobjMac = plsc->lsiobjcontext.iobjMac;
|
||
|
|
||
|
for (iobj = 0; iobj < iobjMac; iobj++)
|
||
|
{
|
||
|
pilsobj = plsc->lsiobjcontext.rgobj[iobj].pilsobj;
|
||
|
if (pilsobj != NULL)
|
||
|
{
|
||
|
lserr = plsc->lsiobjcontext.rgobj[iobj].lsim.pfnDestroyILSObj(pilsobj);
|
||
|
plsc->lsiobjcontext.rgobj[iobj].pilsobj = NULL;
|
||
|
if (lserr != lserrNone)
|
||
|
lserrFinal = lserr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lserrFinal;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
/* F I S L S C O N T E X T V A L I D*/
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: FIsLsContextValid
|
||
|
%%Contact: igorzv
|
||
|
|
||
|
Parameters:
|
||
|
plsc - (IN) ptr to line services context
|
||
|
|
||
|
this function verify that nobody spoiled context, all reasonable integrity checks
|
||
|
should be here
|
||
|
----------------------------------------------------------------------------*/
|
||
|
|
||
|
|
||
|
BOOL FIsLsContextValid(PLSC plsc)
|
||
|
{
|
||
|
DWORD iobjText = IobjTextFromLsc(&plsc->lsiobjcontext);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnCreateILSObj ==CreateILSObjText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnDestroyILSObj == DestroyILSObjText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnSetDoc == SetDocText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnCreateLNObj == CreateLNObjText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnDestroyLNObj == DestroyLNObjText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnTruncateChunk == TruncateText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnFindPrevBreakChunk == FindPrevBreakText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnFindNextBreakChunk == FindNextBreakText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnForceBreakChunk == ForceBreakText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnDisplay == DisplayText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnQueryPointPcp == QueryPointPcpText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnQueryCpPpoint == QueryCpPpointText);
|
||
|
Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnDestroyDObj == DestroyDObjText);
|
||
|
Assert(plsc->lschunkcontextStorage.pcont != NULL);
|
||
|
Assert(plsc->lschunkcontextStorage.pplsdnChunk != NULL);
|
||
|
Assert(plsc->lschunkcontextStorage.locchnkCurrent.plschnk != NULL);
|
||
|
Assert(plsc->lschunkcontextStorage.pplsdnNonText != NULL);
|
||
|
Assert(plsc->lschunkcontextStorage.pfNonTextExpandAfter != NULL);
|
||
|
Assert(plsc->lschunkcontextStorage.pdurOpenBorderBefore != NULL);
|
||
|
Assert(plsc->lschunkcontextStorage.pdurCloseBorderAfter != NULL);
|
||
|
|
||
|
return fTrue; /* if we here than everything OK */
|
||
|
}
|
||
|
#endif
|
||
|
|