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

1846 lines
54 KiB
C

#include "lsmem.h"
#include "lstxtnti.h"
#include "lstxtmod.h"
#include "lstxtmap.h"
#include "lstxtbrs.h"
#include "lsdnset.h"
#include "lsdntext.h"
#include "lschp.h"
#include "lstxtffi.h"
#include "tnti.h"
#include "txtils.h"
#include "txtln.h"
#include "txtobj.h"
#include "lschnke.h"
#include "lsems.h"
#include "objdim.h"
#define max(a,b) ((a) < (b) ? (b) : (a))
#define maskAllCharBasedArrays (fTntiModWidthOnRun | fTntiModWidthSpace | fTntiModWidthPairs | \
fTntiCompressOnRun | fTntiCompressSpace | fTntiCompressTable | \
fTntiExpandOnRun | fTntiExpandSpace | fTntiExpandTable)
#define maskModWidth (fTntiModWidthOnRun | fTntiModWidthSpace | fTntiModWidthPairs)
#define FModWidthSomeDobj(n) (rglschnk[(n)].plschp->fModWidthOnRun || \
rglschnk[(n)].plschp->fModWidthSpace || \
rglschnk[(n)].plschp->fModWidthPairs)
static LSERR PrepareAllArraysGetModWidth(DWORD grpfTnti, DWORD cchnk, const LSCHNKE* rglschnk);
static LSERR ApplyKern(LSTFLOW lstflow, DWORD cchnk, const LSCHNKE* rglschnk);
static LSERR CheckApplyKernBetweenRuns(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjPrev, long itxtobjCur);
static LSERR ApplyKernToRun(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjCur);
static BOOL GetPrevImportantRun(const LSCHNKE* rglschnk, long itxtobj, long* pitxtobjPrev);
static BOOL GetNextImportantRun(DWORD cchnk, const LSCHNKE* rglschnk, long itxtobj, long* pitxtobjNext);
static LSERR GetModWidthClasses(DWORD cchnk, const LSCHNKE* rglschnk);
static LSERR ApplyModWidth(LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk);
static LSERR ApplySnapGrid(DWORD cchnk, const LSCHNKE* rglschnk);
static LSERR ApplyModWidthToRun(LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk, long itxtobjCur);
static LSERR CheckApplyModWidthBetweenRuns(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjPrev, long itxtobjCur);
static LSERR CheckApplyPunctStartLine(PILSOBJ pilsobj, PLSRUN plsrun, LSEMS* plsems, long iwch,
long* pddurChange);
static LSERR CheckApplyModWidthSpace(PILSOBJ pilsobj, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext,
LSEMS* plsems, long iwchPrev, long iwchCur, long iwchNext, long* pddurChange);
static LSERR CheckApplyModWidthOnRun(PILSOBJ pilsobj, PTXTOBJ ptxtobjPrev, PLSRUN plsrunPrev, PLSRUN plsrunCur,
LSEMS* plsems, long iwchFirst, long iwchSecond, long* pddurChange);
static LSERR ApplySnapChanges(PILSOBJ pilsobj, const LSCHNKE* rglschnk, long iwchFirstSnapped,
long itxtobjFirstSnapped, long iwchPrev, long itxtobjPrev, long durTotal);
static LSERR UndoAppliedModWidth(PILSOBJ pilsobj, const LSCHNKE* rglschnk,
long itxtobj, long iwch, BYTE side, long* pdurUndo);
static LSERR CleanUpGrid(PILSOBJ pilsobj, PLSRUN* rgplsrun, LSCP* rgcp, BOOL* rgfSnapped,
LSERR lserr);
static long CalcSnapped(long urPen, long urColumnMax, long cGrid, long durGridWhole, long durGridRem);
static LSERR ApplyGlyphs(LSTFLOW lstflow, DWORD cchnk, const LSCHNKE* rglschnk);
static LSERR ApplyGlyphsToRange(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjFirst, long itxtobjLast);
static LSERR CheckReallocGlyphs(PLNOBJ plnobj, long cglyphs);
static LSERR FixGlyphSpaces(LSTFLOW lstflow, const LSCHNKE* rglschnk,
long itxtobjFirst, long igindVeryFirst, long itxtobjLast);
static LSERR FixTxtobjs(const LSCHNKE* rglschnk, long itxtobjFirst, long igindFirst, long itxtobjLast);
static LSERR Realloc(PILSOBJ pols, void** pInOut, long cbytes);
static void CopyGindices(PLNOBJ plnobj, GINDEX* pgindex, PGPROP pgprop, long cgind, long* pigindFirst);
#define CheckApplyModWidthTwoChars(pilsobj, plsemsFirst, plsemsSecond,\
iwchFirst, iwchSecond, pddurChangeFirst, pddurChangeSecond) \
{\
LSPAIRACT lspairact;\
MWCLS mwclsCur;\
MWCLS mwclsNext;\
BYTE side;\
\
*(pddurChangeFirst) = 0;\
*(pddurChangeSecond) = 0;\
mwclsCur = (BYTE)(pilsobj)->ptxtinf[((iwchFirst))].mwcls;\
mwclsNext = (BYTE)(pilsobj)->ptxtinf[(iwchSecond)].mwcls;\
Assert(mwclsCur < (pilsobj)->cModWidthClasses);\
Assert(mwclsNext < (pilsobj)->cModWidthClasses);\
lspairact = \
(pilsobj)->plspairact[(pilsobj)->pilspairact[(pilsobj)->cModWidthClasses * mwclsCur + mwclsNext]];\
\
if (lspairact.lsactFirst.side != sideNone)\
{\
GetChanges(lspairact.lsactFirst, (plsemsFirst), (pilsobj)->pdur[((iwchFirst))], fFalse, &side, (pddurChangeFirst));\
ApplyChanges((pilsobj), ((iwchFirst)), side, *(pddurChangeFirst));\
/* (pilsobj)->ptxtinf[((iwchFirst))].fModWidthPair = fTrue;*/\
}\
\
if (lspairact.lsactSecond.side != sideNone)\
{\
GetChanges(lspairact.lsactSecond, (plsemsSecond), (pilsobj)->pdur[(iwchSecond)], fFalse, &side, (pddurChangeSecond));\
ApplyChanges((pilsobj), (iwchSecond), side, *(pddurChangeSecond));\
/* (pilsobj)->ptxtinf[(iwchSecond)].fModWidthPair = fTrue;*/\
}\
\
}
LSERR NominalToIdealText(DWORD grpfTnti, LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk)
{
LSERR lserr;
PILSOBJ pilsobj;
Assert(cchnk > 0);
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
lserr = PrepareAllArraysGetModWidth(grpfTnti, cchnk, rglschnk);
if (lserr != lserrNone) return lserr;
if (grpfTnti & fTntiGlyphBased)
{
lserr = ApplyGlyphs(lstflow, cchnk, rglschnk);
if (lserr != lserrNone) return lserr;
}
if (grpfTnti & fTntiKern)
{
lserr = ApplyKern(lstflow, cchnk, rglschnk);
if (lserr != lserrNone) return lserr;
}
if ((grpfTnti & maskModWidth) || (pilsobj->grpf & fTxtPunctStartLine))
{
lserr = ApplyModWidth(lstflow, fFirstOnLine, fAutoNumberPresent, cchnk, rglschnk);
if (lserr != lserrNone) return lserr;
}
if (pilsobj->fSnapGrid)
{
#ifdef DEBUG
{
BOOL fInChildList;
lserr = LsdnFInChildList(pilsobj->plsc, ((PTXTOBJ)rglschnk[0].pdobj)->plsdnUpNode, &fInChildList);
Assert(lserr == lserrNone);
Assert(!(grpfTnti & fTntiGlyphBased) || fInChildList);
}
#endif
lserr = ApplySnapGrid(cchnk, rglschnk);
if (lserr != lserrNone) return lserr;
}
return lserr;
}
/* G E T F I R S T C H A R I N C H U N K */
/*----------------------------------------------------------------------------
%%Function: GetFirstCharInChunk
%%Contact: sergeyge
Prepares information about first visible char in chunk
----------------------------------------------------------------------------*/
LSERR GetFirstCharInChunk(DWORD cchnk, const LSCHNKE* rglschnk, BOOL* pfSuccessful,
WCHAR* pwch, PLSRUN* pplsrun, PHEIGHTS pheights, MWCLS* pmwcls)
{
LSERR lserr;
PILSOBJ pilsobj;
long itxtobj;
long iwch;
PTXTOBJ ptxtobj;
OBJDIM objdim;
Assert(cchnk > 0);
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
*pfSuccessful = fFalse;
if (GetNextImportantRun(cchnk, rglschnk, 0, &itxtobj))
{
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
if (ptxtobj->txtf & txtfModWidthClassed)
{
Assert(!(ptxtobj->txtf & txtfGlyphBased));
*pfSuccessful = fTrue;
iwch = ptxtobj->iwchFirst;
*pwch = pilsobj->pwchOrig[iwch];
*pplsrun = rglschnk[itxtobj].plsrun;
*pmwcls = (MWCLS)pilsobj->ptxtinf[iwch].mwcls;
lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &objdim);
if (lserr != lserrNone) return lserr;
*pheights = objdim.heightsRef;
}
}
return lserrNone;
}
/* G E T L A S T C H A R I N C H U N K */
/*----------------------------------------------------------------------------
%%Function: GetLastCharInChunk
%%Contact: sergeyge
Prepares information about first visible char in chunk
----------------------------------------------------------------------------*/
LSERR GetLastCharInChunk(DWORD cchnk, const LSCHNKE* rglschnk, BOOL* pfSuccessful,
WCHAR* pwch, PLSRUN* pplsrun, PHEIGHTS pheights, MWCLS* pmwcls)
{
LSERR lserr;
PILSOBJ pilsobj;
long itxtobj;
long iwch;
PTXTOBJ ptxtobj;
OBJDIM objdim;
Assert(cchnk > 0);
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
*pfSuccessful = fFalse;
if ( GetPrevImportantRun(rglschnk, cchnk - 1, &itxtobj))
{
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
if (ptxtobj->txtf & txtfModWidthClassed)
{
Assert(!(ptxtobj->txtf & txtfGlyphBased));
*pfSuccessful = fTrue;
iwch = ptxtobj->iwchLim - 1;
*pwch = pilsobj->pwchOrig[iwch];
*pplsrun = rglschnk[itxtobj].plsrun;
*pmwcls = (MWCLS)pilsobj->ptxtinf[iwch].mwcls;
lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &objdim);
if (lserr != lserrNone) return lserr;
*pheights = objdim.heightsRef;
}
}
return lserrNone;
}
/* M O D I F Y F I R S T C H A R I N C H U N K */
/*----------------------------------------------------------------------------
%%Function: ModifyFirstCharInChunk
%%Contact: sergeyge
Prepares information about first visible char in chunk
----------------------------------------------------------------------------*/
LSERR ModifyFirstCharInChunk(DWORD cchnk, const LSCHNKE* rglschnk, long durChange)
{
LSERR lserr;
PILSOBJ pilsobj;
long itxtobj;
long iwch;
PTXTOBJ ptxtobj;
BOOL fFound;
Assert(cchnk > 0);
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
fFound = GetNextImportantRun(cchnk, rglschnk, 0, &itxtobj);
Assert(fFound);
Assert(pilsobj->pdurLeft != NULL);
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
Assert(!(ptxtobj->txtf & txtfGlyphBased));
Assert(ptxtobj->txtf & txtfModWidthClassed);
iwch = ptxtobj->iwchFirst;
ApplyChanges(pilsobj, iwch, sideLeft, durChange);
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, durChange);
return lserrNone;
}
/* M O D I F Y L A S T C H A R I N C H U N K */
/*----------------------------------------------------------------------------
%%Function: ModifyLastCharInChunk
%%Contact: sergeyge
Prepares information about first visible char in chunk
----------------------------------------------------------------------------*/
LSERR ModifyLastCharInChunk(DWORD cchnk, const LSCHNKE* rglschnk, long durChange)
{
LSERR lserr;
PILSOBJ pilsobj;
long itxtobj;
long iwch;
PTXTOBJ ptxtobj;
BOOL fFound;
Assert(cchnk > 0);
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
fFound = GetPrevImportantRun(rglschnk, cchnk-1, &itxtobj);
Assert(fFound);
Assert(pilsobj->pdurRight != NULL);
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
Assert(!(ptxtobj->txtf & txtfGlyphBased));
Assert(ptxtobj->txtf & txtfModWidthClassed);
iwch = ptxtobj->iwchLim - 1;
ApplyChanges(pilsobj, iwch, sideRight, durChange);
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, durChange);
return lserrNone;
}
/* C U T T E X T D O B J */
/*----------------------------------------------------------------------------
%%Function: CutTextDobj
%%Contact: sergeyge
Cuts characters according to dcpMaxContext
----------------------------------------------------------------------------*/
LSERR CutTextDobj(DWORD cchnk, const LSCHNKE* rglschnk)
{
LSERR lserr;
PILSOBJ pilsobj;
PTXTOBJ ptxtobj;
long itxtobjLast;
long dcp;
long dur;
long iwchLim;
long igindLim;
long iwSpacesFirst;
long iwSpacesLim;
BOOL fNonSpaceBeforeFound;
long itxtobjBefore;
long iwchBefore;
OBJDIM objdim;
long itxtobj;
BOOL fFixSpaces = fTrue;
Assert(cchnk > 0);
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
iwchLim = ((PTXTOBJ)rglschnk[cchnk - 1].pdobj)->iwchLim - rglschnk[cchnk-1].plschp->dcpMaxContext + 1;
itxtobjLast = cchnk - 1;
while (itxtobjLast >= 0 && iwchLim <= ((PTXTOBJ)rglschnk[itxtobjLast].pdobj)->iwchFirst)
itxtobjLast--;
if (itxtobjLast >= 0)
{
ptxtobj = (PTXTOBJ)rglschnk[itxtobjLast].pdobj;
fNonSpaceBeforeFound = FindNonSpaceBefore(rglschnk, itxtobjLast, iwchLim - 1, &itxtobjBefore, &iwchBefore);
if (fNonSpaceBeforeFound)
{
if (iwchBefore != iwchLim - 1)
{
Assert(itxtobjBefore >= 0);
itxtobjLast = itxtobjBefore;
iwchLim = iwchBefore + 1;
ptxtobj = (PTXTOBJ)rglschnk[itxtobjLast].pdobj;
}
dcp = iwchLim - ptxtobj->iwchFirst;
lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &objdim);
Assert(lserr == lserrNone);
dur = objdim.dur;
Assert(ptxtobj->iwchFirst + (long)dcp <= ptxtobj->iwchLim);
if (ptxtobj->txtf & txtfGlyphBased)
{
long igind;
Assert(iwchLim >= ptxtobj->iwchFirst);
/* REVIEW sergeyge: We should take IwchLastFromIwch instead and get rid of fFixSpaces---
right?
*/
if (iwchLim > ptxtobj->iwchFirst)
iwchLim = IwchPrevLastFromIwch(ptxtobj, iwchLim) + 1;
/* if part of Dnode is to be left, calculate this part
else delete the whole Dnode
*/
if (iwchLim > ptxtobj->iwchFirst)
{
igindLim = IgindLastFromIwch(ptxtobj, iwchLim - 1) + 1;
for (igind = igindLim; igind < ptxtobj->igindLim; igind++)
dur -= pilsobj->pdurGind[igind];
ptxtobj->iwchLim = iwchLim;
ptxtobj->igindLim = igindLim;
lserr = LsdnSetSimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, dur);
Assert (lserr == lserrNone);
lserr = LsdnResetDcp(pilsobj->plsc,
ptxtobj->plsdnUpNode, iwchLim - ptxtobj->iwchFirst);
Assert (lserr == lserrNone);
}
else
{
itxtobjLast--;
fFixSpaces = fFalse;
}
}
else
{
long iwch;
for (iwch = iwchLim; iwch < ptxtobj->iwchLim; iwch++)
dur -= pilsobj->pdur[iwch];
ptxtobj->iwchLim = iwchLim;
lserr = LsdnSetSimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, dur);
Assert (lserr == lserrNone);
lserr = LsdnResetDcp(pilsobj->plsc, ptxtobj->plsdnUpNode, dcp);
Assert (lserr == lserrNone);
}
if (fFixSpaces)
{
Assert(ptxtobj == (PTXTOBJ)rglschnk[itxtobjLast].pdobj);
iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst;
iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
while (iwSpacesLim > iwSpacesFirst && pilsobj->pwSpaces[iwSpacesLim - 1] > iwchLim - 1)
{
iwSpacesLim--;
}
ptxtobj->u.reg.iwSpacesLim = iwSpacesLim;
Assert(iwchLim == ptxtobj->iwchLim);
if (iwSpacesLim - iwSpacesFirst == iwchLim - ptxtobj->iwchFirst &&
!(pilsobj->grpf & fTxtSpacesInfluenceHeight) &&
objdim.heightsRef.dvMultiLineHeight != dvHeightIgnore)
{
objdim.dur = dur;
objdim.heightsRef.dvMultiLineHeight = dvHeightIgnore;
objdim.heightsPres.dvMultiLineHeight = dvHeightIgnore;
lserr = LsdnResetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &objdim);
Assert (lserr == lserrNone);
}
}
}
else
{
/* dirty triangle: in the case of fNonSpaceFound==fFalse, correct itxtobjLast */
itxtobjLast = -1;
}
}
for (itxtobj = itxtobjLast + 1; itxtobj < (long)cchnk; itxtobj++)
{
lserr = LsdnSetSimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobj].pdobj)->plsdnUpNode, 0);
Assert (lserr == lserrNone);
lserr = LsdnResetDcp(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobj].pdobj)->plsdnUpNode, 0);
Assert (lserr == lserrNone);
}
return lserrNone;
}
/* Internal functions implementation */
static LSERR PrepareAllArraysGetModWidth(DWORD grpfTnti, DWORD cchnk, const LSCHNKE* rglschnk)
{
LSERR lserr;
PLNOBJ plnobj;
PILSOBJ pilsobj;
plnobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj;
pilsobj = plnobj->pilsobj;
Assert ((grpfTnti & maskAllCharBasedArrays) || (pilsobj->grpf & fTxtPunctStartLine) ||
(pilsobj->grpf & fTxtHangingPunct) || (grpfTnti & fTntiGlyphBased) ||
(grpfTnti & fTntiKern) || pilsobj->fSnapGrid);
/* if we got to nti some adjustment is needed and we must allocate pdurAdjust */
if (pilsobj->pduAdjust == NULL)
{
pilsobj->pduAdjust = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax );
if (pilsobj->pduAdjust == NULL)
{
return lserrOutOfMemory;
}
}
if ( (grpfTnti & maskAllCharBasedArrays) || (pilsobj->grpf & fTxtPunctStartLine) ||
(pilsobj->grpf & fTxtHangingPunct) || pilsobj->fSnapGrid || (grpfTnti & fTntiGlyphBased))
{
Assert(pilsobj->pduAdjust != NULL);
if (pilsobj->pdurRight == NULL)
{
Assert (pilsobj->pdurLeft == NULL);
Assert(pilsobj->ptxtinf == NULL);
pilsobj->pdurRight = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax );
pilsobj->pdurLeft = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax );
pilsobj->ptxtinf = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(TXTINF) * pilsobj->wchMax );
if (pilsobj->pdurRight == NULL || pilsobj->pdurLeft == NULL || pilsobj->ptxtinf == NULL)
{
return lserrOutOfMemory;
}
memset(pilsobj->pdurRight, 0, sizeof(long) * pilsobj->wchMax );
memset(pilsobj->pdurLeft, 0, sizeof(long) * pilsobj->wchMax );
memset(pilsobj->ptxtinf, 0, sizeof(TXTINF) * pilsobj->wchMax);
}
pilsobj->fNotSimpleText = fTrue;
}
if (grpfTnti & fTntiGlyphBased)
{
lserr = CheckReallocGlyphs(plnobj, pilsobj->wchMax - 2);
if (lserr != lserrNone) return lserr;
}
if ( (grpfTnti & maskAllCharBasedArrays) || (pilsobj->grpf & fTxtPunctStartLine) ||
(pilsobj->grpf & fTxtHangingPunct) || pilsobj->fSnapGrid)
{
lserr = GetModWidthClasses(cchnk, rglschnk);
if (lserr != lserrNone) return lserr;
}
return lserrNone;
}
static LSERR ApplyKern(LSTFLOW lstflow, DWORD cchnk, const LSCHNKE* rglschnk)
{
LSERR lserr;
PILSOBJ pilsobj;
PLNOBJ plnobj;
long itxtobjPrev = 0;
long itxtobjCur;
BOOL fFoundNextRun;
BOOL fFoundKernedPrevRun;
plnobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj;
pilsobj = plnobj->pilsobj;
fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, 0, &itxtobjCur);
fFoundKernedPrevRun = fFalse;
while (fFoundNextRun)
{
if (fFoundKernedPrevRun && rglschnk[itxtobjCur].plschp->fApplyKern)
{
lserr = CheckApplyKernBetweenRuns(lstflow, rglschnk, itxtobjPrev, itxtobjCur);
if (lserr != lserrNone) return lserr;
}
if (rglschnk[itxtobjCur].plschp->fApplyKern)
{
lserr = ApplyKernToRun(lstflow, rglschnk, itxtobjCur);
if (lserr != lserrNone) return lserr;
fFoundKernedPrevRun = fTrue;
itxtobjPrev = itxtobjCur;
}
else
{
fFoundKernedPrevRun = fFalse;
}
fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, itxtobjCur + 1, &itxtobjCur);
}
return lserrNone;
}
static LSERR CheckApplyKernBetweenRuns(LSTFLOW lstflow, const LSCHNKE* rglschnk,
long itxtobjPrev, long itxtobjCur)
{
LSERR lserr;
PTXTOBJ ptxtobj;
PLNOBJ plnobj;
PILSOBJ pilsobj;
long iwchLim;
BOOL fKernPrevRun;
long dduKern;
WCHAR* pwch = NULL;
WCHAR rgwchTwo[2];
long dduAdjust;
ptxtobj = (PTXTOBJ)rglschnk[itxtobjPrev].pdobj;
plnobj = ptxtobj->plnobj;
pilsobj = plnobj->pilsobj;
Assert(!(ptxtobj->txtf & txtfGlyphBased));
lserr = (*pilsobj->plscbk->pfnCheckRunKernability)(pilsobj->pols, rglschnk[itxtobjPrev].plsrun,
rglschnk[itxtobjCur].plsrun, &fKernPrevRun);
if (lserr != lserrNone) return lserr;
if (fKernPrevRun)
{
iwchLim = ptxtobj->iwchLim;
if (iwchLim == ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst)
{
pwch = &pilsobj->pwchOrig[iwchLim - 1];
}
else
{
rgwchTwo[0] = pilsobj->pwchOrig[iwchLim - 1];
rgwchTwo[1] = pilsobj->pwchOrig[((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst];
pwch = rgwchTwo;
}
lserr = (*pilsobj->plscbk->pfnGetRunCharKerning)(pilsobj->pols, rglschnk[itxtobjPrev].plsrun,
lsdevReference, pwch, 2, lstflow, (int*)&dduKern);
if (lserr != lserrNone) return lserr;
dduAdjust = max(-pilsobj->pdur[iwchLim - 1], dduKern);
pilsobj->pdur[iwchLim - 1] += dduAdjust;
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, dduAdjust);
if (lserr != lserrNone) return lserr;
if (pilsobj->fDisplay)
{
if (!pilsobj->fPresEqualRef)
{
lserr = (*pilsobj->plscbk->pfnGetRunCharKerning)(pilsobj->pols, rglschnk[itxtobjPrev].plsrun,
lsdevPres, pwch, 2, lstflow, (int*)&dduKern);
if (lserr != lserrNone) return lserr;
dduAdjust = max(-plnobj->pdup[iwchLim - 1], dduKern);
plnobj->pdup[iwchLim - 1] += dduAdjust;
}
else
{
plnobj->pdup[iwchLim - 1] = pilsobj->pdur[iwchLim-1];
}
}
}
return lserrNone;
}
static LSERR ApplyKernToRun(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjCur)
{
LSERR lserr;
PTXTOBJ ptxtobj;
PLNOBJ plnobj;
PILSOBJ pilsobj;
long iwchFirst;
long iwchLim;
long iwch;
long dduAdjust;
long ddurChange;
ptxtobj = (PTXTOBJ)rglschnk[itxtobjCur].pdobj;
plnobj = ptxtobj->plnobj;
pilsobj = plnobj->pilsobj;
Assert(!(ptxtobj->txtf & txtfGlyphBased));
Assert(pilsobj->pduAdjust != NULL);
iwchFirst = ptxtobj->iwchFirst;
iwchLim = ptxtobj->iwchLim;
Assert (iwchLim > iwchFirst);
if (iwchLim == iwchFirst + 1)
return lserrNone;
lserr = (*pilsobj->plscbk->pfnGetRunCharKerning)(pilsobj->pols, rglschnk[itxtobjCur].plsrun, lsdevReference,
&pilsobj->pwchOrig[iwchFirst], iwchLim - iwchFirst, lstflow, (int*)&pilsobj->pduAdjust[iwchFirst]);
if (lserr != lserrNone) return lserr;
ddurChange = 0;
for (iwch = iwchFirst; iwch < iwchLim - 1; iwch++)
{
dduAdjust = max(-pilsobj->pdur[iwch], pilsobj->pduAdjust[iwch]);
pilsobj->pdur[iwch] += dduAdjust;
ddurChange += dduAdjust;
}
if (ddurChange != 0)
{
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, ddurChange);
if (lserr != lserrNone) return lserr;
}
if (pilsobj->fDisplay)
{
if (!pilsobj->fPresEqualRef)
{
lserr = (*pilsobj->plscbk->pfnGetRunCharKerning)(pilsobj->pols, rglschnk[itxtobjCur].plsrun, lsdevPres,
&plnobj->pwch[iwchFirst], iwchLim - iwchFirst, lstflow, (int*)&pilsobj->pduAdjust[iwchFirst]);
if (lserr != lserrNone) return lserr;
for (iwch = iwchFirst; iwch < iwchLim - 1; iwch++)
{
dduAdjust = max(-plnobj->pdup[iwch], pilsobj->pduAdjust[iwch]);
plnobj->pdup[iwch] += dduAdjust;
}
}
else
{
memcpy(&plnobj->pdup[iwchFirst], &pilsobj->pdur[iwchFirst], sizeof(long) * (iwchLim - iwchFirst) );
}
}
return lserrNone;
}
static BOOL GetPrevImportantRun(const LSCHNKE* rglschnk, long itxtobj, long* pitxtobjPrev)
{
PTXTOBJ ptxtobj;
while (itxtobj >= 0 /*&& !fFound (fFound logic changed to break)*/)
{
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
if (!(ptxtobj->txtf & txtfSkipAtNti))
{
/*fFound = fTrue;*/
break;
}
else
{
itxtobj--;
}
}
*pitxtobjPrev = itxtobj;
return (itxtobj >= 0);
}
static BOOL GetNextImportantRun(DWORD cchnk, const LSCHNKE* rglschnk, long itxtobj, long* pitxtobjNext)
{
PTXTOBJ ptxtobj;
while (itxtobj < (long)cchnk /*&& !fFound (fFound logic changed to break)*/)
{
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
if (!(ptxtobj->txtf & txtfSkipAtNti))
{
/*fFound = fTrue;*/
break;
}
else
{
itxtobj++;
}
}
*pitxtobjNext = itxtobj;
return (itxtobj < (long)cchnk);
}
static LSERR ApplyModWidth(LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk)
{
LSERR lserr;
PILSOBJ pilsobj;
PLNOBJ plnobj;
long itxtobjPrev=0;
long itxtobjCur;
BOOL fFoundNextRun;
BOOL fFoundModWidthPrevRun;
plnobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj;
pilsobj = plnobj->pilsobj;
fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, 0, &itxtobjCur);
fFoundModWidthPrevRun = fFalse;
while (fFoundNextRun)
{
if (fFoundModWidthPrevRun && FModWidthSomeDobj(itxtobjCur))
{
lserr = CheckApplyModWidthBetweenRuns(lstflow, rglschnk, itxtobjPrev, itxtobjCur);
if (lserr != lserrNone) return lserr;
}
lserr = ApplyModWidthToRun(lstflow, fFirstOnLine, fAutoNumberPresent,cchnk, rglschnk, itxtobjCur);
if (lserr != lserrNone) return lserr;
fFoundModWidthPrevRun = FModWidthSomeDobj(itxtobjCur);
itxtobjPrev = itxtobjCur;
fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, itxtobjCur + 1, &itxtobjCur);
}
return lserrNone;
}
static LSERR ApplyModWidthToRun(LSTFLOW lstflow, BOOL fFirstOnLine, BOOL fAutoNumberPresent, DWORD cchnk, const LSCHNKE* rglschnk, long itxtobjCur)
{
LSERR lserr;
PTXTOBJ ptxtobj;
PLNOBJ plnobj;
PILSOBJ pilsobj;
long iwchVeryFirst;
long iwchVeryLim;
long iwchFirst;
long iwchLim;
long iwch;
long iwchPrev;
long iwchNext;
LSEMS lsems;
PLSRUN plsrun;
PLSRUN plsrunPrev;
PLSRUN plsrunNext;
long itxtobjPrev;
long itxtobjNext;
BOOL fFoundPrevRun;
BOOL fFoundNextRun;
long ddurChangeFirst;
long ddurChangeSecond;
long ddurChange;
WCHAR* pwchOrig;
ptxtobj = (PTXTOBJ)rglschnk[itxtobjCur].pdobj;
plnobj = ptxtobj->plnobj;
pilsobj = plnobj->pilsobj;
plsrun = rglschnk[itxtobjCur].plsrun;
lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrun, lstflow, &lsems);
if (lserr != lserrNone) return lserr;
Assert(ptxtobj->iwchLim > ptxtobj->iwchFirst);
ddurChange = 0;
/* all changes to the last char which depend on the next run will be applied in the next
call to ApplyModWidthBetween runs
*/
iwchLim = ptxtobj->iwchLim;
iwchFirst = ptxtobj->iwchFirst;
if ( (pilsobj->grpf & fTxtPunctStartLine) && fFirstOnLine && itxtobjCur == 0 &&
!(fAutoNumberPresent && (pilsobj->grpf & fTxtNoPunctAfterAutoNumber )) &&
!(ptxtobj->txtf & txtfGlyphBased)
)
{
CheckApplyPunctStartLine(pilsobj, plsrun, &lsems, iwchFirst, &ddurChangeFirst);
ddurChange += ddurChangeFirst;
}
if (rglschnk[itxtobjCur].plschp->fModWidthPairs)
{
Assert(pilsobj->ptxtinf != NULL);
Assert(pilsobj->plspairact != NULL);
Assert(pilsobj->pilspairact != NULL);
Assert(!(ptxtobj->txtf & txtfGlyphBased));
Assert(pilsobj->pilspairact != NULL);
if(pilsobj->pilspairact == NULL)
return lserrModWidthPairsNotSet;
for (iwch = iwchFirst; iwch < iwchLim - 1; iwch++)
{
CheckApplyModWidthTwoChars(pilsobj, &lsems, &lsems, iwch, iwch+1, &ddurChangeFirst, &ddurChangeSecond);
ddurChange += (ddurChangeFirst + ddurChangeSecond);
}
}
/* REVIEW sergeyge(elik): should we try to avoid second loop through characters? */
if (rglschnk[itxtobjCur].plschp->fModWidthSpace)
{
Assert(!(ptxtobj->txtf & txtfGlyphBased));
iwchVeryFirst = ((PTXTOBJ)rglschnk[0].pdobj)->iwchFirst;
iwchVeryLim = ((PTXTOBJ)rglschnk[cchnk-1].pdobj)->iwchLim;
pwchOrig = pilsobj->pwchOrig;
for (iwch = iwchFirst; iwch < iwchLim; iwch++)
{
if (pwchOrig[iwch] == pilsobj->wchSpace)
{
plsrunPrev = NULL;
iwchPrev = 0;
if (iwch > iwchFirst)
{
plsrunPrev = plsrun;
iwchPrev = iwch - 1;
}
else if (iwch > iwchVeryFirst)
{
Assert(itxtobjCur > 0);
fFoundPrevRun = GetPrevImportantRun(rglschnk, itxtobjCur-1, &itxtobjPrev);
if (fFoundPrevRun)
{
Assert(itxtobjPrev >= 0);
plsrunPrev = rglschnk[itxtobjPrev].plsrun;
iwchPrev = ((PTXTOBJ)rglschnk[itxtobjPrev].pdobj)->iwchLim - 1;
}
}
plsrunNext = NULL;
iwchNext = 0;
if (iwch < iwchLim - 1)
{
plsrunNext = plsrun;
iwchNext = iwch + 1;
}
else if (iwch < iwchVeryLim - 1)
{
Assert(itxtobjCur < (long)cchnk - 1);
fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, itxtobjCur+1, &itxtobjNext);
if (fFoundNextRun)
{
Assert(itxtobjNext < (long)cchnk);
plsrunNext = rglschnk[itxtobjNext].plsrun;
iwchNext = ((PTXTOBJ)rglschnk[itxtobjNext].pdobj)->iwchFirst;
}
}
lserr = CheckApplyModWidthSpace(pilsobj, plsrunPrev, plsrun, plsrunNext, &lsems,
iwchPrev, iwch, iwchNext, &ddurChangeFirst);
if (lserr != lserrNone) return lserr;
ddurChange += ddurChangeFirst;
}
}
}
if (ddurChange != 0)
{
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, ddurChange);
if (lserr != lserrNone) return lserr;
}
return lserrNone;
}
static LSERR CheckApplyModWidthBetweenRuns(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjPrev, long itxtobjCur)
{
LSERR lserr;
PTXTOBJ ptxtobjPrev;
PLNOBJ plnobj;
PILSOBJ pilsobj;
long iwchNext;
long iwch;
LSEMS lsemsPrev;
LSEMS lsemsCur;
PLSRUN plsrunPrev;
PLSRUN plsrunCur;
long ddurChangeFirst;
long ddurChangeSecond;
long ddurChangePrev;
long ddurChangeCur;
ddurChangePrev = 0;
ddurChangeCur = 0;
ptxtobjPrev = (PTXTOBJ)rglschnk[itxtobjPrev].pdobj;
plnobj = ptxtobjPrev->plnobj;
pilsobj = plnobj->pilsobj;
plsrunPrev = rglschnk[itxtobjPrev].plsrun;
plsrunCur = rglschnk[itxtobjCur].plsrun;
iwchNext = ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst;
lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrunPrev, lstflow, &lsemsPrev);
if (lserr != lserrNone) return lserr;
lserr = (*pilsobj->plscbk->pfnGetEms)(pilsobj->pols, plsrunCur, lstflow, &lsemsCur);
if (lserr != lserrNone) return lserr;
iwch = ptxtobjPrev->iwchLim - 1;
if (rglschnk[itxtobjPrev].plschp->fModWidthOnRun && rglschnk[itxtobjCur].plschp->fModWidthOnRun)
{
lserr = CheckApplyModWidthOnRun(pilsobj, ptxtobjPrev,
plsrunPrev, plsrunCur, &lsemsPrev, iwch, iwchNext, &ddurChangeFirst);
if (lserr != lserrNone) return lserr;
ddurChangePrev += ddurChangeFirst;
}
if (rglschnk[itxtobjPrev].plschp->fModWidthPairs && rglschnk[itxtobjCur].plschp->fModWidthPairs)
{
Assert ((!(ptxtobjPrev->txtf & txtfGlyphBased)) &&
!(((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->txtf & txtfGlyphBased));
CheckApplyModWidthTwoChars(pilsobj, &lsemsPrev, &lsemsCur, iwch, iwchNext, &ddurChangeFirst, &ddurChangeSecond);
ddurChangePrev += ddurChangeFirst;
ddurChangeCur += ddurChangeSecond;
}
if (ddurChangePrev != 0)
{
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ptxtobjPrev->plsdnUpNode, ddurChangePrev);
if (lserr != lserrNone) return lserr;
}
if (ddurChangeCur != 0)
{
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->plsdnUpNode,
ddurChangeCur);
if (lserr != lserrNone) return lserr;
}
return lserrNone;
}
static LSERR GetModWidthClasses(DWORD cchnk, const LSCHNKE* rglschnk)
{
LSERR lserr;
PILSOBJ pilsobj;
PTXTOBJ ptxtobj;
long itxtobj;
long iwchFirst;
long iwchLim;
long iwch;
long i;
MWCLS* pmwcls;
WCHAR* pwchOrig;
TXTINF* ptxtinf;
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
pwchOrig = pilsobj->pwchOrig;
ptxtinf = pilsobj->ptxtinf;
for (itxtobj = 0; itxtobj < (long)cchnk; itxtobj++)
{
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
if (!(ptxtobj->txtf & txtfGlyphBased))
{
iwchFirst = ptxtobj->iwchFirst;
iwchLim = ptxtobj->iwchLim;
if (iwchLim > iwchFirst)
{
Assert(pilsobj->pduAdjust != NULL);
/* I use pdurAdjust as temporary buffer to read MWCLS info */
pmwcls = (MWCLS*)(&pilsobj->pduAdjust[iwchFirst]);
lserr =(*pilsobj->plscbk->pfnGetModWidthClasses)(pilsobj->pols, rglschnk[itxtobj].plsrun,
&pwchOrig[iwchFirst], (DWORD)(iwchLim - iwchFirst), pmwcls);
if (lserr != lserrNone) return lserr;
for (i=0, iwch = iwchFirst; iwch < iwchLim; i++, iwch++)
{
Assert(pmwcls[i] < pilsobj->cModWidthClasses);
if (pmwcls[i] >= pilsobj->cModWidthClasses)
return lserrInvalidModWidthClass;
ptxtinf[iwch].mwcls = pmwcls[i];
}
}
ptxtobj->txtf |= txtfModWidthClassed;
}
}
return lserrNone;
}
static LSERR CheckApplyPunctStartLine(PILSOBJ pilsobj, PLSRUN plsrun, LSEMS* plsems, long iwch,
long* pddurChange)
{
LSERR lserr;
LSACT lsact;
MWCLS mwcls;
BYTE side;
*pddurChange = 0;
mwcls = (BYTE)pilsobj->ptxtinf[iwch].mwcls;
Assert(mwcls < pilsobj->cModWidthClasses);
lserr = (*pilsobj->plscbk->pfnPunctStartLine)(pilsobj->pols, plsrun, mwcls, pilsobj->pwchOrig[iwch], &lsact);
if (lserr != lserrNone) return lserr;
if (lsact.side != sideNone)
{
GetChanges(lsact, plsems, pilsobj->pdur[iwch], fFalse, &side, pddurChange);
ApplyChanges(pilsobj, iwch, side, *pddurChange);
/* pilsobj->ptxtinf[iwch].fStartLinePunct = fTrue;*/
}
return lserrNone;
}
static LSERR CheckApplyModWidthSpace(PILSOBJ pilsobj, PLSRUN plsrunPrev, PLSRUN plsrunCur, PLSRUN plsrunNext,
LSEMS* plsems, long iwchPrev, long iwchCur, long iwchNext, long* pddurChange)
{
LSERR lserr;
WCHAR wchPrev;
WCHAR wchNext;
LSACT lsact;
BYTE side;
*pddurChange = 0;
wchPrev = 0;
if (plsrunPrev != NULL)
wchPrev = pilsobj->pwchOrig[iwchPrev];
wchNext = 0;
if (plsrunNext != NULL)
wchNext = pilsobj->pwchOrig[iwchNext];
lserr = (*pilsobj->plscbk->pfnModWidthSpace)(pilsobj->pols, plsrunCur, plsrunPrev, wchPrev, plsrunNext, wchNext,
&lsact);
if (lserr != lserrNone) return lserr;
if (lsact.side != sideNone)
{
GetChanges(lsact, plsems, pilsobj->pdur[iwchCur], fTrue, &side, pddurChange);
Assert(side == sideRight);
ApplyChanges(pilsobj, iwchCur, side, *pddurChange);
pilsobj->ptxtinf[iwchCur].fModWidthSpace = fTrue;
}
return lserrNone;
}
static LSERR CheckApplyModWidthOnRun(PILSOBJ pilsobj, PTXTOBJ ptxtobjPrev, PLSRUN plsrunPrev, PLSRUN plsrunCur,
LSEMS* plsems, long iwchFirst, long iwchSecond, long* pddurChange)
{
LSERR lserr;
LSACT lsact;
BYTE side;
long igindLast;
long igind;
*pddurChange = 0;
lserr = (*pilsobj->plscbk->pfnModWidthOnRun)(pilsobj->pols, plsrunPrev, pilsobj->pwchOrig[iwchFirst],
plsrunCur, pilsobj->pwchOrig[iwchSecond], &lsact);
if (lserr != lserrNone) return lserr;
if (lsact.side != sideNone)
{
if (ptxtobjPrev->txtf & txtfGlyphBased)
{
igindLast = IgindLastFromIwch(ptxtobjPrev, iwchFirst);
igind = IgindBaseFromIgind(pilsobj, igindLast);
GetChanges(lsact, plsems, pilsobj->pdurGind[igind], fTrue, &side, pddurChange);
Assert(side == sideRight);
ApplyGlyphChanges(pilsobj, igind, *pddurChange);
}
else
{
GetChanges(lsact, plsems, pilsobj->pdur[iwchFirst], fTrue, &side, pddurChange);
Assert(side == sideRight);
ApplyChanges(pilsobj, iwchFirst, side, *pddurChange);
}
pilsobj->ptxtinf[iwchFirst].fModWidthOnRun = fTrue;
}
return lserrNone;
}
static LSERR ApplySnapGrid(DWORD cchnk, const LSCHNKE* rglschnk)
{
LSERR lserr;
PILSOBJ pilsobj;
long iwchVeryFirst;
long iwchVeryLim;
long iwchFirstInDobj;
long iwchLimInDobj;
long iwch;
long iwchFirstSnapped;
long iwchPrev;
long itxtobj;
long itxtobjCur;
long itxtobjFirstSnapped;
long itxtobjPrev;
PLSRUN* rgplsrun = NULL;
LSCP* rgcp = NULL;
BOOL* rgfSnapped = NULL;
long irg;
PLSRUN plsrunCur;
LSCP cpCur;
long cGrid;
BOOL fFoundNextRun;
long urColumnMax;
long urPen;
long durPen;
long urPenSnapped;
long urPenFirstSnapped;
long durUndo;
long durGridWhole;
long durGridRem;
BOOL fInChildList;
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
lserr = LsdnFInChildList(pilsobj->plsc, ((PTXTOBJ)rglschnk[0].pdobj)->plsdnUpNode, &fInChildList);
Assert(lserr == lserrNone);
if (fInChildList)
return lserrNone;
iwchVeryFirst = ((PTXTOBJ)rglschnk[0].pdobj)->iwchFirst;
iwchVeryLim = ((PTXTOBJ)rglschnk[cchnk - 1].pdobj)->iwchLim;
if (iwchVeryLim <= iwchVeryFirst)
return lserrNone;
rgcp = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, (iwchVeryLim - iwchVeryFirst) * sizeof (LSCP));
if (rgcp == NULL)
return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrOutOfMemory);
rgplsrun = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, (iwchVeryLim - iwchVeryFirst) * sizeof (PLSRUN));
if (rgplsrun == NULL)
return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrOutOfMemory);
rgfSnapped = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, (iwchVeryLim - iwchVeryFirst) * sizeof (BOOL));
if (rgfSnapped == NULL)
return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrOutOfMemory);
irg = 0;
for (itxtobj = 0; itxtobj < (long)cchnk; itxtobj++)
{
iwchFirstInDobj = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchFirst;
iwchLimInDobj = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchLim;
plsrunCur = rglschnk[itxtobj].plsrun;
cpCur = rglschnk[itxtobj].cpFirst;
for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
{
rgcp[irg] = cpCur;
rgplsrun[irg] = plsrunCur;
irg++;
cpCur++;
}
}
lserr = (*pilsobj->plscbk->pfnGetSnapGrid)(pilsobj->pols, &pilsobj->pwchOrig[iwchVeryFirst], rgplsrun, rgcp, irg, rgfSnapped, (DWORD*)&cGrid);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
Assert(cGrid > 0);
if (cGrid <= 0) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrNone);
rgfSnapped[0] = fTrue; /* First character of each lock chunk must be snapped */
fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, 0, &itxtobjCur);
if (fFoundNextRun && rgfSnapped[((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst - iwchVeryFirst])
{
iwchFirstInDobj = ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst;
/* fix for the case when ModWidth was applied before snapping to grid.
Changes to the left of the first character should be undone.
*/
lserr = UndoAppliedModWidth(pilsobj, rglschnk, itxtobjCur, iwchFirstInDobj, sideLeft, &durUndo);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
lserr = LsdnGetUrPenAtBeginningOfChunk(pilsobj->plsc, ((PTXTOBJ)rglschnk[0].pdobj)->plsdnUpNode,
&urPen, &urColumnMax);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
if (urColumnMax <= 0) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrNone);
durGridWhole = urColumnMax / cGrid;
durGridRem = urColumnMax - durGridWhole * cGrid;
urPenSnapped = CalcSnapped(urPen, urColumnMax, cGrid, durGridWhole, durGridRem);
Assert(urPenSnapped >= urPen);
if (urPenSnapped > urPen)
{
ApplyChanges(pilsobj, iwchFirstInDobj, sideLeft, urPenSnapped - urPen);
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->plsdnUpNode,
urPenSnapped - urPen);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
}
/* Dangerous fix to the bug 594. Width of first character was just changed. First iteration of the
following for loop assumes that it was not. So I initialize variables in such way that
first iteration will work correctly---2 errors compensate each other
before fix initialization was:
durPen = 0;
urPen = urPenSnapped
*/
durPen = urPen - urPenSnapped;
/* urPen = urPenSnapped;*/
urPenFirstSnapped = urPenSnapped;
iwchFirstSnapped = iwchFirstInDobj;
itxtobjFirstSnapped = itxtobjCur;
iwchPrev = iwchFirstInDobj;
itxtobjPrev = itxtobjCur;
while (fFoundNextRun)
{
iwchFirstInDobj = ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchFirst;
iwchLimInDobj = ((PTXTOBJ)rglschnk[itxtobjCur].pdobj)->iwchLim;
for (iwch = iwchFirstInDobj; iwch < iwchLimInDobj; iwch++)
{
if (rgfSnapped[iwch - iwchVeryFirst] && iwch > iwchFirstSnapped)
{
/* fix for the case when ModWidth was applied before snapping to grid.
Changes to the right of the last character should be undone.
*/
lserr = UndoAppliedModWidth(pilsobj, rglschnk, itxtobjPrev, iwchPrev, sideRight, &durUndo);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
if (durUndo != 0)
{
urPen += durUndo;
durPen += durUndo;
}
/* end of the fix due to ModWidth */
urPenSnapped = CalcSnapped(urPen, urColumnMax, cGrid, durGridWhole, durGridRem);
Assert(urPenSnapped - urPenFirstSnapped - durPen >= 0);
lserr = ApplySnapChanges(pilsobj, rglschnk, iwchFirstSnapped, itxtobjFirstSnapped,
iwchPrev, itxtobjPrev, urPenSnapped - urPenFirstSnapped - durPen);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
durPen = 0;
urPen = urPenSnapped;
urPenFirstSnapped = urPenSnapped;
iwchFirstSnapped = iwch;
itxtobjFirstSnapped = itxtobjCur;
/* fix for the case when ModWidth was applied before snapping to grid.
Changes to the left of the first character should be undone.
*/
lserr = UndoAppliedModWidth(pilsobj, rglschnk, itxtobjCur, iwch, sideLeft, &durUndo);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
}
urPen += pilsobj->pdur[iwch];
durPen += pilsobj->pdur[iwch];
iwchPrev = iwch;
itxtobjPrev = itxtobjCur;
}
fFoundNextRun = GetNextImportantRun(cchnk, rglschnk, itxtobjCur + 1, &itxtobjCur);
}
/* fix for the case when ModWidth was applied before snapping to grid.
Changes to the right of the last character should be undone.
*/
UndoAppliedModWidth(pilsobj, rglschnk, itxtobjPrev, iwchPrev, sideRight, &durUndo);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
if (durUndo != 0)
{
urPen += durUndo;
durPen += durUndo;
}
/* end of the fix due to ModWidth */
urPenSnapped = CalcSnapped(urPen, urColumnMax, cGrid, durGridWhole, durGridRem);
Assert(urPenSnapped - urPenFirstSnapped - durPen >= 0);
lserr = ApplySnapChanges(pilsobj, rglschnk, iwchFirstSnapped, itxtobjFirstSnapped,
iwchPrev, itxtobjPrev, urPenSnapped - urPenFirstSnapped - durPen);
if (lserr != lserrNone) return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserr);
}
return CleanUpGrid(pilsobj, rgplsrun, rgcp, rgfSnapped, lserrNone);
}
static LSERR UndoAppliedModWidth(PILSOBJ pilsobj, const LSCHNKE* rglschnk,
long itxtobj, long iwch, BYTE side, long* pdurUndo)
{
LSERR lserr;
UndoAppliedChanges(pilsobj, iwch, side, pdurUndo);
if (*pdurUndo != 0)
{
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobj].pdobj)->plsdnUpNode,
*pdurUndo);
if (lserr != lserrNone) return lserr;
pilsobj->ptxtinf[iwch].fModWidthOnRun = fFalse;
pilsobj->ptxtinf[iwch].fModWidthSpace = fTrue;
}
return lserrNone;
}
static LSERR ApplySnapChanges(PILSOBJ pilsobj, const LSCHNKE* rglschnk, long iwchFirstSnapped,
long itxtobjFirstSnapped, long iwchLastSnapped, long itxtobjLastSnapped, long durTotal)
{
LSERR lserr;
long durSnapRight;
long durSnapLeft;
durSnapRight = durTotal >> 1;
durSnapLeft = durTotal - durSnapRight;
ApplyChanges(pilsobj, iwchFirstSnapped, sideLeft, durSnapLeft);
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobjFirstSnapped].pdobj)->plsdnUpNode,
durSnapLeft);
if (lserr != lserrNone) return lserr;
ApplyChanges(pilsobj, iwchLastSnapped, sideRight, durSnapRight);
lserr = LsdnModifySimpleWidth(pilsobj->plsc, ((PTXTOBJ)rglschnk[itxtobjLastSnapped].pdobj)->plsdnUpNode,
durSnapRight);
if (lserr != lserrNone) return lserr;
return lserrNone;
}
static LSERR CleanUpGrid(PILSOBJ pilsobj, PLSRUN* rgplsrun, LSCP* rgcp, BOOL* rgfSnapped,
LSERR lserr)
{
if (rgplsrun != NULL)
(*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, rgplsrun);
if (rgcp != NULL)
(*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, rgcp);
if (rgfSnapped != NULL)
(*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, rgfSnapped);
return lserr;
}
static long CalcSnapped(long urPen, long urColumnMax, long cGrid, long durGridWhole, long durGridRem)
{
long idGrid;
/* It is important to prove that idGrid-->urPenSnapped-->idGrid produces the same idGrid we started with.
Here is the proof:
idGrid-->urPenSnapped: (idGrid * durGridWhole + durGridRem*idGrid/cGrid)---it is urPenSnapped
urPenSnapped-->idGrid:
(urPenSnapped * cGrid + urColumnMax - 1 ) / urColumnMax =
((idGrid * durGridWhole + durGridRem*idGrid/cGrid) * cGrid + urColumnMax - 1) / urColumnMax =
(idGrid * (urColumnMax - durGridRem) + durGridRem * idGrid + urColumnMax - 1) / urColumnMax =
(idGrid * urColumnMax + urColumnMax - 1) / urColumnMax = idGrid
It shows also that if one takes urPenSnapped + 1, result will be idGrid + 1 which is exactly correct
*/
if (urPen >= 0)
idGrid = (urPen * cGrid + urColumnMax - 1 ) / urColumnMax;
else
idGrid = - ((-urPen * cGrid) / urColumnMax);
return idGrid * durGridWhole + durGridRem * idGrid / cGrid;
}
#define cwchShapedTogetherMax 0x7FFF
/* Glyph-related activities */
static LSERR ApplyGlyphs(LSTFLOW lstflow, DWORD cchnk, const LSCHNKE* rglschnk)
{
LSERR lserr;
PILSOBJ pilsobj;
long itxtobj;
long itxtobjFirst;
long itxtobjLast;
BOOL fInterruptShaping;
long iwchFirstGlobal;
long iwchLimGlobal;
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
itxtobj = 0;
while (itxtobj < (long)cchnk && !(((PTXTOBJ)rglschnk[itxtobj].pdobj)->txtf & txtfGlyphBased))
itxtobj++;
/* Following Assert is surprisingly wrong, counterexample: glyph-based EOP and nothing else on the line */
/* Assert(itxtobj < (long)cchnk); */
while (itxtobj < (long)cchnk)
{
itxtobjFirst = itxtobj;
iwchFirstGlobal = ((PTXTOBJ)rglschnk[itxtobjFirst].pdobj)->iwchFirst;
iwchLimGlobal = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchLim;
Assert(iwchLimGlobal - iwchFirstGlobal < cwchShapedTogetherMax);
itxtobj++;
fInterruptShaping = fFalse;
if (itxtobj < (long)cchnk)
iwchLimGlobal = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchLim;
while (iwchLimGlobal - iwchFirstGlobal < cwchShapedTogetherMax &&
!fInterruptShaping && itxtobj < (long)cchnk &&
(((PTXTOBJ)rglschnk[itxtobj].pdobj)->txtf & txtfGlyphBased))
{
lserr = (*pilsobj->plscbk->pfnFInterruptShaping)(pilsobj->pols, lstflow,
rglschnk[itxtobj-1].plsrun, rglschnk[itxtobj].plsrun, &fInterruptShaping);
if (lserr != lserrNone) return lserr;
if (!fInterruptShaping)
itxtobj++;
if (itxtobj < (long)cchnk)
iwchLimGlobal = ((PTXTOBJ)rglschnk[itxtobj].pdobj)->iwchLim;
}
itxtobjLast = itxtobj - 1;
lserr = ApplyGlyphsToRange(lstflow, rglschnk, itxtobjFirst, itxtobjLast);
if (lserr != lserrNone) return lserr;
while (itxtobj < (long)cchnk && !(((PTXTOBJ)rglschnk[itxtobj].pdobj)->txtf & txtfGlyphBased))
itxtobj++;
}
return lserrNone;
}
static LSERR ApplyGlyphsToRange(LSTFLOW lstflow, const LSCHNKE* rglschnk, long itxtobjFirst, long itxtobjLast)
{
LSERR lserr;
PILSOBJ pilsobj;
PLNOBJ plnobj;
PTXTOBJ ptxtobjFirst;
PTXTOBJ ptxtobjLast;
PLSRUN plsrun;
long iwchFirstGlobal;
long iwchLimGlobal;
GINDEX* pgindex;
PGPROP pgprop;
DWORD cgind;
long igindFirst;
ptxtobjFirst = (PTXTOBJ)rglschnk[itxtobjFirst].pdobj;
ptxtobjLast = (PTXTOBJ)rglschnk[itxtobjLast].pdobj;
plnobj = ptxtobjFirst->plnobj;
pilsobj = plnobj->pilsobj;
iwchFirstGlobal = ptxtobjFirst->iwchFirst;
iwchLimGlobal = ptxtobjLast->iwchLim;
plsrun = rglschnk[itxtobjFirst].plsrun;
lserr = (*pilsobj->plscbk->pfnGetGlyphs)(pilsobj->pols, plsrun, &pilsobj->pwchOrig[iwchFirstGlobal],
iwchLimGlobal - iwchFirstGlobal, lstflow,
&plnobj->pgmap[iwchFirstGlobal], &pgindex, &pgprop, &cgind);
if (lserr != lserrNone) return lserr;
lserr = CheckReallocGlyphs(plnobj, cgind);
if (lserr != lserrNone) return lserr;
CopyGindices(plnobj, pgindex, pgprop, cgind, &igindFirst);
lserr = (*pilsobj->plscbk->pfnGetGlyphPositions)(pilsobj->pols, plsrun, lsdevReference, &pilsobj->pwchOrig[iwchFirstGlobal],
&plnobj->pgmap[iwchFirstGlobal], iwchLimGlobal - iwchFirstGlobal,
&plnobj->pgind[igindFirst], &plnobj->pgprop[igindFirst], cgind, lstflow,
(int*)&pilsobj->pdurGind[igindFirst], &plnobj->pgoffs[igindFirst]);
if (lserr != lserrNone) return lserr;
if (pilsobj->fDisplay)
{
if (!pilsobj->fPresEqualRef)
{
lserr = (*pilsobj->plscbk->pfnGetGlyphPositions)(pilsobj->pols, plsrun, lsdevPres, &pilsobj->pwchOrig[iwchFirstGlobal],
&plnobj->pgmap[iwchFirstGlobal], iwchLimGlobal - iwchFirstGlobal,
&plnobj->pgind[igindFirst], &plnobj->pgprop[igindFirst], cgind, lstflow,
(int*)&plnobj->pdupGind[igindFirst], &plnobj->pgoffs[igindFirst]);
if (lserr != lserrNone) return lserr;
}
/* ScaleSides will take care of the following memcpy */
// else
// memcpy (&plnobj->pdupGind[igindFirst], &pilsobj->pdurGind[igindFirst], sizeof(long)*cgind);
}
InterpretMap(plnobj, iwchFirstGlobal, iwchLimGlobal - iwchFirstGlobal, igindFirst, cgind);
Assert(plnobj->pgmap[iwchFirstGlobal] == 0);
if (pilsobj->fDisplay && (pilsobj->grpf & fTxtVisiSpaces) && rglschnk[itxtobjFirst].cpFirst >= 0)
{
FixGlyphSpaces(lstflow, rglschnk, itxtobjFirst, igindFirst, itxtobjLast);
}
lserr = FixTxtobjs(rglschnk, itxtobjFirst, igindFirst, itxtobjLast);
if (lserr != lserrNone) return lserr;
ptxtobjFirst->txtf |= txtfFirstShaping;
while (ptxtobjLast->iwchLim == ptxtobjLast->iwchFirst)
{
itxtobjLast--;
Assert (itxtobjLast >= itxtobjFirst);
ptxtobjLast = (PTXTOBJ)rglschnk[itxtobjLast].pdobj;
}
ptxtobjLast->txtf |= txtfLastShaping;
return lserrNone;
}
static LSERR FixTxtobjs(const LSCHNKE* rglschnk, long itxtobjFirst, long igindVeryFirst, long itxtobjLast)
{
LSERR lserr;
PILSOBJ pilsobj;
PTXTOBJ ptxtobj;
long itxtobj;
long iwchFirst;
long iwchLast;
long dcpFirst;
long durTotal;
long iwSpacesVeryLim;
long iwSpacesFirst;
long iwSpacesLim;
int igind;
pilsobj = ((PTXTOBJ)rglschnk[itxtobjFirst].pdobj)->plnobj->pilsobj;
iwchFirst = ((PTXTOBJ)rglschnk[itxtobjFirst].pdobj)->iwchFirst;
iwSpacesVeryLim = ((PTXTOBJ)rglschnk[itxtobjLast].pdobj)->u.reg.iwSpacesLim;
for (itxtobj = itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
{
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
Assert(ptxtobj->txtkind == txtkindRegular);
Assert((long)rglschnk[itxtobj].dcp == ptxtobj->iwchLim - ptxtobj->iwchFirst);
dcpFirst = iwchFirst - ptxtobj->iwchFirst;
Assert(dcpFirst >= 0);
ptxtobj->iwchFirst = iwchFirst;
iwchLast = ptxtobj->iwchLim - 1;
if (iwchLast < iwchFirst)
{
ptxtobj->iwchLim = iwchFirst;
ptxtobj->u.reg.iwSpacesLim = ptxtobj->u.reg.iwSpacesFirst;
Assert(itxtobj > itxtobjFirst);
ptxtobj->igindFirst = ((PTXTOBJ)rglschnk[itxtobj-1].pdobj)->iwchLim;
ptxtobj->igindLim = ptxtobj->igindFirst;
lserr = LsdnSetSimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, 0);
if (lserr != lserrNone) return lserr;
lserr = LsdnResetDcpMerge(pilsobj->plsc,
ptxtobj->plsdnUpNode, rglschnk[itxtobj].cpFirst + dcpFirst, 0);
if (lserr != lserrNone) return lserr;
/* It would be cleaner to mark these dobj's by another flag, but is it
worth to introduce one?
*/
ptxtobj->txtf |= txtfSkipAtNti;
}
else
{
while (!pilsobj->ptxtinf[iwchLast].fLastInContext)
iwchLast++;
Assert(iwchLast < (long)pilsobj->wchMac);
ptxtobj->iwchLim = iwchLast + 1;
lserr = LsdnResetDcpMerge(pilsobj->plsc, ptxtobj->plsdnUpNode, rglschnk[itxtobj].cpFirst + dcpFirst, iwchLast + 1 - iwchFirst);
if (lserr != lserrNone) return lserr;
Assert (iwchFirst == ptxtobj->iwchFirst);
Assert (FIwchFirstInContext (pilsobj, iwchFirst));
Assert (FIwchLastInContext (pilsobj, iwchLast));
ptxtobj->igindFirst = IgindFirstFromIwchVeryFirst (ptxtobj, igindVeryFirst, iwchFirst);
ptxtobj->igindLim = IgindLastFromIwchVeryFirst (ptxtobj, igindVeryFirst, iwchLast) + 1;
durTotal = 0;
for (igind = ptxtobj->igindFirst; igind < ptxtobj->igindLim; igind++)
durTotal += pilsobj->pdurGind[igind];
lserr = LsdnSetSimpleWidth(pilsobj->plsc, ptxtobj->plsdnUpNode, durTotal);
if (lserr != lserrNone) return lserr;
iwSpacesFirst = ptxtobj->u.reg.iwSpacesFirst;
iwSpacesLim = ptxtobj->u.reg.iwSpacesLim;
while (iwSpacesLim < iwSpacesVeryLim && pilsobj->pwSpaces[iwSpacesLim] < ptxtobj->iwchLim)
{
iwSpacesLim++;
}
while (iwSpacesFirst < iwSpacesLim && pilsobj->pwSpaces[iwSpacesFirst] < ptxtobj->iwchFirst)
{
iwSpacesFirst++;
}
ptxtobj->u.reg.iwSpacesFirst = iwSpacesFirst;
ptxtobj->u.reg.iwSpacesLim = iwSpacesLim;
iwchFirst = ptxtobj->iwchLim;
}
}
return lserrNone;
}
static LSERR CheckReallocGlyphs(PLNOBJ plnobj, long cglyphs)
{
LSERR lserr;
PILSOBJ pilsobj;
long igindLocalStart;
long cNew;
void* pTemp;
pilsobj = plnobj->pilsobj;
igindLocalStart = pilsobj->gindMac;
if (plnobj->pgmap == NULL)
{
pTemp = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(GMAP) * pilsobj->wchMax );
if (pTemp == NULL) return lserrOutOfMemory;
plnobj->pgmap = pTemp;
}
if ( igindLocalStart + cglyphs <= (long)pilsobj->gindMax - 2)
{
return lserrNone;
}
else
{
cNew = gindAddM + pilsobj->gindMax;
if (cNew - 2 < igindLocalStart + cglyphs)
{
cNew = igindLocalStart + cglyphs + 2;
}
lserr = Realloc(pilsobj, &pilsobj->pdurGind, sizeof(long) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &pilsobj->pginf, sizeof(TXTGINF) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &pilsobj->pduGright, sizeof(long) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &pilsobj->plsexpinf, sizeof(LSEXPINFO) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &plnobj->pgind, sizeof(GINDEX) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &plnobj->pdupGind, sizeof(long) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &plnobj->pgoffs, sizeof(GOFFSET) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &plnobj->pexpt, sizeof(EXPTYPE) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &plnobj->pdupBeforeJust, sizeof(long) * cNew);
if (lserr != lserrNone) return lserr;
lserr = Realloc(pilsobj, &plnobj->pgprop, sizeof(GPROP) * cNew);
if (lserr != lserrNone) return lserr;
memset(&pilsobj->plsexpinf[pilsobj->gindMax], 0, sizeof(LSEXPINFO) * (cNew - pilsobj->gindMax) );
memset(&pilsobj->pduGright[pilsobj->gindMax], 0, sizeof(long) * (cNew - pilsobj->gindMax) );
memset(&plnobj->pexpt[pilsobj->gindMax], 0, sizeof(EXPTYPE) * (cNew - pilsobj->gindMax) );
pilsobj->gindMax = cNew;
plnobj->gindMax = cNew;
}
return lserrNone;
}
static LSERR Realloc(PILSOBJ pilsobj, void** pInOut, long cbytes)
{
void* pTemp;
if (*pInOut == NULL)
pTemp = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, cbytes );
else
pTemp = (*pilsobj->plscbk->pfnReallocPtr)(pilsobj->pols, *pInOut, cbytes );
if (pTemp == NULL)
{
return lserrOutOfMemory;
}
*pInOut = pTemp;
return lserrNone;
}
static void CopyGindices(PLNOBJ plnobj, GINDEX* pgindex, PGPROP pgprop, long cgind, long* pigindFirst)
{
*pigindFirst = plnobj->pilsobj->gindMac;
memcpy(&plnobj->pgind[*pigindFirst], pgindex, sizeof(GINDEX) * cgind);
memcpy(&plnobj->pgprop[*pigindFirst], pgprop, sizeof(GPROP) * cgind);
plnobj->pilsobj->gindMac += cgind;
}
/* F I X G L Y P H S P A C E S */
/*----------------------------------------------------------------------------
%%Function: FixGlyphSpaces
%%Contact: sergeyge
Fixes space glyph index for the Visi Spaces situation
----------------------------------------------------------------------------*/
static LSERR FixGlyphSpaces(LSTFLOW lstflow, const LSCHNKE* rglschnk,
long itxtobjFirst, long igindVeryFirst, long itxtobjLast)
{
LSERR lserr;
PILSOBJ pilsobj;
PLNOBJ plnobj;
PTXTOBJ ptxtobj;
long itxtobj;
long iwSpace;
long iwch;
GMAP gmapTemp;
GINDEX* pgindTemp;
GPROP* pgpropTemp;
DWORD cgind;
plnobj = ((PTXTOBJ)rglschnk[itxtobjFirst].pdobj)->plnobj;
pilsobj = plnobj->pilsobj;
lserr = (*pilsobj->plscbk->pfnGetGlyphs)(pilsobj->pols, rglschnk[itxtobjFirst].plsrun,
&pilsobj->wchVisiSpace, 1, lstflow, &gmapTemp, &pgindTemp, &pgpropTemp, &cgind);
if (lserr != lserrNone) return lserr;
if (cgind != 1)
{
return lserrNone;
}
for (itxtobj=itxtobjFirst; itxtobj <= itxtobjLast; itxtobj++)
{
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
Assert(ptxtobj->txtkind == txtkindRegular);
for (iwSpace = ptxtobj->u.reg.iwSpacesFirst; iwSpace < ptxtobj->u.reg.iwSpacesLim; iwSpace++)
{
iwch = pilsobj->pwSpaces[iwSpace];
if ( FIwchOneToOne(pilsobj, iwch) )
plnobj->pgind[IgindFirstFromIwchVeryFirst (ptxtobj, igindVeryFirst, iwch)] = *pgindTemp;
}
}
return lserrNone;
}