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.

839 lines
22 KiB

  1. #include "lsmem.h"
  2. #include <limits.h>
  3. #include "lstxtbrs.h"
  4. #include "lstxtmap.h"
  5. #include "lsdntext.h"
  6. #include "zqfromza.h"
  7. #include "locchnk.h"
  8. #include "posichnk.h"
  9. #include "objdim.h"
  10. #include "lskysr.h"
  11. #include "lstxtffi.h"
  12. #include "txtils.h"
  13. #include "txtln.h"
  14. #include "txtobj.h"
  15. static void GetOneCharWidth(PTXTOBJ ptxtobj, long dwch, long* pdurChar);
  16. static LSERR GetWidthOfGlyph(PILSOBJ pilsobj, PLSRUN plsrun, LSTFLOW lstflow, WCHAR wch, BOOL* pfSuccessful,
  17. GINDEX* pgind, long* pdurNew, long* pdupNew);
  18. static LSERR GetWidthOfChar(PILSOBJ pilsobj, PLSRUN plsrun, LSTFLOW lstflow, WCHAR wch,
  19. long* pdurNew, long* pdupNew);
  20. /* F I N D N O N S P A C E B E F O R E */
  21. /*----------------------------------------------------------------------------
  22. %%Function: FindNonSpaceBefore
  23. %%Contact: sergeyge
  24. ----------------------------------------------------------------------------*/
  25. BOOL FindNonSpaceBefore(PCLSCHNK rglschnk, long itxtobjCur, long iwchCur,
  26. long* pitxtobjBefore, long* piwchBefore)
  27. {
  28. PILSOBJ pilsobj;
  29. long iwch;
  30. BOOL fInSpace;
  31. long itxtobj;
  32. PTXTOBJ ptxtobj;
  33. long iwchFirst;
  34. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  35. fInSpace = fTrue;
  36. itxtobj = itxtobjCur;
  37. iwch = iwchCur;
  38. while (fInSpace && itxtobj >= 0)
  39. {
  40. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  41. if ((ptxtobj->txtkind != txtkindRegular && ptxtobj->txtkind != txtkindSpecSpace ||
  42. (pilsobj->grpf & fTxtWrapAllSpaces)) && ptxtobj->txtkind != txtkindEOL )
  43. {
  44. *pitxtobjBefore = itxtobj;
  45. *piwchBefore = ptxtobj->iwchLim - 1;
  46. if (iwchCur < *piwchBefore)
  47. *piwchBefore = iwchCur;
  48. fInSpace = fFalse;
  49. }
  50. else if (ptxtobj->txtkind == txtkindRegular)
  51. {
  52. iwchFirst = ptxtobj->iwchFirst;
  53. for (; iwch >= iwchFirst && pilsobj->pwchOrig[iwch] == pilsobj->wchSpace; iwch--);
  54. if (iwch >= iwchFirst)
  55. {
  56. *pitxtobjBefore = itxtobj;
  57. *piwchBefore = iwch;
  58. fInSpace = fFalse;
  59. }
  60. }
  61. iwch = ptxtobj->iwchFirst - 1;
  62. itxtobj--;
  63. }
  64. if (fInSpace)
  65. {
  66. *pitxtobjBefore = 0;
  67. *piwchBefore = iwch;
  68. }
  69. return !fInSpace;
  70. }
  71. /* F I N D N O N S P A C E A F T E R */
  72. /*----------------------------------------------------------------------------
  73. %%Function: FindNonSpaceAfter
  74. %%Contact: sergeyge
  75. ----------------------------------------------------------------------------*/
  76. BOOL FindNonSpaceAfter(PCLSCHNK rglschnk, DWORD clschnk, long itxtobjCur, long iwchCur,
  77. long* pitxtobjAfter, long* piwchAfter)
  78. {
  79. PILSOBJ pilsobj;
  80. long iwch;
  81. BOOL fInSpace;
  82. long itxtobj;
  83. PTXTOBJ ptxtobj;
  84. long iwchLim;
  85. pilsobj = ((PTXTOBJ)rglschnk[0].pdobj)->plnobj->pilsobj;
  86. fInSpace = fTrue;
  87. itxtobj = itxtobjCur;
  88. iwch = iwchCur;
  89. while (fInSpace && itxtobj < (long)clschnk)
  90. {
  91. ptxtobj = (PTXTOBJ)rglschnk[itxtobj].pdobj;
  92. if (ptxtobj->txtkind != txtkindRegular && ptxtobj->txtkind != txtkindSpecSpace ||
  93. (pilsobj->grpf & fTxtWrapAllSpaces))
  94. {
  95. *pitxtobjAfter = itxtobj;
  96. *piwchAfter = ptxtobj->iwchFirst;
  97. if (iwchCur > *piwchAfter)
  98. *piwchAfter = iwchCur;
  99. fInSpace = fFalse;
  100. }
  101. else if (ptxtobj->txtkind == txtkindRegular)
  102. {
  103. iwchLim = ptxtobj->iwchLim;
  104. for (; iwch < iwchLim && pilsobj->pwchOrig[iwch] == pilsobj->wchSpace; iwch++);
  105. if (iwch < iwchLim)
  106. {
  107. *pitxtobjAfter = itxtobj;
  108. *piwchAfter = iwch;
  109. fInSpace = fFalse;
  110. }
  111. }
  112. iwch = ptxtobj->iwchLim;
  113. itxtobj++;
  114. }
  115. if (fInSpace)
  116. {
  117. *pitxtobjAfter = clschnk - 1; /* Important for correct ptbo settting in TryBreakAcrossSpaces */
  118. *piwchAfter = iwch;
  119. }
  120. return !fInSpace;
  121. }
  122. /* F I N D P R E V C H A R */
  123. /*----------------------------------------------------------------------------
  124. %%Function: FindPrevChar
  125. %%Contact: sergeyge
  126. ----------------------------------------------------------------------------*/
  127. BOOL FindPrevChar(PCLSCHNK rglschnk, long itxtobjCur, long iwchCur,
  128. long* pitxtobjBefore, long* piwchBefore)
  129. {
  130. PTXTOBJ ptxtobj;
  131. ptxtobj = (PTXTOBJ)rglschnk[itxtobjCur].pdobj;
  132. if (iwchCur > ptxtobj->iwchFirst)
  133. {
  134. *pitxtobjBefore = itxtobjCur;
  135. *piwchBefore = iwchCur - 1;
  136. return fTrue;
  137. }
  138. else if (itxtobjCur > 0)
  139. {
  140. *pitxtobjBefore = itxtobjCur - 1;
  141. *piwchBefore = ((PTXTOBJ)rglschnk[*pitxtobjBefore].pdobj)->iwchLim - 1;
  142. return fTrue;
  143. }
  144. else
  145. {
  146. *pitxtobjBefore = 0;
  147. *piwchBefore = ((PTXTOBJ)rglschnk[0].pdobj)->iwchFirst - 1;
  148. }
  149. return fFalse;
  150. }
  151. /* F I N D N E X T C H A R */
  152. /*----------------------------------------------------------------------------
  153. %%Function: FindNextChar
  154. %%Contact: sergeyge
  155. ----------------------------------------------------------------------------*/
  156. BOOL FindNextChar(PCLSCHNK rglschnk, DWORD clschnk, long itxtobjCur, long iwchCur,
  157. long* pitxtobjAfter, long* piwchAfter)
  158. {
  159. PTXTOBJ ptxtobj;
  160. ptxtobj = (PTXTOBJ)rglschnk[itxtobjCur].pdobj;
  161. if (iwchCur < ptxtobj->iwchLim - 1)
  162. {
  163. *pitxtobjAfter = itxtobjCur;
  164. *piwchAfter = iwchCur + 1;
  165. return fTrue;
  166. }
  167. else if (itxtobjCur < (long)clschnk - 1)
  168. {
  169. *pitxtobjAfter = itxtobjCur + 1;
  170. *piwchAfter = ((PTXTOBJ)rglschnk[*pitxtobjAfter].pdobj)->iwchFirst;
  171. return fTrue;
  172. }
  173. else
  174. {
  175. /* not found but set correct values for ptbo in TryBreakAcrossSpaces */
  176. *pitxtobjAfter = clschnk - 1;
  177. *piwchAfter = ((PTXTOBJ)rglschnk[*pitxtobjAfter].pdobj)->iwchLim;
  178. }
  179. return fFalse;
  180. }
  181. /* C A L C P A R T W I D T H S */
  182. /*----------------------------------------------------------------------------
  183. %%Function: CalcPartWidths
  184. %%Contact: sergeyge
  185. Calculates width from the beginning of the dobj until character iwchLim
  186. ----------------------------------------------------------------------------*/
  187. LSERR CalcPartWidths(PTXTOBJ ptxtobj, long dwchLim, POBJDIM pobjdim, long* pdur)
  188. {
  189. LSERR lserr;
  190. PILSOBJ pilsobj;
  191. long* rgdur;
  192. long durSum;
  193. long i;
  194. pilsobj = ptxtobj->plnobj->pilsobj;
  195. rgdur = pilsobj->pdur;
  196. Assert(dwchLim <= ptxtobj->iwchLim - ptxtobj->iwchFirst);
  197. lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, pobjdim);
  198. if (lserr != lserrNone) return lserr;
  199. if (dwchLim == 0)
  200. {
  201. *pdur = 0;
  202. return lserrNone;
  203. }
  204. durSum = 0;
  205. /* Calculate the tail of the string, then subtract */
  206. for (i = ptxtobj->iwchFirst + dwchLim; i < ptxtobj->iwchLim; i++)
  207. {
  208. durSum += rgdur[i];
  209. }
  210. *pdur = pobjdim->dur - durSum;
  211. return lserrNone;
  212. }
  213. /* C A L C P A R T W I D T H S G L Y P H S */
  214. /*----------------------------------------------------------------------------
  215. %%Function: CalcPartWidthsGlyphs
  216. %%Contact: sergeyge
  217. Calculates width from the beginning of the dobj until character iwchLim
  218. ----------------------------------------------------------------------------*/
  219. LSERR CalcPartWidthsGlyphs(PTXTOBJ ptxtobj, long dwchLim, POBJDIM pobjdim, long* pdur)
  220. {
  221. LSERR lserr;
  222. PILSOBJ pilsobj;
  223. long* rgdurGind;
  224. long durSum;
  225. long igindStart;
  226. long i;
  227. pilsobj = ptxtobj->plnobj->pilsobj;
  228. rgdurGind = pilsobj->pdurGind;
  229. Assert(dwchLim <= ptxtobj->iwchLim - ptxtobj->iwchFirst);
  230. Assert(ptxtobj->iwchFirst + dwchLim == ptxtobj->iwchLim ||
  231. pilsobj->ptxtinf[ptxtobj->iwchFirst + dwchLim].fFirstInContext);
  232. igindStart = IgindFirstFromIwch(ptxtobj, ptxtobj->iwchFirst + dwchLim);
  233. lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, pobjdim);
  234. if (lserr != lserrNone) return lserr;
  235. durSum = 0;
  236. /* Calculate the tail of the string, then subtract */
  237. for (i = igindStart; i < ptxtobj->igindLim; i++)
  238. {
  239. durSum += rgdurGind[i];
  240. }
  241. *pdur = pobjdim->dur - durSum;
  242. return lserrNone;
  243. }
  244. /* C H E C K H O T Z O N E */
  245. /*----------------------------------------------------------------------------
  246. %%Function: CheckHotZone
  247. %%Contact: sergeyge
  248. ----------------------------------------------------------------------------*/
  249. LSERR CheckHotZone(PCLOCCHNK plocchnk, long itxtobj, long iwch, BOOL* pfInHyphenZone)
  250. {
  251. LSERR lserr;
  252. PILSOBJ pilsobj;
  253. PTXTOBJ ptxtobj;
  254. long dur;
  255. long durLeftIndent;
  256. OBJDIM objdim;
  257. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
  258. pilsobj = ptxtobj->plnobj->pilsobj;
  259. if (ptxtobj->txtf & txtfGlyphBased)
  260. lserr = CalcPartWidthsGlyphs(ptxtobj, iwch + 1 - ptxtobj->iwchFirst, &objdim, &dur);
  261. else
  262. lserr = CalcPartWidths(ptxtobj, iwch + 1 - ptxtobj->iwchFirst, &objdim, &dur);
  263. if (lserr != lserrNone) return lserr;
  264. durLeftIndent = 0;
  265. if (pilsobj->grpf & fTxtIndentChangesHyphenZone )
  266. {
  267. lserr = LsdnGetLeftIndentDur(pilsobj->plsc, &durLeftIndent);
  268. Assert(lserr == lserrNone);
  269. }
  270. *pfInHyphenZone =
  271. (plocchnk->lsfgi.urColumnMax - (plocchnk->ppointUvLoc[itxtobj].u + dur) + durLeftIndent >=
  272. UrFromUa(plocchnk->lsfgi.lstflow, &pilsobj->lsdevres, pilsobj->duaHyphenationZone) );
  273. return lserrNone;
  274. }
  275. /* P R O C E S S Y S R */
  276. /*----------------------------------------------------------------------------
  277. %%Function: ProcessYsr
  278. %%Contact: sergeyge
  279. ----------------------------------------------------------------------------*/
  280. LSERR ProcessYsr(PCLOCCHNK plocchnk, long itxtobjYsr, long dwchYsr, long itxtobjPrev, long itxtobjPrevPrev,
  281. YSRINF ysrinf, BOOL* pfSuccess, HYPHOUT* phyphout)
  282. {
  283. LSERR lserr;
  284. PILSOBJ pilsobj;
  285. PLNOBJ plnobj;
  286. PTXTOBJ ptxtobjYsr;
  287. PTXTOBJ ptxtobjPrev;
  288. PTXTOBJ ptxtobjPrevPrev;
  289. const LSCHNKE* pchnkeYsr;
  290. const LSCHNKE* pchnkePrev;
  291. const LSCHNKE* pchnkePrevPrev;
  292. long iwchYsr;
  293. long durPrevOld = 0;
  294. long durPrevPrevOld = 0;
  295. long dupNew;
  296. long durNew;
  297. long dupHyphen;
  298. long durHyphen;
  299. BOOL fSuccessful;
  300. GINDEX gind;
  301. memset(phyphout, 0, sizeof(*phyphout));
  302. *pfSuccess = fTrue;
  303. pchnkeYsr = &plocchnk->plschnk[itxtobjYsr];
  304. ptxtobjYsr = (PTXTOBJ)pchnkeYsr->pdobj;
  305. plnobj = ptxtobjYsr->plnobj;
  306. pilsobj = plnobj->pilsobj;
  307. iwchYsr = ptxtobjYsr->iwchFirst + dwchYsr;
  308. if (ptxtobjYsr->txtf & txtfGlyphBased)
  309. {
  310. lserr = GetWidthOfGlyph(pilsobj, pchnkeYsr->plsrun, plocchnk->lsfgi.lstflow, pilsobj->wchHyphen,
  311. &fSuccessful, &gind, &durHyphen, &dupHyphen);
  312. if (lserr != lserrNone) return lserr;
  313. if (!fSuccessful)
  314. {
  315. *pfSuccess = fFalse;
  316. return lserrNone;
  317. }
  318. phyphout->gindHyphen = gind;
  319. phyphout->igindHyphen = IgindFirstFromIwch(ptxtobjYsr, iwchYsr) + 1;
  320. }
  321. else
  322. {
  323. lserr = GetWidthOfChar(pilsobj, pchnkeYsr->plsrun, plocchnk->lsfgi.lstflow, pilsobj->wchHyphen, &durHyphen, &dupHyphen);
  324. if (lserr != lserrNone) return lserr;
  325. }
  326. phyphout->durHyphen = durHyphen;
  327. phyphout->dupHyphen = dupHyphen;
  328. Assert(phyphout->wchPrev == 0);
  329. Assert(phyphout->durPrev == 0);
  330. Assert(phyphout->dupPrev == 0);
  331. Assert(phyphout->wchPrevPrev == 0);
  332. Assert(phyphout->durPrevPrev == 0);
  333. Assert(phyphout->dupPrevPrev == 0);
  334. switch (ysrinf.kysr)
  335. {
  336. case kysrNormal:
  337. case kysrChangeAfter:
  338. if (itxtobjPrev == itxtobjYsr && (ptxtobjYsr->txtf & txtfGlyphBased) && !FIwchOneToOne(pilsobj, iwchYsr))
  339. {
  340. *pfSuccess = fFalse;
  341. return lserrNone;
  342. }
  343. phyphout->iwchLim = iwchYsr + 2;
  344. phyphout->dwchYsr = 2;
  345. phyphout->durChangeTotal = durHyphen;
  346. break;
  347. case kysrChangeBefore:
  348. if (itxtobjPrev == ichnkOutside)
  349. {
  350. *pfSuccess = fFalse;
  351. return lserrNone;
  352. }
  353. pchnkePrev = &plocchnk->plschnk[itxtobjPrev];
  354. ptxtobjPrev = (PTXTOBJ)pchnkePrev->pdobj;
  355. if (iwchYsr < ptxtobjPrev->iwchFirst || iwchYsr >= ptxtobjPrev->iwchLim)
  356. {
  357. *pfSuccess = fFalse;
  358. return lserrNone;
  359. }
  360. if (ptxtobjPrev->txtf & txtfGlyphBased)
  361. {
  362. lserr = GetWidthOfGlyph(pilsobj, pchnkePrev->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr,
  363. &fSuccessful, &gind, &durNew, &dupNew);
  364. if (lserr != lserrNone) return lserr;
  365. if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr))
  366. {
  367. *pfSuccess = fFalse;
  368. return lserrNone;
  369. }
  370. phyphout->gindPrev = gind;
  371. phyphout->igindPrev = IgindFirstFromIwch(ptxtobjPrev, iwchYsr);
  372. }
  373. else
  374. {
  375. lserr = GetWidthOfChar(pilsobj, pchnkePrev->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr, &durNew, &dupNew);
  376. if (lserr != lserrNone) return lserr;
  377. }
  378. GetOneCharWidth(ptxtobjPrev, iwchYsr, &durPrevOld);
  379. phyphout->iwchLim = iwchYsr + 2;
  380. phyphout->dwchYsr = 2;
  381. phyphout->wchPrev = ysrinf.wchYsr;
  382. phyphout->durPrev = durNew;
  383. phyphout->dupPrev = dupNew;
  384. phyphout->durChangeTotal = durHyphen + durNew - durPrevOld;
  385. break;
  386. case kysrAddBefore:
  387. if (ptxtobjYsr->txtf & txtfGlyphBased)
  388. {
  389. lserr = GetWidthOfGlyph(pilsobj, pchnkeYsr->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr,
  390. &fSuccessful, &gind, &durNew, &dupNew);
  391. if (lserr != lserrNone) return lserr;
  392. if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr))
  393. {
  394. *pfSuccess = fFalse;
  395. return lserrNone;
  396. }
  397. phyphout->gindPrev = gind;
  398. phyphout->igindHyphen++;
  399. phyphout->igindPrev = phyphout->igindHyphen - 1;
  400. }
  401. else
  402. {
  403. lserr = GetWidthOfChar(pilsobj, pchnkeYsr->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr, &durNew, &dupNew);
  404. if (lserr != lserrNone) return lserr;
  405. }
  406. /* procedure CheckReallocArrays made shure we have enough space in arrays */
  407. phyphout->iwchLim = iwchYsr + 3;
  408. phyphout->dwchYsr = 3;
  409. phyphout->wchPrev = ysrinf.wchYsr;
  410. phyphout->durPrev = durNew;
  411. phyphout->dupPrev = dupNew;
  412. phyphout->durChangeTotal = durHyphen + durNew;
  413. break;
  414. case kysrDelAndChange:
  415. if (itxtobjPrev == ichnkOutside || itxtobjPrevPrev == ichnkOutside)
  416. {
  417. *pfSuccess = fFalse;
  418. return lserrNone;
  419. }
  420. pchnkePrev = &plocchnk->plschnk[itxtobjPrev];
  421. ptxtobjPrev = (PTXTOBJ)pchnkePrev->pdobj;
  422. pchnkePrevPrev = &plocchnk->plschnk[itxtobjPrevPrev];
  423. ptxtobjPrevPrev = (PTXTOBJ)pchnkePrevPrev->pdobj;
  424. if (iwchYsr < ptxtobjPrev->iwchFirst || iwchYsr >= ptxtobjPrev->iwchLim ||
  425. iwchYsr - 1 < ptxtobjPrevPrev->iwchFirst || iwchYsr - 1>= ptxtobjPrevPrev->iwchLim)
  426. {
  427. *pfSuccess = fFalse;
  428. return lserrNone;
  429. }
  430. GetOneCharWidth(ptxtobjPrev, iwchYsr, &durPrevOld);
  431. GetOneCharWidth(ptxtobjPrevPrev, iwchYsr - 1, &durPrevPrevOld);
  432. if (ptxtobjPrev->txtf & txtfGlyphBased)
  433. {
  434. lserr = GetWidthOfGlyph(pilsobj, pchnkePrev->plsrun, plocchnk->lsfgi.lstflow, pilsobj->wchSpace,
  435. &fSuccessful, &gind, &durNew, &dupNew);
  436. if (lserr != lserrNone) return lserr;
  437. if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr))
  438. {
  439. *pfSuccess = fFalse;
  440. return lserrNone;
  441. }
  442. phyphout->gindPrev = gind;
  443. phyphout->igindPrev = IgindFirstFromIwch(ptxtobjPrev, iwchYsr);
  444. }
  445. if (ptxtobjPrevPrev->txtf & txtfGlyphBased)
  446. {
  447. lserr = GetWidthOfGlyph(pilsobj, pchnkePrevPrev->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr,
  448. &fSuccessful, &gind, &durNew, &dupNew);
  449. if (lserr != lserrNone) return lserr;
  450. if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr - 1))
  451. {
  452. *pfSuccess = fFalse;
  453. return lserrNone;
  454. }
  455. phyphout->gindPrevPrev = gind;
  456. phyphout->igindPrevPrev = IgindFirstFromIwch(ptxtobjPrevPrev, iwchYsr - 1);
  457. }
  458. else
  459. {
  460. lserr = GetWidthOfChar(pilsobj, pchnkePrevPrev->plsrun, plocchnk->lsfgi.lstflow, ysrinf.wchYsr, &durNew, &dupNew);
  461. if (lserr != lserrNone) return lserr;
  462. }
  463. phyphout->iwchLim = iwchYsr + 2;
  464. phyphout->dwchYsr = 2;
  465. phyphout->wchPrev = pilsobj->wchSpace;
  466. phyphout->durPrev = 0;
  467. phyphout->dupPrev = 0;
  468. phyphout->wchPrevPrev = ysrinf.wchYsr;
  469. phyphout->durPrevPrev = durNew;
  470. phyphout->dupPrevPrev = dupNew;
  471. phyphout->durChangeTotal = durHyphen + durNew - durPrevOld - durPrevPrevOld;
  472. break;
  473. case kysrDeleteBefore:
  474. if (itxtobjPrev == ichnkOutside)
  475. {
  476. *pfSuccess = fFalse;
  477. return lserrNone;
  478. }
  479. pchnkePrev = &plocchnk->plschnk[itxtobjPrev];
  480. ptxtobjPrev = (PTXTOBJ)pchnkePrev->pdobj;
  481. if (iwchYsr < ptxtobjPrev->iwchFirst || iwchYsr >= ptxtobjPrev->iwchLim)
  482. {
  483. *pfSuccess = fFalse;
  484. return lserrNone;
  485. }
  486. GetOneCharWidth(ptxtobjPrev, iwchYsr, &durPrevOld);
  487. if (ptxtobjPrev->txtf & txtfGlyphBased)
  488. {
  489. lserr = GetWidthOfGlyph(pilsobj, pchnkePrev->plsrun, plocchnk->lsfgi.lstflow, pilsobj->wchSpace,
  490. &fSuccessful, &gind, &durNew, &dupNew);
  491. if (lserr != lserrNone) return lserr;
  492. if (!fSuccessful || !FIwchOneToOne(pilsobj, iwchYsr))
  493. {
  494. *pfSuccess = fFalse;
  495. return lserrNone;
  496. }
  497. phyphout->gindPrev = gind;
  498. phyphout->igindPrev = IgindFirstFromIwch(ptxtobjPrev, iwchYsr);
  499. }
  500. phyphout->iwchLim = iwchYsr + 2;
  501. phyphout->dwchYsr = 2;
  502. phyphout->wchPrev = pilsobj->wchSpace;
  503. phyphout->durPrev = 0;
  504. phyphout->dupPrev = 0;
  505. phyphout->durChangeTotal = durHyphen - durPrevOld;
  506. break;
  507. default:
  508. NotReached();
  509. }
  510. if (itxtobjPrev != itxtobjYsr && durPrevOld != 0)
  511. {
  512. phyphout->ddurDnodePrev += (phyphout->durPrev - durPrevOld);
  513. }
  514. if (itxtobjPrevPrev != itxtobjYsr && durPrevPrevOld != 0)
  515. {
  516. if (itxtobjPrev == itxtobjPrevPrev || itxtobjPrev == itxtobjYsr)
  517. {
  518. phyphout->ddurDnodePrev += (phyphout->durPrevPrev - durPrevPrevOld);
  519. }
  520. else
  521. {
  522. phyphout->ddurDnodePrevPrev += (phyphout->durPrevPrev - durPrevPrevOld);
  523. }
  524. }
  525. return lserrNone;
  526. }
  527. #define cIncreaseBeakInfoMax 4
  528. /* G E T P B R K I N F */
  529. /*----------------------------------------------------------------------------
  530. %%Function: GetPbrkinf
  531. %%Contact: sergeyge
  532. Gets the pointer to the available BREAKINFO staructure
  533. ----------------------------------------------------------------------------*/
  534. LSERR GetPbrkinf(PILSOBJ pilsobj, PDOBJ pdobj, BRKKIND brkkind, BREAKINFO** ppbrkinf)
  535. {
  536. LSERR lserr;
  537. BREAKINFO* pbreakinf;
  538. long ibrkinf = 0xFFFF;
  539. BOOL fInChildList;
  540. pbreakinf = pilsobj->pbreakinf;
  541. lserr = LsdnFInChildList(pilsobj->plsc, ((PTXTOBJ)pdobj)->plsdnUpNode, &fInChildList);
  542. Assert(lserr == lserrNone);
  543. if (!fInChildList)
  544. {
  545. switch(brkkind)
  546. {
  547. case brkkindPrev:
  548. ibrkinf = 0;
  549. break;
  550. case brkkindNext:
  551. ibrkinf = 1;
  552. break;
  553. case brkkindForce:
  554. ibrkinf = 2;
  555. break;
  556. default:
  557. NotReached();
  558. }
  559. }
  560. else
  561. {
  562. for (ibrkinf = 3; ibrkinf < (long)pilsobj->breakinfMac &&
  563. (pbreakinf[ibrkinf].pdobj != pdobj || pbreakinf[ibrkinf].brkkind != brkkind); ibrkinf++);
  564. }
  565. if (ibrkinf < (long)pilsobj->breakinfMac)
  566. {
  567. Assert(ibrkinf < 3 || pbreakinf[ibrkinf].pdobj == pdobj && pbreakinf[ibrkinf].brkkind == brkkind);
  568. *ppbrkinf = &pbreakinf[ibrkinf];
  569. }
  570. else if (pilsobj->breakinfMac < pilsobj->breakinfMax)
  571. {
  572. *ppbrkinf = &pilsobj->pbreakinf[pilsobj->breakinfMac];
  573. pilsobj->breakinfMac++;
  574. }
  575. else
  576. {
  577. Assert(pilsobj->breakinfMac == pilsobj->breakinfMax);
  578. pbreakinf = (*pilsobj->plscbk->pfnReallocPtr)(pilsobj->pols, pilsobj->pbreakinf,
  579. (pilsobj->breakinfMax + cIncreaseBeakInfoMax) * sizeof(BREAKINFO) );
  580. if (pbreakinf == NULL)
  581. {
  582. return lserrOutOfMemory;
  583. }
  584. pilsobj->pbreakinf = pbreakinf;
  585. pilsobj->breakinfMax += cIncreaseBeakInfoMax;
  586. *ppbrkinf = &pilsobj->pbreakinf[pilsobj->breakinfMac];
  587. pilsobj->breakinfMac++;
  588. }
  589. memset(*ppbrkinf, 0, sizeof(BREAKINFO));
  590. return lserrNone;
  591. }
  592. /* Internal functions implementation */
  593. /* G E T O N E C H A R W I D T H */
  594. /*----------------------------------------------------------------------------
  595. %%Function: GetOneCharWidth
  596. %%Contact: sergeyge
  597. Reports width of the character iwch
  598. ----------------------------------------------------------------------------*/
  599. static void GetOneCharWidth(PTXTOBJ ptxtobj, long iwch, long* pdurChar)
  600. {
  601. if (ptxtobj->txtf & txtfGlyphBased)
  602. *pdurChar = ptxtobj->plnobj->pilsobj->pdurGind[IgindFirstFromIwch(ptxtobj, iwch)];
  603. else
  604. *pdurChar = ptxtobj->plnobj->pilsobj->pdur[iwch];
  605. }
  606. /* G E T W I D T H O F C H A R */
  607. /*----------------------------------------------------------------------------
  608. %%Function: GetWidthOfChar
  609. %%Contact: sergeyge
  610. Reports width of the character wch with plsrun
  611. ----------------------------------------------------------------------------*/
  612. static LSERR GetWidthOfChar(PILSOBJ pilsobj, PLSRUN plsrun, LSTFLOW lstflow, WCHAR wch, long* pdurNew, long* pdupNew)
  613. {
  614. LSERR lserr;
  615. long durSumJunk;
  616. long limDurJunk;
  617. lserr = (*pilsobj->plscbk->pfnGetRunCharWidths)(pilsobj->pols, plsrun, lsdevReference, &wch, 1, LONG_MAX, lstflow,
  618. (int*)pdurNew, &durSumJunk, &limDurJunk);
  619. if (lserr != lserrNone) return lserr;
  620. if (pilsobj->fDisplay)
  621. {
  622. if (!pilsobj->fPresEqualRef)
  623. {
  624. lserr = (*pilsobj->plscbk->pfnGetRunCharWidths)(pilsobj->pols, plsrun, lsdevPres, &wch, 1, LONG_MAX, lstflow,
  625. (int*)pdupNew, &durSumJunk, &limDurJunk);
  626. if (lserr != lserrNone) return lserr;
  627. }
  628. else /* fPresEqualRef */
  629. {
  630. *pdupNew = *pdurNew;
  631. }
  632. }
  633. return lserrNone;
  634. }
  635. /* G E T W I D T H O F G L Y P H */
  636. /*----------------------------------------------------------------------------
  637. %%Function: GetWidthOfGlyph
  638. %%Contact: sergeyge
  639. Reports width of the glyph corresponding to the character with plsrun
  640. ----------------------------------------------------------------------------*/
  641. static LSERR GetWidthOfGlyph(PILSOBJ pilsobj, PLSRUN plsrun, LSTFLOW lstflow, WCHAR wch, BOOL* pfSuccessful,
  642. GINDEX* pgind, long* pdurNew, long* pdupNew)
  643. {
  644. LSERR lserr;
  645. GPROP* pgpropTemp;
  646. GPROP gprop;
  647. GMAP gmap;
  648. GINDEX* pgindTemp;
  649. DWORD cgind;
  650. GOFFSET goffs;
  651. *pfSuccessful = fTrue;
  652. lserr = (*pilsobj->plscbk->pfnGetGlyphs)(pilsobj->pols, plsrun, &wch, 1, lstflow, &gmap, &pgindTemp, &pgpropTemp, &cgind);
  653. if (lserr != lserrNone) return lserr;
  654. if (cgind != 1)
  655. {
  656. *pfSuccessful = fFalse;
  657. return lserrNone;
  658. }
  659. *pgind = *pgindTemp;
  660. gprop = *pgpropTemp;
  661. lserr = (*pilsobj->plscbk->pfnGetGlyphPositions)(pilsobj->pols, plsrun, lsdevReference, &wch, &gmap, 1, pgind,
  662. &gprop, cgind, lstflow,
  663. (int*)pdurNew, &goffs);
  664. if (lserr != lserrNone) return lserr;
  665. Assert(goffs.du == 0);
  666. Assert(goffs.dv == 0);
  667. if (pilsobj->fDisplay)
  668. {
  669. if (!pilsobj->fPresEqualRef)
  670. {
  671. lserr = (*pilsobj->plscbk->pfnGetGlyphPositions)(pilsobj->pols, plsrun, lsdevPres, &wch, &gmap, 1, pgind,
  672. &gprop, cgind, lstflow,
  673. (int*)pdupNew, &goffs);
  674. if (lserr != lserrNone) return lserr;
  675. }
  676. else
  677. *pdupNew = *pdurNew;
  678. }
  679. return lserrNone;
  680. }