#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