840 lines
22 KiB
C
840 lines
22 KiB
C
|
#include "lsmem.h"
|
||
|
#include <limits.h>
|
||
|
#include "lstxtbrs.h"
|
||
|
#include "lstxtmap.h"
|
||
|
#include "lsdntext.h"
|
||
|
#include "zqfromza.h"
|
||
|
#include "locchnk.h"
|
||
|
#include "posichnk.h"
|
||
|
#include "objdim.h"
|
||
|
#include "lskysr.h"
|
||
|
#include "lstxtffi.h"
|
||
|
#include "txtils.h"
|
||
|
#include "txtln.h"
|
||
|
#include "txtobj.h"
|
||
|
|
||
|
static void GetOneCharWidth(PTXTOBJ ptxtobj, long dwch, long* pdurChar);
|
||
|
static LSERR GetWidthOfGlyph(PILSOBJ pilsobj, PLSRUN plsrun, LSTFLOW lstflow, WCHAR wch, BOOL* pfSuccessful,
|
||
|
GINDEX* pgind, long* pdurNew, long* pdupNew);
|
||
|
static LSERR GetWidthOfChar(PILSOBJ pilsobj, PLSRUN plsrun, LSTFLOW lstflow, WCHAR wch,
|
||
|
long* pdurNew, long* pdupNew);
|
||
|
|
||
|
|
||
|
/* F I N D N O N S P A C E B E F O R E */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: FindNonSpaceBefore
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
BOOL FindNonSpaceBefore(PCLSCHNK rglschnk, long itxtobjCur, long iwchCur,
|
||
|
long* pitxtobjBefore, long* piwchBefore)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
long iwch;
|
||
|
BOOL fInSpace;
|
||
|
long itxtobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
long iwchFirst;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
fInSpace = fTrue;
|
||
|
itxtobj = itxtobjCur;
|
||
|
|
||
|
iwch = iwchCur;
|
||
|
|
||
|
while (fInSpace && itxtobj >= 0)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
|
||
|
|
||
|
if ((ptxtobj->txtkind != txtkindRegular && ptxtobj->txtkind != txtkindSpecSpace ||
|
||
|
(pilsobj->grpf & fTxtWrapAllSpaces)) && ptxtobj->txtkind != txtkindEOL )
|
||
|
{
|
||
|
*pitxtobjBefore = itxtobj;
|
||
|
*piwchBefore = ptxtobj->iwchLim - 1;
|
||
|
if (iwchCur < *piwchBefore)
|
||
|
*piwchBefore = iwchCur;
|
||
|
fInSpace = fFalse;
|
||
|
}
|
||
|
else if (ptxtobj->txtkind == txtkindRegular)
|
||
|
{
|
||
|
iwchFirst = ptxtobj->iwchFirst;
|
||
|
|
||
|
for (; iwch >= iwchFirst && pilsobj->pwchOrig[iwch] == pilsobj->wchSpace; iwch--);
|
||
|
|
||
|
if (iwch >= iwchFirst)
|
||
|
{
|
||
|
*pitxtobjBefore = itxtobj;
|
||
|
*piwchBefore = iwch;
|
||
|
fInSpace = fFalse;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
iwch = ptxtobj->iwchFirst - 1;
|
||
|
itxtobj--;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (fInSpace)
|
||
|
{
|
||
|
*pitxtobjBefore = 0;
|
||
|
*piwchBefore = iwch;
|
||
|
}
|
||
|
|
||
|
return !fInSpace;
|
||
|
|
||
|
}
|
||
|
|
||
|
/* F I N D N O N S P A C E A F T E R */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: FindNonSpaceAfter
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
BOOL FindNonSpaceAfter(PCLSCHNK rglschnk, DWORD clschnk, long itxtobjCur, long iwchCur,
|
||
|
long* pitxtobjAfter, long* piwchAfter)
|
||
|
{
|
||
|
PILSOBJ pilsobj;
|
||
|
long iwch;
|
||
|
BOOL fInSpace;
|
||
|
long itxtobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
long iwchLim;
|
||
|
|
||
|
pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
|
||
|
|
||
|
fInSpace = fTrue;
|
||
|
itxtobj = itxtobjCur;
|
||
|
|
||
|
iwch = iwchCur;
|
||
|
|
||
|
while (fInSpace && itxtobj < (long)clschnk)
|
||
|
{
|
||
|
ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
|
||
|
|
||
|
if (ptxtobj->txtkind != txtkindRegular && ptxtobj->txtkind != txtkindSpecSpace ||
|
||
|
(pilsobj->grpf & fTxtWrapAllSpaces))
|
||
|
{
|
||
|
*pitxtobjAfter = itxtobj;
|
||
|
*piwchAfter = ptxtobj->iwchFirst;
|
||
|
if (iwchCur > *piwchAfter)
|
||
|
*piwchAfter = iwchCur;
|
||
|
fInSpace = fFalse;
|
||
|
}
|
||
|
else if (ptxtobj->txtkind == txtkindRegular)
|
||
|
{
|
||
|
iwchLim = ptxtobj->iwchLim;
|
||
|
for (; iwch < iwchLim && pilsobj->pwchOrig[iwch] == pilsobj->wchSpace; iwch++);
|
||
|
if (iwch < iwchLim)
|
||
|
{
|
||
|
*pitxtobjAfter = itxtobj;
|
||
|
*piwchAfter = iwch;
|
||
|
fInSpace = fFalse;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
iwch = ptxtobj->iwchLim;
|
||
|
itxtobj++;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (fInSpace)
|
||
|
{
|
||
|
*pitxtobjAfter = clschnk - 1; /* Important for correct ptbo settting in TryBreakAcrossSpaces */
|
||
|
*piwchAfter = iwch;
|
||
|
}
|
||
|
|
||
|
return !fInSpace;
|
||
|
|
||
|
}
|
||
|
|
||
|
/* F I N D P R E V C H A R */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: FindPrevChar
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
BOOL FindPrevChar(PCLSCHNK rglschnk, long itxtobjCur, long iwchCur,
|
||
|
long* pitxtobjBefore, long* piwchBefore)
|
||
|
{
|
||
|
PTXTOBJ ptxtobj;
|
||
|
|
||
|
ptxtobj = (PTXTOBJ)rglschnk[itxtobjCur].pdobj;
|
||
|
|
||
|
if (iwchCur > ptxtobj->iwchFirst)
|
||
|
{
|
||
|
*pitxtobjBefore = itxtobjCur;
|
||
|
*piwchBefore = iwchCur - 1;
|
||
|
return fTrue;
|
||
|
}
|
||
|
else if (itxtobjCur > 0)
|
||
|
{
|
||
|
*pitxtobjBefore = itxtobjCur - 1;
|
||
|
*piwchBefore = ((PTXTOBJ)rglschnk[*pitxtobjBefore].pdobj)->iwchLim - 1;
|
||
|
return fTrue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pitxtobjBefore = 0;
|
||
|
*piwchBefore = ((PTXTOBJ)rglschnk[0].pdobj)->iwchFirst - 1;
|
||
|
}
|
||
|
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* F I N D N E X T C H A R */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: FindNextChar
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
BOOL FindNextChar(PCLSCHNK rglschnk, DWORD clschnk, long itxtobjCur, long iwchCur,
|
||
|
long* pitxtobjAfter, long* piwchAfter)
|
||
|
{
|
||
|
PTXTOBJ ptxtobj;
|
||
|
|
||
|
ptxtobj = (PTXTOBJ)rglschnk[itxtobjCur].pdobj;
|
||
|
|
||
|
if (iwchCur < ptxtobj->iwchLim - 1)
|
||
|
{
|
||
|
*pitxtobjAfter = itxtobjCur;
|
||
|
*piwchAfter = iwchCur + 1;
|
||
|
return fTrue;
|
||
|
}
|
||
|
else if (itxtobjCur < (long)clschnk - 1)
|
||
|
{
|
||
|
*pitxtobjAfter = itxtobjCur + 1;
|
||
|
*piwchAfter = ((PTXTOBJ)rglschnk[*pitxtobjAfter].pdobj)->iwchFirst;
|
||
|
return fTrue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* not found but set correct values for ptbo in TryBreakAcrossSpaces */
|
||
|
*pitxtobjAfter = clschnk - 1;
|
||
|
*piwchAfter = ((PTXTOBJ)rglschnk[*pitxtobjAfter].pdobj)->iwchLim;
|
||
|
}
|
||
|
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* C A L C P A R T W I D T H S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CalcPartWidths
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Calculates width from the beginning of the dobj until character iwchLim
|
||
|
----------------------------------------------------------------------------*/
|
||
|
LSERR CalcPartWidths(PTXTOBJ ptxtobj, long dwchLim, POBJDIM pobjdim, long* pdur)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
long* rgdur;
|
||
|
long durSum;
|
||
|
long i;
|
||
|
|
||
|
pilsobj = ptxtobj->plnobj->pilsobj;
|
||
|
|
||
|
rgdur = pilsobj->pdur;
|
||
|
|
||
|
Assert(dwchLim <= ptxtobj->iwchLim - ptxtobj->iwchFirst);
|
||
|
|
||
|
lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, pobjdim);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (dwchLim == 0)
|
||
|
{
|
||
|
*pdur = 0;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
durSum = 0;
|
||
|
/* Calculate the tail of the string, then subtract */
|
||
|
for (i = ptxtobj->iwchFirst + dwchLim; i < ptxtobj->iwchLim; i++)
|
||
|
{
|
||
|
durSum += rgdur[i];
|
||
|
}
|
||
|
|
||
|
*pdur = pobjdim->dur - durSum;
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* C A L C P A R T W I D T H S G L Y P H S */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CalcPartWidthsGlyphs
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Calculates width from the beginning of the dobj until character iwchLim
|
||
|
----------------------------------------------------------------------------*/
|
||
|
LSERR CalcPartWidthsGlyphs(PTXTOBJ ptxtobj, long dwchLim, POBJDIM pobjdim, long* pdur)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
long* rgdurGind;
|
||
|
long durSum;
|
||
|
long igindStart;
|
||
|
long i;
|
||
|
|
||
|
pilsobj = ptxtobj->plnobj->pilsobj;
|
||
|
|
||
|
rgdurGind = pilsobj->pdurGind;
|
||
|
|
||
|
Assert(dwchLim <= ptxtobj->iwchLim - ptxtobj->iwchFirst);
|
||
|
|
||
|
|
||
|
Assert(ptxtobj->iwchFirst + dwchLim == ptxtobj->iwchLim ||
|
||
|
pilsobj->ptxtinf[ptxtobj->iwchFirst + dwchLim].fFirstInContext);
|
||
|
igindStart = IgindFirstFromIwch(ptxtobj, ptxtobj->iwchFirst + dwchLim);
|
||
|
|
||
|
lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, pobjdim);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
durSum = 0;
|
||
|
/* Calculate the tail of the string, then subtract */
|
||
|
for (i = igindStart; i < ptxtobj->igindLim; i++)
|
||
|
{
|
||
|
durSum += rgdurGind[i];
|
||
|
}
|
||
|
|
||
|
*pdur = pobjdim->dur - durSum;
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* C H E C K H O T Z O N E */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: CheckHotZone
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
LSERR CheckHotZone(PCLOCCHNK plocchnk, long itxtobj, long iwch, BOOL* pfInHyphenZone)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
PTXTOBJ ptxtobj;
|
||
|
long dur;
|
||
|
long durLeftIndent;
|
||
|
OBJDIM objdim;
|
||
|
|
||
|
ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
|
||
|
pilsobj = ptxtobj->plnobj->pilsobj;
|
||
|
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
lserr = CalcPartWidthsGlyphs(ptxtobj, iwch + 1 - ptxtobj->iwchFirst, &objdim, &dur);
|
||
|
else
|
||
|
lserr = CalcPartWidths(ptxtobj, iwch + 1 - ptxtobj->iwchFirst, &objdim, &dur);
|
||
|
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
durLeftIndent = 0;
|
||
|
|
||
|
if (pilsobj->grpf & fTxtIndentChangesHyphenZone )
|
||
|
{
|
||
|
lserr = LsdnGetLeftIndentDur(pilsobj->plsc, &durLeftIndent);
|
||
|
Assert(lserr == lserrNone);
|
||
|
}
|
||
|
|
||
|
*pfInHyphenZone =
|
||
|
(plocchnk->lsfgi.urColumnMax - (plocchnk->ppointUvLoc[itxtobj].u + dur) + durLeftIndent >=
|
||
|
UrFromUa(plocchnk->lsfgi.lstflow, &pilsobj->lsdevres, pilsobj->duaHyphenationZone) );
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* P R O C E S S Y S R */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: ProcessYsr
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
LSERR ProcessYsr(PCLOCCHNK plocchnk, long itxtobjYsr, long dwchYsr, long itxtobjPrev, long itxtobjPrevPrev,
|
||
|
YSRINF ysrinf, BOOL* pfSuccess, HYPHOUT* phyphout)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
PILSOBJ pilsobj;
|
||
|
PLNOBJ plnobj;
|
||
|
PTXTOBJ ptxtobjYsr;
|
||
|
PTXTOBJ ptxtobjPrev;
|
||
|
PTXTOBJ ptxtobjPrevPrev;
|
||
|
const LSCHNKE* pchnkeYsr;
|
||
|
const LSCHNKE* pchnkePrev;
|
||
|
const LSCHNKE* pchnkePrevPrev;
|
||
|
long iwchYsr;
|
||
|
long durPrevOld = 0;
|
||
|
long durPrevPrevOld = 0;
|
||
|
long dupNew;
|
||
|
long durNew;
|
||
|
long dupHyphen;
|
||
|
long durHyphen;
|
||
|
BOOL fSuccessful;
|
||
|
GINDEX gind;
|
||
|
|
||
|
memset(phyphout, 0, sizeof(*phyphout));
|
||
|
*pfSuccess = fTrue;
|
||
|
|
||
|
pchnkeYsr = &plocchnk->plschnk[itxtobjYsr];
|
||
|
ptxtobjYsr = (PTXTOBJ)pchnkeYsr->pdobj;
|
||
|
plnobj = ptxtobjYsr->plnobj;
|
||
|
pilsobj = plnobj->pilsobj;
|
||
|
|
||
|
iwchYsr = ptxtobjYsr->iwchFirst + dwchYsr;
|
||
|
|
||
|
if (ptxtobjYsr->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
lserr = GetWidthOfGlyph(pilsobj, pchnkeYsr->plsrun, plocchnk->lsfgi.lstflow, pilsobj->wchHyphen,
|
||
|
&fSuccessful, &gind, &durHyphen, &dupHyphen);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (!fSuccessful)
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
phyphout->gindHyphen = gind;
|
||
|
phyphout->igindHyphen = IgindFirstFromIwch(ptxtobjYsr, iwchYsr) + 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lserr = GetWidthOfChar(pilsobj, pchnkeYsr->plsrun, plocchnk->lsfgi.lstflow, pilsobj->wchHyphen, &durHyphen, &dupHyphen);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
}
|
||
|
|
||
|
phyphout->durHyphen = durHyphen;
|
||
|
phyphout->dupHyphen = dupHyphen;
|
||
|
Assert(phyphout->wchPrev == 0);
|
||
|
Assert(phyphout->durPrev == 0);
|
||
|
Assert(phyphout->dupPrev == 0);
|
||
|
Assert(phyphout->wchPrevPrev == 0);
|
||
|
Assert(phyphout->durPrevPrev == 0);
|
||
|
Assert(phyphout->dupPrevPrev == 0);
|
||
|
|
||
|
switch (ysrinf.kysr)
|
||
|
{
|
||
|
case kysrNormal:
|
||
|
case kysrChangeAfter:
|
||
|
if (itxtobjPrev == itxtobjYsr && (ptxtobjYsr->txtf & txtfGlyphBased) && !FIwchOneToOne(pilsobj, iwchYsr))
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
phyphout->iwchLim = iwchYsr + 2;
|
||
|
phyphout->dwchYsr = 2;
|
||
|
|
||
|
phyphout->durChangeTotal = durHyphen;
|
||
|
break;
|
||
|
|
||
|
case kysrChangeBefore:
|
||
|
if (itxtobjPrev == ichnkOutside)
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
pchnkePrev = &plocchnk->plschnk[itxtobjPrev];
|
||
|
ptxtobjPrev = (PTXTOBJ)pchnkePrev->pdobj;
|
||
|
|
||
|
if (iwchYsr < ptxtobjPrev->iwchFirst || iwchYsr >= ptxtobjPrev->iwchLim)
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
if (ptxtobjPrev->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
lserr = GetWidthOfGlyph(pilsobj, pchnkePrev->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr,
|
||
|
&fSuccessful, &gind, &durNew, &dupNew);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr))
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
phyphout->gindPrev = gind;
|
||
|
phyphout->igindPrev = IgindFirstFromIwch(ptxtobjPrev, iwchYsr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lserr = GetWidthOfChar(pilsobj, pchnkePrev->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr, &durNew, &dupNew);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
}
|
||
|
|
||
|
GetOneCharWidth(ptxtobjPrev, iwchYsr, &durPrevOld);
|
||
|
|
||
|
phyphout->iwchLim = iwchYsr + 2;
|
||
|
phyphout->dwchYsr = 2;
|
||
|
|
||
|
phyphout->wchPrev = ysrinf.wchYsr;
|
||
|
phyphout->durPrev = durNew;
|
||
|
phyphout->dupPrev = dupNew;
|
||
|
|
||
|
phyphout->durChangeTotal = durHyphen + durNew - durPrevOld;
|
||
|
break;
|
||
|
|
||
|
case kysrAddBefore:
|
||
|
if (ptxtobjYsr->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
lserr = GetWidthOfGlyph(pilsobj, pchnkeYsr->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr,
|
||
|
&fSuccessful, &gind, &durNew, &dupNew);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr))
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
phyphout->gindPrev = gind;
|
||
|
phyphout->igindHyphen++;
|
||
|
phyphout->igindPrev = phyphout->igindHyphen - 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lserr = GetWidthOfChar(pilsobj, pchnkeYsr->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr, &durNew, &dupNew);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
}
|
||
|
|
||
|
/* procedure CheckReallocArrays made shure we have enough space in arrays */
|
||
|
phyphout->iwchLim = iwchYsr + 3;
|
||
|
phyphout->dwchYsr = 3;
|
||
|
|
||
|
phyphout->wchPrev = ysrinf.wchYsr;
|
||
|
phyphout->durPrev = durNew;
|
||
|
phyphout->dupPrev = dupNew;
|
||
|
|
||
|
phyphout->durChangeTotal = durHyphen + durNew;
|
||
|
break;
|
||
|
|
||
|
case kysrDelAndChange:
|
||
|
if (itxtobjPrev == ichnkOutside || itxtobjPrevPrev == ichnkOutside)
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
|
||
|
pchnkePrev = &plocchnk->plschnk[itxtobjPrev];
|
||
|
ptxtobjPrev = (PTXTOBJ)pchnkePrev->pdobj;
|
||
|
pchnkePrevPrev = &plocchnk->plschnk[itxtobjPrevPrev];
|
||
|
ptxtobjPrevPrev = (PTXTOBJ)pchnkePrevPrev->pdobj;
|
||
|
|
||
|
if (iwchYsr < ptxtobjPrev->iwchFirst || iwchYsr >= ptxtobjPrev->iwchLim ||
|
||
|
iwchYsr - 1 < ptxtobjPrevPrev->iwchFirst || iwchYsr - 1>= ptxtobjPrevPrev->iwchLim)
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
GetOneCharWidth(ptxtobjPrev, iwchYsr, &durPrevOld);
|
||
|
GetOneCharWidth(ptxtobjPrevPrev, iwchYsr - 1, &durPrevPrevOld);
|
||
|
|
||
|
if (ptxtobjPrev->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
lserr = GetWidthOfGlyph(pilsobj, pchnkePrev->plsrun, plocchnk->lsfgi.lstflow, pilsobj->wchSpace,
|
||
|
&fSuccessful, &gind, &durNew, &dupNew);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr))
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
phyphout->gindPrev = gind;
|
||
|
phyphout->igindPrev = IgindFirstFromIwch(ptxtobjPrev, iwchYsr);
|
||
|
}
|
||
|
|
||
|
if (ptxtobjPrevPrev->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
lserr = GetWidthOfGlyph(pilsobj, pchnkePrevPrev->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr,
|
||
|
&fSuccessful, &gind, &durNew, &dupNew);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr - 1))
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
phyphout->gindPrevPrev = gind;
|
||
|
phyphout->igindPrevPrev = IgindFirstFromIwch(ptxtobjPrevPrev, iwchYsr - 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lserr = GetWidthOfChar(pilsobj, pchnkePrevPrev->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr, &durNew, &dupNew);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
}
|
||
|
|
||
|
|
||
|
phyphout->iwchLim = iwchYsr + 2;
|
||
|
phyphout->dwchYsr = 2;
|
||
|
|
||
|
phyphout->wchPrev = pilsobj->wchSpace;
|
||
|
phyphout->durPrev = 0;
|
||
|
phyphout->dupPrev = 0;
|
||
|
phyphout->wchPrevPrev = ysrinf.wchYsr;
|
||
|
phyphout->durPrevPrev = durNew;
|
||
|
phyphout->dupPrevPrev = dupNew;
|
||
|
|
||
|
phyphout->durChangeTotal = durHyphen + durNew - durPrevOld - durPrevPrevOld;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case kysrDeleteBefore:
|
||
|
if (itxtobjPrev == ichnkOutside)
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
pchnkePrev = &plocchnk->plschnk[itxtobjPrev];
|
||
|
ptxtobjPrev = (PTXTOBJ)pchnkePrev->pdobj;
|
||
|
|
||
|
if (iwchYsr < ptxtobjPrev->iwchFirst || iwchYsr >= ptxtobjPrev->iwchLim)
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
GetOneCharWidth(ptxtobjPrev, iwchYsr, &durPrevOld);
|
||
|
|
||
|
if (ptxtobjPrev->txtf & txtfGlyphBased)
|
||
|
{
|
||
|
lserr = GetWidthOfGlyph(pilsobj, pchnkePrev->plsrun, plocchnk->lsfgi.lstflow, pilsobj->wchSpace,
|
||
|
&fSuccessful, &gind, &durNew, &dupNew);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr))
|
||
|
{
|
||
|
*pfSuccess = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
phyphout->gindPrev = gind;
|
||
|
phyphout->igindPrev = IgindFirstFromIwch(ptxtobjPrev, iwchYsr);
|
||
|
}
|
||
|
|
||
|
|
||
|
phyphout->iwchLim = iwchYsr + 2;
|
||
|
phyphout->dwchYsr = 2;
|
||
|
|
||
|
phyphout->wchPrev = pilsobj->wchSpace;
|
||
|
phyphout->durPrev = 0;
|
||
|
phyphout->dupPrev = 0;
|
||
|
|
||
|
phyphout->durChangeTotal = durHyphen - durPrevOld;
|
||
|
break;
|
||
|
default:
|
||
|
NotReached();
|
||
|
}
|
||
|
|
||
|
if (itxtobjPrev != itxtobjYsr && durPrevOld != 0)
|
||
|
{
|
||
|
phyphout->ddurDnodePrev += (phyphout->durPrev - durPrevOld);
|
||
|
}
|
||
|
|
||
|
if (itxtobjPrevPrev != itxtobjYsr && durPrevPrevOld != 0)
|
||
|
{
|
||
|
if (itxtobjPrev == itxtobjPrevPrev || itxtobjPrev == itxtobjYsr)
|
||
|
{
|
||
|
phyphout->ddurDnodePrev += (phyphout->durPrevPrev - durPrevPrevOld);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
phyphout->ddurDnodePrevPrev += (phyphout->durPrevPrev - durPrevPrevOld);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
#define cIncreaseBeakInfoMax 4
|
||
|
|
||
|
/* G E T P B R K I N F */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetPbrkinf
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Gets the pointer to the available BREAKINFO staructure
|
||
|
----------------------------------------------------------------------------*/
|
||
|
LSERR GetPbrkinf(PILSOBJ pilsobj, PDOBJ pdobj, BRKKIND brkkind, BREAKINFO** ppbrkinf)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
BREAKINFO* pbreakinf;
|
||
|
long ibrkinf = 0xFFFF;
|
||
|
BOOL fInChildList;
|
||
|
|
||
|
pbreakinf = pilsobj->pbreakinf;
|
||
|
|
||
|
lserr = LsdnFInChildList(pilsobj->plsc, ((PTXTOBJ)pdobj)->plsdnUpNode, &fInChildList);
|
||
|
Assert(lserr == lserrNone);
|
||
|
|
||
|
if (!fInChildList)
|
||
|
{
|
||
|
switch(brkkind)
|
||
|
{
|
||
|
case brkkindPrev:
|
||
|
ibrkinf = 0;
|
||
|
break;
|
||
|
case brkkindNext:
|
||
|
ibrkinf = 1;
|
||
|
break;
|
||
|
case brkkindForce:
|
||
|
ibrkinf = 2;
|
||
|
break;
|
||
|
default:
|
||
|
NotReached();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (ibrkinf = 3; ibrkinf < (long)pilsobj->breakinfMac &&
|
||
|
(pbreakinf[ibrkinf].pdobj != pdobj || pbreakinf[ibrkinf].brkkind != brkkind); ibrkinf++);
|
||
|
}
|
||
|
|
||
|
if (ibrkinf < (long)pilsobj->breakinfMac)
|
||
|
{
|
||
|
Assert(ibrkinf < 3 || pbreakinf[ibrkinf].pdobj == pdobj && pbreakinf[ibrkinf].brkkind == brkkind);
|
||
|
*ppbrkinf = &pbreakinf[ibrkinf];
|
||
|
}
|
||
|
else if (pilsobj->breakinfMac < pilsobj->breakinfMax)
|
||
|
{
|
||
|
*ppbrkinf = &pilsobj->pbreakinf[pilsobj->breakinfMac];
|
||
|
pilsobj->breakinfMac++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Assert(pilsobj->breakinfMac == pilsobj->breakinfMax);
|
||
|
pbreakinf = (*pilsobj->plscbk->pfnReallocPtr)(pilsobj->pols, pilsobj->pbreakinf,
|
||
|
(pilsobj->breakinfMax + cIncreaseBeakInfoMax) * sizeof(BREAKINFO) );
|
||
|
if (pbreakinf == NULL)
|
||
|
{
|
||
|
return lserrOutOfMemory;
|
||
|
}
|
||
|
pilsobj->pbreakinf = pbreakinf;
|
||
|
pilsobj->breakinfMax += cIncreaseBeakInfoMax;
|
||
|
|
||
|
*ppbrkinf = &pilsobj->pbreakinf[pilsobj->breakinfMac];
|
||
|
pilsobj->breakinfMac++;
|
||
|
}
|
||
|
|
||
|
memset(*ppbrkinf, 0, sizeof(BREAKINFO));
|
||
|
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
/* Internal functions implementation */
|
||
|
|
||
|
/* G E T O N E C H A R W I D T H */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetOneCharWidth
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Reports width of the character iwch
|
||
|
----------------------------------------------------------------------------*/
|
||
|
static void GetOneCharWidth(PTXTOBJ ptxtobj, long iwch, long* pdurChar)
|
||
|
{
|
||
|
if (ptxtobj->txtf & txtfGlyphBased)
|
||
|
*pdurChar = ptxtobj->plnobj->pilsobj->pdurGind[IgindFirstFromIwch(ptxtobj, iwch)];
|
||
|
else
|
||
|
*pdurChar = ptxtobj->plnobj->pilsobj->pdur[iwch];
|
||
|
}
|
||
|
|
||
|
/* G E T W I D T H O F C H A R */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetWidthOfChar
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Reports width of the character wch with plsrun
|
||
|
----------------------------------------------------------------------------*/
|
||
|
static LSERR GetWidthOfChar(PILSOBJ pilsobj, PLSRUN plsrun, LSTFLOW lstflow, WCHAR wch, long* pdurNew, long* pdupNew)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
long durSumJunk;
|
||
|
long limDurJunk;
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnGetRunCharWidths)(pilsobj->pols, plsrun, lsdevReference, &wch, 1, LONG_MAX, lstflow,
|
||
|
(int*)pdurNew, &durSumJunk, &limDurJunk);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (pilsobj->fDisplay)
|
||
|
{
|
||
|
if (!pilsobj->fPresEqualRef)
|
||
|
{
|
||
|
lserr = (*pilsobj->plscbk->pfnGetRunCharWidths)(pilsobj->pols, plsrun, lsdevPres, &wch, 1, LONG_MAX, lstflow,
|
||
|
(int*)pdupNew, &durSumJunk, &limDurJunk);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
}
|
||
|
else /* fPresEqualRef */
|
||
|
{
|
||
|
*pdupNew = *pdurNew;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
|
||
|
}
|
||
|
|
||
|
/* G E T W I D T H O F G L Y P H */
|
||
|
/*----------------------------------------------------------------------------
|
||
|
%%Function: GetWidthOfGlyph
|
||
|
%%Contact: sergeyge
|
||
|
|
||
|
Reports width of the glyph corresponding to the character with plsrun
|
||
|
----------------------------------------------------------------------------*/
|
||
|
static LSERR GetWidthOfGlyph(PILSOBJ pilsobj, PLSRUN plsrun, LSTFLOW lstflow, WCHAR wch, BOOL* pfSuccessful,
|
||
|
GINDEX* pgind, long* pdurNew, long* pdupNew)
|
||
|
{
|
||
|
LSERR lserr;
|
||
|
GPROP* pgpropTemp;
|
||
|
GPROP gprop;
|
||
|
GMAP gmap;
|
||
|
GINDEX* pgindTemp;
|
||
|
DWORD cgind;
|
||
|
GOFFSET goffs;
|
||
|
|
||
|
*pfSuccessful = fTrue;
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnGetGlyphs)(pilsobj->pols, plsrun, &wch, 1, lstflow, &gmap, &pgindTemp, &pgpropTemp, &cgind);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
if (cgind != 1)
|
||
|
{
|
||
|
*pfSuccessful = fFalse;
|
||
|
return lserrNone;
|
||
|
}
|
||
|
|
||
|
*pgind = *pgindTemp;
|
||
|
gprop = *pgpropTemp;
|
||
|
|
||
|
lserr = (*pilsobj->plscbk->pfnGetGlyphPositions)(pilsobj->pols, plsrun, lsdevReference, &wch, &gmap, 1, pgind,
|
||
|
&gprop, cgind, lstflow,
|
||
|
(int*)pdurNew, &goffs);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
|
||
|
Assert(goffs.du == 0);
|
||
|
Assert(goffs.dv == 0);
|
||
|
|
||
|
if (pilsobj->fDisplay)
|
||
|
{
|
||
|
if (!pilsobj->fPresEqualRef)
|
||
|
{
|
||
|
lserr = (*pilsobj->plscbk->pfnGetGlyphPositions)(pilsobj->pols, plsrun, lsdevPres, &wch, &gmap, 1, pgind,
|
||
|
&gprop, cgind, lstflow,
|
||
|
(int*)pdupNew, &goffs);
|
||
|
if (lserr != lserrNone) return lserr;
|
||
|
}
|
||
|
else
|
||
|
*pdupNew = *pdurNew;
|
||
|
}
|
||
|
|
||
|
return lserrNone;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|