mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1692 lines
53 KiB
1692 lines
53 KiB
/************************************************************/
|
|
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
|
/************************************************************/
|
|
|
|
/*--- Module not really used, just the idea behind FORMAT.ASM ---*/
|
|
|
|
|
|
#define NOCLIPBOARD
|
|
#define NOGDICAPMASKS
|
|
#define NOCTLMGR
|
|
#define NOVIRTUALKEYCODES
|
|
#define NOWINMESSAGES
|
|
#define NOWINSTYLES
|
|
#define NOKEYSTATE
|
|
#define NOSYSCOMMANDS
|
|
#define NORASTEROPS
|
|
#define NOSHOWWINDOW
|
|
#define NOCLIPBOARD
|
|
#define NOWINSTYLES
|
|
#define NOSYSMETRICS
|
|
#define NOMENUS
|
|
#define NOATOM
|
|
#define NOCREATESTRUCT
|
|
#define NODRAWTEXT
|
|
#define NOMB
|
|
#define NOMEMMGR
|
|
#define NOMETAFILE
|
|
#define NOWH
|
|
#define NOWINOFFSETS
|
|
#define NOWNDCLASS
|
|
#include <windows.h>
|
|
/* #include "wwsmall.h" */
|
|
|
|
#include "mw.h"
|
|
#include "cmddefs.h"
|
|
#include "fmtdefs.h"
|
|
#include "propdefs.h"
|
|
#include "ch.h"
|
|
#include "docdefs.h"
|
|
#include "ffdefs.h"
|
|
#include "filedefs.h"
|
|
#include "fkpdefs.h"
|
|
#include "dispdefs.h"
|
|
#include "scrndefs.h"
|
|
#include "macro.h"
|
|
#include "debug.h"
|
|
#include "fontdefs.h"
|
|
#include "str.h"
|
|
#include "wwdefs.h"
|
|
#ifdef DBCS
|
|
#include "dbcs.h"
|
|
#endif
|
|
|
|
#ifdef DFLI
|
|
#define Dfli(x) x /* Enable debug-format-line info */
|
|
#else
|
|
#define Dfli(x)
|
|
#endif
|
|
|
|
#ifdef CASHMERE
|
|
#define cchSmcapMax 16
|
|
#endif /* CASHMERE */
|
|
|
|
static int ichpFormat;
|
|
|
|
#ifdef CASHMERE
|
|
static CHAR mptlcch[] = " .-_";
|
|
#endif /* CASHMERE */
|
|
|
|
extern int docHelp;
|
|
extern struct FLI vfli;
|
|
extern struct CHP (**vhgchpFormat)[];
|
|
extern int ichpMacFormat;
|
|
extern struct CHP vchpAbs;
|
|
extern struct PAP vpapAbs;
|
|
extern struct SEP vsepAbs;
|
|
extern struct SEP vsepPage;
|
|
extern struct CHP vchpNormal;
|
|
extern struct DOD (**hpdocdod)[];
|
|
extern typeCP vcpLimSectCache;
|
|
extern typeCP vcpFirstParaCache;
|
|
extern typeCP vcpLimParaCache;
|
|
extern typeCP vcpFetch;
|
|
extern int vichFetch;
|
|
extern int vccpFetch;
|
|
extern CHAR *vpchFetch;
|
|
extern int vcchFetch;
|
|
extern int vftc;
|
|
extern int ypSubSuper;
|
|
extern int ypSubSuperPr;
|
|
extern HDC vhMDC;
|
|
extern HDC vhDCPrinter;
|
|
extern int dxpLogInch;
|
|
extern int dypLogInch;
|
|
extern int dxaPrPage;
|
|
extern int dyaPrPage;
|
|
extern int dxpPrPage;
|
|
extern int dypPrPage;
|
|
extern int dypMax;
|
|
extern struct FMI vfmiScreen, vfmiPrint;
|
|
extern int vfOutOfMemory;
|
|
extern CHAR vchDecimal; /* "decimal point" character */
|
|
extern int vzaTabDflt; /* width of default tab */
|
|
#ifdef CASHMERE
|
|
extern int vfVisiMode;
|
|
#endif /* CASHMERE */
|
|
|
|
|
|
/* F O R M A T L I N E */
|
|
FormatLine(doc, cp, ichCp, cpMac, flm)
|
|
int doc;
|
|
typeCP cp;
|
|
int ichCp;
|
|
typeCP cpMac;
|
|
int flm;
|
|
{
|
|
/* Fills up vfli with a line of text */
|
|
|
|
int near Justify(struct IFI *, unsigned, int);
|
|
int near FGrowFormatHeap(void);
|
|
int near FFirstIch(int);
|
|
|
|
struct IFI ifi;
|
|
struct TBD *ptbd;
|
|
struct CHP chpLocal;
|
|
int xpTab;
|
|
|
|
#ifdef CASHMERE
|
|
int dypBefore;
|
|
#endif /* CASHMERE */
|
|
|
|
int dypAscent;
|
|
int dypDescent;
|
|
int dypAscentMac;
|
|
int dypDescentMac;
|
|
unsigned xaLeft;
|
|
unsigned xaRight;
|
|
struct PAP *ppap;
|
|
struct SEP *psep;
|
|
int fFlmPrinting = flm & flmPrinting;
|
|
int dxaFormat;
|
|
int dyaFormat;
|
|
int dxpFormat;
|
|
int dypFormat;
|
|
int ypSubSuperFormat;
|
|
int fTruncated = false; /* if the run was truncated */
|
|
int ichpNRH;
|
|
|
|
|
|
|
|
#ifdef CASHMERE
|
|
struct FNTB **hfntb;
|
|
int fVisiMode;
|
|
#endif /* CASHMERE */
|
|
|
|
/* Check for fli current */
|
|
if (vfli.doc == doc && vfli.cpMin == cp && vfli.ichCpMin == ichCp &&
|
|
vfli.flm == flm)
|
|
{
|
|
/* Just did this one */
|
|
return;
|
|
}
|
|
|
|
Scribble(5, 'F');
|
|
bltc(&vfli, 0, cwFLIBase);
|
|
/* This means:
|
|
vfli.fSplat = false;
|
|
vfli.dcpDepend = 0;
|
|
vfli.ichCpMac = 0;
|
|
vfli.dypLine = 0;
|
|
vfli.dypAfter = 0;
|
|
vfli.dypFont = 0;
|
|
vfli.dypBase = 0;
|
|
*/
|
|
|
|
/* vfSplatNext = FALSE; No longer used. */
|
|
|
|
/* Rest of format loads up cache with current data */
|
|
vfli.doc = doc;
|
|
vfli.cpMin = cp;
|
|
vfli.ichCpMin = ichCp;
|
|
vfli.flm = flm;
|
|
|
|
if (cp > cpMac)
|
|
{
|
|
/* Space after the endmark. Reset the cache because the footnotes come
|
|
at the same cp in the footnote window */
|
|
vfli.doc = docNil;
|
|
vfli.cpMac = cp;
|
|
vfli.rgdxp[0] = 0;
|
|
|
|
/* Line after end mark is taller than screen */
|
|
|
|
#ifdef CASHMERE
|
|
vfli.dypBase = vfli.dypFont = vfli.dypAfter = ((vfli.dypLine = dypMax)
|
|
>> 1);
|
|
#else /* not CASHMERE */
|
|
vfli.dypBase = vfli.dypFont = ((vfli.dypLine = dypMax) >> 1);
|
|
#endif /* not CASHMERE */
|
|
|
|
Scribble(5, ' ');
|
|
return;
|
|
}
|
|
|
|
/* Initialize run tables */
|
|
ichpFormat = 0;
|
|
|
|
/* Cache section and paragraph properties */
|
|
|
|
#ifdef CASHMERE
|
|
hfntb = (**hpdocdod)[doc].hfntb;
|
|
if (hfntb == 0 || cp < (**hfntb).rgfnd[0].cpFtn)
|
|
{
|
|
/* Normal text */
|
|
CacheSect(doc, cp);
|
|
}
|
|
else
|
|
{
|
|
/* Footnote section properties come from the section of the footnote
|
|
reference. */
|
|
CacheSect(doc, CpRefFromFtn(doc, cp));
|
|
}
|
|
#else /* not CASHMERE */
|
|
CacheSect(doc, cp);
|
|
#endif /* not CASHMERE */
|
|
|
|
psep = &vsepAbs;
|
|
|
|
CachePara(doc, cp);
|
|
ppap = &vpapAbs;
|
|
|
|
/* Now we have:
|
|
ppap paragraph properties
|
|
psep division properties
|
|
*/
|
|
|
|
if (ppap->fGraphics)
|
|
{
|
|
/* Format a picture paragraph in a special way (see picture.c) */
|
|
FormatGraphics(doc, cp, ichCp, cpMac, flm);
|
|
Scribble(5, ' ');
|
|
return;
|
|
}
|
|
|
|
/* Assure we have a good memory DC for font stuff */
|
|
ValidateMemoryDC();
|
|
if (vhMDC == NULL || vhDCPrinter == NULL)
|
|
{
|
|
Scribble(5, ' ');
|
|
return;
|
|
}
|
|
|
|
#ifdef CASHMERE
|
|
/* When printing, don't show visible characters */
|
|
fVisiMode = vfVisiMode && !fFlmPrinting;
|
|
#endif /* CASHMERE */
|
|
|
|
bltc(&ifi, 0, cwIFI);
|
|
/* This means:
|
|
ifi.ich = 0;
|
|
ifi.ichPrev = 0;
|
|
ifi.ichFetch = 0;
|
|
ifi.cchSpace = 0;
|
|
ifi.ichLeft = 0;
|
|
*/
|
|
|
|
ifi.jc = jcTabLeft;
|
|
ifi.fPrevSpace = true;
|
|
|
|
/* Set up some variables that have different value depending on whether we
|
|
are printing or not. */
|
|
if (fFlmPrinting)
|
|
{
|
|
dxaFormat = dxaPrPage;
|
|
dyaFormat = dyaPrPage;
|
|
dxpFormat = dxpPrPage;
|
|
dypFormat = dypPrPage;
|
|
ypSubSuperFormat = ypSubSuperPr;
|
|
}
|
|
else
|
|
{
|
|
dxaFormat = dyaFormat = czaInch;
|
|
dxpFormat = dxpLogInch;
|
|
dypFormat = dypLogInch;
|
|
ypSubSuperFormat = ypSubSuper;
|
|
}
|
|
|
|
/* Calculate line height and width measures. Compute
|
|
xaLeft left indent 0 means at left margin
|
|
xaRight width of column measured from left margin (not from left
|
|
indent).
|
|
*/
|
|
xaLeft = ppap->dxaLeft;
|
|
|
|
/* If this is the first line of a paragraph, adjust xaLeft for the first
|
|
line indent. (Also, set dypBefore, since its handy.) */
|
|
if (cp == vcpFirstParaCache)
|
|
{
|
|
xaLeft += ppap->dxaLeft1;
|
|
|
|
#ifdef CASHMERE
|
|
dypBefore = MultDiv(ppap->dyaBefore, dypLogInch, czaInch);
|
|
#endif /* CASHMERE */
|
|
|
|
}
|
|
|
|
#ifdef CASHMERE
|
|
else
|
|
{
|
|
dypBefore = 0;
|
|
}
|
|
#endif /* CASHMERE */
|
|
|
|
/* Now, set xaRight (width measured in twips). */
|
|
|
|
#ifdef CASHMERE
|
|
xaRight = (ppap->rhc ? vsepPage.xaMac - vsepPage.dxaGutter :
|
|
psep->dxaText) - ppap->dxaRight;
|
|
#else /* not CASHMERE */
|
|
xaRight = psep->dxaText - ppap->dxaRight;
|
|
#endif /* not CASHMERE */
|
|
|
|
|
|
/* Do necessary checks on xaLeft and xaRight */
|
|
if (xaRight > xaRightMax)
|
|
{
|
|
xaRight = xaRightMax;
|
|
}
|
|
if (xaLeft > xaRightMax)
|
|
{
|
|
xaLeft = xaRightMax;
|
|
}
|
|
if (xaLeft < 0)
|
|
{
|
|
xaLeft = 0;
|
|
}
|
|
if (xaRight < xaLeft)
|
|
{
|
|
xaRight = xaLeft + 1;
|
|
}
|
|
|
|
vfli.xpLeft = ifi.xp = ifi.xpLeft = MultDiv(xaLeft, dxpFormat, dxaFormat);
|
|
vfli.xpMarg = ifi.xpRight = MultDiv(xaRight, dxpFormat, dxaFormat);
|
|
ifi.xpPr = MultDiv(xaLeft, dxpPrPage, dxaPrPage);
|
|
ifi.xpPrRight = MultDiv(xaRight, dxpPrPage, dxaPrPage);
|
|
|
|
/* Get a pointer to the tab-stop table. */
|
|
ptbd = ppap->rgtbd;
|
|
|
|
/* Turn off justification. */
|
|
SetTextJustification(fFlmPrinting ? vhDCPrinter : vhMDC, 0, 0);
|
|
|
|
/* Initialize the line height information. */
|
|
dypAscentMac = dypDescentMac = 0;
|
|
|
|
/* To tell if there were any tabs */
|
|
ifi.ichLeft = -1;
|
|
|
|
/* Get the first run, and away we go... */
|
|
FetchCp(doc, cp, ichCp, fcmBoth + fcmParseCaps);
|
|
goto FirstCps;
|
|
|
|
for ( ; ; )
|
|
{
|
|
int iichNew;
|
|
int xpPrev;
|
|
int dxp;
|
|
int dxpPr;
|
|
|
|
/* The number of characters to process (usually vcchFetch) */
|
|
int cch;
|
|
|
|
/* The number of characters in current run already used */
|
|
int cchUsed;
|
|
|
|
/* A pointer to the current list of characters (usually vpchFetch) */
|
|
CHAR *pch;
|
|
|
|
#ifdef CASHMERE
|
|
CHAR rgchSmcap[cchSmcapMax];
|
|
#endif /* CASHMERE */
|
|
|
|
if (ifi.ichFetch == cch)
|
|
{
|
|
/* End of a run */
|
|
int dich;
|
|
BOOL fSizeChanged;
|
|
|
|
if (ifi.ich >= ichMaxLine)
|
|
/* End of run because of line length limit has been reached. */
|
|
{
|
|
goto DoBreak;
|
|
}
|
|
|
|
if (fTruncated)
|
|
{
|
|
cchUsed += cch;
|
|
pch = vpchFetch + cchUsed;
|
|
cch = vcchFetch - cchUsed;
|
|
fTruncated = false;
|
|
goto OldRun; /* use the rest of the old run */
|
|
}
|
|
|
|
NullRun:
|
|
FetchCp(docNil, cpNil, 0, fcmBoth + fcmParseCaps);
|
|
FirstCps:
|
|
|
|
cchUsed = 0;
|
|
|
|
/* Continue fetching runs until a run is found with a nonzero
|
|
length. */
|
|
if ((cch = vcchFetch) == 0)
|
|
{
|
|
goto NullRun;
|
|
}
|
|
|
|
pch = vpchFetch;
|
|
if (vcpFetch >= cpMac || (!fFlmPrinting && *pch == chSect))
|
|
{
|
|
#ifdef SYSENDMARK
|
|
/* Force end mark and section mark to be in standard system
|
|
font. */
|
|
blt(&vchpNormal, &vchpAbs, cwCHP);
|
|
vchpAbs.ftc = ftcSystem;
|
|
vchpAbs.ftcXtra = 0;
|
|
vchpAbs.hps = hpsDefault;
|
|
#else
|
|
#ifdef REVIEW
|
|
/* The following comment is absolutely misleading! Ftc==0
|
|
doesn't give you a system font. It gives you the first
|
|
entry in the font table. */
|
|
#endif /* REVIEW */
|
|
/* Force end mark and section mark to be in standard system
|
|
font. */
|
|
blt(&vchpNormal, &vchpAbs, cwCHP);
|
|
vchpAbs.ftc = 0;
|
|
vchpAbs.ftcXtra = 0;
|
|
vchpAbs.hps = hpsDefault;
|
|
#endif /* if-else-def KANJI */
|
|
}
|
|
|
|
#ifdef CASHMERE
|
|
/* Adjust the size of the font for "small capitals". */
|
|
if (vchpAbs.csm == csmSmallCaps)
|
|
{
|
|
vchpAbs.hps = HpsAlter(vchpAbs.hps, -1);
|
|
}
|
|
#endif /* CASHMERE */
|
|
|
|
/* Now we have:
|
|
ichpFormat index into gchp table
|
|
vcpFetch first cp of current run
|
|
vfli.cpMin first cp of line
|
|
ifi.ich ???
|
|
*/
|
|
|
|
/* since LoadFont could change vchpAbs, and we don't want
|
|
that to happen, we copy vchpAbs into vchpLocal and use
|
|
vchpLocal in place of vchpAbs hereafter. Note that vchpAbs
|
|
is intentionally used above for handling the endmark. */
|
|
|
|
blt(&vchpAbs, &chpLocal, cwCHP);
|
|
|
|
|
|
if (fFlmPrinting)
|
|
{
|
|
LoadFont(doc, &chpLocal, mdFontPrint);
|
|
dypAscent = vfmiPrint.dypAscent + vfmiPrint.dypLeading;
|
|
dypDescent = vfmiPrint.dypDescent;
|
|
}
|
|
else
|
|
{
|
|
LoadFont(doc, &chpLocal, mdFontJam);
|
|
dypAscent = vfmiScreen.dypAscent + vfmiScreen.dypLeading;
|
|
dypDescent = vfmiScreen.dypDescent;
|
|
}
|
|
|
|
#ifdef ENABLE /* BRYANL 8/27/87: New philosophy for handling
|
|
font selection failures is: font selection
|
|
ALWAYS succeeds. This prevents FormatLine
|
|
returns that do not advance. */
|
|
/* Bail out if there is a memory failure. */
|
|
if (vfOutOfMemory)
|
|
{
|
|
goto DoBreak;
|
|
}
|
|
#endif /* ENABLE */
|
|
|
|
/* Floating line size algorithm */
|
|
if (chpLocal.hpsPos != 0)
|
|
{
|
|
/* Modify font for subscript/superscript */
|
|
if (chpLocal.hpsPos < hpsNegMin)
|
|
{
|
|
dypAscent += ypSubSuperFormat;
|
|
}
|
|
else
|
|
{
|
|
dypDescent += ypSubSuperFormat;
|
|
}
|
|
}
|
|
|
|
/* Update the maximum ascent and descent of the line. */
|
|
fSizeChanged = FALSE;
|
|
if (dypDescentMac < dypDescent)
|
|
{
|
|
dypDescentMac = dypDescent;
|
|
fSizeChanged = TRUE;
|
|
}
|
|
if (dypAscentMac < dypAscent)
|
|
{
|
|
dypAscentMac = dypAscent;
|
|
fSizeChanged = TRUE;
|
|
}
|
|
|
|
|
|
if (fSizeChanged)
|
|
{
|
|
|
|
#ifdef AUTO_SPACING
|
|
/* This is the original Mac Word code that assumed line spacing
|
|
of 0 in a PAP meant auto line spacing. PC Word defaults to 1
|
|
line invalidating this assumption. */
|
|
if (ppap->dyaLine == 0)
|
|
{
|
|
|
|
#ifdef CASHMERE
|
|
ifi.dypLineSize = dypDescentMac + dypAscentMac + dypBefore;
|
|
#else /* not CASHMERE */
|
|
ifi.dypLineSize = dypDescentMac + dypAscentMac;
|
|
#endif /* not CASHMERE */
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
#ifdef CASHMERE
|
|
ifi.dypLineSize = imax(MultDiv(ppap->dyaLine, dypFormat,
|
|
dyaFormat) + dypBefore, dypBefore + 1);
|
|
#else /* not CASHMERE */
|
|
ifi.dypLineSize = imax(MultDiv(ppap->dyaLine, dypFormat,
|
|
dyaFormat), 1);
|
|
#endif /* not CASHMERE */
|
|
|
|
}
|
|
#else /* not AUTO_SPACING */
|
|
/* This code forces auto line spacing except in the case where
|
|
the user specifies a line spacing greater than the auto line
|
|
spacing. */
|
|
{
|
|
#ifdef CASHMERE
|
|
register int dypAuto = dypDescentMac + dypAscentMac +
|
|
dypBefore;
|
|
#else /* not CASHMERE */
|
|
register int dypAuto = dypDescentMac + dypAscentMac;
|
|
#endif /* not CASHMERE */
|
|
|
|
if (ppap->dyaLine > czaLine)
|
|
{
|
|
|
|
#ifdef CASHMERE
|
|
register int dypUser = imax(MultDiv(ppap->dyaLine,
|
|
dypFormat, dyaFormat) + dypBefore, dypBefore + 1);
|
|
#else /* not CASHMERE */
|
|
register int dypUser = imax(MultDiv(ppap->dyaLine,
|
|
dypFormat, dyaFormat), 1);
|
|
#endif /* not CASHMERE */
|
|
|
|
ifi.dypLineSize = max(dypAuto, dypUser);
|
|
}
|
|
else
|
|
{
|
|
ifi.dypLineSize = dypAuto;
|
|
}
|
|
}
|
|
#endif /* not AUTO_SPACING */
|
|
|
|
}
|
|
|
|
OldRun:
|
|
/* Calculate length of the run but no greater than 256 */
|
|
iichNew = (int)(vcpFetch - vfli.cpMin);
|
|
if (iichNew >= ichMaxLine)
|
|
{
|
|
iichNew = ichMaxLine - 1;
|
|
}
|
|
dich = iichNew - ifi.ich;
|
|
|
|
/* Ensure that all tab and non-required hyphen characters start at
|
|
beginning of run */
|
|
if (ichpFormat <= 0 || dich > 0 || CchDiffer(&chpLocal,
|
|
&(**vhgchpFormat)[ichpFormat - 1], cchCHPUsed) != 0 || *pch ==
|
|
chTab || *pch == chNRHFile)
|
|
{
|
|
#ifdef DFLI
|
|
if (*pch == chNRHFile)
|
|
CommSz("CHNRHFILE at beginning of run");
|
|
#endif
|
|
if (ichpFormat != ichpMacFormat || FGrowFormatHeap())
|
|
{
|
|
register struct CHP *pchp = &(**vhgchpFormat)[ichpFormat -
|
|
1];
|
|
|
|
if (ichpFormat > 0)
|
|
{
|
|
pchp->cchRun = ifi.ich - ifi.ichPrev;
|
|
pchp->ichRun = ifi.ichPrev;
|
|
}
|
|
blt(&chpLocal, ++pchp, cwCHP);
|
|
|
|
#ifdef ENABLE /* font codes */
|
|
pchp->ftc = vftc;
|
|
pchp->ftcXtra = (vftc & 0x01c0) >> 6;
|
|
pchp->hps = vhps;
|
|
#endif /* ENABLE */
|
|
|
|
pchp->cchRun = ichMaxLine;
|
|
if (dich <= 0)
|
|
{
|
|
pchp->ichRun = ifi.ich;
|
|
}
|
|
else
|
|
{
|
|
/* Q&D insert */
|
|
bltc(&vfli.rgdxp[ifi.ich], 0, dich);
|
|
bltbc(&vfli.rgch[ifi.ich], 0, dich);
|
|
pchp->ichRun = ifi.ich = iichNew;
|
|
}
|
|
ifi.ichPrev = ifi.ich;
|
|
ichpFormat++;
|
|
}
|
|
}
|
|
|
|
if (vcpFetch >= cpMac)
|
|
{
|
|
/* End of doc reached */
|
|
if (!ifi.fPrevSpace || vcpFetch == cp)
|
|
{
|
|
vfli.ichReal = ifi.ich;
|
|
vfli.xpReal = ifi.xpReal = ifi.xp;
|
|
}
|
|
if (!fFlmPrinting && (doc != docHelp))
|
|
{
|
|
vfli.rgch[ifi.ich] = chEMark;
|
|
vfli.xpReal += (vfli.rgdxp[ifi.ich++] = DxpFromCh(chEMark,
|
|
false));
|
|
}
|
|
vfli.dypLine = ifi.dypLineSize;
|
|
vfli.dypBase = dypDescentMac;
|
|
vfli.dypFont = dypAscentMac + dypDescentMac;
|
|
vfli.ichMac = vfli.ichReal = ifi.ich;
|
|
vfli.cpMac = cpMac + 1;
|
|
goto JustEol; /* dcpDepend == 0 */
|
|
}
|
|
|
|
/* Here we have ifi.ich, cch */
|
|
if (ifi.ich + cch > ichMaxLine)
|
|
/* If this run would put the line over 255, truncate it and set a
|
|
flag. */
|
|
{
|
|
cch = ichMaxLine - ifi.ich;
|
|
fTruncated = true;
|
|
}
|
|
|
|
ifi.ichFetch = 0;
|
|
|
|
#ifdef CASHMERE
|
|
if (chpLocal.csm != csmNormal)
|
|
{
|
|
int ich;
|
|
CHAR *pchT = &rgchSmcap[0];
|
|
|
|
/* We can handle only a run of cchSmcapMax small capital
|
|
characters. If the run is larger then truncate. */
|
|
if (cch > cchSmcapMax)
|
|
{
|
|
cch = cchSmcapMax;
|
|
fTruncated = true;
|
|
}
|
|
|
|
/* Raise the case of the characters. */
|
|
for (ich = 0 ; ich < cch ; ich++)
|
|
{
|
|
*pchT++ = ChUpper(*pch++);
|
|
}
|
|
pch = &rgchSmcap[0];
|
|
}
|
|
#endif /* CASHMERE */
|
|
|
|
/* Do "special" characters here */
|
|
if (chpLocal.fSpecial)
|
|
{
|
|
if (!FFormatSpecials(&ifi, flm, vsepAbs.nfcPgn))
|
|
{
|
|
if (ifi.chBreak == 0) /* No breaks in this line */
|
|
{
|
|
goto Unbroken;
|
|
}
|
|
else
|
|
{
|
|
vfli.dcpDepend = vcpFetch + ifi.ichFetch - vfli.cpMac;
|
|
goto JustBreak;
|
|
}
|
|
}
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
/* End of new run treatment. We are back in the "for every character"
|
|
section. */
|
|
{
|
|
register int ch = pch[ifi.ichFetch++];
|
|
|
|
NormChar:
|
|
|
|
if (ch == chSpace)
|
|
{
|
|
/* Speed kludge for spaces */
|
|
ifi.xp += (vfli.rgdxp[ifi.ich] = dxp =
|
|
fFlmPrinting ? vfmiPrint.dxpSpace : vfmiScreen.dxpSpace);
|
|
ifi.xpPr += (dxpPr = vfmiPrint.dxpSpace);
|
|
vfli.rgch[ifi.ich++] = chSpace;
|
|
#ifdef DFLI
|
|
{
|
|
char rgch[100];
|
|
|
|
wsprintf(rgch," chSpace , xp==%d/%d, xpPr==%d/%d",
|
|
ifi.xp, ifi.xpRight, ifi.xpPr, ifi.xpPrRight);
|
|
CommSz(rgch);
|
|
}
|
|
#endif
|
|
goto BreakOppr;
|
|
}
|
|
|
|
/* If the printer width is not in the printer width table, then get
|
|
it. */
|
|
if (ch < chFmiMin || ch >= chFmiMax || (dxpPr =
|
|
vfmiPrint.mpchdxp[ch]) == dxpNil)
|
|
{
|
|
dxpPr = DxpFromCh(ch, TRUE);
|
|
}
|
|
|
|
if (fFlmPrinting)
|
|
{
|
|
/* If we are printing, then there is no need to bother with the
|
|
screen width. */
|
|
dxp = dxpPr;
|
|
}
|
|
else if (ch < chFmiMin || ch >= chFmiMax ||
|
|
(dxp = vfmiScreen.mpchdxp[ch]) == dxpNil)
|
|
dxp = DxpFromCh(ch, FALSE);
|
|
|
|
#ifdef DBCS
|
|
if (IsDBCSLeadByte(ch))
|
|
{
|
|
ifi.xp += (vfli.rgdxp[ifi.ich] = dxp);
|
|
ifi.xpPr += dxpPr;
|
|
vfli.rgch[ifi.ich++] = ch;
|
|
ifi.xp += (vfli.rgdxp[ifi.ich] = dxp);
|
|
ifi.xpPr += dxpPr;
|
|
vfli.rgch[ifi.ich++] = pch[ifi.ichFetch++];
|
|
}
|
|
else
|
|
{
|
|
ifi.xp += (vfli.rgdxp[ifi.ich] = dxp);
|
|
ifi.xpPr += dxpPr;
|
|
vfli.rgch[ifi.ich++] = ch;
|
|
}
|
|
#else
|
|
ifi.xp += (vfli.rgdxp[ifi.ich] = dxp);
|
|
ifi.xpPr += dxpPr;
|
|
vfli.rgch[ifi.ich++] = ch;
|
|
#endif
|
|
|
|
/* special case "normal characters" above hyphen */
|
|
|
|
if (ch > chHyphen)
|
|
goto DefaultCh;
|
|
|
|
switch (ch)
|
|
{
|
|
|
|
#ifdef CRLF
|
|
case chReturn:
|
|
/* Undo damage */
|
|
ifi.ich--;
|
|
ifi.xp -= dxp;
|
|
ifi.xpPr -= dxpPr;
|
|
continue;
|
|
#endif /* CRLF */
|
|
|
|
case chNRHFile:
|
|
/* Undo damage */
|
|
ifi.ich--;
|
|
ifi.xp -= dxp;
|
|
ifi.xpPr -= dxpPr;
|
|
|
|
ichpNRH = ichpFormat - 1;
|
|
#ifdef DFLI
|
|
{
|
|
char rgch[100];
|
|
|
|
wsprintf(rgch," OptHyph: width==%d, xpPr==%d/%d\n\r",
|
|
DxpFromCh(chHyphen,true), ifi.xpPr,ifi.xpPrRight);
|
|
CommSz(rgch);
|
|
}
|
|
#endif
|
|
if (ifi.xpPr + DxpFromCh(chHyphen, true) > ifi.xpPrRight)
|
|
{
|
|
/* Won't fit, force a break */
|
|
goto DoBreak;
|
|
}
|
|
|
|
#ifdef CASHMERE
|
|
else if (fVisiMode)
|
|
{
|
|
/* Treat just like a normal hyphen */
|
|
ch = chHyphen;
|
|
goto NormChar;
|
|
}
|
|
#endif /* CASHMERE */
|
|
|
|
xpPrev = ifi.xp;
|
|
vfli.rgch[ifi.ich] = chTab;
|
|
goto Tab0;
|
|
|
|
case chSect:
|
|
/* Undo damage */
|
|
ifi.ich--;
|
|
ifi.xp -= dxp;
|
|
ifi.xpPr -= dxpPr;
|
|
|
|
vfli.dypFont = vfli.dypLine = (dypAscentMac + (vfli.dypBase
|
|
= dypDescentMac));
|
|
vfli.cpMac = vcpFetch + ifi.ichFetch;
|
|
if (FFirstIch(ifi.ich))
|
|
{
|
|
/* Beginning of line; return a splat */
|
|
vfli.fSplat = true;
|
|
|
|
if (!fFlmPrinting)
|
|
{
|
|
|
|
#ifdef CASHMERE
|
|
int chT = vfli.cpMac == vcpLimSectCache ?
|
|
chSectSplat : chSplat;
|
|
#else /* not CASHMERE */
|
|
int chT = chSplat;
|
|
#endif /* not CASHMERE */
|
|
|
|
int dxpCh = DxpFromCh(chT, false);
|
|
|
|
/* Set the width of the splat to be about 8.5" */
|
|
int cch = min((dxpLogInch * 17 / 2) / dxpCh,
|
|
ichMaxLine - 32);
|
|
|
|
bltbc(&vfli.rgch[ifi.ich], chT, cch);
|
|
bltc(&vfli.rgdxp[ifi.ich], dxpCh, cch);
|
|
vfli.ichMac = cch + ifi.ich;
|
|
vfli.xpReal = LOWORD(GetTextExtent(vhMDC,
|
|
(LPSTR)vfli.rgch, cch));
|
|
vfli.xpLeft = 0;
|
|
}
|
|
else
|
|
{
|
|
vfli.ichMac = 0;
|
|
}
|
|
goto EndFormat;
|
|
}
|
|
|
|
/* The section character is in the middle of a line, the
|
|
line will terminate in front of the character. */
|
|
/* vfSplatNext = TRUE; No longer used*/
|
|
vfli.cpMac += cchUsed - 1;
|
|
vfli.dcpDepend = 1;
|
|
if (!ifi.fPrevSpace)
|
|
{
|
|
ifi.cBreak = ifi.cchSpace;
|
|
vfli.ichReal = ifi.ich;
|
|
vfli.xpReal = ifi.xpReal = ifi.xp;
|
|
}
|
|
vfli.ichMac = ifi.ich;
|
|
vfli.dypLine = ifi.dypLineSize;
|
|
goto JustBreak;
|
|
|
|
case chTab:
|
|
/* Undo damage */
|
|
ifi.ich--;
|
|
ifi.xp -= dxp;
|
|
ifi.xpPr -= dxpPr;
|
|
|
|
if (ifi.xpPr < ifi.xpPrRight)
|
|
{
|
|
register struct CHP *pchp;
|
|
unsigned xaPr;
|
|
unsigned xaTab;
|
|
|
|
if (!ifi.fPrevSpace)
|
|
{
|
|
/* Remember number of spaces to left and number of
|
|
real chars in line for justification */
|
|
ifi.cBreak = ifi.cchSpace;
|
|
vfli.ichReal = ifi.ich;
|
|
ifi.xpReal = ifi.xp;
|
|
}
|
|
|
|
if (ifi.jc != jcTabLeft)
|
|
{
|
|
Justify(&ifi, xpTab, flm);
|
|
}
|
|
xpPrev = ifi.xp;
|
|
|
|
/* Now get info about this tab */
|
|
xaPr = MultDiv(ifi.xpPr, dxaPrPage, dxpPrPage);
|
|
while ((xaTab = ptbd->dxa) != 0)
|
|
{
|
|
if (xaTab > xaRight)
|
|
{
|
|
/* Don't let tabs extend past right margin. */
|
|
xaTab = xaRight;
|
|
}
|
|
|
|
if (xaTab >= xaPr)
|
|
{
|
|
/* Use tab stop information */
|
|
|
|
#ifdef CASHMERE
|
|
ifi.tlc = ptbd->tlc;
|
|
#endif /* CASHMERE */
|
|
|
|
ifi.jc = jcTabMin + (ptbd++)->jc;
|
|
|
|
#ifdef ENABLE /* we do the mapping in HgtbdCreate */
|
|
if (ifi.jc != jcTabDecimal)
|
|
{
|
|
ifi.jc = jcTabLeft;
|
|
}
|
|
#endif
|
|
goto TabFound;
|
|
}
|
|
ptbd++;
|
|
}
|
|
|
|
/* Out of set tabs; go to next nth column */
|
|
xaTab = (xaPr / (vzaTabDflt) + 1) * (vzaTabDflt);
|
|
|
|
#ifdef CASHMERE
|
|
ifi.tlc = tlcWhite;
|
|
#endif /* CASHMERE */
|
|
|
|
ifi.jc = jcTabLeft;
|
|
|
|
TabFound:
|
|
xpTab = imax(MultDiv(xaTab, dxpFormat, dxaFormat),
|
|
ifi.xp);
|
|
|
|
/* Do left-justified tabs immediately */
|
|
if (ifi.jc == jcTabLeft)
|
|
{
|
|
ifi.xp = xpTab;
|
|
ifi.xpPr = MultDiv(xaTab, dxpPrPage, dxaPrPage);
|
|
}
|
|
ifi.xpLeft = ifi.xp;
|
|
ifi.ichLeft = ifi.ich;
|
|
ifi.cchSpace = 0;
|
|
ifi.chBreak = 0;
|
|
Tab0:
|
|
ifi.fPrevSpace = false;
|
|
vfli.ichMac = ifi.ich;
|
|
vfli.xpReal = ifi.xp;
|
|
vfli.dypLine = ifi.dypLineSize;
|
|
vfli.dypBase = dypDescentMac;
|
|
vfli.dypFont = dypAscentMac + dypDescentMac;
|
|
|
|
if (ifi.ichFetch != 1 && (ichpFormat != ichpMacFormat
|
|
|| FGrowFormatHeap()))
|
|
{
|
|
/* Probably in real trouble if FGrowFormatHeap fails
|
|
at this point */
|
|
pchp = &(**vhgchpFormat)[ichpFormat - 1];
|
|
if (ichpFormat > 0)
|
|
{
|
|
/* Finish off previous run */
|
|
pchp->ichRun = ifi.ichPrev;
|
|
pchp->cchRun = ifi.ich - ifi.ichPrev;
|
|
}
|
|
|
|
blt(&chpLocal, ++pchp, cwCHP);
|
|
ichpFormat++;
|
|
}
|
|
else
|
|
{
|
|
pchp = &(**vhgchpFormat)[ichpFormat - 1];
|
|
}
|
|
pchp->ichRun = ifi.ich;
|
|
pchp->cchRun = ichMaxLine;
|
|
|
|
#ifdef CASHMERE
|
|
pchp->chLeader = mptlcch[ifi.tlc];
|
|
#endif /* CASHMERE */
|
|
|
|
vfli.rgdxp[ifi.ichPrev = ifi.ich++] = ifi.xp - xpPrev;
|
|
|
|
if (ch != chTab)
|
|
{
|
|
/* This character is a non-required hyphen. */
|
|
Dfli(CommSz("ch is really OptHyph "));
|
|
goto BreakOppr;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
ch = chNBSFile;
|
|
goto NormChar;
|
|
}
|
|
|
|
case chHyphen:
|
|
if (ifi.xpPr > ifi.xpPrRight)
|
|
{
|
|
goto DoBreak;
|
|
}
|
|
|
|
BreakOppr:
|
|
Dfli(CommSz(" BKOPPR\n\r"));
|
|
/* this case never used in switch - always goto here */
|
|
/* case chSpace: */
|
|
if (ifi.ich >= ichMaxLine)
|
|
{
|
|
Dfli(CommSzNum(" Unbroken, ich>ichMaxLine\n\r"));
|
|
goto Unbroken;
|
|
}
|
|
|
|
case chEol:
|
|
case chNewLine:
|
|
ifi.chBreak = ch;
|
|
vfli.cpMac = vcpFetch + cchUsed + ifi.ichFetch;
|
|
vfli.xpReal = ifi.xp;
|
|
vfli.ichMac = ifi.ich;
|
|
vfli.dypLine = ifi.dypLineSize;
|
|
vfli.dypFont = dypAscentMac + (vfli.dypBase =
|
|
dypDescentMac);
|
|
Dfli(CommSzNumNum(" vfli.xpReal, ichMac ",vfli.xpReal,vfli.ichMac));
|
|
|
|
|
|
if (ch == chHyphen || ch == chNRHFile)
|
|
{
|
|
Dfli(CommSz(" chHyph/OptHyph catch \n\r"));
|
|
ifi.cBreak = ifi.cchSpace;
|
|
vfli.ichReal = ifi.ich;
|
|
vfli.xpReal = ifi.xpReal = ifi.xp;
|
|
}
|
|
else
|
|
{
|
|
if (!ifi.fPrevSpace)
|
|
{
|
|
Dfli(CommSz("!fPrevSpace \n\r"));
|
|
ifi.cBreak = ifi.cchSpace;
|
|
vfli.ichReal = ifi.ich - 1;
|
|
ifi.xpReal = (vfli.xpReal = ifi.xp) - dxp;
|
|
}
|
|
if (ch == chEol || ch == chNewLine)
|
|
{
|
|
|
|
#ifdef CASHMERE
|
|
if (hfntb != 0 && vfli.cpMac ==
|
|
(**hfntb).rgfnd[0].cpFtn)
|
|
{
|
|
/* End of footnote */
|
|
if (!fFlmPrinting)
|
|
{
|
|
vfli.rgch[ifi.ich - 1] = chEMark;
|
|
vfli.xpReal += (vfli.rgdxp[ifi.ich - 1] =
|
|
DxpFromCh(chEMark, false)) - dxp;
|
|
vfli.ichReal++; /* show this guy */
|
|
}
|
|
}
|
|
else
|
|
#endif /* CASHMERE */
|
|
{
|
|
|
|
#ifdef CASHMERE
|
|
int chT = fVisiMode ? ChVisible(ch) : chSpace;
|
|
#else /* not CASHMERE */
|
|
int chT = chSpace;
|
|
#endif /* not CASHMERE */
|
|
|
|
int dxpNew = DxpFromCh(chT, fFlmPrinting);
|
|
|
|
vfli.rgch[ifi.ich - 1] = chT;
|
|
vfli.rgdxp[ifi.ich - 1] = dxpNew;
|
|
|
|
vfli.xpReal += (vfli.rgdxp[ifi.ich - 1] =
|
|
dxpNew) - dxp;
|
|
|
|
|
|
if (!ifi.fPrevSpace)
|
|
{
|
|
vfli.xpReal += dxpNew - dxp;
|
|
#ifdef CASHMERE
|
|
vfli.ichReal =
|
|
fVisiMode ? ifi.ich : ifi.ich - 1;
|
|
#else /* not CASHMERE */
|
|
vfli.ichReal = ifi.ich - 1;
|
|
#endif /* not CASHMERE */
|
|
}
|
|
}
|
|
|
|
|
|
if (ch == chEol)
|
|
{
|
|
JustEol:
|
|
if (fFlmPrinting)
|
|
{
|
|
vfli.ichMac = vfli.ichReal;
|
|
}
|
|
if (ifi.jc != jcTabLeft)
|
|
{
|
|
/* Handle last tab's text */
|
|
Justify(&ifi, xpTab, flm);
|
|
}
|
|
else if ((ifi.jc = ppap->jc) != jcBoth &&
|
|
ifi.jc != jcLeft)
|
|
{
|
|
/* Do line justification */
|
|
Justify(&ifi, ifi.xpRight, flm);
|
|
}
|
|
vfli.xpRight = ifi.xpRight;
|
|
goto EndFormat;
|
|
}
|
|
else
|
|
{
|
|
/* Handle a line break */
|
|
goto JustBreak;
|
|
}
|
|
}
|
|
++ifi.cchSpace;
|
|
ifi.fPrevSpace = true;
|
|
}
|
|
break;
|
|
|
|
DefaultCh:
|
|
|
|
default:
|
|
|
|
#ifdef DFLI
|
|
{
|
|
char rgch[100];
|
|
wsprintf(rgch," DefaultCh: %c, xp==%d/%d, xpPr==%d/%d\n\r",
|
|
ch, ifi.xp, ifi.xpRight, ifi.xpPr, ifi.xpPrRight);
|
|
CommSz(rgch);
|
|
}
|
|
#endif /* ifdef DFLI */
|
|
|
|
if (ifi.xpPr > ifi.xpPrRight)
|
|
DoBreak:
|
|
{
|
|
Dfli(CommSz(" BREAK!\n\r"));
|
|
if (ifi.chBreak == 0)
|
|
Unbroken:
|
|
{
|
|
/* Admit first character to the line, even if margin
|
|
is crossed. First character at ifi.ich - 1 may be
|
|
preceded by 0 width characters. */
|
|
#ifdef DBCS
|
|
if (IsDBCSLeadByte(ch))
|
|
{
|
|
if (FFirstIch(ifi.ich-2) && ifi.ich<ichMaxLine)
|
|
goto PChar;
|
|
vfli.cpMac = vcpFetch+cchUsed+ifi.ichFetch-2;
|
|
vfli.ichReal = vfli.ichMac = ifi.ich - 2;
|
|
vfli.dypLine = ifi.dypLineSize;
|
|
vfli.dypFont = dypAscentMac + (vfli.dypBase =
|
|
dypDescentMac);
|
|
vfli.dcpDepend = 1;
|
|
vfli.xpReal = ifi.xpReal = ifi.xp - (dxp * 2);
|
|
}
|
|
else
|
|
{
|
|
if (FFirstIch(ifi.ich-1) && ifi.ich<ichMaxLine)
|
|
goto PChar;
|
|
vfli.cpMac = vcpFetch+cchUsed+ifi.ichFetch-1;
|
|
vfli.ichReal = vfli.ichMac = ifi.ich - 1;
|
|
vfli.dypLine = ifi.dypLineSize;
|
|
vfli.dypFont = dypAscentMac + (vfli.dypBase =
|
|
dypDescentMac);
|
|
vfli.dcpDepend = 1;
|
|
vfli.xpReal = ifi.xpReal = ifi.xp - dxp;
|
|
}
|
|
#else
|
|
if (FFirstIch(ifi.ich - 1) && ifi.ich < ichMaxLine)
|
|
{
|
|
goto PChar;
|
|
}
|
|
vfli.cpMac = vcpFetch + cchUsed + ifi.ichFetch - 1;
|
|
vfli.ichReal = vfli.ichMac = ifi.ich - 1;
|
|
vfli.dypLine = ifi.dypLineSize;
|
|
vfli.dypFont = dypAscentMac + (vfli.dypBase =
|
|
dypDescentMac);
|
|
vfli.dcpDepend = 1;
|
|
vfli.xpReal = ifi.xpReal = ifi.xp - dxp;
|
|
#endif
|
|
goto DoJustify;
|
|
}
|
|
|
|
vfli.dcpDepend = vcpFetch + ifi.ichFetch - vfli.cpMac;
|
|
JustBreak:
|
|
if (ifi.chBreak == chNRHFile)
|
|
{
|
|
/* Append a non-required hyphen to the end of the
|
|
line. (Replace zero length tab previously
|
|
inserted) */
|
|
|
|
Dfli(CommSz(" Breaking line at OptHyphen\n\r"));
|
|
ifi.xpReal += (vfli.rgdxp[vfli.ichReal - 1] =
|
|
DxpFromCh(chHyphen, fFlmPrinting));
|
|
vfli.xpRight = vfli.xpReal = ifi.xpReal;
|
|
vfli.rgch[vfli.ichReal - 1] = chHyphen;
|
|
vfli.ichMac = vfli.ichReal;
|
|
if (ichpNRH < ichpFormat - 1)
|
|
{
|
|
register struct CHP *pchp =
|
|
&(**vhgchpFormat)[ichpNRH];
|
|
|
|
pchp->cchRun++;
|
|
if (pchp->ichRun >= vfli.ichMac)
|
|
{
|
|
pchp->ichRun = vfli.ichMac - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fFlmPrinting)
|
|
{
|
|
vfli.ichMac = vfli.ichReal;
|
|
}
|
|
if (ifi.jc != jcTabLeft)
|
|
{
|
|
Justify(&ifi, xpTab, flm);
|
|
}
|
|
else
|
|
{
|
|
DoJustify:
|
|
if ((ifi.jc = ppap->jc) != jcLeft)
|
|
{
|
|
Dfli(CommSzNum(" DoJustify: xpRight ",ifi.xpRight));
|
|
Justify(&ifi, ifi.xpRight, flm);
|
|
}
|
|
}
|
|
vfli.xpRight = ifi.xpRight;
|
|
EndFormat:
|
|
vfli.ichLastTab = ifi.ichLeft;
|
|
|
|
#ifdef CASHMERE
|
|
if (vfli.cpMac == vcpLimParaCache)
|
|
{
|
|
vfli.dypAfter = vpapAbs.dyaAfter / DyaPerPixFormat;
|
|
vfli.dypLine += vfli.dypAfter;
|
|
vfli.dypBase += vfli.dypAfter;
|
|
}
|
|
#endif /* CASHMERE */
|
|
|
|
Scribble(5, ' ');
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
PChar:
|
|
/* A printing character */
|
|
ifi.fPrevSpace = false;
|
|
}
|
|
break;
|
|
|
|
} /* Switch */
|
|
}
|
|
} /* for ( ; ; ) */
|
|
|
|
Scribble(5, ' ');
|
|
}
|
|
|
|
|
|
/* J U S T I F Y */
|
|
near Justify(pifi, xpTab, flm)
|
|
struct IFI *pifi;
|
|
unsigned xpTab;
|
|
int flm;
|
|
{
|
|
int dxp;
|
|
int ichT;
|
|
int xpLeft;
|
|
|
|
|
|
xpLeft = pifi->xpLeft;
|
|
switch (pifi->jc)
|
|
{
|
|
CHAR *pch;
|
|
unsigned *pdxp;
|
|
|
|
#ifdef CASHMERE
|
|
case jcTabLeft:
|
|
case jcLeft:
|
|
return;
|
|
|
|
case jcTabRight:
|
|
dxp = xpTab - pifi->xpReal;
|
|
break;
|
|
|
|
case jcTabCenter:
|
|
dxp = (xpTab - xpLeft) - ((pifi->xpReal - xpLeft + 1) >> 1);
|
|
break;
|
|
#endif /* CASHMERE */
|
|
|
|
case jcTabDecimal:
|
|
dxp = xpTab - xpLeft;
|
|
for (ichT = pifi->ichLeft + 1; ichT < vfli.ichReal &&
|
|
vfli.rgch[ichT] != vchDecimal; ichT++)
|
|
{
|
|
dxp -= vfli.rgdxp[ichT];
|
|
}
|
|
break;
|
|
|
|
case jcCenter:
|
|
if ((dxp = xpTab - pifi->xpReal) <= 0)
|
|
{
|
|
return;
|
|
}
|
|
dxp = dxp >> 1;
|
|
break;
|
|
|
|
case jcRight:
|
|
dxp = xpTab - pifi->xpReal;
|
|
break;
|
|
|
|
case jcBoth:
|
|
if (pifi->cBreak == 0)
|
|
{
|
|
/* Ragged edge forced */
|
|
return;
|
|
}
|
|
|
|
if ((dxp = xpTab - pifi->xpReal) <= 0)
|
|
{
|
|
/* There is nothing to do. */
|
|
return;
|
|
}
|
|
|
|
pifi->xp += dxp;
|
|
vfli.xpReal += dxp;
|
|
vfli.dxpExtra = dxp / pifi->cBreak;
|
|
|
|
/* Rounding becomes a non-existant issue due to brilliant
|
|
re-thinking.
|
|
"What a piece of work is man
|
|
How noble in reason
|
|
In form and movement,
|
|
how abject and admirable..."
|
|
|
|
Bill "Shake" Spear [describing Sand Word] */
|
|
{
|
|
register CHAR *pch = &vfli.rgch[vfli.ichReal];
|
|
register int *pdxp = &vfli.rgdxp[vfli.ichReal];
|
|
int dxpT = dxp;
|
|
int cBreak = pifi->cBreak;
|
|
int cxpQuotient = (dxpT / cBreak) + 1;
|
|
int cWideSpaces = dxpT % cBreak;
|
|
|
|
vfli.fAdjSpace = fTrue;
|
|
|
|
for ( ; ; )
|
|
{
|
|
/* Widen blanks */
|
|
--pch;
|
|
--pdxp;
|
|
if (*pch == chSpace)
|
|
{
|
|
if (cWideSpaces-- == 0)
|
|
{
|
|
int *pdxpT = pdxp + 1;
|
|
|
|
while (*pdxpT == 0)
|
|
{
|
|
pdxpT++;
|
|
}
|
|
vfli.ichFirstWide = pdxpT - vfli.rgdxp;
|
|
cxpQuotient--;
|
|
}
|
|
*pdxp += cxpQuotient;
|
|
if ((dxpT -= cxpQuotient) <= 0)
|
|
{
|
|
if (pifi->cBreak > 1)
|
|
{
|
|
int *pdxpT = pdxp + 1;
|
|
|
|
while (*pdxpT == 0)
|
|
{
|
|
pdxpT++;
|
|
}
|
|
vfli.ichFirstWide = pdxpT - vfli.rgdxp;
|
|
}
|
|
return;
|
|
}
|
|
pifi->cBreak--;
|
|
}
|
|
}
|
|
}
|
|
} /* Switch */
|
|
|
|
if (dxp <= 0)
|
|
{
|
|
/* Nothing to do */
|
|
return;
|
|
}
|
|
|
|
pifi->xp += dxp;
|
|
|
|
if (flm & flmPrinting)
|
|
{
|
|
pifi->xpPr += dxp;
|
|
}
|
|
else
|
|
{
|
|
/* This statememt might introduce rounding errors in pifi->xpPr, but
|
|
with luck, they will be small. */
|
|
pifi->xpPr += MultDiv(MultDiv(dxp, czaInch, dxpLogInch), dxpPrPage,
|
|
dxaPrPage);
|
|
}
|
|
|
|
if (pifi->ichLeft < 0)
|
|
{
|
|
/* Normal justification */
|
|
vfli.xpLeft += dxp;
|
|
}
|
|
else
|
|
{
|
|
/* Tab justification */
|
|
vfli.rgdxp[pifi->ichLeft] += dxp;
|
|
}
|
|
vfli.xpReal += dxp;
|
|
}
|
|
|
|
|
|
/* F G R O W F O R M A T H E A P */
|
|
int near FGrowFormatHeap()
|
|
{
|
|
/* Grow vhgchpFormat by 20% */
|
|
int cchpIncr = ichpMacFormat / 5 + 1;
|
|
|
|
#ifdef WINHEAP
|
|
if (!LocalReAlloc((HANDLE)vhgchpFormat, (ichpMacFormat + cchpIncr) * cchCHP,
|
|
NONZEROLHND))
|
|
#else /* not WINHEAP */
|
|
if (!FChngSizeH(vhgchpFormat, (ichpMacFormat + cchpIncr) * cwCHP, false))
|
|
#endif /* not WINHEAP */
|
|
|
|
{
|
|
/* Sorry, charlie */
|
|
return false;
|
|
}
|
|
ichpMacFormat += cchpIncr;
|
|
return true;
|
|
}
|
|
|
|
|
|
/* #define DBEMG */
|
|
/* D X P F R O M C H */
|
|
#ifdef DBCS
|
|
/* DxpFromCh() assumes that ch passed is the first byte of a DBCS character
|
|
if it is a part of such character. */
|
|
#endif
|
|
int DxpFromCh(ch, fPrinter)
|
|
int ch;
|
|
int fPrinter;
|
|
{
|
|
int *pdxp; // changed to int (7.23.91) v-dougk
|
|
int dxpDummy; // changed to int (7.23.91) v-dougk
|
|
|
|
extern int dxpLogCh;
|
|
extern struct FCE *vpfceScreen;
|
|
|
|
/* If the width is not in the width table, then get it. */
|
|
if (ch < chFmiMin)
|
|
{
|
|
switch (ch)
|
|
{
|
|
case chTab:
|
|
case chEol:
|
|
case chReturn:
|
|
case chSect:
|
|
case chNewLine:
|
|
case chNRHFile:
|
|
/* the width for these characters aren't really important */
|
|
pdxp = (CHAR *)(fPrinter ? &vfmiPrint.dxpSpace : &vfmiScreen.dxpSpace);
|
|
break;
|
|
default:
|
|
pdxp = &dxpDummy;
|
|
*pdxp = dxpNil;
|
|
break;
|
|
}
|
|
}
|
|
else if (ch >= chFmiMax)
|
|
{
|
|
/* outside the range we hold in our table - kludge it */
|
|
pdxp = &dxpDummy;
|
|
*pdxp = dxpNil;
|
|
}
|
|
else
|
|
{
|
|
/* inside our table */
|
|
pdxp = (fPrinter ? vfmiPrint.mpchdxp : vfmiScreen.mpchdxp) + ch;
|
|
}
|
|
|
|
#ifdef DBCS
|
|
if (*pdxp == dxpNil && IsDBCSLeadByte(ch) )
|
|
{
|
|
int dxp;
|
|
#else
|
|
if (*pdxp == dxpNil)
|
|
{
|
|
int dxp;
|
|
#endif
|
|
|
|
#ifdef DBCS
|
|
struct FMI *pfmi;
|
|
int rgchT[cchDBCS]; // changed to int (7.23.91) v-dougk
|
|
int dxpT;
|
|
int dxpDBCS;
|
|
|
|
pfmi = fPrinter ? (&vfmiPrint) : (&vfmiScreen);
|
|
Assert(pfmi->bDummy == dxpNil);
|
|
if (pfmi->dxpDBCS == dxpNil)
|
|
{
|
|
/* Get the width from GDI. */
|
|
rgchT[0] = rgchT[1] = ch;
|
|
dxpDBCS = (fPrinter ?
|
|
LOWORD(GetTextExtent(vhDCPrinter,
|
|
(LPSTR) rgchT, cchDBCS)) :
|
|
LOWORD(GetTextExtent(vhMDC,
|
|
(LPSTR) rgchT, cchDBCS)));
|
|
/* Store in fmi, if it fits. */
|
|
if (0 <= dxpDBCS && dxpDBCS < dxpNil)
|
|
pfmi->dxpDBCS = (BYTE) dxpDBCS;
|
|
return (dxpDBCS - pfmi->dxpOverhang);
|
|
}
|
|
else
|
|
return (pfmi->dxpDBCS - pfmi->dxpOverhang);
|
|
}
|
|
else {
|
|
int dxp;
|
|
#endif /* DBCS */
|
|
/* get width from GDI */
|
|
dxp = fPrinter ? LOWORD(GetTextExtent(vhDCPrinter, (LPSTR)&ch, 1)) -
|
|
vfmiPrint.dxpOverhang : LOWORD(GetTextExtent(vhMDC, (LPSTR)&ch, 1)) -
|
|
vfmiScreen.dxpOverhang;
|
|
#ifdef DBEMG
|
|
CommSzNum("Get this.... ", dxp);
|
|
#endif
|
|
//(7.24.91) v-dougk if (dxp >= 0 && dxp < dxpNil)
|
|
{
|
|
/* only store dxp's that fit in a byte */
|
|
*pdxp = dxp;
|
|
}
|
|
|
|
#ifdef DBEMG
|
|
{
|
|
char szT[10];
|
|
CommSzSz("fPrinter: ", (fPrinter ? "Printer" : "Screen"));
|
|
if (ch == 0x0D) {
|
|
szT[0] = 'C'; szT[1] = 'R'; szT[2] = '\0';
|
|
}
|
|
else if (ch == 0x0A) {
|
|
szT[0] = 'L'; szT[1] = 'F'; szT[2] = '\0';
|
|
}
|
|
else if (32 <= ch && ch <= 126) {
|
|
szT[0] = ch; szT[1] ='\0';
|
|
}
|
|
else if (FKanji1(ch)) {
|
|
szT[0] = 'K'; szT[1] = 'A'; szT[2] = 'N'; szT[3] = 'J';
|
|
szT[4] = 'I'; szT[5] = '\0';
|
|
}
|
|
else {
|
|
szT[0] = szT[1] = szT[2] = '-'; szT[3] = '\0';
|
|
}
|
|
CommSzSz("Character: ", szT);
|
|
CommSzNum("Dxp: ", (int) dxp);
|
|
CommSzNum("OverHang: ", (int) (fPrinter ? vfmiPrint.dxpOverhang : vfmiScreen.dxpOverhang));
|
|
}
|
|
#endif
|
|
return(dxp);
|
|
}
|
|
|
|
#ifdef DBEMG
|
|
{
|
|
char szT[10];
|
|
CommSzSz("fPrinter: ", (fPrinter ? "Printer" : "Screen"));
|
|
if (ch == 0x0D) {
|
|
szT[0] = 'C'; szT[1] = 'R'; szT[2] = '\0';
|
|
}
|
|
else if (ch == 0x0A) {
|
|
szT[0] = 'L'; szT[1] = 'F'; szT[2] = '\0';
|
|
}
|
|
else if (32 <= ch && ch <= 126) {
|
|
szT[0] = ch; szT[1] ='\0';
|
|
}
|
|
else if (FKanji1(ch)) {
|
|
szT[0] = 'K'; szT[1] = 'A'; szT[2] = 'N'; szT[3] = 'J';
|
|
szT[4] = 'I'; szT[5] = '\0';
|
|
}
|
|
else {
|
|
szT[0] = szT[1] = szT[2] = '-'; szT[3] = '\0';
|
|
}
|
|
CommSzSz("Character: ", szT);
|
|
CommSzNum("Dxp: ", (int) *pdxp);
|
|
CommSzNum("OverHang: ", (int) (fPrinter ? vfmiPrint.dxpOverhang : vfmiScreen.dxpOverhang));
|
|
}
|
|
#endif
|
|
return(*pdxp);
|
|
}
|
|
|
|
|
|
/* F F I R S T I C H */
|
|
int near FFirstIch(ich)
|
|
int ich;
|
|
{
|
|
/* Returns true iff ich is 0 or preceded only by 0 width characters */
|
|
register int ichT;
|
|
register int *pdxp = &vfli.rgdxp[0];
|
|
|
|
for (ichT = 0; ichT < ich; ichT++)
|
|
{
|
|
if (*pdxp++)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
ValidateMemoryDC()
|
|
{
|
|
/* Attempt to assure that vhMDC and vhDCPrinter are valid. If we have not
|
|
already run out of memory, then vhDCPrinter is guaranteed, but vhMDC may
|
|
fail due to out of memory -- it is the callers responsibility to check for
|
|
vhMDC == NULL. */
|
|
|
|
extern int vfOutOfMemory;
|
|
extern HDC vhMDC;
|
|
extern BOOL vfMonochrome;
|
|
extern long rgbText;
|
|
extern struct WWD *pwwdCur;
|
|
|
|
/* If we are out of memory, then we shouldn't try to gobble it up by getting
|
|
DC's. */
|
|
if (!vfOutOfMemory)
|
|
{
|
|
if (vhMDC == NULL)
|
|
{
|
|
/* Create a memory DC compatible with the screen if necessary. */
|
|
vhMDC = CreateCompatibleDC(pwwdCur->hDC);
|
|
|
|
/* Callers are responsible for checking for vhMDC == NULL case */
|
|
if (vhMDC != NULL)
|
|
{
|
|
/* Put the memory DC in transparent mode. */
|
|
SetBkMode(vhMDC, TRANSPARENT);
|
|
|
|
/* If the display is a monochrome device, then set the text
|
|
color for the memory DC. Monochrome bitmaps will not be
|
|
converted to the foreground and background colors in this case,
|
|
we must do the conversion. */
|
|
if (vfMonochrome = (GetDeviceCaps(pwwdCur->hDC, NUMCOLORS) ==
|
|
2))
|
|
{
|
|
SetTextColor(vhMDC, rgbText);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If the printer DC is NULL then we need to reestablish it. */
|
|
if (vhDCPrinter == NULL)
|
|
{
|
|
GetPrinterDC(FALSE);
|
|
/* GetPrinterDC has already called SetMapperFlags() on vhDCPrinter. */
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|