Source code of Windows XP (NT5)
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.

1691 lines
53 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1992 Microsoft Corporation */
  3. /************************************************************/
  4. /*--- Module not really used, just the idea behind FORMAT.ASM ---*/
  5. #define NOCLIPBOARD
  6. #define NOGDICAPMASKS
  7. #define NOCTLMGR
  8. #define NOVIRTUALKEYCODES
  9. #define NOWINMESSAGES
  10. #define NOWINSTYLES
  11. #define NOKEYSTATE
  12. #define NOSYSCOMMANDS
  13. #define NORASTEROPS
  14. #define NOSHOWWINDOW
  15. #define NOCLIPBOARD
  16. #define NOWINSTYLES
  17. #define NOSYSMETRICS
  18. #define NOMENUS
  19. #define NOATOM
  20. #define NOCREATESTRUCT
  21. #define NODRAWTEXT
  22. #define NOMB
  23. #define NOMEMMGR
  24. #define NOMETAFILE
  25. #define NOWH
  26. #define NOWINOFFSETS
  27. #define NOWNDCLASS
  28. #include <windows.h>
  29. /* #include "wwsmall.h" */
  30. #include "mw.h"
  31. #include "cmddefs.h"
  32. #include "fmtdefs.h"
  33. #include "propdefs.h"
  34. #include "ch.h"
  35. #include "docdefs.h"
  36. #include "ffdefs.h"
  37. #include "filedefs.h"
  38. #include "fkpdefs.h"
  39. #include "dispdefs.h"
  40. #include "scrndefs.h"
  41. #include "macro.h"
  42. #include "debug.h"
  43. #include "fontdefs.h"
  44. #include "str.h"
  45. #include "wwdefs.h"
  46. #ifdef DBCS
  47. #include "dbcs.h"
  48. #endif
  49. #ifdef DFLI
  50. #define Dfli(x) x /* Enable debug-format-line info */
  51. #else
  52. #define Dfli(x)
  53. #endif
  54. #ifdef CASHMERE
  55. #define cchSmcapMax 16
  56. #endif /* CASHMERE */
  57. static int ichpFormat;
  58. #ifdef CASHMERE
  59. static CHAR mptlcch[] = " .-_";
  60. #endif /* CASHMERE */
  61. extern int docHelp;
  62. extern struct FLI vfli;
  63. extern struct CHP (**vhgchpFormat)[];
  64. extern int ichpMacFormat;
  65. extern struct CHP vchpAbs;
  66. extern struct PAP vpapAbs;
  67. extern struct SEP vsepAbs;
  68. extern struct SEP vsepPage;
  69. extern struct CHP vchpNormal;
  70. extern struct DOD (**hpdocdod)[];
  71. extern typeCP vcpLimSectCache;
  72. extern typeCP vcpFirstParaCache;
  73. extern typeCP vcpLimParaCache;
  74. extern typeCP vcpFetch;
  75. extern int vichFetch;
  76. extern int vccpFetch;
  77. extern CHAR *vpchFetch;
  78. extern int vcchFetch;
  79. extern int vftc;
  80. extern int ypSubSuper;
  81. extern int ypSubSuperPr;
  82. extern HDC vhMDC;
  83. extern HDC vhDCPrinter;
  84. extern int dxpLogInch;
  85. extern int dypLogInch;
  86. extern int dxaPrPage;
  87. extern int dyaPrPage;
  88. extern int dxpPrPage;
  89. extern int dypPrPage;
  90. extern int dypMax;
  91. extern struct FMI vfmiScreen, vfmiPrint;
  92. extern int vfOutOfMemory;
  93. extern CHAR vchDecimal; /* "decimal point" character */
  94. extern int vzaTabDflt; /* width of default tab */
  95. #ifdef CASHMERE
  96. extern int vfVisiMode;
  97. #endif /* CASHMERE */
  98. /* F O R M A T L I N E */
  99. FormatLine(doc, cp, ichCp, cpMac, flm)
  100. int doc;
  101. typeCP cp;
  102. int ichCp;
  103. typeCP cpMac;
  104. int flm;
  105. {
  106. /* Fills up vfli with a line of text */
  107. int near Justify(struct IFI *, unsigned, int);
  108. int near FGrowFormatHeap(void);
  109. int near FFirstIch(int);
  110. struct IFI ifi;
  111. struct TBD *ptbd;
  112. struct CHP chpLocal;
  113. int xpTab;
  114. #ifdef CASHMERE
  115. int dypBefore;
  116. #endif /* CASHMERE */
  117. int dypAscent;
  118. int dypDescent;
  119. int dypAscentMac;
  120. int dypDescentMac;
  121. unsigned xaLeft;
  122. unsigned xaRight;
  123. struct PAP *ppap;
  124. struct SEP *psep;
  125. int fFlmPrinting = flm & flmPrinting;
  126. int dxaFormat;
  127. int dyaFormat;
  128. int dxpFormat;
  129. int dypFormat;
  130. int ypSubSuperFormat;
  131. int fTruncated = false; /* if the run was truncated */
  132. int ichpNRH;
  133. #ifdef CASHMERE
  134. struct FNTB **hfntb;
  135. int fVisiMode;
  136. #endif /* CASHMERE */
  137. /* Check for fli current */
  138. if (vfli.doc == doc && vfli.cpMin == cp && vfli.ichCpMin == ichCp &&
  139. vfli.flm == flm)
  140. {
  141. /* Just did this one */
  142. return;
  143. }
  144. Scribble(5, 'F');
  145. bltc(&vfli, 0, cwFLIBase);
  146. /* This means:
  147. vfli.fSplat = false;
  148. vfli.dcpDepend = 0;
  149. vfli.ichCpMac = 0;
  150. vfli.dypLine = 0;
  151. vfli.dypAfter = 0;
  152. vfli.dypFont = 0;
  153. vfli.dypBase = 0;
  154. */
  155. /* vfSplatNext = FALSE; No longer used. */
  156. /* Rest of format loads up cache with current data */
  157. vfli.doc = doc;
  158. vfli.cpMin = cp;
  159. vfli.ichCpMin = ichCp;
  160. vfli.flm = flm;
  161. if (cp > cpMac)
  162. {
  163. /* Space after the endmark. Reset the cache because the footnotes come
  164. at the same cp in the footnote window */
  165. vfli.doc = docNil;
  166. vfli.cpMac = cp;
  167. vfli.rgdxp[0] = 0;
  168. /* Line after end mark is taller than screen */
  169. #ifdef CASHMERE
  170. vfli.dypBase = vfli.dypFont = vfli.dypAfter = ((vfli.dypLine = dypMax)
  171. >> 1);
  172. #else /* not CASHMERE */
  173. vfli.dypBase = vfli.dypFont = ((vfli.dypLine = dypMax) >> 1);
  174. #endif /* not CASHMERE */
  175. Scribble(5, ' ');
  176. return;
  177. }
  178. /* Initialize run tables */
  179. ichpFormat = 0;
  180. /* Cache section and paragraph properties */
  181. #ifdef CASHMERE
  182. hfntb = (**hpdocdod)[doc].hfntb;
  183. if (hfntb == 0 || cp < (**hfntb).rgfnd[0].cpFtn)
  184. {
  185. /* Normal text */
  186. CacheSect(doc, cp);
  187. }
  188. else
  189. {
  190. /* Footnote section properties come from the section of the footnote
  191. reference. */
  192. CacheSect(doc, CpRefFromFtn(doc, cp));
  193. }
  194. #else /* not CASHMERE */
  195. CacheSect(doc, cp);
  196. #endif /* not CASHMERE */
  197. psep = &vsepAbs;
  198. CachePara(doc, cp);
  199. ppap = &vpapAbs;
  200. /* Now we have:
  201. ppap paragraph properties
  202. psep division properties
  203. */
  204. if (ppap->fGraphics)
  205. {
  206. /* Format a picture paragraph in a special way (see picture.c) */
  207. FormatGraphics(doc, cp, ichCp, cpMac, flm);
  208. Scribble(5, ' ');
  209. return;
  210. }
  211. /* Assure we have a good memory DC for font stuff */
  212. ValidateMemoryDC();
  213. if (vhMDC == NULL || vhDCPrinter == NULL)
  214. {
  215. Scribble(5, ' ');
  216. return;
  217. }
  218. #ifdef CASHMERE
  219. /* When printing, don't show visible characters */
  220. fVisiMode = vfVisiMode && !fFlmPrinting;
  221. #endif /* CASHMERE */
  222. bltc(&ifi, 0, cwIFI);
  223. /* This means:
  224. ifi.ich = 0;
  225. ifi.ichPrev = 0;
  226. ifi.ichFetch = 0;
  227. ifi.cchSpace = 0;
  228. ifi.ichLeft = 0;
  229. */
  230. ifi.jc = jcTabLeft;
  231. ifi.fPrevSpace = true;
  232. /* Set up some variables that have different value depending on whether we
  233. are printing or not. */
  234. if (fFlmPrinting)
  235. {
  236. dxaFormat = dxaPrPage;
  237. dyaFormat = dyaPrPage;
  238. dxpFormat = dxpPrPage;
  239. dypFormat = dypPrPage;
  240. ypSubSuperFormat = ypSubSuperPr;
  241. }
  242. else
  243. {
  244. dxaFormat = dyaFormat = czaInch;
  245. dxpFormat = dxpLogInch;
  246. dypFormat = dypLogInch;
  247. ypSubSuperFormat = ypSubSuper;
  248. }
  249. /* Calculate line height and width measures. Compute
  250. xaLeft left indent 0 means at left margin
  251. xaRight width of column measured from left margin (not from left
  252. indent).
  253. */
  254. xaLeft = ppap->dxaLeft;
  255. /* If this is the first line of a paragraph, adjust xaLeft for the first
  256. line indent. (Also, set dypBefore, since its handy.) */
  257. if (cp == vcpFirstParaCache)
  258. {
  259. xaLeft += ppap->dxaLeft1;
  260. #ifdef CASHMERE
  261. dypBefore = MultDiv(ppap->dyaBefore, dypLogInch, czaInch);
  262. #endif /* CASHMERE */
  263. }
  264. #ifdef CASHMERE
  265. else
  266. {
  267. dypBefore = 0;
  268. }
  269. #endif /* CASHMERE */
  270. /* Now, set xaRight (width measured in twips). */
  271. #ifdef CASHMERE
  272. xaRight = (ppap->rhc ? vsepPage.xaMac - vsepPage.dxaGutter :
  273. psep->dxaText) - ppap->dxaRight;
  274. #else /* not CASHMERE */
  275. xaRight = psep->dxaText - ppap->dxaRight;
  276. #endif /* not CASHMERE */
  277. /* Do necessary checks on xaLeft and xaRight */
  278. if (xaRight > xaRightMax)
  279. {
  280. xaRight = xaRightMax;
  281. }
  282. if (xaLeft > xaRightMax)
  283. {
  284. xaLeft = xaRightMax;
  285. }
  286. if (xaLeft < 0)
  287. {
  288. xaLeft = 0;
  289. }
  290. if (xaRight < xaLeft)
  291. {
  292. xaRight = xaLeft + 1;
  293. }
  294. vfli.xpLeft = ifi.xp = ifi.xpLeft = MultDiv(xaLeft, dxpFormat, dxaFormat);
  295. vfli.xpMarg = ifi.xpRight = MultDiv(xaRight, dxpFormat, dxaFormat);
  296. ifi.xpPr = MultDiv(xaLeft, dxpPrPage, dxaPrPage);
  297. ifi.xpPrRight = MultDiv(xaRight, dxpPrPage, dxaPrPage);
  298. /* Get a pointer to the tab-stop table. */
  299. ptbd = ppap->rgtbd;
  300. /* Turn off justification. */
  301. SetTextJustification(fFlmPrinting ? vhDCPrinter : vhMDC, 0, 0);
  302. /* Initialize the line height information. */
  303. dypAscentMac = dypDescentMac = 0;
  304. /* To tell if there were any tabs */
  305. ifi.ichLeft = -1;
  306. /* Get the first run, and away we go... */
  307. FetchCp(doc, cp, ichCp, fcmBoth + fcmParseCaps);
  308. goto FirstCps;
  309. for ( ; ; )
  310. {
  311. int iichNew;
  312. int xpPrev;
  313. int dxp;
  314. int dxpPr;
  315. /* The number of characters to process (usually vcchFetch) */
  316. int cch;
  317. /* The number of characters in current run already used */
  318. int cchUsed;
  319. /* A pointer to the current list of characters (usually vpchFetch) */
  320. CHAR *pch;
  321. #ifdef CASHMERE
  322. CHAR rgchSmcap[cchSmcapMax];
  323. #endif /* CASHMERE */
  324. if (ifi.ichFetch == cch)
  325. {
  326. /* End of a run */
  327. int dich;
  328. BOOL fSizeChanged;
  329. if (ifi.ich >= ichMaxLine)
  330. /* End of run because of line length limit has been reached. */
  331. {
  332. goto DoBreak;
  333. }
  334. if (fTruncated)
  335. {
  336. cchUsed += cch;
  337. pch = vpchFetch + cchUsed;
  338. cch = vcchFetch - cchUsed;
  339. fTruncated = false;
  340. goto OldRun; /* use the rest of the old run */
  341. }
  342. NullRun:
  343. FetchCp(docNil, cpNil, 0, fcmBoth + fcmParseCaps);
  344. FirstCps:
  345. cchUsed = 0;
  346. /* Continue fetching runs until a run is found with a nonzero
  347. length. */
  348. if ((cch = vcchFetch) == 0)
  349. {
  350. goto NullRun;
  351. }
  352. pch = vpchFetch;
  353. if (vcpFetch >= cpMac || (!fFlmPrinting && *pch == chSect))
  354. {
  355. #ifdef SYSENDMARK
  356. /* Force end mark and section mark to be in standard system
  357. font. */
  358. blt(&vchpNormal, &vchpAbs, cwCHP);
  359. vchpAbs.ftc = ftcSystem;
  360. vchpAbs.ftcXtra = 0;
  361. vchpAbs.hps = hpsDefault;
  362. #else
  363. #ifdef REVIEW
  364. /* The following comment is absolutely misleading! Ftc==0
  365. doesn't give you a system font. It gives you the first
  366. entry in the font table. */
  367. #endif /* REVIEW */
  368. /* Force end mark and section mark to be in standard system
  369. font. */
  370. blt(&vchpNormal, &vchpAbs, cwCHP);
  371. vchpAbs.ftc = 0;
  372. vchpAbs.ftcXtra = 0;
  373. vchpAbs.hps = hpsDefault;
  374. #endif /* if-else-def KANJI */
  375. }
  376. #ifdef CASHMERE
  377. /* Adjust the size of the font for "small capitals". */
  378. if (vchpAbs.csm == csmSmallCaps)
  379. {
  380. vchpAbs.hps = HpsAlter(vchpAbs.hps, -1);
  381. }
  382. #endif /* CASHMERE */
  383. /* Now we have:
  384. ichpFormat index into gchp table
  385. vcpFetch first cp of current run
  386. vfli.cpMin first cp of line
  387. ifi.ich ???
  388. */
  389. /* since LoadFont could change vchpAbs, and we don't want
  390. that to happen, we copy vchpAbs into vchpLocal and use
  391. vchpLocal in place of vchpAbs hereafter. Note that vchpAbs
  392. is intentionally used above for handling the endmark. */
  393. blt(&vchpAbs, &chpLocal, cwCHP);
  394. if (fFlmPrinting)
  395. {
  396. LoadFont(doc, &chpLocal, mdFontPrint);
  397. dypAscent = vfmiPrint.dypAscent + vfmiPrint.dypLeading;
  398. dypDescent = vfmiPrint.dypDescent;
  399. }
  400. else
  401. {
  402. LoadFont(doc, &chpLocal, mdFontJam);
  403. dypAscent = vfmiScreen.dypAscent + vfmiScreen.dypLeading;
  404. dypDescent = vfmiScreen.dypDescent;
  405. }
  406. #ifdef ENABLE /* BRYANL 8/27/87: New philosophy for handling
  407. font selection failures is: font selection
  408. ALWAYS succeeds. This prevents FormatLine
  409. returns that do not advance. */
  410. /* Bail out if there is a memory failure. */
  411. if (vfOutOfMemory)
  412. {
  413. goto DoBreak;
  414. }
  415. #endif /* ENABLE */
  416. /* Floating line size algorithm */
  417. if (chpLocal.hpsPos != 0)
  418. {
  419. /* Modify font for subscript/superscript */
  420. if (chpLocal.hpsPos < hpsNegMin)
  421. {
  422. dypAscent += ypSubSuperFormat;
  423. }
  424. else
  425. {
  426. dypDescent += ypSubSuperFormat;
  427. }
  428. }
  429. /* Update the maximum ascent and descent of the line. */
  430. fSizeChanged = FALSE;
  431. if (dypDescentMac < dypDescent)
  432. {
  433. dypDescentMac = dypDescent;
  434. fSizeChanged = TRUE;
  435. }
  436. if (dypAscentMac < dypAscent)
  437. {
  438. dypAscentMac = dypAscent;
  439. fSizeChanged = TRUE;
  440. }
  441. if (fSizeChanged)
  442. {
  443. #ifdef AUTO_SPACING
  444. /* This is the original Mac Word code that assumed line spacing
  445. of 0 in a PAP meant auto line spacing. PC Word defaults to 1
  446. line invalidating this assumption. */
  447. if (ppap->dyaLine == 0)
  448. {
  449. #ifdef CASHMERE
  450. ifi.dypLineSize = dypDescentMac + dypAscentMac + dypBefore;
  451. #else /* not CASHMERE */
  452. ifi.dypLineSize = dypDescentMac + dypAscentMac;
  453. #endif /* not CASHMERE */
  454. }
  455. else
  456. {
  457. #ifdef CASHMERE
  458. ifi.dypLineSize = imax(MultDiv(ppap->dyaLine, dypFormat,
  459. dyaFormat) + dypBefore, dypBefore + 1);
  460. #else /* not CASHMERE */
  461. ifi.dypLineSize = imax(MultDiv(ppap->dyaLine, dypFormat,
  462. dyaFormat), 1);
  463. #endif /* not CASHMERE */
  464. }
  465. #else /* not AUTO_SPACING */
  466. /* This code forces auto line spacing except in the case where
  467. the user specifies a line spacing greater than the auto line
  468. spacing. */
  469. {
  470. #ifdef CASHMERE
  471. register int dypAuto = dypDescentMac + dypAscentMac +
  472. dypBefore;
  473. #else /* not CASHMERE */
  474. register int dypAuto = dypDescentMac + dypAscentMac;
  475. #endif /* not CASHMERE */
  476. if (ppap->dyaLine > czaLine)
  477. {
  478. #ifdef CASHMERE
  479. register int dypUser = imax(MultDiv(ppap->dyaLine,
  480. dypFormat, dyaFormat) + dypBefore, dypBefore + 1);
  481. #else /* not CASHMERE */
  482. register int dypUser = imax(MultDiv(ppap->dyaLine,
  483. dypFormat, dyaFormat), 1);
  484. #endif /* not CASHMERE */
  485. ifi.dypLineSize = max(dypAuto, dypUser);
  486. }
  487. else
  488. {
  489. ifi.dypLineSize = dypAuto;
  490. }
  491. }
  492. #endif /* not AUTO_SPACING */
  493. }
  494. OldRun:
  495. /* Calculate length of the run but no greater than 256 */
  496. iichNew = (int)(vcpFetch - vfli.cpMin);
  497. if (iichNew >= ichMaxLine)
  498. {
  499. iichNew = ichMaxLine - 1;
  500. }
  501. dich = iichNew - ifi.ich;
  502. /* Ensure that all tab and non-required hyphen characters start at
  503. beginning of run */
  504. if (ichpFormat <= 0 || dich > 0 || CchDiffer(&chpLocal,
  505. &(**vhgchpFormat)[ichpFormat - 1], cchCHPUsed) != 0 || *pch ==
  506. chTab || *pch == chNRHFile)
  507. {
  508. #ifdef DFLI
  509. if (*pch == chNRHFile)
  510. CommSz("CHNRHFILE at beginning of run");
  511. #endif
  512. if (ichpFormat != ichpMacFormat || FGrowFormatHeap())
  513. {
  514. register struct CHP *pchp = &(**vhgchpFormat)[ichpFormat -
  515. 1];
  516. if (ichpFormat > 0)
  517. {
  518. pchp->cchRun = ifi.ich - ifi.ichPrev;
  519. pchp->ichRun = ifi.ichPrev;
  520. }
  521. blt(&chpLocal, ++pchp, cwCHP);
  522. #ifdef ENABLE /* font codes */
  523. pchp->ftc = vftc;
  524. pchp->ftcXtra = (vftc & 0x01c0) >> 6;
  525. pchp->hps = vhps;
  526. #endif /* ENABLE */
  527. pchp->cchRun = ichMaxLine;
  528. if (dich <= 0)
  529. {
  530. pchp->ichRun = ifi.ich;
  531. }
  532. else
  533. {
  534. /* Q&D insert */
  535. bltc(&vfli.rgdxp[ifi.ich], 0, dich);
  536. bltbc(&vfli.rgch[ifi.ich], 0, dich);
  537. pchp->ichRun = ifi.ich = iichNew;
  538. }
  539. ifi.ichPrev = ifi.ich;
  540. ichpFormat++;
  541. }
  542. }
  543. if (vcpFetch >= cpMac)
  544. {
  545. /* End of doc reached */
  546. if (!ifi.fPrevSpace || vcpFetch == cp)
  547. {
  548. vfli.ichReal = ifi.ich;
  549. vfli.xpReal = ifi.xpReal = ifi.xp;
  550. }
  551. if (!fFlmPrinting && (doc != docHelp))
  552. {
  553. vfli.rgch[ifi.ich] = chEMark;
  554. vfli.xpReal += (vfli.rgdxp[ifi.ich++] = DxpFromCh(chEMark,
  555. false));
  556. }
  557. vfli.dypLine = ifi.dypLineSize;
  558. vfli.dypBase = dypDescentMac;
  559. vfli.dypFont = dypAscentMac + dypDescentMac;
  560. vfli.ichMac = vfli.ichReal = ifi.ich;
  561. vfli.cpMac = cpMac + 1;
  562. goto JustEol; /* dcpDepend == 0 */
  563. }
  564. /* Here we have ifi.ich, cch */
  565. if (ifi.ich + cch > ichMaxLine)
  566. /* If this run would put the line over 255, truncate it and set a
  567. flag. */
  568. {
  569. cch = ichMaxLine - ifi.ich;
  570. fTruncated = true;
  571. }
  572. ifi.ichFetch = 0;
  573. #ifdef CASHMERE
  574. if (chpLocal.csm != csmNormal)
  575. {
  576. int ich;
  577. CHAR *pchT = &rgchSmcap[0];
  578. /* We can handle only a run of cchSmcapMax small capital
  579. characters. If the run is larger then truncate. */
  580. if (cch > cchSmcapMax)
  581. {
  582. cch = cchSmcapMax;
  583. fTruncated = true;
  584. }
  585. /* Raise the case of the characters. */
  586. for (ich = 0 ; ich < cch ; ich++)
  587. {
  588. *pchT++ = ChUpper(*pch++);
  589. }
  590. pch = &rgchSmcap[0];
  591. }
  592. #endif /* CASHMERE */
  593. /* Do "special" characters here */
  594. if (chpLocal.fSpecial)
  595. {
  596. if (!FFormatSpecials(&ifi, flm, vsepAbs.nfcPgn))
  597. {
  598. if (ifi.chBreak == 0) /* No breaks in this line */
  599. {
  600. goto Unbroken;
  601. }
  602. else
  603. {
  604. vfli.dcpDepend = vcpFetch + ifi.ichFetch - vfli.cpMac;
  605. goto JustBreak;
  606. }
  607. }
  608. }
  609. continue;
  610. }
  611. /* End of new run treatment. We are back in the "for every character"
  612. section. */
  613. {
  614. register int ch = pch[ifi.ichFetch++];
  615. NormChar:
  616. if (ch == chSpace)
  617. {
  618. /* Speed kludge for spaces */
  619. ifi.xp += (vfli.rgdxp[ifi.ich] = dxp =
  620. fFlmPrinting ? vfmiPrint.dxpSpace : vfmiScreen.dxpSpace);
  621. ifi.xpPr += (dxpPr = vfmiPrint.dxpSpace);
  622. vfli.rgch[ifi.ich++] = chSpace;
  623. #ifdef DFLI
  624. {
  625. char rgch[100];
  626. wsprintf(rgch," chSpace , xp==%d/%d, xpPr==%d/%d",
  627. ifi.xp, ifi.xpRight, ifi.xpPr, ifi.xpPrRight);
  628. CommSz(rgch);
  629. }
  630. #endif
  631. goto BreakOppr;
  632. }
  633. /* If the printer width is not in the printer width table, then get
  634. it. */
  635. if (ch < chFmiMin || ch >= chFmiMax || (dxpPr =
  636. vfmiPrint.mpchdxp[ch]) == dxpNil)
  637. {
  638. dxpPr = DxpFromCh(ch, TRUE);
  639. }
  640. if (fFlmPrinting)
  641. {
  642. /* If we are printing, then there is no need to bother with the
  643. screen width. */
  644. dxp = dxpPr;
  645. }
  646. else if (ch < chFmiMin || ch >= chFmiMax ||
  647. (dxp = vfmiScreen.mpchdxp[ch]) == dxpNil)
  648. dxp = DxpFromCh(ch, FALSE);
  649. #ifdef DBCS
  650. if (IsDBCSLeadByte(ch))
  651. {
  652. ifi.xp += (vfli.rgdxp[ifi.ich] = dxp);
  653. ifi.xpPr += dxpPr;
  654. vfli.rgch[ifi.ich++] = ch;
  655. ifi.xp += (vfli.rgdxp[ifi.ich] = dxp);
  656. ifi.xpPr += dxpPr;
  657. vfli.rgch[ifi.ich++] = pch[ifi.ichFetch++];
  658. }
  659. else
  660. {
  661. ifi.xp += (vfli.rgdxp[ifi.ich] = dxp);
  662. ifi.xpPr += dxpPr;
  663. vfli.rgch[ifi.ich++] = ch;
  664. }
  665. #else
  666. ifi.xp += (vfli.rgdxp[ifi.ich] = dxp);
  667. ifi.xpPr += dxpPr;
  668. vfli.rgch[ifi.ich++] = ch;
  669. #endif
  670. /* special case "normal characters" above hyphen */
  671. if (ch > chHyphen)
  672. goto DefaultCh;
  673. switch (ch)
  674. {
  675. #ifdef CRLF
  676. case chReturn:
  677. /* Undo damage */
  678. ifi.ich--;
  679. ifi.xp -= dxp;
  680. ifi.xpPr -= dxpPr;
  681. continue;
  682. #endif /* CRLF */
  683. case chNRHFile:
  684. /* Undo damage */
  685. ifi.ich--;
  686. ifi.xp -= dxp;
  687. ifi.xpPr -= dxpPr;
  688. ichpNRH = ichpFormat - 1;
  689. #ifdef DFLI
  690. {
  691. char rgch[100];
  692. wsprintf(rgch," OptHyph: width==%d, xpPr==%d/%d\n\r",
  693. DxpFromCh(chHyphen,true), ifi.xpPr,ifi.xpPrRight);
  694. CommSz(rgch);
  695. }
  696. #endif
  697. if (ifi.xpPr + DxpFromCh(chHyphen, true) > ifi.xpPrRight)
  698. {
  699. /* Won't fit, force a break */
  700. goto DoBreak;
  701. }
  702. #ifdef CASHMERE
  703. else if (fVisiMode)
  704. {
  705. /* Treat just like a normal hyphen */
  706. ch = chHyphen;
  707. goto NormChar;
  708. }
  709. #endif /* CASHMERE */
  710. xpPrev = ifi.xp;
  711. vfli.rgch[ifi.ich] = chTab;
  712. goto Tab0;
  713. case chSect:
  714. /* Undo damage */
  715. ifi.ich--;
  716. ifi.xp -= dxp;
  717. ifi.xpPr -= dxpPr;
  718. vfli.dypFont = vfli.dypLine = (dypAscentMac + (vfli.dypBase
  719. = dypDescentMac));
  720. vfli.cpMac = vcpFetch + ifi.ichFetch;
  721. if (FFirstIch(ifi.ich))
  722. {
  723. /* Beginning of line; return a splat */
  724. vfli.fSplat = true;
  725. if (!fFlmPrinting)
  726. {
  727. #ifdef CASHMERE
  728. int chT = vfli.cpMac == vcpLimSectCache ?
  729. chSectSplat : chSplat;
  730. #else /* not CASHMERE */
  731. int chT = chSplat;
  732. #endif /* not CASHMERE */
  733. int dxpCh = DxpFromCh(chT, false);
  734. /* Set the width of the splat to be about 8.5" */
  735. int cch = min((dxpLogInch * 17 / 2) / dxpCh,
  736. ichMaxLine - 32);
  737. bltbc(&vfli.rgch[ifi.ich], chT, cch);
  738. bltc(&vfli.rgdxp[ifi.ich], dxpCh, cch);
  739. vfli.ichMac = cch + ifi.ich;
  740. vfli.xpReal = LOWORD(GetTextExtent(vhMDC,
  741. (LPSTR)vfli.rgch, cch));
  742. vfli.xpLeft = 0;
  743. }
  744. else
  745. {
  746. vfli.ichMac = 0;
  747. }
  748. goto EndFormat;
  749. }
  750. /* The section character is in the middle of a line, the
  751. line will terminate in front of the character. */
  752. /* vfSplatNext = TRUE; No longer used*/
  753. vfli.cpMac += cchUsed - 1;
  754. vfli.dcpDepend = 1;
  755. if (!ifi.fPrevSpace)
  756. {
  757. ifi.cBreak = ifi.cchSpace;
  758. vfli.ichReal = ifi.ich;
  759. vfli.xpReal = ifi.xpReal = ifi.xp;
  760. }
  761. vfli.ichMac = ifi.ich;
  762. vfli.dypLine = ifi.dypLineSize;
  763. goto JustBreak;
  764. case chTab:
  765. /* Undo damage */
  766. ifi.ich--;
  767. ifi.xp -= dxp;
  768. ifi.xpPr -= dxpPr;
  769. if (ifi.xpPr < ifi.xpPrRight)
  770. {
  771. register struct CHP *pchp;
  772. unsigned xaPr;
  773. unsigned xaTab;
  774. if (!ifi.fPrevSpace)
  775. {
  776. /* Remember number of spaces to left and number of
  777. real chars in line for justification */
  778. ifi.cBreak = ifi.cchSpace;
  779. vfli.ichReal = ifi.ich;
  780. ifi.xpReal = ifi.xp;
  781. }
  782. if (ifi.jc != jcTabLeft)
  783. {
  784. Justify(&ifi, xpTab, flm);
  785. }
  786. xpPrev = ifi.xp;
  787. /* Now get info about this tab */
  788. xaPr = MultDiv(ifi.xpPr, dxaPrPage, dxpPrPage);
  789. while ((xaTab = ptbd->dxa) != 0)
  790. {
  791. if (xaTab > xaRight)
  792. {
  793. /* Don't let tabs extend past right margin. */
  794. xaTab = xaRight;
  795. }
  796. if (xaTab >= xaPr)
  797. {
  798. /* Use tab stop information */
  799. #ifdef CASHMERE
  800. ifi.tlc = ptbd->tlc;
  801. #endif /* CASHMERE */
  802. ifi.jc = jcTabMin + (ptbd++)->jc;
  803. #ifdef ENABLE /* we do the mapping in HgtbdCreate */
  804. if (ifi.jc != jcTabDecimal)
  805. {
  806. ifi.jc = jcTabLeft;
  807. }
  808. #endif
  809. goto TabFound;
  810. }
  811. ptbd++;
  812. }
  813. /* Out of set tabs; go to next nth column */
  814. xaTab = (xaPr / (vzaTabDflt) + 1) * (vzaTabDflt);
  815. #ifdef CASHMERE
  816. ifi.tlc = tlcWhite;
  817. #endif /* CASHMERE */
  818. ifi.jc = jcTabLeft;
  819. TabFound:
  820. xpTab = imax(MultDiv(xaTab, dxpFormat, dxaFormat),
  821. ifi.xp);
  822. /* Do left-justified tabs immediately */
  823. if (ifi.jc == jcTabLeft)
  824. {
  825. ifi.xp = xpTab;
  826. ifi.xpPr = MultDiv(xaTab, dxpPrPage, dxaPrPage);
  827. }
  828. ifi.xpLeft = ifi.xp;
  829. ifi.ichLeft = ifi.ich;
  830. ifi.cchSpace = 0;
  831. ifi.chBreak = 0;
  832. Tab0:
  833. ifi.fPrevSpace = false;
  834. vfli.ichMac = ifi.ich;
  835. vfli.xpReal = ifi.xp;
  836. vfli.dypLine = ifi.dypLineSize;
  837. vfli.dypBase = dypDescentMac;
  838. vfli.dypFont = dypAscentMac + dypDescentMac;
  839. if (ifi.ichFetch != 1 && (ichpFormat != ichpMacFormat
  840. || FGrowFormatHeap()))
  841. {
  842. /* Probably in real trouble if FGrowFormatHeap fails
  843. at this point */
  844. pchp = &(**vhgchpFormat)[ichpFormat - 1];
  845. if (ichpFormat > 0)
  846. {
  847. /* Finish off previous run */
  848. pchp->ichRun = ifi.ichPrev;
  849. pchp->cchRun = ifi.ich - ifi.ichPrev;
  850. }
  851. blt(&chpLocal, ++pchp, cwCHP);
  852. ichpFormat++;
  853. }
  854. else
  855. {
  856. pchp = &(**vhgchpFormat)[ichpFormat - 1];
  857. }
  858. pchp->ichRun = ifi.ich;
  859. pchp->cchRun = ichMaxLine;
  860. #ifdef CASHMERE
  861. pchp->chLeader = mptlcch[ifi.tlc];
  862. #endif /* CASHMERE */
  863. vfli.rgdxp[ifi.ichPrev = ifi.ich++] = ifi.xp - xpPrev;
  864. if (ch != chTab)
  865. {
  866. /* This character is a non-required hyphen. */
  867. Dfli(CommSz("ch is really OptHyph "));
  868. goto BreakOppr;
  869. }
  870. continue;
  871. }
  872. else
  873. {
  874. ch = chNBSFile;
  875. goto NormChar;
  876. }
  877. case chHyphen:
  878. if (ifi.xpPr > ifi.xpPrRight)
  879. {
  880. goto DoBreak;
  881. }
  882. BreakOppr:
  883. Dfli(CommSz(" BKOPPR\n\r"));
  884. /* this case never used in switch - always goto here */
  885. /* case chSpace: */
  886. if (ifi.ich >= ichMaxLine)
  887. {
  888. Dfli(CommSzNum(" Unbroken, ich>ichMaxLine\n\r"));
  889. goto Unbroken;
  890. }
  891. case chEol:
  892. case chNewLine:
  893. ifi.chBreak = ch;
  894. vfli.cpMac = vcpFetch + cchUsed + ifi.ichFetch;
  895. vfli.xpReal = ifi.xp;
  896. vfli.ichMac = ifi.ich;
  897. vfli.dypLine = ifi.dypLineSize;
  898. vfli.dypFont = dypAscentMac + (vfli.dypBase =
  899. dypDescentMac);
  900. Dfli(CommSzNumNum(" vfli.xpReal, ichMac ",vfli.xpReal,vfli.ichMac));
  901. if (ch == chHyphen || ch == chNRHFile)
  902. {
  903. Dfli(CommSz(" chHyph/OptHyph catch \n\r"));
  904. ifi.cBreak = ifi.cchSpace;
  905. vfli.ichReal = ifi.ich;
  906. vfli.xpReal = ifi.xpReal = ifi.xp;
  907. }
  908. else
  909. {
  910. if (!ifi.fPrevSpace)
  911. {
  912. Dfli(CommSz("!fPrevSpace \n\r"));
  913. ifi.cBreak = ifi.cchSpace;
  914. vfli.ichReal = ifi.ich - 1;
  915. ifi.xpReal = (vfli.xpReal = ifi.xp) - dxp;
  916. }
  917. if (ch == chEol || ch == chNewLine)
  918. {
  919. #ifdef CASHMERE
  920. if (hfntb != 0 && vfli.cpMac ==
  921. (**hfntb).rgfnd[0].cpFtn)
  922. {
  923. /* End of footnote */
  924. if (!fFlmPrinting)
  925. {
  926. vfli.rgch[ifi.ich - 1] = chEMark;
  927. vfli.xpReal += (vfli.rgdxp[ifi.ich - 1] =
  928. DxpFromCh(chEMark, false)) - dxp;
  929. vfli.ichReal++; /* show this guy */
  930. }
  931. }
  932. else
  933. #endif /* CASHMERE */
  934. {
  935. #ifdef CASHMERE
  936. int chT = fVisiMode ? ChVisible(ch) : chSpace;
  937. #else /* not CASHMERE */
  938. int chT = chSpace;
  939. #endif /* not CASHMERE */
  940. int dxpNew = DxpFromCh(chT, fFlmPrinting);
  941. vfli.rgch[ifi.ich - 1] = chT;
  942. vfli.rgdxp[ifi.ich - 1] = dxpNew;
  943. vfli.xpReal += (vfli.rgdxp[ifi.ich - 1] =
  944. dxpNew) - dxp;
  945. if (!ifi.fPrevSpace)
  946. {
  947. vfli.xpReal += dxpNew - dxp;
  948. #ifdef CASHMERE
  949. vfli.ichReal =
  950. fVisiMode ? ifi.ich : ifi.ich - 1;
  951. #else /* not CASHMERE */
  952. vfli.ichReal = ifi.ich - 1;
  953. #endif /* not CASHMERE */
  954. }
  955. }
  956. if (ch == chEol)
  957. {
  958. JustEol:
  959. if (fFlmPrinting)
  960. {
  961. vfli.ichMac = vfli.ichReal;
  962. }
  963. if (ifi.jc != jcTabLeft)
  964. {
  965. /* Handle last tab's text */
  966. Justify(&ifi, xpTab, flm);
  967. }
  968. else if ((ifi.jc = ppap->jc) != jcBoth &&
  969. ifi.jc != jcLeft)
  970. {
  971. /* Do line justification */
  972. Justify(&ifi, ifi.xpRight, flm);
  973. }
  974. vfli.xpRight = ifi.xpRight;
  975. goto EndFormat;
  976. }
  977. else
  978. {
  979. /* Handle a line break */
  980. goto JustBreak;
  981. }
  982. }
  983. ++ifi.cchSpace;
  984. ifi.fPrevSpace = true;
  985. }
  986. break;
  987. DefaultCh:
  988. default:
  989. #ifdef DFLI
  990. {
  991. char rgch[100];
  992. wsprintf(rgch," DefaultCh: %c, xp==%d/%d, xpPr==%d/%d\n\r",
  993. ch, ifi.xp, ifi.xpRight, ifi.xpPr, ifi.xpPrRight);
  994. CommSz(rgch);
  995. }
  996. #endif /* ifdef DFLI */
  997. if (ifi.xpPr > ifi.xpPrRight)
  998. DoBreak:
  999. {
  1000. Dfli(CommSz(" BREAK!\n\r"));
  1001. if (ifi.chBreak == 0)
  1002. Unbroken:
  1003. {
  1004. /* Admit first character to the line, even if margin
  1005. is crossed. First character at ifi.ich - 1 may be
  1006. preceded by 0 width characters. */
  1007. #ifdef DBCS
  1008. if (IsDBCSLeadByte(ch))
  1009. {
  1010. if (FFirstIch(ifi.ich-2) && ifi.ich<ichMaxLine)
  1011. goto PChar;
  1012. vfli.cpMac = vcpFetch+cchUsed+ifi.ichFetch-2;
  1013. vfli.ichReal = vfli.ichMac = ifi.ich - 2;
  1014. vfli.dypLine = ifi.dypLineSize;
  1015. vfli.dypFont = dypAscentMac + (vfli.dypBase =
  1016. dypDescentMac);
  1017. vfli.dcpDepend = 1;
  1018. vfli.xpReal = ifi.xpReal = ifi.xp - (dxp * 2);
  1019. }
  1020. else
  1021. {
  1022. if (FFirstIch(ifi.ich-1) && ifi.ich<ichMaxLine)
  1023. goto PChar;
  1024. vfli.cpMac = vcpFetch+cchUsed+ifi.ichFetch-1;
  1025. vfli.ichReal = vfli.ichMac = ifi.ich - 1;
  1026. vfli.dypLine = ifi.dypLineSize;
  1027. vfli.dypFont = dypAscentMac + (vfli.dypBase =
  1028. dypDescentMac);
  1029. vfli.dcpDepend = 1;
  1030. vfli.xpReal = ifi.xpReal = ifi.xp - dxp;
  1031. }
  1032. #else
  1033. if (FFirstIch(ifi.ich - 1) && ifi.ich < ichMaxLine)
  1034. {
  1035. goto PChar;
  1036. }
  1037. vfli.cpMac = vcpFetch + cchUsed + ifi.ichFetch - 1;
  1038. vfli.ichReal = vfli.ichMac = ifi.ich - 1;
  1039. vfli.dypLine = ifi.dypLineSize;
  1040. vfli.dypFont = dypAscentMac + (vfli.dypBase =
  1041. dypDescentMac);
  1042. vfli.dcpDepend = 1;
  1043. vfli.xpReal = ifi.xpReal = ifi.xp - dxp;
  1044. #endif
  1045. goto DoJustify;
  1046. }
  1047. vfli.dcpDepend = vcpFetch + ifi.ichFetch - vfli.cpMac;
  1048. JustBreak:
  1049. if (ifi.chBreak == chNRHFile)
  1050. {
  1051. /* Append a non-required hyphen to the end of the
  1052. line. (Replace zero length tab previously
  1053. inserted) */
  1054. Dfli(CommSz(" Breaking line at OptHyphen\n\r"));
  1055. ifi.xpReal += (vfli.rgdxp[vfli.ichReal - 1] =
  1056. DxpFromCh(chHyphen, fFlmPrinting));
  1057. vfli.xpRight = vfli.xpReal = ifi.xpReal;
  1058. vfli.rgch[vfli.ichReal - 1] = chHyphen;
  1059. vfli.ichMac = vfli.ichReal;
  1060. if (ichpNRH < ichpFormat - 1)
  1061. {
  1062. register struct CHP *pchp =
  1063. &(**vhgchpFormat)[ichpNRH];
  1064. pchp->cchRun++;
  1065. if (pchp->ichRun >= vfli.ichMac)
  1066. {
  1067. pchp->ichRun = vfli.ichMac - 1;
  1068. }
  1069. }
  1070. }
  1071. if (fFlmPrinting)
  1072. {
  1073. vfli.ichMac = vfli.ichReal;
  1074. }
  1075. if (ifi.jc != jcTabLeft)
  1076. {
  1077. Justify(&ifi, xpTab, flm);
  1078. }
  1079. else
  1080. {
  1081. DoJustify:
  1082. if ((ifi.jc = ppap->jc) != jcLeft)
  1083. {
  1084. Dfli(CommSzNum(" DoJustify: xpRight ",ifi.xpRight));
  1085. Justify(&ifi, ifi.xpRight, flm);
  1086. }
  1087. }
  1088. vfli.xpRight = ifi.xpRight;
  1089. EndFormat:
  1090. vfli.ichLastTab = ifi.ichLeft;
  1091. #ifdef CASHMERE
  1092. if (vfli.cpMac == vcpLimParaCache)
  1093. {
  1094. vfli.dypAfter = vpapAbs.dyaAfter / DyaPerPixFormat;
  1095. vfli.dypLine += vfli.dypAfter;
  1096. vfli.dypBase += vfli.dypAfter;
  1097. }
  1098. #endif /* CASHMERE */
  1099. Scribble(5, ' ');
  1100. return;
  1101. }
  1102. else
  1103. {
  1104. PChar:
  1105. /* A printing character */
  1106. ifi.fPrevSpace = false;
  1107. }
  1108. break;
  1109. } /* Switch */
  1110. }
  1111. } /* for ( ; ; ) */
  1112. Scribble(5, ' ');
  1113. }
  1114. /* J U S T I F Y */
  1115. near Justify(pifi, xpTab, flm)
  1116. struct IFI *pifi;
  1117. unsigned xpTab;
  1118. int flm;
  1119. {
  1120. int dxp;
  1121. int ichT;
  1122. int xpLeft;
  1123. xpLeft = pifi->xpLeft;
  1124. switch (pifi->jc)
  1125. {
  1126. CHAR *pch;
  1127. unsigned *pdxp;
  1128. #ifdef CASHMERE
  1129. case jcTabLeft:
  1130. case jcLeft:
  1131. return;
  1132. case jcTabRight:
  1133. dxp = xpTab - pifi->xpReal;
  1134. break;
  1135. case jcTabCenter:
  1136. dxp = (xpTab - xpLeft) - ((pifi->xpReal - xpLeft + 1) >> 1);
  1137. break;
  1138. #endif /* CASHMERE */
  1139. case jcTabDecimal:
  1140. dxp = xpTab - xpLeft;
  1141. for (ichT = pifi->ichLeft + 1; ichT < vfli.ichReal &&
  1142. vfli.rgch[ichT] != vchDecimal; ichT++)
  1143. {
  1144. dxp -= vfli.rgdxp[ichT];
  1145. }
  1146. break;
  1147. case jcCenter:
  1148. if ((dxp = xpTab - pifi->xpReal) <= 0)
  1149. {
  1150. return;
  1151. }
  1152. dxp = dxp >> 1;
  1153. break;
  1154. case jcRight:
  1155. dxp = xpTab - pifi->xpReal;
  1156. break;
  1157. case jcBoth:
  1158. if (pifi->cBreak == 0)
  1159. {
  1160. /* Ragged edge forced */
  1161. return;
  1162. }
  1163. if ((dxp = xpTab - pifi->xpReal) <= 0)
  1164. {
  1165. /* There is nothing to do. */
  1166. return;
  1167. }
  1168. pifi->xp += dxp;
  1169. vfli.xpReal += dxp;
  1170. vfli.dxpExtra = dxp / pifi->cBreak;
  1171. /* Rounding becomes a non-existant issue due to brilliant
  1172. re-thinking.
  1173. "What a piece of work is man
  1174. How noble in reason
  1175. In form and movement,
  1176. how abject and admirable..."
  1177. Bill "Shake" Spear [describing Sand Word] */
  1178. {
  1179. register CHAR *pch = &vfli.rgch[vfli.ichReal];
  1180. register int *pdxp = &vfli.rgdxp[vfli.ichReal];
  1181. int dxpT = dxp;
  1182. int cBreak = pifi->cBreak;
  1183. int cxpQuotient = (dxpT / cBreak) + 1;
  1184. int cWideSpaces = dxpT % cBreak;
  1185. vfli.fAdjSpace = fTrue;
  1186. for ( ; ; )
  1187. {
  1188. /* Widen blanks */
  1189. --pch;
  1190. --pdxp;
  1191. if (*pch == chSpace)
  1192. {
  1193. if (cWideSpaces-- == 0)
  1194. {
  1195. int *pdxpT = pdxp + 1;
  1196. while (*pdxpT == 0)
  1197. {
  1198. pdxpT++;
  1199. }
  1200. vfli.ichFirstWide = pdxpT - vfli.rgdxp;
  1201. cxpQuotient--;
  1202. }
  1203. *pdxp += cxpQuotient;
  1204. if ((dxpT -= cxpQuotient) <= 0)
  1205. {
  1206. if (pifi->cBreak > 1)
  1207. {
  1208. int *pdxpT = pdxp + 1;
  1209. while (*pdxpT == 0)
  1210. {
  1211. pdxpT++;
  1212. }
  1213. vfli.ichFirstWide = pdxpT - vfli.rgdxp;
  1214. }
  1215. return;
  1216. }
  1217. pifi->cBreak--;
  1218. }
  1219. }
  1220. }
  1221. } /* Switch */
  1222. if (dxp <= 0)
  1223. {
  1224. /* Nothing to do */
  1225. return;
  1226. }
  1227. pifi->xp += dxp;
  1228. if (flm & flmPrinting)
  1229. {
  1230. pifi->xpPr += dxp;
  1231. }
  1232. else
  1233. {
  1234. /* This statememt might introduce rounding errors in pifi->xpPr, but
  1235. with luck, they will be small. */
  1236. pifi->xpPr += MultDiv(MultDiv(dxp, czaInch, dxpLogInch), dxpPrPage,
  1237. dxaPrPage);
  1238. }
  1239. if (pifi->ichLeft < 0)
  1240. {
  1241. /* Normal justification */
  1242. vfli.xpLeft += dxp;
  1243. }
  1244. else
  1245. {
  1246. /* Tab justification */
  1247. vfli.rgdxp[pifi->ichLeft] += dxp;
  1248. }
  1249. vfli.xpReal += dxp;
  1250. }
  1251. /* F G R O W F O R M A T H E A P */
  1252. int near FGrowFormatHeap()
  1253. {
  1254. /* Grow vhgchpFormat by 20% */
  1255. int cchpIncr = ichpMacFormat / 5 + 1;
  1256. #ifdef WINHEAP
  1257. if (!LocalReAlloc((HANDLE)vhgchpFormat, (ichpMacFormat + cchpIncr) * cchCHP,
  1258. NONZEROLHND))
  1259. #else /* not WINHEAP */
  1260. if (!FChngSizeH(vhgchpFormat, (ichpMacFormat + cchpIncr) * cwCHP, false))
  1261. #endif /* not WINHEAP */
  1262. {
  1263. /* Sorry, charlie */
  1264. return false;
  1265. }
  1266. ichpMacFormat += cchpIncr;
  1267. return true;
  1268. }
  1269. /* #define DBEMG */
  1270. /* D X P F R O M C H */
  1271. #ifdef DBCS
  1272. /* DxpFromCh() assumes that ch passed is the first byte of a DBCS character
  1273. if it is a part of such character. */
  1274. #endif
  1275. int DxpFromCh(ch, fPrinter)
  1276. int ch;
  1277. int fPrinter;
  1278. {
  1279. int *pdxp; // changed to int (7.23.91) v-dougk
  1280. int dxpDummy; // changed to int (7.23.91) v-dougk
  1281. extern int dxpLogCh;
  1282. extern struct FCE *vpfceScreen;
  1283. /* If the width is not in the width table, then get it. */
  1284. if (ch < chFmiMin)
  1285. {
  1286. switch (ch)
  1287. {
  1288. case chTab:
  1289. case chEol:
  1290. case chReturn:
  1291. case chSect:
  1292. case chNewLine:
  1293. case chNRHFile:
  1294. /* the width for these characters aren't really important */
  1295. pdxp = (CHAR *)(fPrinter ? &vfmiPrint.dxpSpace : &vfmiScreen.dxpSpace);
  1296. break;
  1297. default:
  1298. pdxp = &dxpDummy;
  1299. *pdxp = dxpNil;
  1300. break;
  1301. }
  1302. }
  1303. else if (ch >= chFmiMax)
  1304. {
  1305. /* outside the range we hold in our table - kludge it */
  1306. pdxp = &dxpDummy;
  1307. *pdxp = dxpNil;
  1308. }
  1309. else
  1310. {
  1311. /* inside our table */
  1312. pdxp = (fPrinter ? vfmiPrint.mpchdxp : vfmiScreen.mpchdxp) + ch;
  1313. }
  1314. #ifdef DBCS
  1315. if (*pdxp == dxpNil && IsDBCSLeadByte(ch) )
  1316. {
  1317. int dxp;
  1318. #else
  1319. if (*pdxp == dxpNil)
  1320. {
  1321. int dxp;
  1322. #endif
  1323. #ifdef DBCS
  1324. struct FMI *pfmi;
  1325. int rgchT[cchDBCS]; // changed to int (7.23.91) v-dougk
  1326. int dxpT;
  1327. int dxpDBCS;
  1328. pfmi = fPrinter ? (&vfmiPrint) : (&vfmiScreen);
  1329. Assert(pfmi->bDummy == dxpNil);
  1330. if (pfmi->dxpDBCS == dxpNil)
  1331. {
  1332. /* Get the width from GDI. */
  1333. rgchT[0] = rgchT[1] = ch;
  1334. dxpDBCS = (fPrinter ?
  1335. LOWORD(GetTextExtent(vhDCPrinter,
  1336. (LPSTR) rgchT, cchDBCS)) :
  1337. LOWORD(GetTextExtent(vhMDC,
  1338. (LPSTR) rgchT, cchDBCS)));
  1339. /* Store in fmi, if it fits. */
  1340. if (0 <= dxpDBCS && dxpDBCS < dxpNil)
  1341. pfmi->dxpDBCS = (BYTE) dxpDBCS;
  1342. return (dxpDBCS - pfmi->dxpOverhang);
  1343. }
  1344. else
  1345. return (pfmi->dxpDBCS - pfmi->dxpOverhang);
  1346. }
  1347. else {
  1348. int dxp;
  1349. #endif /* DBCS */
  1350. /* get width from GDI */
  1351. dxp = fPrinter ? LOWORD(GetTextExtent(vhDCPrinter, (LPSTR)&ch, 1)) -
  1352. vfmiPrint.dxpOverhang : LOWORD(GetTextExtent(vhMDC, (LPSTR)&ch, 1)) -
  1353. vfmiScreen.dxpOverhang;
  1354. #ifdef DBEMG
  1355. CommSzNum("Get this.... ", dxp);
  1356. #endif
  1357. //(7.24.91) v-dougk if (dxp >= 0 && dxp < dxpNil)
  1358. {
  1359. /* only store dxp's that fit in a byte */
  1360. *pdxp = dxp;
  1361. }
  1362. #ifdef DBEMG
  1363. {
  1364. char szT[10];
  1365. CommSzSz("fPrinter: ", (fPrinter ? "Printer" : "Screen"));
  1366. if (ch == 0x0D) {
  1367. szT[0] = 'C'; szT[1] = 'R'; szT[2] = '\0';
  1368. }
  1369. else if (ch == 0x0A) {
  1370. szT[0] = 'L'; szT[1] = 'F'; szT[2] = '\0';
  1371. }
  1372. else if (32 <= ch && ch <= 126) {
  1373. szT[0] = ch; szT[1] ='\0';
  1374. }
  1375. else if (FKanji1(ch)) {
  1376. szT[0] = 'K'; szT[1] = 'A'; szT[2] = 'N'; szT[3] = 'J';
  1377. szT[4] = 'I'; szT[5] = '\0';
  1378. }
  1379. else {
  1380. szT[0] = szT[1] = szT[2] = '-'; szT[3] = '\0';
  1381. }
  1382. CommSzSz("Character: ", szT);
  1383. CommSzNum("Dxp: ", (int) dxp);
  1384. CommSzNum("OverHang: ", (int) (fPrinter ? vfmiPrint.dxpOverhang : vfmiScreen.dxpOverhang));
  1385. }
  1386. #endif
  1387. return(dxp);
  1388. }
  1389. #ifdef DBEMG
  1390. {
  1391. char szT[10];
  1392. CommSzSz("fPrinter: ", (fPrinter ? "Printer" : "Screen"));
  1393. if (ch == 0x0D) {
  1394. szT[0] = 'C'; szT[1] = 'R'; szT[2] = '\0';
  1395. }
  1396. else if (ch == 0x0A) {
  1397. szT[0] = 'L'; szT[1] = 'F'; szT[2] = '\0';
  1398. }
  1399. else if (32 <= ch && ch <= 126) {
  1400. szT[0] = ch; szT[1] ='\0';
  1401. }
  1402. else if (FKanji1(ch)) {
  1403. szT[0] = 'K'; szT[1] = 'A'; szT[2] = 'N'; szT[3] = 'J';
  1404. szT[4] = 'I'; szT[5] = '\0';
  1405. }
  1406. else {
  1407. szT[0] = szT[1] = szT[2] = '-'; szT[3] = '\0';
  1408. }
  1409. CommSzSz("Character: ", szT);
  1410. CommSzNum("Dxp: ", (int) *pdxp);
  1411. CommSzNum("OverHang: ", (int) (fPrinter ? vfmiPrint.dxpOverhang : vfmiScreen.dxpOverhang));
  1412. }
  1413. #endif
  1414. return(*pdxp);
  1415. }
  1416. /* F F I R S T I C H */
  1417. int near FFirstIch(ich)
  1418. int ich;
  1419. {
  1420. /* Returns true iff ich is 0 or preceded only by 0 width characters */
  1421. register int ichT;
  1422. register int *pdxp = &vfli.rgdxp[0];
  1423. for (ichT = 0; ichT < ich; ichT++)
  1424. {
  1425. if (*pdxp++)
  1426. {
  1427. return false;
  1428. }
  1429. }
  1430. return true;
  1431. }
  1432. ValidateMemoryDC()
  1433. {
  1434. /* Attempt to assure that vhMDC and vhDCPrinter are valid. If we have not
  1435. already run out of memory, then vhDCPrinter is guaranteed, but vhMDC may
  1436. fail due to out of memory -- it is the callers responsibility to check for
  1437. vhMDC == NULL. */
  1438. extern int vfOutOfMemory;
  1439. extern HDC vhMDC;
  1440. extern BOOL vfMonochrome;
  1441. extern long rgbText;
  1442. extern struct WWD *pwwdCur;
  1443. /* If we are out of memory, then we shouldn't try to gobble it up by getting
  1444. DC's. */
  1445. if (!vfOutOfMemory)
  1446. {
  1447. if (vhMDC == NULL)
  1448. {
  1449. /* Create a memory DC compatible with the screen if necessary. */
  1450. vhMDC = CreateCompatibleDC(pwwdCur->hDC);
  1451. /* Callers are responsible for checking for vhMDC == NULL case */
  1452. if (vhMDC != NULL)
  1453. {
  1454. /* Put the memory DC in transparent mode. */
  1455. SetBkMode(vhMDC, TRANSPARENT);
  1456. /* If the display is a monochrome device, then set the text
  1457. color for the memory DC. Monochrome bitmaps will not be
  1458. converted to the foreground and background colors in this case,
  1459. we must do the conversion. */
  1460. if (vfMonochrome = (GetDeviceCaps(pwwdCur->hDC, NUMCOLORS) ==
  1461. 2))
  1462. {
  1463. SetTextColor(vhMDC, rgbText);
  1464. }
  1465. }
  1466. }
  1467. /* If the printer DC is NULL then we need to reestablish it. */
  1468. if (vhDCPrinter == NULL)
  1469. {
  1470. GetPrinterDC(FALSE);
  1471. /* GetPrinterDC has already called SetMapperFlags() on vhDCPrinter. */
  1472. }
  1473. }
  1474. }
  1475.