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

338 lines
9.1 KiB
C

#include "dnutils.h"
#include "dninfo.h"
#include "iobj.h"
#include "lsdnode.h"
#include "lscbk.h"
#include "qheap.h"
#include "lstext.h"
#include "lsmem.h" /* memset() prototype */
#define FIsOutOfLine(plsc, plsdn) \
(((plsdn) == NULL) || \
(((plsc)->plslineCur->lslinfo.cpLim != 0) && ((plsc)->plslineCur->lslinfo.cpLim <= (plsdn)->cpFirst)))
/* F I N D L I S T D U P */
/*----------------------------------------------------------------------------
%%Function: FindListDup
%%Contact: igorzv
Visit each node in the list of DNODES, until reaching cpLim
Compute dup between start and end points.
----------------------------------------------------------------------------*/
void FindListDup(PLSDNODE plsdnFirst, LSCP cpLim, long *pdup)
{
PLSDNODE plsdn;
/* tolerate pldnFirst == NULL */
*pdup = 0;
plsdn = plsdnFirst;
while (plsdn != NULL && plsdn->cpLimOriginal <= cpLim)
{
Assert(FIsLSDNODE(plsdn));
*pdup += DupFromDnode(plsdn);
plsdn = plsdn->plsdnNext;
}
}
/* F I N D L I S T F I N A L P E N M O V E M E N T*/
/*----------------------------------------------------------------------------
%%Function: FindListFinalPenMovement
%%Contact: igorzv
Visit each node in the list of DNODES, until reaching cpLim
Compute dur dvr dvp between start and end points.
----------------------------------------------------------------------------*/
void FindListFinalPenMovement(PLSDNODE plsdnFirst, PLSDNODE plsdnLast, long *pdur, long *pdvr, long *pdvp)
{
PLSDNODE plsdn;
/* tolerate pldnFirst == NULL */
*pdur = 0;
*pdvr = 0;
*pdvp = 0;
plsdn = plsdnFirst;
while (plsdn != NULL && plsdn->plsdnPrev != plsdnLast)
{
Assert(FIsLSDNODE(plsdn));
*pdur += DurFromDnode(plsdn);
*pdvr += DvrFromDnode(plsdn);
*pdvp += DvpFromDnode(plsdn);
plsdn = plsdn->plsdnNext;
}
}
/* F I N D L I S T D I M S */
/*----------------------------------------------------------------------------
%%Function: FindListDims
%%Contact: igorzv
Visit each node in the list of DNODES, until reaching plsdnLast.
Compute OBJDIM which describes the list.
----------------------------------------------------------------------------*/
LSERR FindListDims(PLSDNODE plsdnFirst, PLSDNODE plsdnLast, OBJDIM* pobjdimList)
{
PLSDNODE plsdn;
long urPen = 0;
long urLim = 0;
long vpPen = 0;
long vrPen = 0;
OBJDIM objdimFound;
long dvpNode, dvrNode, durNode;
long dvpAscentNext;
long dvrAscentNext;
long dvpDescentNext;
long dvrDescentNext;
long dvpLineHeight;
long dvrLineHeight;
POBJDIM pobjdimNode;
BOOL fFindLast;
OBJDIM* pobjdimLastSkiped = NULL;
/* N.B. Tolerate an empty input list! */
Assert(((plsdnFirst == NULL) && (plsdnLast == NULL)) || (FIsLSDNODE(plsdnFirst) && FIsLSDNODE(plsdnLast)));
/* the most efficient way to put zeroes in heights */
memset(&objdimFound, 0, sizeof objdimFound);
/* quick return if list is empty */
if (plsdnFirst == NULL)
{
*pobjdimList = objdimFound; /* in objdim will be zeroes */
return lserrNone;
}
fFindLast = fFalse;
for (plsdn = plsdnFirst; !fFindLast ; plsdn = plsdn->plsdnNext)
{
if (plsdn == NULL)
/* we dont found plsdnLast, so return error */
return lserrInvalidParameter;
if (plsdn == plsdnLast)
fFindLast = fTrue;
if (plsdn->klsdn == klsdnReal)
{
pobjdimNode = &plsdn->u.real.objdim;
durNode = pobjdimNode->dur;
Assert(durNode >= 0);
dvrNode = 0;
dvpNode = 0;
dvpAscentNext = pobjdimNode->heightsPres.dvAscent + vpPen;
dvrAscentNext = pobjdimNode->heightsRef.dvAscent + vrPen;
dvpDescentNext = pobjdimNode->heightsPres.dvDescent - vpPen;
dvrDescentNext = pobjdimNode->heightsRef.dvDescent - vrPen;
dvpLineHeight = pobjdimNode->heightsPres.dvMultiLineHeight;
dvrLineHeight = pobjdimNode->heightsRef.dvMultiLineHeight;
if (dvrLineHeight != dvHeightIgnore) /* dvrLineHeight == dvHeightIgnore */
/* for us is sign that we */
{ /* should not take into account for height calculation
this dnode */
if (objdimFound.heightsPres.dvAscent < dvpAscentNext)
objdimFound.heightsPres.dvAscent = dvpAscentNext;
if (objdimFound.heightsRef.dvAscent < dvrAscentNext)
objdimFound.heightsRef.dvAscent = dvrAscentNext;
if (objdimFound.heightsPres.dvDescent < dvpDescentNext)
objdimFound.heightsPres.dvDescent = dvpDescentNext;
if (objdimFound.heightsRef.dvDescent < dvrDescentNext)
objdimFound.heightsRef.dvDescent = dvrDescentNext;
if (objdimFound.heightsPres.dvMultiLineHeight < dvpLineHeight)
objdimFound.heightsPres.dvMultiLineHeight = dvpLineHeight;
if (objdimFound.heightsRef.dvMultiLineHeight < dvrLineHeight)
objdimFound.heightsRef.dvMultiLineHeight = dvrLineHeight;
}
else /* if final heights is 0, we will take ascent and desent from
this dnode */
{
pobjdimLastSkiped = pobjdimNode;
}
}
else /* klsdnPenOrBorder*/
{
dvpNode = plsdn->u.pen.dvp;
durNode = plsdn->u.pen.dur;
dvrNode = plsdn->u.pen.dvr;
}
vpPen += dvpNode;
urPen += durNode;
vrPen += dvrNode;
if (urLim < urPen)
urLim = urPen;
}
if (objdimFound.heightsRef.dvAscent == 0 && objdimFound.heightsRef.dvDescent == 0
&& pobjdimLastSkiped != NULL)
{
objdimFound.heightsPres.dvAscent = pobjdimLastSkiped->heightsPres.dvAscent + vpPen;
objdimFound.heightsRef.dvAscent = pobjdimLastSkiped->heightsRef.dvAscent + vrPen;
objdimFound.heightsPres.dvDescent = pobjdimLastSkiped->heightsPres.dvDescent - vpPen;
objdimFound.heightsRef.dvDescent = pobjdimLastSkiped->heightsRef.dvDescent - vrPen;
objdimFound.heightsPres.dvMultiLineHeight = dvHeightIgnore;
objdimFound.heightsRef.dvMultiLineHeight = dvHeightIgnore;
}
*pobjdimList = objdimFound;
pobjdimList->dur = urLim;
return lserrNone;
}
/* D E S T R O Y D N O D E L I S T */
/*----------------------------------------------------------------------------
%%Function: DestroyDnodeList
%%Contact: igorzv
Parameters:
plscbk - (IN) callbacks
pols - (IN) pols to pass for callbacks
plsiobjcontext - (IN) object handlers
plsdn - (IN) first dnode in list
fDontReleaseRuns - (IN) not to call release run
----------------------------------------------------------------------------*/
LSERR DestroyDnodeList(LSCBK* plscbk, POLS pols, PLSIOBJCONTEXT plsiobjcontext,
PLSDNODE plsdn, BOOL fDontReleaseRuns)
{
LSERR lserr, lserrFinal = lserrNone;
PLSDNODE plsdnNext;
PDOBJ pdobj;
PLSRUN plsrun;
DWORD iobj;
if (plsdn == NULL)
return lserrNone;
Assert(FIsLSDNODE(plsdn));
/* link with this dnode should be broken before */
Assert(plsdn->plsdnPrev == NULL || plsdn->plsdnPrev->plsdnNext != plsdn );
for (; plsdn != NULL; plsdn = plsdnNext)
{
Assert(FIsLSDNODE(plsdn));
if (plsdn->klsdn == klsdnReal)
{
if (plsdn->u.real.pinfosubl != NULL)
{
if (plsdn->u.real.pinfosubl->rgpsubl != NULL)
{
plscbk->pfnDisposePtr(pols, plsdn->u.real.pinfosubl->rgpsubl);
}
plscbk->pfnDisposePtr(pols, plsdn->u.real.pinfosubl);
}
iobj = plsdn->u.real.lschp.idObj;
plsrun = plsdn->u.real.plsrun;
pdobj = plsdn->u.real.pdobj;
}
else
{
Assert (FIsDnodePen(plsdn) || FIsDnodeBorder(plsdn));
iobj = 0;
plsrun = NULL;
pdobj = NULL;
}
if (plsrun != NULL && !fDontReleaseRuns)
{
lserr = plscbk->pfnReleaseRun(pols, plsrun);
if (lserr != lserrNone && lserrFinal == lserrNone)
lserrFinal = lserr;
}
if (pdobj != NULL)
{
lserr = (PLsimFromLsc(plsiobjcontext, iobj))->pfnDestroyDObj (pdobj);
if (lserr != lserrNone && lserrFinal == lserrNone)
lserrFinal = lserr;
}
plsdn->tag = tagInvalid;
plsdnNext = plsdn->plsdnNext;
}
return lserrFinal;
}
/* ---------------------------------------------------------------------- */
/* D U R B O R D E R F R O M D N O D E I N S I D E*/
/*----------------------------------------------------------------------------
%%Function: DurBorderFromDnodeInside
%%Contact: igorzv
Parameters:
plsdn - (IN) dnode inside borders
----------------------------------------------------------------------------*/
long DurBorderFromDnodeInside(PLSDNODE plsdn) /* IN: dnode inside borders */
{
PLSDNODE plsdnBorder = plsdn;
while (!FIsDnodeBorder(plsdnBorder))
{
plsdnBorder = plsdnBorder->plsdnPrev;
Assert(FIsLSDNODE(plsdnBorder));
}
Assert(FIsDnodeBorder(plsdnBorder));
Assert(plsdnBorder->fOpenBorder);
return plsdnBorder->u.pen.dur;
}
/* ---------------------------------------------------------------------- */
/* F S P A C E S O N L Y*/
/*----------------------------------------------------------------------------
%%Function: FSpacesOnly
%%Contact: igorzv
Parameters:
plsdn - (IN) dnode
iObjText- (IN) id for text dnode
----------------------------------------------------------------------------*/
BOOL FSpacesOnly(PLSDNODE plsdn, DWORD iObjText)
{
DWORD dcpTrailing;
long durTrailing;
if (FIsDnodeSplat(plsdn))
return fTrue;
else if (FIsDnodeReal(plsdn)
&& (IdObjFromDnode(plsdn) == iObjText)
&& !(plsdn->fTab))
{
GetTrailInfoText(PdobjFromDnode(plsdn), plsdn->dcp,
&dcpTrailing, &durTrailing);
if (dcpTrailing == plsdn->dcp)
return fTrue;
}
return fFalse;
}