windows-nt/Source/XPSP1/NT/windows/richedit/lssrc/lscontxt.c
2020-09-26 16:20:57 +08:00

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