338 lines
9.1 KiB
C
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;
|
|
}
|