Leaked source code of windows server 2003
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.

2114 lines
68 KiB

  1. #include <limits.h>
  2. #include "lsmem.h"
  3. #include "lstxtbrk.h"
  4. #include "lstxtbrs.h"
  5. #include "lstxtmap.h"
  6. #include "lsdntext.h"
  7. #include "brko.h"
  8. #include "locchnk.h"
  9. #include "lschp.h"
  10. #include "posichnk.h"
  11. #include "objdim.h"
  12. #include "lshyph.h"
  13. #include "lskysr.h"
  14. #include "lstxtffi.h"
  15. #include "txtils.h"
  16. #include "txtln.h"
  17. #include "txtobj.h"
  18. #define FWrapTrailingSpaces(pilsobj, ptxtobj, fInChildList) \
  19. (lserr = LsdnFInChildList((pilsobj)->plsc, (ptxtobj)->plsdnUpNode, &(fInChildList)), \
  20. Assert(lserr == lserrNone), \
  21. (fInChildList) || ((pilsobj)->grpf & fTxtWrapTrailingSpaces))
  22. #define FRegularBreakableBeforeDobj(ptxtobj) \
  23. ((ptxtobj)->txtkind == txtkindRegular || (ptxtobj)->txtkind == txtkindYsrChar || \
  24. (ptxtobj)->txtkind == txtkindSpecSpace || (ptxtobj)->txtkind == txtkindHardHyphen)
  25. #define FRegularBreakableAfterDobj(ptxtobj) \
  26. ((ptxtobj)->txtkind == txtkindRegular || (ptxtobj)->txtkind == txtkindYsrChar || \
  27. (ptxtobj)->txtkind == txtkindSpecSpace)
  28. /* Internal Functions prototypes */
  29. static BOOL FindPrevSpace(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  30. long* pitxtobjSpace, long* piwchSpace);
  31. static BOOL FindNextSpace(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  32. long* pitxtobjSpace, long* piwchSpace);
  33. static LSERR TryPrevBreakFindYsr(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  34. long itxtobjSpace, long iwchSpace,
  35. BOOL* pfBroken, BOOL* pfFoundYsr, long* pitxtobjYsr, PBRKOUT ptbo);
  36. static LSERR TryNextBreakFindYsr(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  37. long itxtobjSpace, long iwchSpace,
  38. BOOL* pfBroken, PBRKOUT ptbo);
  39. static LSERR TryBreakWithHyphen(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  40. BOOL fSpaceFound, long itxtobjSpace, long iwchSpace,
  41. BOOL fFoundYsr, long itxtobjYsr, BOOL* pfBroken, PBRKOUT ptbo);
  42. static LSERR TryBreakAtSpace(PCLOCCHNK plocchnk, PCPOSICHNK pposichnk,long itxtobjSpace, long iwchSpace,
  43. BRKKIND brkkind, BOOL* pfBroken, long* pitxtobjCurNew, long* piwchCurNew, PBRKOUT ptbo);
  44. static LSERR TryBreakAtSpaceWrap(PCLOCCHNK plocchnk, PCPOSICHNK pposichnk,
  45. long itxtobjSpace, long iwchSpace, BRKKIND brkkind,
  46. BOOL* pfBroken, long* pitxtobjCurNew, long* piwchCurNew, PBRKOUT ptbo);
  47. static LSERR TryBreakAtSpaceNormal(PCLOCCHNK plocchnk, long itxtobjSpace, long iwchSpace, BRKKIND brkkind,
  48. BOOL* pfBroken, long* pitxtobjCurNew, long* piwchCurNew, PBRKOUT ptbo);
  49. static LSERR TryBreakAcrossSpaces(PCLOCCHNK plocchnk,
  50. BOOL fBeforeFound, long itxtobjBefore, long iwchBefore,
  51. BOOL fAfterFound, long itxtobjAfter, long iwchAfter, BRKKIND brkkind,
  52. BOOL* pfBroken, PBRKOUT ptbo);
  53. static LSERR TryPrevBreakRegular(PCLOCCHNK plocchnk, long itxtobj, long iwchSpace, long iwchCur,
  54. BOOL* pfBroken, PBRKOUT ptbo);
  55. static LSERR TryNextBreakRegular(PCLOCCHNK plocchnk, long itxtobj, long iwchSpace, long iwchCur,
  56. BOOL* pfBroken, PBRKOUT ptbo);
  57. static LSERR CheckBreakAtLastChar(PCLOCCHNK pclocchnk, BRKCLS brkclsLeading, long iwch, long itxtobj,
  58. BOOL* pfBroken);
  59. static LSERR TryBreakAtHardHyphen(PCLOCCHNK plocchnk, long itxtobj, long iwch, BRKKIND brkkind,
  60. BOOL* pfBroken, PBRKOUT ptbo);
  61. static LSERR TryBreakAtOptBreak(PCLOCCHNK plocchnk, long itxtobj, BRKKIND brkkind,
  62. BOOL* pfBroken, PBRKOUT ptbo);
  63. static LSERR TryBreakAtEOL(PCLOCCHNK plocchnk, long itxtobj, BRKKIND brkkind, BOOL* pfBroken, PBRKOUT ptbo);
  64. static LSERR TryBreakAtNonReqHyphen(PCLOCCHNK plocchnk, long itxtobj, BRKKIND brkkind,
  65. BOOL* pfBroken, PBRKOUT ptbo);
  66. static LSERR TryBreakAfterChunk(PCLOCCHNK plocchnk, BRKCOND brkcond, BOOL* pfBroken, PBRKOUT ptbo);
  67. static LSERR TryBreakBeforeChunk(PCLOCCHNK plocchnk, BRKCOND brkcond, BOOL* pfBroken, PBRKOUT ptbo);
  68. static LSERR CanBreakBeforeText(PCLOCCHNK plocchnk, BRKCOND* pbrktxt);
  69. static LSERR CanBreakAfterText(PCLOCCHNK plocchnk, BOOL fNonSpaceFound, long itxtobjBefore,
  70. long iwchBefore, BRKCOND* pbrktxt);
  71. static LSERR FillPtboPbrkinf(PCLOCCHNK plocchnk, long itxtobj, long iwch,
  72. /*long itxtobjBeforeTrail,*/ long iwchBeforeTrail, BRKKIND brkkind,
  73. BREAKINFO** ppbrkinf, PBRKOUT ptbo);
  74. /* Export Functions Implementation */
  75. /* F I N D P R E V B R E A K T E X T */
  76. /*----------------------------------------------------------------------------
  77. %%Function: FindPrevBreakTxt
  78. %%Contact: sergeyge
  79. Breaks the line in general case.
  80. Strategy:
  81. in loop while break was not found:
  82. --Finds the last space.
  83. --Checks for break opportunity behind last space. If it exists, performs break.
  84. --If there is no such an opportunity tries to hyphenate if needed.
  85. --Tries to breaks at space, if other possibilies did not work
  86. ----------------------------------------------------------------------------*/
  87. LSERR WINAPI FindPrevBreakText(PCLOCCHNK plocchnk, PCPOSICHNK pposichnk, BRKCOND brkcondAfter, PBRKOUT ptbo)
  88. {
  89. LSERR lserr;
  90. PILSOBJ pilsobj;
  91. long iwchFirst;
  92. long itxtobjCur = 0; /* Initialization to keep compiler satisfied */
  93. PTXTOBJ ptxtobjCur;
  94. long iwchCur = 0; /* Initialization to keep compiler satisfied */ /* Absolute index of current char in rgwch */
  95. long itxtobjSpace;
  96. long iwchSpace; /* Absolute index of last space in rgwch */
  97. long itxtobjYsr;
  98. BOOL fSpaceFound;
  99. BOOL fBroken;
  100. BOOL fFoundYsr;
  101. long itxtobjCurNew;
  102. long iwchCurNew;
  103. BOOL fInChildList;
  104. Assert(plocchnk->clschnk > 0);
  105. pilsobj = ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  106. iwchFirst = ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->iwchFirst;
  107. fBroken = fFalse;
  108. if (pposichnk->ichnk == ichnkOutside)
  109. {
  110. /* Check break after chunk. If break is impossible, make sure that it is not considered any longer */
  111. lserr = TryBreakAfterChunk(plocchnk, brkcondAfter, &fBroken, ptbo);
  112. if (lserr != lserrNone) return lserr;
  113. if (!fBroken)
  114. {
  115. itxtobjCur = plocchnk->clschnk-1;
  116. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  117. iwchCur = ptxtobjCur->iwchFirst + plocchnk->plschnk[itxtobjCur].dcp - 1;
  118. if (iwchCur < ptxtobjCur->iwchFirst)
  119. itxtobjCur--;
  120. Assert(itxtobjCur >= 0 || iwchCur < iwchFirst);
  121. if (itxtobjCur >= 0)
  122. FindNonSpaceBefore(plocchnk->plschnk, itxtobjCur, iwchCur, &itxtobjCur, &iwchCur);
  123. /* if not found, we are safe because iwchCur will be < iwchFirst in this case */
  124. }
  125. }
  126. else
  127. {
  128. itxtobjCur = pposichnk->ichnk;
  129. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  130. Assert(ptxtobjCur->iwchFirst + pposichnk->dcp > 0);
  131. iwchCur = ptxtobjCur->iwchFirst + pposichnk->dcp - 1;
  132. if (ptxtobjCur->txtkind == txtkindEOL)
  133. {
  134. lserr = TryBreakAtEOL(plocchnk, itxtobjCur, brkkindPrev, &fBroken, ptbo);
  135. if (lserr != lserrNone) return lserr;
  136. }
  137. else if (!FRegularBreakableAfterDobj(ptxtobjCur))
  138. {
  139. /* It won't be done after FindPrevSpace for non-regular DOBJ's, because they might overwrite
  140. don't break before space logic
  141. */
  142. iwchCur--;
  143. if (iwchCur < ptxtobjCur->iwchFirst)
  144. itxtobjCur--;
  145. }
  146. }
  147. while (!fBroken && iwchCur >= iwchFirst)
  148. {
  149. /* it is important to start search for space before subtructing 1,
  150. since space might have been a truncation point
  151. it is not very beautiful that iwchCur is wrong for ichnkOutside, but
  152. fortunately it still works correctly with FindPrevSpace.
  153. */
  154. fSpaceFound = FindPrevSpace(plocchnk, itxtobjCur, iwchCur, &itxtobjSpace, &iwchSpace);
  155. /* now index of the current wchar should be decreased by 1 in both starting situation(obviously)
  156. and following iterations (because break cannot happen before space),
  157. but not for non-Regular DOBJ's.
  158. At starting situation it has already been done. In following iterations Hard/OptBreak's should
  159. produce hard-coded break opportunity
  160. */
  161. Assert(itxtobjCur >= 0);
  162. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  163. if (FRegularBreakableAfterDobj(ptxtobjCur))
  164. {
  165. iwchCur--;
  166. if (iwchCur < ptxtobjCur->iwchFirst && itxtobjCur > 0)
  167. itxtobjCur--;
  168. }
  169. /* Check if there is break opportunity behind last space */
  170. lserr = TryPrevBreakFindYsr(plocchnk, itxtobjCur, iwchCur, itxtobjSpace, iwchSpace,
  171. &fBroken, &fFoundYsr, &itxtobjYsr, ptbo);
  172. if (lserr != lserrNone) return lserr;
  173. if (!fBroken)
  174. {
  175. if ((pilsobj->grpf & fTxtDoHyphenation) && iwchCur > iwchSpace)
  176. {
  177. lserr = LsdnFInChildList(ptxtobjCur->plnobj->pilsobj->plsc, ptxtobjCur->plsdnUpNode, &fInChildList);
  178. if (lserr != lserrNone) return lserr;
  179. if (!fInChildList)
  180. {
  181. lserr = TryBreakWithHyphen(plocchnk, itxtobjCur, iwchCur, fSpaceFound, itxtobjSpace, iwchSpace,
  182. fFoundYsr, itxtobjYsr, &fBroken, ptbo);
  183. if (lserr != lserrNone) return lserr;
  184. }
  185. }
  186. if (!fBroken)
  187. {
  188. if (fSpaceFound)
  189. {
  190. lserr = TryBreakAtSpace(plocchnk, pposichnk, itxtobjSpace, iwchSpace, brkkindPrev,
  191. &fBroken, &itxtobjCurNew, &iwchCurNew, ptbo);
  192. if (lserr != lserrNone) return lserr;
  193. iwchCur = iwchCurNew;
  194. itxtobjCur = itxtobjCurNew;
  195. }
  196. else
  197. {
  198. iwchCur = iwchFirst - 1;
  199. }
  200. }
  201. }
  202. }
  203. if (!fBroken)
  204. {
  205. memset(ptbo, 0, sizeof (*ptbo));
  206. Assert(ptbo->fSuccessful == fFalse);
  207. /* Addition for the new break logic---brkcond is added as input/output*/
  208. ptbo->brkcond = brkcondCan;
  209. if (pilsobj->grpf & fTxtApplyBreakingRules)
  210. {
  211. lserr = CanBreakBeforeText(plocchnk, &ptbo->brkcond);
  212. if (lserr != lserrNone) return lserr;
  213. }
  214. /* end of new breaking logic */
  215. }
  216. return lserrNone;
  217. }
  218. /* F I N D N E X T B R E A K T E X T */
  219. /*----------------------------------------------------------------------------
  220. %%Function: FindNextBreakTxt
  221. %%Contact: sergeyge
  222. Breaks the line in general case.
  223. Strategy:
  224. in loop while break was not found:
  225. --Finds the next space.
  226. --Checks for break opportunity before found space. If it exists, performs break.
  227. --Tries to breaks at space, if other possibilies did not work
  228. ----------------------------------------------------------------------------*/
  229. LSERR WINAPI FindNextBreakText(PCLOCCHNK plocchnk, PCPOSICHNK pposichnk, BRKCOND brkcondBefore, PBRKOUT ptbo)
  230. {
  231. LSERR lserr;
  232. PILSOBJ pilsobj;
  233. long iwchLast;
  234. long itxtobjCur = 0; /* Initialization to keep compiler satisfied */
  235. PTXTOBJ ptxtobjCur; /* Initialization to keep compiler satisfied */
  236. long iwchCur = 0; /* Absolute index of current char in rgwch */
  237. long itxtobjSpace;
  238. long iwchSpace; /* Absolute index of last space in rgwch */
  239. BOOL fSpaceFound;
  240. BOOL fBroken;
  241. long itxtobjCurNew;
  242. long iwchCurNew;
  243. BOOL fInChildList;
  244. BOOL fNonSpaceFound;
  245. long itxtobjBefore;
  246. long iwchBefore;
  247. BREAKINFO* pbrkinf;
  248. Assert(plocchnk->clschnk > 0);
  249. pilsobj = ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  250. iwchLast = ((PTXTOBJ)plocchnk->plschnk[plocchnk->clschnk - 1].pdobj)->iwchLim - 1;
  251. fBroken = fFalse;
  252. if (pposichnk->ichnk == ichnkOutside)
  253. {
  254. /* Check break after chunk. If break is impossible, make sure that it is not considered any longer */
  255. lserr = TryBreakBeforeChunk(plocchnk, brkcondBefore, &fBroken, ptbo);
  256. if (lserr != lserrNone) return lserr;
  257. if (!fBroken)
  258. {
  259. itxtobjCur = 0;
  260. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[0].pdobj;
  261. iwchCur = ptxtobjCur->iwchFirst;
  262. /* Hack: In the case of NRH or alike satisfy condition of the while loop below */
  263. if (ptxtobjCur->iwchLim == ptxtobjCur->iwchFirst)
  264. iwchCur--;
  265. }
  266. }
  267. else
  268. {
  269. itxtobjCur = pposichnk->ichnk;
  270. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  271. Assert(ptxtobjCur->iwchFirst + pposichnk->dcp > 0);
  272. iwchCur = ptxtobjCur->iwchFirst + pposichnk->dcp - 1;
  273. /* if truncation point was space, find first next opportunity after spaces */
  274. if (!FWrapTrailingSpaces(pilsobj, ptxtobjCur, fInChildList))
  275. {
  276. FindNonSpaceAfter(plocchnk->plschnk, plocchnk->clschnk,
  277. itxtobjCur, iwchCur, &itxtobjCur, &iwchCur);
  278. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  279. }
  280. /* Hack: In the case of NRH or alike satisfy condition of the while loop below */
  281. if (ptxtobjCur->iwchLim == ptxtobjCur->iwchFirst)
  282. iwchCur = ptxtobjCur->iwchFirst - 1;
  283. }
  284. while (!fBroken && iwchCur <= iwchLast)
  285. {
  286. fSpaceFound = FindNextSpace(plocchnk, itxtobjCur, iwchCur, &itxtobjSpace, &iwchSpace);
  287. /* Check if there is break opportunity before next space */
  288. lserr = TryNextBreakFindYsr(plocchnk, itxtobjCur, iwchCur, itxtobjSpace, iwchSpace,
  289. &fBroken, ptbo);
  290. if (lserr != lserrNone) return lserr;
  291. if (!fBroken)
  292. {
  293. if (fSpaceFound)
  294. {
  295. lserr = TryBreakAtSpace(plocchnk, pposichnk, itxtobjSpace, iwchSpace, brkkindNext,
  296. &fBroken, &itxtobjCurNew, &iwchCurNew, ptbo);
  297. if (lserr != lserrNone) return lserr;
  298. if (!fBroken)
  299. {
  300. iwchCur = iwchCurNew;
  301. itxtobjCur = itxtobjCurNew;
  302. Assert(itxtobjCur >= 0 && itxtobjCur < (long)plocchnk->clschnk);
  303. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  304. /* Hack: In the case of NRH or alike satisfy condition of the while loop */
  305. if (ptxtobjCur->iwchLim == ptxtobjCur->iwchFirst)
  306. iwchCur--;
  307. }
  308. }
  309. else
  310. {
  311. iwchCur = iwchLast + 1;
  312. }
  313. }
  314. }
  315. if (!fBroken)
  316. {
  317. memset(ptbo, 0, sizeof (*ptbo));
  318. Assert(ptbo->fSuccessful == fFalse);
  319. ptbo->brkcond = brkcondCan;
  320. Assert(plocchnk->clschnk > 0);
  321. itxtobjCur = plocchnk->clschnk - 1;
  322. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  323. iwchCur = ptxtobjCur->iwchLim - 1;
  324. fNonSpaceFound = FindNonSpaceBefore(plocchnk->plschnk, itxtobjCur, iwchCur,
  325. &itxtobjBefore, &iwchBefore);
  326. if (pilsobj->grpf & fTxtApplyBreakingRules)
  327. {
  328. lserr = CanBreakAfterText(plocchnk, fNonSpaceFound, itxtobjBefore, iwchBefore, &ptbo->brkcond);
  329. if (lserr != lserrNone) return lserr;
  330. if (iwchBefore != iwchCur && ptbo->brkcond == brkcondCan)
  331. ptbo->brkcond = brkcondPlease;
  332. }
  333. if (ptbo->brkcond != brkcondNever)
  334. {
  335. /* if following Assert fails, iwchCur is calculated incorrectly a few lines above,
  336. but it must be correct, because NonRecHyphen/... would have already caused break
  337. */
  338. Assert(ptxtobjCur->iwchLim > ptxtobjCur->iwchFirst);
  339. lserr = FillPtboPbrkinf(plocchnk, itxtobjCur, iwchCur, /*itxtobjBefore,*/ iwchBefore,
  340. brkkindNext, &pbrkinf, ptbo);
  341. if (lserr != lserrNone) return lserr;
  342. ptbo->fSuccessful = fFalse;
  343. /* next if statement with comment is copied from TryBreakNextNormal() with replacement of
  344. iwchCur - 1 by iwchCur */
  345. /* fModWidthSpace can be at the last char here only iff fWrapAllSpaces;
  346. if we touch balanced space here, the logic of GetMinCompressAmount should be rethinked!*/
  347. if (pilsobj->pdurRight != NULL && pilsobj->pdurRight[iwchCur] != 0 &&
  348. !pilsobj->ptxtinf[iwchCur].fModWidthSpace)
  349. {
  350. pbrkinf->u.normal.durFix = - pilsobj->pdurRight[iwchCur];
  351. ptbo->objdim.dur -= pilsobj->pdurRight[iwchCur];
  352. }
  353. }
  354. }
  355. return lserrNone;
  356. }
  357. /* Internal Functions Implementation */
  358. /* F I N D P R E V S P A C E */
  359. /*----------------------------------------------------------------------------
  360. %%Function: FindPrevSpace
  361. %%Contact: sergeyge
  362. Returns TRUE if there is a space and FALSE otherwise.
  363. Reports the index of the dobj containing last space
  364. and space's index in rgwchOrig array.
  365. ----------------------------------------------------------------------------*/
  366. static BOOL FindPrevSpace(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  367. long* pitxtobjSpace, long* piwchSpace)
  368. {
  369. PILSOBJ pilsobj;
  370. BOOL fSpaceFound;
  371. PTXTOBJ ptxtobjCur;
  372. long* rgwSpaces;
  373. long iwSpacesCur;
  374. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  375. pilsobj = ptxtobjCur->plnobj->pilsobj;
  376. rgwSpaces = pilsobj->pwSpaces;
  377. fSpaceFound = fFalse;
  378. /* In the case fWrapAllSpaces space is treated as a regular character */
  379. if (!(pilsobj->grpf & fTxtWrapAllSpaces))
  380. {
  381. if (ptxtobjCur->txtkind == txtkindRegular)
  382. {
  383. iwSpacesCur = ptxtobjCur->u.reg.iwSpacesLim - 1;
  384. while (iwSpacesCur >= ptxtobjCur->u.reg.iwSpacesFirst &&
  385. /* current character might be space, if text chunk is not last on the line */
  386. rgwSpaces[iwSpacesCur] > iwchCur)
  387. {
  388. iwSpacesCur--;
  389. }
  390. if (ptxtobjCur->txtf & txtfGlyphBased)
  391. {
  392. while (iwSpacesCur >= ptxtobjCur->u.reg.iwSpacesFirst &&
  393. !FIwchOneToOne(pilsobj, rgwSpaces[iwSpacesCur]))
  394. iwSpacesCur--;
  395. }
  396. if (iwSpacesCur >= ptxtobjCur->u.reg.iwSpacesFirst)
  397. {
  398. fSpaceFound = fTrue;
  399. *pitxtobjSpace = itxtobjCur;
  400. *piwchSpace = rgwSpaces[iwSpacesCur];
  401. }
  402. }
  403. else if (ptxtobjCur->txtkind == txtkindSpecSpace)
  404. {
  405. fSpaceFound = fTrue;
  406. *pitxtobjSpace = itxtobjCur;
  407. *piwchSpace = iwchCur;
  408. }
  409. itxtobjCur--;
  410. while (!fSpaceFound && itxtobjCur >= 0)
  411. {
  412. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  413. if (ptxtobjCur->txtkind == txtkindRegular)
  414. {
  415. iwSpacesCur = ptxtobjCur->u.reg.iwSpacesLim - 1;
  416. if (ptxtobjCur->txtf & txtfGlyphBased)
  417. {
  418. while (iwSpacesCur >= ptxtobjCur->u.reg.iwSpacesFirst &&
  419. !FIwchOneToOne(pilsobj, rgwSpaces[iwSpacesCur]))
  420. iwSpacesCur--;
  421. }
  422. if (iwSpacesCur >= ptxtobjCur->u.reg.iwSpacesFirst)
  423. {
  424. fSpaceFound = fTrue;
  425. *pitxtobjSpace = itxtobjCur;
  426. *piwchSpace = rgwSpaces[iwSpacesCur];
  427. }
  428. }
  429. else if (ptxtobjCur->txtkind == txtkindSpecSpace)
  430. {
  431. fSpaceFound = fTrue;
  432. *pitxtobjSpace = itxtobjCur;
  433. *piwchSpace = ptxtobjCur->iwchLim - 1;
  434. }
  435. itxtobjCur--;
  436. }
  437. }
  438. if (!fSpaceFound)
  439. {
  440. *pitxtobjSpace = -1;
  441. *piwchSpace = ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->iwchFirst - 1;
  442. }
  443. return fSpaceFound;
  444. }
  445. /* F I N D N E X T S P A C E */
  446. /*----------------------------------------------------------------------------
  447. %%Function: FindNextSpace
  448. %%Contact: sergeyge
  449. Returns TRUE if there is a space and FALSE otherwise.
  450. Reports the index of the dobj containing last space
  451. and space's index in rgwchOrig array.
  452. ----------------------------------------------------------------------------*/
  453. static BOOL FindNextSpace(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  454. long* pitxtobjSpace, long* piwchSpace)
  455. {
  456. PILSOBJ pilsobj;
  457. BOOL fSpaceFound;
  458. PTXTOBJ ptxtobjCur;
  459. long* rgwSpaces;
  460. long iwSpacesCur;
  461. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  462. pilsobj = ptxtobjCur->plnobj->pilsobj;
  463. rgwSpaces = pilsobj->pwSpaces;
  464. fSpaceFound = fFalse;
  465. /* In the case fWrapAllSpaces space is treated as a regular character */
  466. if (!(pilsobj->grpf & fTxtWrapAllSpaces))
  467. {
  468. if (ptxtobjCur->txtkind == txtkindRegular)
  469. {
  470. iwSpacesCur = ptxtobjCur->u.reg.iwSpacesFirst;
  471. while (iwSpacesCur < ptxtobjCur->u.reg.iwSpacesLim &&
  472. rgwSpaces[iwSpacesCur] < iwchCur)
  473. {
  474. iwSpacesCur++;
  475. }
  476. if (ptxtobjCur->txtf & txtfGlyphBased)
  477. {
  478. while (iwSpacesCur < ptxtobjCur->u.reg.iwSpacesLim &&
  479. !FIwchOneToOne(pilsobj, rgwSpaces[iwSpacesCur]))
  480. iwSpacesCur++;
  481. }
  482. if (iwSpacesCur < ptxtobjCur->u.reg.iwSpacesLim)
  483. {
  484. fSpaceFound = fTrue;
  485. *pitxtobjSpace = itxtobjCur;
  486. *piwchSpace = rgwSpaces[iwSpacesCur];
  487. }
  488. }
  489. else if (ptxtobjCur->txtkind == txtkindSpecSpace)
  490. {
  491. fSpaceFound = fTrue;
  492. *pitxtobjSpace = itxtobjCur;
  493. *piwchSpace = iwchCur;
  494. }
  495. itxtobjCur++;
  496. while (!fSpaceFound && itxtobjCur < (long)plocchnk->clschnk)
  497. {
  498. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  499. if (ptxtobjCur->txtkind == txtkindRegular)
  500. {
  501. iwSpacesCur = ptxtobjCur->u.reg.iwSpacesFirst;
  502. if (ptxtobjCur->txtf & txtfGlyphBased)
  503. {
  504. while (iwSpacesCur < ptxtobjCur->u.reg.iwSpacesLim &&
  505. !FIwchOneToOne(pilsobj, rgwSpaces[iwSpacesCur]))
  506. iwSpacesCur++;
  507. }
  508. if (iwSpacesCur < ptxtobjCur->u.reg.iwSpacesLim)
  509. {
  510. fSpaceFound = fTrue;
  511. *pitxtobjSpace = itxtobjCur;
  512. *piwchSpace = rgwSpaces[iwSpacesCur];
  513. }
  514. }
  515. else if (ptxtobjCur->txtkind == txtkindSpecSpace)
  516. {
  517. fSpaceFound = fTrue;
  518. *pitxtobjSpace = itxtobjCur;
  519. *piwchSpace = ptxtobjCur->iwchFirst;
  520. }
  521. itxtobjCur++;
  522. }
  523. }
  524. if (!fSpaceFound)
  525. {
  526. *pitxtobjSpace = plocchnk->clschnk;
  527. *piwchSpace = ((PTXTOBJ)plocchnk->plschnk[plocchnk->clschnk-1].pdobj)->iwchLim;
  528. }
  529. return fSpaceFound;
  530. }
  531. /* T R Y P R E V B R E A K F I N D Y S R */
  532. /*----------------------------------------------------------------------------
  533. %%Function: TryPrevBreakFindYsr
  534. %%Contact: sergeyge
  535. Realizes break if there is one before next space.
  536. Since each special character has its own dobj we need to check only type of dobj
  537. ----------------------------------------------------------------------------*/
  538. static LSERR TryPrevBreakFindYsr(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  539. long itxtobjSpace, long iwchSpace,
  540. BOOL* pfBroken, BOOL* pfFoundYsr, long* pitxtobjYsr, PBRKOUT ptbo)
  541. {
  542. LSERR lserr;
  543. PILSOBJ pilsobj;
  544. PTXTOBJ ptxtobjCur;
  545. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  546. pilsobj = ptxtobjCur->plnobj->pilsobj;
  547. *pfBroken = fFalse;
  548. *pfFoundYsr = fFalse;
  549. /* following condition is almost always TRUE,
  550. so in bread-and-butter situation we do almost nothing */
  551. if ((long)itxtobjCur == itxtobjSpace && !(pilsobj->grpf & fTxtApplyBreakingRules))
  552. {
  553. return lserrNone;
  554. }
  555. /* In loop condition check for itxtobjCur > itxtobjSpace is necessary for the case of empty
  556. DOBJ's: NonReqHyphen, OptBreak
  557. */
  558. while((itxtobjCur > itxtobjSpace || iwchCur > iwchSpace) && !*pfBroken)
  559. {
  560. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  561. Assert(ptxtobjCur->txtkind != txtkindEOL && ptxtobjCur->txtkind != txtkindTab);
  562. Assert(ptxtobjCur->txtkind != txtkindSpecSpace || (pilsobj->grpf & fTxtWrapAllSpaces));
  563. switch (ptxtobjCur->txtkind)
  564. {
  565. case txtkindRegular:
  566. if (pilsobj->grpf & fTxtApplyBreakingRules)
  567. {
  568. lserr = TryPrevBreakRegular(plocchnk, itxtobjCur, iwchSpace, iwchCur, pfBroken, ptbo);
  569. if (lserr != lserrNone) return lserr;
  570. }
  571. break;
  572. case txtkindHardHyphen:
  573. lserr = TryBreakAtHardHyphen(plocchnk, itxtobjCur, iwchCur, brkkindPrev, pfBroken, ptbo);
  574. if (lserr != lserrNone) return lserr;
  575. break;
  576. case txtkindOptBreak:
  577. lserr = TryBreakAtOptBreak(plocchnk, itxtobjCur, brkkindPrev, pfBroken, ptbo);
  578. if (lserr != lserrNone) return lserr;
  579. break;
  580. case txtkindNonReqHyphen:
  581. lserr = TryBreakAtNonReqHyphen(plocchnk, itxtobjCur, brkkindPrev, pfBroken, ptbo);
  582. if (lserr != lserrNone) return lserr;
  583. break;
  584. case txtkindYsrChar:
  585. if (!*pfFoundYsr)
  586. {
  587. *pfFoundYsr = fTrue;
  588. *pitxtobjYsr = itxtobjCur;
  589. }
  590. break;
  591. case txtkindSpecSpace:
  592. /* It is possible for fTxtWrapAllSpaces case */
  593. Assert(pilsobj->grpf & fTxtApplyBreakingRules);
  594. Assert(pilsobj->grpf & fTxtWrapAllSpaces);
  595. lserr = TryPrevBreakRegular(plocchnk, itxtobjCur, iwchSpace, iwchCur, pfBroken, ptbo);
  596. if (lserr != lserrNone) return lserr;
  597. break;
  598. }
  599. iwchCur = ptxtobjCur->iwchFirst - 1;
  600. itxtobjCur--;
  601. }
  602. return lserrNone;
  603. }
  604. /* T R Y N E X T B R E A K F I N D Y S R */
  605. /*----------------------------------------------------------------------------
  606. %%Function: TryPrevBreakFindYsr
  607. %%Contact: sergeyge
  608. Realizes break if there is one after last space.
  609. Also fills info about last YSR character after last space.
  610. Since each special character has its own dobj we need to check only type of dobj
  611. ----------------------------------------------------------------------------*/
  612. static LSERR TryNextBreakFindYsr(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  613. long itxtobjSpace, long iwchSpace,
  614. BOOL* pfBroken, PBRKOUT ptbo)
  615. {
  616. LSERR lserr;
  617. PILSOBJ pilsobj;
  618. PTXTOBJ ptxtobjCur;
  619. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  620. pilsobj = ptxtobjCur->plnobj->pilsobj;
  621. *pfBroken = fFalse;
  622. /* In loop condition check for itxtobjCur < itxtobjSpace is necessary for the case of empty
  623. DOBJ's: NonReqHyphen, OptBreak
  624. */
  625. while((itxtobjCur < itxtobjSpace || iwchCur < iwchSpace) && !*pfBroken)
  626. {
  627. ptxtobjCur = (PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj;
  628. Assert(ptxtobjCur->txtkind != txtkindSpecSpace || (pilsobj->grpf & fTxtWrapAllSpaces));
  629. switch (ptxtobjCur->txtkind)
  630. {
  631. case txtkindRegular:
  632. if (pilsobj->grpf & fTxtApplyBreakingRules)
  633. {
  634. lserr = TryNextBreakRegular(plocchnk, itxtobjCur, iwchSpace, iwchCur, pfBroken, ptbo);
  635. if (lserr != lserrNone) return lserr;
  636. }
  637. break;
  638. case txtkindHardHyphen:
  639. lserr = TryBreakAtHardHyphen(plocchnk, itxtobjCur, iwchCur, brkkindNext, pfBroken, ptbo);
  640. if (lserr != lserrNone) return lserr;
  641. break;
  642. case txtkindOptBreak:
  643. lserr = TryBreakAtOptBreak(plocchnk, itxtobjCur, brkkindNext, pfBroken, ptbo);
  644. if (lserr != lserrNone) return lserr;
  645. break;
  646. case txtkindEOL:
  647. lserr = TryBreakAtEOL(plocchnk, itxtobjCur, brkkindNext, pfBroken, ptbo);
  648. if (lserr != lserrNone) return lserr;
  649. break;
  650. case txtkindNonReqHyphen:
  651. lserr = TryBreakAtNonReqHyphen(plocchnk, itxtobjCur, brkkindNext, pfBroken, ptbo);
  652. if (lserr != lserrNone) return lserr;
  653. break;
  654. case txtkindSpecSpace:
  655. /* It is possible for fTxtWrapAllSpaces case */
  656. Assert(pilsobj->grpf & fTxtApplyBreakingRules);
  657. Assert(pilsobj->grpf & fTxtWrapAllSpaces);
  658. lserr = TryNextBreakRegular(plocchnk, itxtobjCur, iwchSpace, iwchCur, pfBroken, ptbo);
  659. if (lserr != lserrNone) return lserr;
  660. break;
  661. }
  662. iwchCur = ptxtobjCur->iwchLim;
  663. itxtobjCur++;
  664. }
  665. return lserrNone;
  666. }
  667. /* T R Y B R E A K W I T H H Y P H E N */
  668. /*----------------------------------------------------------------------------
  669. %%Function: TryBreakWithHyphen
  670. %%Contact: sergeyge
  671. Tries to realize break as hyphenation
  672. Strategy:
  673. --Checks if hyphenation should be performed (CheckHotZone)
  674. --If it should, calls hyphenator.
  675. ` --If hyphenator is successful tryes to insert hyphen
  676. else sets break opportunity at the last space
  677. ----------------------------------------------------------------------------*/
  678. static LSERR TryBreakWithHyphen(PCLOCCHNK plocchnk, long itxtobjCur, long iwchCur,
  679. BOOL fSpaceFound, long itxtobjSpace, long iwchSpace,
  680. BOOL fFoundYsr, long itxtobjYsr, BOOL* pfBroken, PBRKOUT ptbo)
  681. {
  682. LSERR lserr;
  683. PILSOBJ pilsobj;
  684. long itxtobjWordStart;
  685. long iwchWordStart;
  686. PTXTOBJ ptxtobjWordStart;
  687. PTXTOBJ ptxtobjYsr;
  688. long dwchYsr;
  689. LSCP cpMac;
  690. LSCP cpWordStart;
  691. PLSRUN plsrunYsr;
  692. YSRINF ysrinf;
  693. HYPHOUT hyphout;
  694. struct lshyph lshyphLast;
  695. struct lshyph lshyphNew;
  696. BOOL fHyphenInserted;
  697. BOOL fInHyphenZone = fTrue;
  698. DWORD kysr;
  699. WCHAR wchYsr;
  700. long urPenLast;
  701. OBJDIM objdim;
  702. BREAKINFO* pbrkinf;
  703. long itxtobjPrevPrev;
  704. long durBorder;
  705. BOOL fSuccessful;
  706. long i;
  707. if (!fSpaceFound)
  708. {
  709. itxtobjWordStart = 0;
  710. iwchWordStart = ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->iwchFirst;
  711. }
  712. else
  713. {
  714. itxtobjWordStart = itxtobjSpace;
  715. iwchWordStart = iwchSpace + 1;
  716. lserr = CheckHotZone(plocchnk, itxtobjSpace, iwchSpace, &fInHyphenZone);
  717. if (lserr != lserrNone) return lserr;
  718. }
  719. ptxtobjWordStart = (PTXTOBJ)plocchnk->plschnk[itxtobjWordStart].pdobj;
  720. pilsobj = ptxtobjWordStart->plnobj->pilsobj;
  721. fHyphenInserted = fFalse;
  722. if (fInHyphenZone)
  723. {
  724. /* Fill lshyphLast if there was YSR character */
  725. if (fFoundYsr)
  726. {
  727. plsrunYsr = plocchnk->plschnk[itxtobjYsr].plsrun;
  728. lserr = (*pilsobj->plscbk->pfnGetHyphenInfo)(pilsobj->pols, plsrunYsr, &kysr, &wchYsr);
  729. if (lserr != lserrNone) return lserr;
  730. lshyphLast.kysr = kysr;
  731. lshyphLast.wchYsr = wchYsr;
  732. lshyphLast.cpYsr = plocchnk->plschnk[itxtobjYsr].cpFirst;
  733. }
  734. else
  735. {
  736. lshyphLast.kysr = kysrNil;
  737. }
  738. Assert (iwchCur >= ((PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj)->iwchFirst ||
  739. ((PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj)->iwchFirst == ((PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj)->iwchLim);
  740. cpMac = plocchnk->plschnk[itxtobjCur].cpFirst +
  741. (iwchCur - ((PTXTOBJ)plocchnk->plschnk[itxtobjCur].pdobj)->iwchFirst) + 1;
  742. cpWordStart = plocchnk->plschnk[itxtobjWordStart].cpFirst +
  743. (iwchWordStart - ptxtobjWordStart->iwchFirst);
  744. lshyphNew.kysr = kysrNormal;
  745. while (!fHyphenInserted && lshyphNew.kysr != kysrNil)
  746. {
  747. lserr = (pilsobj->plscbk->pfnHyphenate)(pilsobj->pols, &lshyphLast, cpWordStart, cpMac, &lshyphNew);
  748. if (lserr != lserrNone) return lserr;
  749. if (lshyphNew.kysr != kysrNil)
  750. {
  751. /* if TryBreak.. will be unsuccessful we will try hyphenation again with a new cpMac */
  752. Assert(lshyphNew.cpYsr >= cpWordStart && lshyphNew.cpYsr < cpMac);
  753. cpMac = lshyphNew.cpYsr;
  754. lshyphLast = lshyphNew;
  755. for (i=0; i <= itxtobjCur && plocchnk->plschnk[i].cpFirst <= cpMac; i++);
  756. itxtobjYsr = i - 1;
  757. Assert(lshyphNew.cpYsr < plocchnk->plschnk[itxtobjYsr].cpFirst +
  758. (long)plocchnk->plschnk[itxtobjYsr].dcp);
  759. dwchYsr = cpMac - plocchnk->plschnk[itxtobjYsr].cpFirst;
  760. ysrinf.wchYsr = lshyphNew.wchYsr;
  761. ysrinf.kysr = (WORD)lshyphNew.kysr;
  762. itxtobjPrevPrev = ichnkOutside;
  763. for (i=itxtobjYsr; i >= 0 && plocchnk->plschnk[i].cpFirst > cpMac - 1; i--);
  764. if (i >= 0)
  765. itxtobjPrevPrev = i;
  766. lserr = ProcessYsr(plocchnk, itxtobjYsr, dwchYsr, itxtobjYsr, itxtobjPrevPrev, ysrinf,
  767. &fSuccessful, &hyphout);
  768. if (lserr != lserrNone) return lserr;
  769. Assert(hyphout.ddurDnodePrevPrev == 0);
  770. if (fSuccessful)
  771. {
  772. /* try break may be unsuccessful because it won't fit in the column */
  773. ptxtobjYsr = (PTXTOBJ)plocchnk->plschnk[itxtobjYsr].pdobj;
  774. if (ptxtobjYsr->txtf & txtfGlyphBased)
  775. lserr = CalcPartWidthsGlyphs(ptxtobjYsr, dwchYsr + 1, &objdim, &urPenLast);
  776. else
  777. lserr = CalcPartWidths(ptxtobjYsr, dwchYsr + 1, &objdim, &urPenLast);
  778. if (lserr != lserrNone) return lserr;
  779. durBorder = 0;
  780. if (plocchnk->plschnk[itxtobjYsr].plschp->fBorder)
  781. {
  782. lserr = LsdnGetBorderAfter(pilsobj->plsc, ptxtobjYsr->plsdnUpNode, &durBorder);
  783. Assert(lserr == lserrNone);
  784. }
  785. if (plocchnk->ppointUvLoc[itxtobjYsr].u + urPenLast + hyphout.durChangeTotal + durBorder
  786. <= plocchnk->lsfgi.urColumnMax)
  787. {
  788. fHyphenInserted = fTrue;
  789. ptbo->fSuccessful = fTrue;
  790. ptbo->posichnk.ichnk = itxtobjYsr;
  791. ptbo->posichnk.dcp = dwchYsr + 1;
  792. ptbo->objdim = objdim;
  793. ptbo->objdim.dur = urPenLast + hyphout.durChangeTotal;
  794. lserr = GetPbrkinf(pilsobj, plocchnk->plschnk[itxtobjYsr].pdobj, brkkindPrev, &pbrkinf);
  795. if (lserr != lserrNone) return lserr;
  796. pbrkinf->pdobj = plocchnk->plschnk[itxtobjYsr].pdobj;
  797. pbrkinf->brkkind = brkkindPrev;
  798. pbrkinf->dcp = dwchYsr + 1;
  799. pbrkinf->brkt = brktHyphen;
  800. pbrkinf->u.hyphen.iwchLim = hyphout.iwchLim;
  801. pbrkinf->u.hyphen.dwchYsr = hyphout.dwchYsr;
  802. pbrkinf->u.hyphen.durHyphen = hyphout.durHyphen;
  803. pbrkinf->u.hyphen.dupHyphen = hyphout.dupHyphen;
  804. pbrkinf->u.hyphen.durPrev = hyphout.durPrev;
  805. pbrkinf->u.hyphen.dupPrev = hyphout.dupPrev;
  806. pbrkinf->u.hyphen.durPrevPrev = hyphout.durPrevPrev;
  807. pbrkinf->u.hyphen.dupPrevPrev = hyphout.dupPrevPrev;
  808. pbrkinf->u.hyphen.ddurDnodePrev = hyphout.ddurDnodePrev;
  809. pbrkinf->u.hyphen.wchPrev = hyphout.wchPrev;
  810. pbrkinf->u.hyphen.wchPrevPrev = hyphout.wchPrevPrev;
  811. pbrkinf->u.hyphen.gindHyphen = hyphout.gindHyphen;
  812. pbrkinf->u.hyphen.gindPrev = hyphout.gindPrev;
  813. pbrkinf->u.hyphen.gindPrevPrev = hyphout.gindPrevPrev;
  814. pbrkinf->u.hyphen.igindHyphen = hyphout.igindHyphen;
  815. pbrkinf->u.hyphen.igindPrev = hyphout.igindPrev;
  816. pbrkinf->u.hyphen.igindPrevPrev = hyphout.igindPrevPrev;
  817. }
  818. }
  819. }
  820. }
  821. }
  822. *pfBroken = fHyphenInserted;
  823. return lserrNone;
  824. }
  825. /* T R Y B R E A K A T S P A C E */
  826. /*----------------------------------------------------------------------------
  827. %%Function: TryBreakAtSpace
  828. %%Contact: sergeyge
  829. Dispatchs desicion to either TryBreakAtSpaceNormal or
  830. TryBreakAtSpaceWrap
  831. ----------------------------------------------------------------------------*/
  832. static LSERR TryBreakAtSpace(PCLOCCHNK plocchnk, PCPOSICHNK pposichnk, long itxtobjSpace, long iwchSpace,
  833. BRKKIND brkkind, BOOL* pfBroken, long* pitxtobjCurNew, long* piwchCurNew, PBRKOUT ptbo)
  834. {
  835. LSERR lserr;
  836. PILSOBJ pilsobj;
  837. PTXTOBJ ptxtobj;
  838. BOOL fInChildList;
  839. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobjSpace].pdobj;
  840. pilsobj = ptxtobj->plnobj->pilsobj;
  841. Assert(!(pilsobj->grpf & fTxtWrapAllSpaces));
  842. if (FWrapTrailingSpaces(pilsobj, ptxtobj, fInChildList))
  843. {
  844. lserr = TryBreakAtSpaceWrap(plocchnk, pposichnk, itxtobjSpace, iwchSpace, brkkind,
  845. pfBroken, pitxtobjCurNew, piwchCurNew, ptbo);
  846. }
  847. else
  848. {
  849. lserr = TryBreakAtSpaceNormal(plocchnk, itxtobjSpace, iwchSpace, brkkind,
  850. pfBroken, pitxtobjCurNew, piwchCurNew, ptbo);
  851. }
  852. return lserr;
  853. }
  854. /* T R Y B R E A K A T S P A C E W R A P */
  855. /*----------------------------------------------------------------------------
  856. %%Function: TryBreakAtSpaceWrap
  857. %%Contact: sergeyge
  858. Realizes break at space for the fWrapTrailingSpaces case.
  859. ----------------------------------------------------------------------------*/
  860. static LSERR TryBreakAtSpaceWrap(PCLOCCHNK plocchnk, PCPOSICHNK pposichnk,
  861. long itxtobjSpace, long iwchSpace, BRKKIND brkkind,
  862. BOOL* pfBroken, long* pitxtobjCurNew, long* piwchCurNew, PBRKOUT ptbo)
  863. {
  864. LSERR lserr;
  865. PILSOBJ pilsobj;
  866. PTXTOBJ ptxtobjSpace;
  867. long itxtobjBefore;
  868. long itxtobjAfter;
  869. long iwchBefore;
  870. long iwchAfter;
  871. BOOL fBeforeFound;
  872. BOOL fAfterFound = fTrue;
  873. *pfBroken = fFalse;
  874. *pitxtobjCurNew = -1;
  875. *piwchCurNew = -1;
  876. ptxtobjSpace = (PTXTOBJ)plocchnk->plschnk[itxtobjSpace].pdobj;
  877. pilsobj = ptxtobjSpace->plnobj->pilsobj;
  878. fBeforeFound = FindNonSpaceBefore(plocchnk->plschnk, itxtobjSpace, iwchSpace,
  879. &itxtobjBefore, &iwchBefore);
  880. Assert(fBeforeFound || iwchBefore == ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->iwchFirst - 1);
  881. /* iwchBefore is needed for check that previous char is not space */
  882. if (brkkind == brkkindPrev && /* previous break only, next break must be after */
  883. iwchSpace - iwchBefore > 1 && /* previous character is space */
  884. pposichnk->ichnk != ichnkOutside && /* and space exceeds right margin */
  885. iwchSpace == (long)(((PTXTOBJ)plocchnk->plschnk[pposichnk->ichnk].pdobj)->iwchFirst +
  886. pposichnk->dcp - 1))
  887. {
  888. fAfterFound = fTrue;
  889. itxtobjAfter = itxtobjSpace;
  890. iwchAfter = iwchSpace;
  891. }
  892. else
  893. {
  894. fAfterFound = FindNextChar(plocchnk->plschnk, plocchnk->clschnk, itxtobjSpace, iwchSpace,
  895. &itxtobjAfter, &iwchAfter);
  896. }
  897. lserr = TryBreakAcrossSpaces(plocchnk,
  898. fBeforeFound, itxtobjBefore, iwchBefore,
  899. fAfterFound, itxtobjAfter, iwchAfter, brkkind, pfBroken, ptbo);
  900. if (lserr != lserrNone) return lserr;
  901. if (!*pfBroken)
  902. {
  903. if (brkkind == brkkindPrev)
  904. {
  905. FindPrevChar(plocchnk->plschnk, itxtobjSpace, iwchSpace,
  906. pitxtobjCurNew, piwchCurNew);
  907. }
  908. else
  909. {
  910. Assert(brkkind == brkkindNext);
  911. *pitxtobjCurNew = itxtobjAfter;
  912. *piwchCurNew = iwchAfter;
  913. }
  914. }
  915. return lserrNone;
  916. }
  917. /* T R Y B R E A K A T S P A C E N O R M A L */
  918. /*----------------------------------------------------------------------------
  919. %%Function: TryBreakAtSpaceNormal
  920. %%Contact: sergeyge
  921. Realizes break at space for the normal (!fWrapTrailingSpaces) case.
  922. ----------------------------------------------------------------------------*/
  923. static LSERR TryBreakAtSpaceNormal(PCLOCCHNK plocchnk, long itxtobjSpace, long iwchSpace, BRKKIND brkkind,
  924. BOOL* pfBroken, long* pitxtobjCurNew, long* piwchCurNew, PBRKOUT ptbo)
  925. {
  926. LSERR lserr;
  927. PILSOBJ pilsobj;
  928. PTXTOBJ ptxtobjSpace;
  929. long itxtobjBefore;
  930. long itxtobjAfter;
  931. long iwchBefore;
  932. long iwchAfter;
  933. BOOL fBeforeFound;
  934. BOOL fAfterFound;
  935. *pfBroken = fFalse;
  936. *pitxtobjCurNew = -1;
  937. *piwchCurNew = -1;
  938. ptxtobjSpace = (PTXTOBJ)plocchnk->plschnk[itxtobjSpace].pdobj;
  939. pilsobj = ptxtobjSpace->plnobj->pilsobj;
  940. fBeforeFound = FindNonSpaceBefore(plocchnk->plschnk,
  941. itxtobjSpace, iwchSpace, &itxtobjBefore, &iwchBefore);
  942. Assert(fBeforeFound || iwchBefore == ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->iwchFirst - 1);
  943. fAfterFound = FindNonSpaceAfter(plocchnk->plschnk, plocchnk->clschnk,
  944. itxtobjSpace, iwchSpace, &itxtobjAfter, &iwchAfter);
  945. lserr = TryBreakAcrossSpaces(plocchnk, fBeforeFound, itxtobjBefore, iwchBefore,
  946. fAfterFound, itxtobjAfter, iwchAfter, brkkind, pfBroken, ptbo);
  947. if (lserr != lserrNone) return lserr;
  948. if (!*pfBroken)
  949. {
  950. if (brkkind == brkkindPrev)
  951. {
  952. *pitxtobjCurNew = itxtobjBefore;
  953. *piwchCurNew = iwchBefore;
  954. }
  955. else
  956. {
  957. Assert(brkkind == brkkindNext);
  958. *pitxtobjCurNew = itxtobjAfter;
  959. *piwchCurNew = iwchAfter;
  960. }
  961. }
  962. return lserrNone;
  963. }
  964. /* T R Y B R E A K A C R O S S S P A C E S */
  965. /*----------------------------------------------------------------------------
  966. %%Function: TryBreakAcrossSpaces
  967. %%Contact: sergeyge
  968. Checks break across spaces, sets it if it is possible
  969. ----------------------------------------------------------------------------*/
  970. static LSERR TryBreakAcrossSpaces(PCLOCCHNK plocchnk,
  971. BOOL fBeforeFound, long itxtobjBefore, long iwchBefore,
  972. BOOL fAfterFound, long itxtobjAfter, long iwchAfter, BRKKIND brkkind,
  973. BOOL* pfBroken, PBRKOUT ptbo)
  974. {
  975. LSERR lserr;
  976. PILSOBJ pilsobj;
  977. PTXTOBJ ptxtobjBefore = NULL;
  978. PTXTOBJ ptxtobjAfter = NULL;
  979. BRKCLS brkclsLeading = 0; /* Initialization to keep compiler satisfied */
  980. BRKCLS brkclsFollowing = 0; /* Initialization to keep compiler satisfied */
  981. BRKCLS brkclsJunk;
  982. BRKCOND brktxt;
  983. BREAKINFO* pbrkinf;
  984. BOOL fCanBreak;
  985. pilsobj = ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  986. fCanBreak = fTrue;
  987. *pfBroken = fFalse;
  988. if (fAfterFound)
  989. {
  990. ptxtobjAfter = (PTXTOBJ)plocchnk->plschnk[itxtobjAfter].pdobj;
  991. if (ptxtobjAfter->txtkind == txtkindEOL)
  992. {
  993. lserr = TryBreakAtEOL(plocchnk, itxtobjAfter, brkkind, pfBroken, ptbo);
  994. if (lserr != lserrNone) return lserr;
  995. Assert (*pfBroken == fTrue);
  996. }
  997. }
  998. if (!*pfBroken && (pilsobj->grpf & fTxtApplyBreakingRules) )
  999. {
  1000. if (fAfterFound)
  1001. {
  1002. Assert(ptxtobjAfter->txtkind != txtkindTab && ptxtobjAfter->txtkind != txtkindEOL);
  1003. /* Space After is possible for fWarapTrailingSpaces case*/
  1004. if (ptxtobjAfter->txtkind == txtkindOptBreak ||
  1005. ptxtobjAfter->txtkind == txtkindNonReqHyphen)
  1006. {
  1007. fAfterFound = fFalse; /* After char of no importance for making break decision */
  1008. }
  1009. else if (!FRegularBreakableBeforeDobj(ptxtobjAfter))
  1010. {
  1011. fCanBreak = fFalse; /* Cannot break before non-standard dobj's,
  1012. compare with CheckBreakAtLastChar */
  1013. }
  1014. else if ((ptxtobjAfter->txtf & txtfGlyphBased) && iwchAfter > ptxtobjAfter->iwchFirst)
  1015. /* if iwchAfter is first character of Dnode, it is definitely not shaped together
  1016. with the previous char */
  1017. {
  1018. if (!FIwchLastInContext(pilsobj, iwchAfter - 1))
  1019. {
  1020. fCanBreak = fFalse;
  1021. /* Additional hack to handle case when Accented spaces are separated by spaces */
  1022. if (iwchAfter - 1 > iwchBefore + 1 && /* There are more spaces in between */
  1023. FIwchFirstInContext(pilsobj, iwchAfter - 1) )
  1024. {
  1025. fCanBreak = fTrue;
  1026. iwchAfter--;
  1027. }
  1028. }
  1029. }
  1030. }
  1031. else
  1032. {
  1033. if (brkkind == brkkindPrev)
  1034. /* patch for the cases when we break across spaces
  1035. at the end of text chunk during PrevBreak logic.
  1036. Problems are possible because trailing spaces could exceed RM,
  1037. and no information about following chunk was passed in.
  1038. */
  1039. {
  1040. BOOL fStoppedAfter;
  1041. Assert(fCanBreak);
  1042. Assert(plocchnk->clschnk > 0);
  1043. /* Check if there is Splat, or Hidden text producing fStopped after this chunk
  1044. In this case we must break after
  1045. (we will set fAfterFound and fBeforeFound to False to ensure it)
  1046. */
  1047. lserr = LsdnFStoppedAfterChunk(pilsobj->plsc,
  1048. ((PTXTOBJ)plocchnk->plschnk[plocchnk->clschnk-1].pdobj)->plsdnUpNode,
  1049. &fStoppedAfter);
  1050. if (lserr != lserrNone) return lserr;
  1051. if (fStoppedAfter)
  1052. {
  1053. Assert(fCanBreak);
  1054. Assert(!fAfterFound);
  1055. fBeforeFound = fFalse;
  1056. }
  1057. else
  1058. /* If there is no Splat, or Hidden text producing fStopped after this chunk
  1059. we should not break if next chunk returnd brkcondNever on the left side.
  1060. */
  1061. {
  1062. lserr = LsdnFCanBreakBeforeNextChunk(pilsobj->plsc,
  1063. ((PTXTOBJ)plocchnk->plschnk[plocchnk->clschnk-1].pdobj)->plsdnUpNode,
  1064. &fCanBreak);
  1065. if (lserr != lserrNone) return lserr;
  1066. }
  1067. }
  1068. else
  1069. {
  1070. Assert (brkkind == brkkindNext);
  1071. fCanBreak = fFalse; /* Do not break; let code at the ens of FindNextBreak set correct brkcond */
  1072. }
  1073. }
  1074. if (fBeforeFound)
  1075. {
  1076. ptxtobjBefore = (PTXTOBJ)plocchnk->plschnk[itxtobjBefore].pdobj;
  1077. Assert(ptxtobjBefore->txtkind != txtkindTab &&
  1078. ptxtobjBefore->txtkind != txtkindSpecSpace &&
  1079. ptxtobjBefore->txtkind != txtkindEOL);
  1080. if (ptxtobjBefore->txtkind == txtkindHardHyphen ||
  1081. ptxtobjBefore->txtkind == txtkindOptBreak ||
  1082. ptxtobjBefore->txtkind == txtkindNonReqHyphen)
  1083. {
  1084. fBeforeFound = fFalse; /* Before char of no importance for making break decision */
  1085. }
  1086. else if (ptxtobjBefore->txtkind == txtkindNonBreakSpace ||
  1087. ptxtobjBefore->txtkind == txtkindNonBreakHyphen ||
  1088. ptxtobjBefore->txtkind == txtkindOptNonBreak)
  1089. {
  1090. fCanBreak = fFalse; /* Cannot break after Non-Breaks */
  1091. }
  1092. }
  1093. if (fCanBreak)
  1094. {
  1095. if (fBeforeFound)
  1096. {
  1097. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plocchnk->plschnk[itxtobjBefore].plsrun,
  1098. plocchnk->plschnk[itxtobjBefore].cpFirst + (iwchBefore - ptxtobjBefore->iwchFirst),
  1099. pilsobj->pwchOrig[iwchBefore], &brkclsLeading, &brkclsJunk);
  1100. if (lserr != lserrNone) return lserr;
  1101. Assert(brkclsLeading < pilsobj->cBreakingClasses && brkclsJunk < pilsobj->cBreakingClasses);
  1102. if (brkclsLeading >= pilsobj->cBreakingClasses || brkclsJunk >= pilsobj->cBreakingClasses)
  1103. return lserrInvalidBreakingClass;
  1104. }
  1105. if (fAfterFound)
  1106. {
  1107. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plocchnk->plschnk[itxtobjAfter].plsrun,
  1108. plocchnk->plschnk[itxtobjAfter].cpFirst + (iwchAfter - ptxtobjAfter->iwchFirst),
  1109. pilsobj->pwchOrig[iwchAfter], &brkclsJunk, &brkclsFollowing);
  1110. if (lserr != lserrNone) return lserr;
  1111. Assert(brkclsJunk < pilsobj->cBreakingClasses && brkclsFollowing < pilsobj->cBreakingClasses);
  1112. if (brkclsJunk >= pilsobj->cBreakingClasses || brkclsFollowing >= pilsobj->cBreakingClasses)
  1113. return lserrInvalidBreakingClass;
  1114. }
  1115. if (fBeforeFound && fAfterFound)
  1116. {
  1117. fCanBreak = FCanBreakAcrossSpaces(pilsobj, brkclsLeading, brkclsFollowing);
  1118. }
  1119. else if (fBeforeFound && !fAfterFound)
  1120. {
  1121. lserr = (*pilsobj->plscbk->pfnCanBreakAfterChar)(pilsobj->pols, brkclsLeading, &brktxt);
  1122. if (lserr != lserrNone) return lserr;
  1123. fCanBreak = (brktxt != brkcondNever);
  1124. }
  1125. else if (!fBeforeFound && fAfterFound)
  1126. {
  1127. lserr = (*pilsobj->plscbk->pfnCanBreakBeforeChar)(pilsobj->pols, brkclsFollowing, &brktxt);
  1128. if (lserr != lserrNone) return lserr;
  1129. fCanBreak = (brktxt != brkcondNever);
  1130. }
  1131. }
  1132. }
  1133. if (!*pfBroken && fCanBreak)
  1134. {
  1135. FillPtboPbrkinf(plocchnk, itxtobjAfter, iwchAfter - 1, /*itxtobjBefore,*/ iwchBefore,
  1136. brkkind, &pbrkinf, ptbo);
  1137. *pfBroken = fTrue;
  1138. }
  1139. return lserrNone;
  1140. }
  1141. /* T R Y P R E V B R E A K R E G U L A R */
  1142. /*----------------------------------------------------------------------------
  1143. %%Function: TryPrevBreakRegular
  1144. %%Contact: sergeyge
  1145. Checks (and sets) for prev break inside regular dobj
  1146. ----------------------------------------------------------------------------*/
  1147. static LSERR TryPrevBreakRegular(PCLOCCHNK plocchnk, long itxtobj, long iwchSpace, long iwchCur,
  1148. BOOL* pfBroken, PBRKOUT ptbo)
  1149. {
  1150. LSERR lserr;
  1151. PTXTOBJ ptxtobj;
  1152. PILSOBJ pilsobj;
  1153. PLSRUN plsrun;
  1154. long iwchFirst;
  1155. BRKCLS brkclsFollowingCache;
  1156. BRKCLS brkclsLeading;
  1157. BRKCLS brkclsFollowing;
  1158. BREAKINFO* pbrkinf;
  1159. *pfBroken = fFalse;
  1160. if (iwchCur <= iwchSpace) return lserrNone;
  1161. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
  1162. pilsobj = ptxtobj->plnobj->pilsobj;
  1163. Assert(ptxtobj->txtkind == txtkindRegular ||
  1164. (ptxtobj->txtkind == txtkindSpecSpace && (pilsobj->grpf & fTxtWrapAllSpaces)));
  1165. Assert( pilsobj->grpf & fTxtApplyBreakingRules );
  1166. plsrun = plocchnk->plschnk[itxtobj].plsrun;
  1167. iwchFirst = ptxtobj->iwchFirst;
  1168. if (iwchSpace + 1 > iwchFirst)
  1169. iwchFirst = iwchSpace + 1;
  1170. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plsrun,
  1171. plocchnk->plschnk[itxtobj].cpFirst + (iwchCur - ptxtobj->iwchFirst),
  1172. pilsobj->pwchOrig[iwchCur], &brkclsLeading, &brkclsFollowingCache);
  1173. if (lserr != lserrNone) return lserr;
  1174. Assert(brkclsLeading < pilsobj->cBreakingClasses && brkclsFollowingCache < pilsobj->cBreakingClasses);
  1175. if (brkclsLeading >= pilsobj->cBreakingClasses || brkclsFollowingCache >= pilsobj->cBreakingClasses)
  1176. return lserrInvalidBreakingClass;
  1177. lserr = CheckBreakAtLastChar(plocchnk, brkclsLeading, iwchCur, itxtobj, pfBroken);
  1178. if (lserr != lserrNone) return lserr;
  1179. iwchCur--;
  1180. while (!*pfBroken && iwchCur >= iwchFirst)
  1181. {
  1182. brkclsFollowing = brkclsFollowingCache;
  1183. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plsrun,
  1184. plocchnk->plschnk[itxtobj].cpFirst + (iwchCur - ptxtobj->iwchFirst),
  1185. pilsobj->pwchOrig[iwchCur], &brkclsLeading, &brkclsFollowingCache);
  1186. if (lserr != lserrNone) return lserr;
  1187. Assert(brkclsLeading < pilsobj->cBreakingClasses && brkclsFollowingCache < pilsobj->cBreakingClasses);
  1188. if (brkclsLeading >= pilsobj->cBreakingClasses || brkclsFollowingCache >= pilsobj->cBreakingClasses)
  1189. return lserrInvalidBreakingClass;
  1190. *pfBroken = FCanBreak(pilsobj, brkclsLeading, brkclsFollowing) &&
  1191. (!(ptxtobj->txtf & txtfGlyphBased) || FIwchLastInContext(pilsobj, iwchCur));
  1192. iwchCur --;
  1193. }
  1194. if (*pfBroken)
  1195. {
  1196. lserr = FillPtboPbrkinf(plocchnk, itxtobj, iwchCur+1, /*itxtobj,*/ iwchCur+1,
  1197. brkkindPrev, &pbrkinf, ptbo);
  1198. if (lserr != lserrNone) return lserr;
  1199. /* fModWidthSpace can be at the last char here only iff fWrapAllSpaces;
  1200. if we touch balanced space here, the logic of GetMinCompressAmount should be rethinked!*/
  1201. if (pilsobj->pdurRight != NULL && pilsobj->pdurRight[iwchCur + 1] > 0 &&
  1202. !pilsobj->ptxtinf[iwchCur - 1].fModWidthSpace)
  1203. {
  1204. pbrkinf->u.normal.durFix = - pilsobj->pdurRight[iwchCur + 1];
  1205. ptbo->objdim.dur -= pilsobj->pdurRight[iwchCur + 1];
  1206. }
  1207. }
  1208. return lserrNone;
  1209. }
  1210. /* T R Y N E X T B R E A K R E G U L A R */
  1211. /*----------------------------------------------------------------------------
  1212. %%Function: TryNextBreakRegular
  1213. %%Contact: sergeyge
  1214. Checks (and sets) for next break inside regular dobj
  1215. ----------------------------------------------------------------------------*/
  1216. static LSERR TryNextBreakRegular(PCLOCCHNK plocchnk, long itxtobj, long iwchSpace, long iwchCur,
  1217. BOOL* pfBroken, PBRKOUT ptbo)
  1218. {
  1219. LSERR lserr;
  1220. PTXTOBJ ptxtobj;
  1221. PILSOBJ pilsobj;
  1222. PLSRUN plsrun;
  1223. long iwchLast;
  1224. BRKCLS brkclsLeadingCache;
  1225. BRKCLS brkclsLeading;
  1226. BRKCLS brkclsFollowing;
  1227. BRKCLS brkclsJunk;
  1228. BREAKINFO* pbrkinf;
  1229. *pfBroken = fFalse;
  1230. if (iwchCur >= iwchSpace) return lserrNone;
  1231. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
  1232. pilsobj = ptxtobj->plnobj->pilsobj;
  1233. Assert(ptxtobj->txtkind == txtkindRegular ||
  1234. (ptxtobj->txtkind == txtkindSpecSpace && (pilsobj->grpf & fTxtWrapAllSpaces)));
  1235. Assert(pilsobj->grpf & fTxtApplyBreakingRules);
  1236. plsrun = plocchnk->plschnk[itxtobj].plsrun;
  1237. iwchLast = ptxtobj->iwchLim - 1;
  1238. /* The last possibility for break is BEFORE LAST CHAR before space */
  1239. if (iwchSpace - 1 < iwchLast)
  1240. iwchLast = iwchSpace - 1;
  1241. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plsrun,
  1242. plocchnk->plschnk[itxtobj].cpFirst + (iwchCur - ptxtobj->iwchFirst),
  1243. pilsobj->pwchOrig[iwchCur], &brkclsLeadingCache, &brkclsJunk);
  1244. if (lserr != lserrNone) return lserr;
  1245. Assert(brkclsLeadingCache < pilsobj->cBreakingClasses && brkclsJunk < pilsobj->cBreakingClasses);
  1246. if (brkclsLeadingCache >= pilsobj->cBreakingClasses || brkclsJunk >= pilsobj->cBreakingClasses)
  1247. return lserrInvalidBreakingClass;
  1248. while (!*pfBroken && iwchCur < iwchLast)
  1249. {
  1250. brkclsLeading = brkclsLeadingCache;
  1251. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plsrun,
  1252. plocchnk->plschnk[itxtobj].cpFirst + (iwchCur + 1 - ptxtobj->iwchFirst),
  1253. pilsobj->pwchOrig[iwchCur + 1], &brkclsLeadingCache, &brkclsFollowing);
  1254. if (lserr != lserrNone) return lserr;
  1255. Assert(brkclsLeadingCache < pilsobj->cBreakingClasses && brkclsFollowing < pilsobj->cBreakingClasses);
  1256. if (brkclsLeadingCache >= pilsobj->cBreakingClasses || brkclsFollowing >= pilsobj->cBreakingClasses)
  1257. return lserrInvalidBreakingClass;
  1258. *pfBroken = FCanBreak(pilsobj, brkclsLeading, brkclsFollowing) &&
  1259. (!(ptxtobj->txtf & txtfGlyphBased) || FIwchLastInContext(pilsobj, iwchCur));
  1260. iwchCur++;
  1261. }
  1262. if (!*pfBroken && iwchCur == iwchLast && iwchLast < iwchSpace - 1)
  1263. {
  1264. lserr = CheckBreakAtLastChar(plocchnk, brkclsLeadingCache, iwchLast, itxtobj, pfBroken);
  1265. iwchCur++;
  1266. if (lserr != lserrNone) return lserr;
  1267. }
  1268. if (*pfBroken)
  1269. {
  1270. Assert (iwchCur >= 1);
  1271. FillPtboPbrkinf(plocchnk, itxtobj, iwchCur-1, /*itxtobj,*/ iwchCur-1, brkkindNext, &pbrkinf, ptbo);
  1272. /* fModWidthSpace can be at the last char here only iff fWrapAllSpaces;
  1273. if we touch balanced space here, the logic of GetMinCompressAmount should be rethinked!*/
  1274. if (pilsobj->pdurRight != NULL && pilsobj->pdurRight[iwchCur - 1] != 0 &&
  1275. !pilsobj->ptxtinf[iwchCur - 1].fModWidthSpace)
  1276. {
  1277. pbrkinf->u.normal.durFix = - pilsobj->pdurRight[iwchCur - 1];
  1278. ptbo->objdim.dur -= pilsobj->pdurRight[iwchCur - 1];
  1279. }
  1280. }
  1281. return lserrNone;
  1282. }
  1283. /* C H E C K B R E A K A T L A S T C H A R */
  1284. /*----------------------------------------------------------------------------
  1285. %%Function: CheckBreakAtLastChar
  1286. %%Contact: sergeyge
  1287. Checks (and sets) for prev break inside regular dobj
  1288. ----------------------------------------------------------------------------*/
  1289. static LSERR CheckBreakAtLastChar(PCLOCCHNK plocchnk, BRKCLS brkclsLeading, long iwch, long itxtobj, BOOL* pfBroken)
  1290. {
  1291. LSERR lserr;
  1292. PTXTOBJ ptxtobj;
  1293. PILSOBJ pilsobj;
  1294. long itxtobjAfter;
  1295. long iwchAfter;
  1296. BRKCLS brkclsFollowing;
  1297. BRKCLS brkclsJunk;
  1298. /* BRKTXTCOND brktxt;*/
  1299. *pfBroken = fFalse;
  1300. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
  1301. pilsobj = ptxtobj->plnobj->pilsobj;
  1302. if ((ptxtobj->txtf & txtfGlyphBased) && !FIwchLastInContext(pilsobj, iwch))
  1303. return lserrNone;
  1304. pilsobj = ptxtobj->plnobj->pilsobj;
  1305. if (iwch < ptxtobj->iwchLim - 1)
  1306. {
  1307. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plocchnk->plschnk[itxtobj].plsrun,
  1308. plocchnk->plschnk[itxtobj].cpFirst + (iwch + 1 - ptxtobj->iwchFirst),
  1309. pilsobj->pwchOrig[iwch + 1], &brkclsJunk, &brkclsFollowing);
  1310. if (lserr != lserrNone) return lserr;
  1311. Assert(brkclsJunk < pilsobj->cBreakingClasses && brkclsFollowing < pilsobj->cBreakingClasses);
  1312. if (brkclsJunk >= pilsobj->cBreakingClasses || brkclsFollowing >= pilsobj->cBreakingClasses)
  1313. return lserrInvalidBreakingClass;
  1314. *pfBroken = FCanBreak(pilsobj, brkclsLeading, brkclsFollowing);
  1315. }
  1316. else if (FindNextChar(plocchnk->plschnk, plocchnk->clschnk, itxtobj, iwch,
  1317. &itxtobjAfter, &iwchAfter))
  1318. {
  1319. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobjAfter].pdobj;
  1320. if (FRegularBreakableBeforeDobj(ptxtobj))
  1321. {
  1322. Assert(ptxtobj->txtkind != txtkindSpecSpace || (pilsobj->grpf & fTxtWrapAllSpaces) );
  1323. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plocchnk->plschnk[itxtobjAfter].plsrun,
  1324. plocchnk->plschnk[itxtobjAfter].cpFirst + (iwchAfter - ptxtobj->iwchFirst),
  1325. pilsobj->pwchOrig[iwchAfter], &brkclsJunk, &brkclsFollowing);
  1326. if (lserr != lserrNone) return lserr;
  1327. Assert(brkclsJunk < pilsobj->cBreakingClasses && brkclsFollowing < pilsobj->cBreakingClasses);
  1328. if (brkclsJunk >= pilsobj->cBreakingClasses || brkclsFollowing >= pilsobj->cBreakingClasses)
  1329. return lserrInvalidBreakingClass;
  1330. *pfBroken = FCanBreak(pilsobj, brkclsLeading, brkclsFollowing);
  1331. }
  1332. }
  1333. /* Manager takes care of the ELSE situation; */
  1334. return lserrNone;
  1335. }
  1336. /* T R Y B R E A K A T H A R D H Y P H E N */
  1337. /*----------------------------------------------------------------------------
  1338. %%Function: TryBreakAtHardHyphen
  1339. %%Contact: sergeyge
  1340. Realizes break at hard hyphen
  1341. ----------------------------------------------------------------------------*/
  1342. static LSERR TryBreakAtHardHyphen(PCLOCCHNK plocchnk, long itxtobj, long iwch, BRKKIND brkkind,
  1343. BOOL* pfBroken, PBRKOUT ptbo)
  1344. {
  1345. LSERR lserr;
  1346. BREAKINFO* pbrkinf;
  1347. Assert(((PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj)->txtkind == txtkindHardHyphen);
  1348. Assert(!(((PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj)->txtf & txtfGlyphBased));
  1349. lserr = FillPtboPbrkinf(plocchnk, itxtobj, iwch, /*itxtobj,*/ iwch, brkkind, &pbrkinf, ptbo);
  1350. if (lserr != lserrNone) return lserr;
  1351. *pfBroken = fTrue;
  1352. return lserrNone;
  1353. }
  1354. /* T R Y B R E A K A T O P T B R E A K */
  1355. /*----------------------------------------------------------------------------
  1356. %%Function: TryBreakAtOptBreak
  1357. %%Contact: sergeyge
  1358. Realizes break at OptBreak
  1359. ----------------------------------------------------------------------------*/
  1360. static LSERR TryBreakAtOptBreak(PCLOCCHNK plocchnk, long itxtobj, BRKKIND brkkind,
  1361. BOOL* pfBroken, PBRKOUT ptbo)
  1362. {
  1363. LSERR lserr;
  1364. PTXTOBJ ptxtobj;
  1365. BREAKINFO* pbrkinf;
  1366. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
  1367. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  1368. Assert(ptxtobj->txtkind == txtkindOptBreak);
  1369. Assert(ptxtobj->iwchLim == ptxtobj->iwchFirst + 1 && (ptxtobj->txtf & txtfVisi)||
  1370. ptxtobj->iwchLim == ptxtobj->iwchFirst);
  1371. lserr = FillPtboPbrkinf(plocchnk, itxtobj, ptxtobj->iwchLim-1, /*itxtobj,*/ ptxtobj->iwchLim-1,
  1372. brkkind, &pbrkinf, ptbo);
  1373. if (lserr != lserrNone) return lserr;
  1374. ptbo->posichnk.dcp = 1;
  1375. pbrkinf->dcp = 1;
  1376. pbrkinf->brkt = brktOptBreak;
  1377. *pfBroken = fTrue;
  1378. return lserrNone;
  1379. }
  1380. /* T R Y B R E A K A T E O L */
  1381. /*----------------------------------------------------------------------------
  1382. %%Function: TryBreakAtEOL
  1383. %%Contact: sergeyge
  1384. Realizes break at EOP/EOL
  1385. ----------------------------------------------------------------------------*/
  1386. static LSERR TryBreakAtEOL(PCLOCCHNK plocchnk, long itxtobj, BRKKIND brkkind, BOOL* pfBroken, PBRKOUT ptbo)
  1387. {
  1388. LSERR lserr;
  1389. PTXTOBJ ptxtobj;
  1390. long itxtobjBefore;
  1391. long iwchBefore;
  1392. BREAKINFO* pbrkinf;
  1393. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
  1394. Assert(ptxtobj->txtkind == txtkindEOL);
  1395. Assert(ptxtobj->iwchLim == ptxtobj->iwchFirst + 1);
  1396. FindNonSpaceBefore(plocchnk->plschnk, itxtobj, ptxtobj->iwchFirst, &itxtobjBefore, &iwchBefore);
  1397. lserr = FillPtboPbrkinf(plocchnk, itxtobj, ptxtobj->iwchFirst, /*itxtobjBefore,*/ iwchBefore,
  1398. brkkind, &pbrkinf, ptbo);
  1399. if (lserr != lserrNone) return lserr;
  1400. *pfBroken = fTrue;
  1401. return lserrNone;
  1402. }
  1403. /* T R Y B R E A K A T N O N R E Q H Y P H E N */
  1404. /*----------------------------------------------------------------------------
  1405. %%Function: TryBreakAtNonReqHyphen
  1406. %%Contact: sergeyge
  1407. Realizes break at NonReqHyphen.
  1408. ----------------------------------------------------------------------------*/
  1409. static LSERR TryBreakAtNonReqHyphen(PCLOCCHNK plocchnk, long itxtobj, BRKKIND brkkind,
  1410. BOOL* pfBroken, PBRKOUT ptbo)
  1411. {
  1412. LSERR lserr;
  1413. PILSOBJ pilsobj;
  1414. PLNOBJ plnobj;
  1415. PTXTOBJ ptxtobj;
  1416. YSRINF ysrinf;
  1417. HYPHOUT hyphout;
  1418. BREAKINFO* pbrkinf;
  1419. LSCP cpMac;
  1420. DWORD kysr;
  1421. WCHAR wchYsr;
  1422. long itxtobjPrev;
  1423. long itxtobjPrevPrev;
  1424. BOOL fSuccessful;
  1425. long durBorder;
  1426. long i;
  1427. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
  1428. plnobj = ptxtobj->plnobj;
  1429. pilsobj = plnobj->pilsobj;
  1430. cpMac = plocchnk->plschnk[itxtobj].cpFirst;
  1431. Assert( ptxtobj->txtkind == txtkindNonReqHyphen);
  1432. Assert(!(ptxtobj->txtf & txtfGlyphBased));
  1433. lserr = (*pilsobj->plscbk->pfnGetHyphenInfo)(pilsobj->pols, plocchnk->plschnk[itxtobj].plsrun, &kysr, &wchYsr);
  1434. if (lserr != lserrNone) return lserr;
  1435. if (kysr == kysrNil)
  1436. kysr = kysrNormal;
  1437. ysrinf.wchYsr = wchYsr;
  1438. ysrinf.kysr = (WORD)kysr;
  1439. itxtobjPrev = ichnkOutside;
  1440. for (i=itxtobj; i >= 0 && plocchnk->plschnk[i].cpFirst > cpMac - 1; i--);
  1441. if (i >= 0)
  1442. itxtobjPrev = i;
  1443. itxtobjPrevPrev = ichnkOutside;
  1444. for (i=itxtobj; i >= 0 && plocchnk->plschnk[i].cpFirst > cpMac - 2; i--);
  1445. if (i >= 0)
  1446. itxtobjPrevPrev = i;
  1447. lserr = ProcessYsr(plocchnk, itxtobj, - 1, itxtobjPrev, itxtobjPrevPrev, ysrinf, &fSuccessful, &hyphout);
  1448. if (lserr != lserrNone) return lserr;
  1449. if (fSuccessful)
  1450. {
  1451. durBorder = 0;
  1452. if (plocchnk->plschnk[itxtobj].plschp->fBorder)
  1453. {
  1454. lserr = LsdnGetBorderAfter(pilsobj->plsc, ptxtobj->plsdnUpNode, &durBorder);
  1455. Assert(lserr == lserrNone);
  1456. }
  1457. if (plocchnk->ppointUvLoc[itxtobj].u + hyphout.durChangeTotal + durBorder <=
  1458. plocchnk->lsfgi.urColumnMax || brkkind == brkkindNext)
  1459. {
  1460. *pfBroken = fTrue;
  1461. ptbo->fSuccessful = fTrue;
  1462. ptbo->posichnk.ichnk = itxtobj;
  1463. ptbo->posichnk.dcp = 1;
  1464. lserr = LsdnGetObjDim(pilsobj->plsc, ptxtobj->plsdnUpNode, &ptbo->objdim);
  1465. if (lserr != lserrNone) return lserr;
  1466. ptbo->objdim.dur += hyphout.durChangeTotal;
  1467. lserr = GetPbrkinf(pilsobj, plocchnk->plschnk[itxtobj].pdobj, brkkind, &pbrkinf);
  1468. if (lserr != lserrNone) return lserr;
  1469. pbrkinf->pdobj = plocchnk->plschnk[itxtobj].pdobj;
  1470. pbrkinf->brkkind = brkkind;
  1471. pbrkinf->dcp = 1;
  1472. pbrkinf->brkt = brktNonReq;
  1473. pbrkinf->u.nonreq.durHyphen = hyphout.durHyphen;
  1474. if (pilsobj->grpf & fTxtVisiCondHyphens)
  1475. {
  1476. pbrkinf->u.nonreq.wchHyphenPres = pilsobj->wchVisiNonReqHyphen;
  1477. pbrkinf->u.nonreq.dupHyphen = plnobj->pdup[ptxtobj->iwchFirst];
  1478. }
  1479. else
  1480. {
  1481. pbrkinf->u.nonreq.wchHyphenPres = pilsobj->wchHyphen;
  1482. pbrkinf->u.nonreq.dupHyphen = hyphout.dupHyphen;
  1483. }
  1484. pbrkinf->u.nonreq.iwchLim = hyphout.iwchLim;
  1485. pbrkinf->u.nonreq.dwchYsr = hyphout.dwchYsr - 1;
  1486. pbrkinf->u.nonreq.durPrev = hyphout.durPrev;
  1487. pbrkinf->u.nonreq.dupPrev = hyphout.dupPrev;
  1488. pbrkinf->u.nonreq.durPrevPrev = hyphout.durPrevPrev;
  1489. pbrkinf->u.nonreq.dupPrevPrev = hyphout.dupPrevPrev;
  1490. pbrkinf->u.nonreq.ddurDnodePrev = hyphout.ddurDnodePrev;
  1491. pbrkinf->u.nonreq.ddurDnodePrevPrev = hyphout.ddurDnodePrevPrev;
  1492. pbrkinf->u.nonreq.ddurTotal = hyphout.durChangeTotal;
  1493. pbrkinf->u.nonreq.wchPrev = hyphout.wchPrev;
  1494. pbrkinf->u.nonreq.wchPrevPrev = hyphout.wchPrevPrev;
  1495. pbrkinf->u.nonreq.gindPrev = hyphout.gindPrev;
  1496. pbrkinf->u.nonreq.gindPrevPrev = hyphout.gindPrevPrev;
  1497. pbrkinf->u.nonreq.igindPrev = hyphout.igindPrev;
  1498. pbrkinf->u.nonreq.igindPrevPrev = hyphout.igindPrevPrev;
  1499. }
  1500. }
  1501. return lserrNone;
  1502. }
  1503. /* T R Y B R E A K A F T E R C H U N K */
  1504. /*----------------------------------------------------------------------------
  1505. %%Function: TryBreakAfterChunk
  1506. %%Contact: sergeyge
  1507. ----------------------------------------------------------------------------*/
  1508. static LSERR TryBreakAfterChunk(PCLOCCHNK plocchnk, BRKCOND brkcond, BOOL* pfBroken, PBRKOUT ptbo)
  1509. {
  1510. LSERR lserr;
  1511. PILSOBJ pilsobj;
  1512. PTXTOBJ ptxtobjLast;
  1513. long itxtobjLast;
  1514. long iwchLast;
  1515. long itxtobjBefore;
  1516. long iwchBefore;
  1517. BOOL fNonSpaceFound;
  1518. BRKCOND brkcondTemp;
  1519. BREAKINFO* pbrkinf;
  1520. *pfBroken = fFalse;
  1521. itxtobjLast = plocchnk->clschnk-1;
  1522. ptxtobjLast = (PTXTOBJ)plocchnk->plschnk[itxtobjLast].pdobj;
  1523. pilsobj = ptxtobjLast->plnobj->pilsobj;
  1524. iwchLast = ptxtobjLast->iwchLim - 1;
  1525. Assert(ptxtobjLast->txtkind != txtkindTab &&
  1526. ptxtobjLast->txtkind != txtkindEOL);
  1527. switch (ptxtobjLast->txtkind)
  1528. {
  1529. case txtkindRegular:
  1530. case txtkindSpecSpace:
  1531. case txtkindYsrChar:
  1532. fNonSpaceFound = FindNonSpaceBefore(plocchnk->plschnk, itxtobjLast, iwchLast,
  1533. &itxtobjBefore, &iwchBefore);
  1534. if (pilsobj->grpf & fTxtApplyBreakingRules)
  1535. {
  1536. lserr = CanBreakAfterText(plocchnk, fNonSpaceFound, itxtobjBefore, iwchBefore, &brkcondTemp);
  1537. if (lserr != lserrNone) return lserr;
  1538. if (iwchBefore != iwchLast && brkcondTemp == brkcondCan)
  1539. brkcondTemp = brkcondPlease;
  1540. if (brkcond == brkcondPlease && brkcondTemp != brkcondNever ||
  1541. brkcond == brkcondCan && brkcondTemp == brkcondPlease)
  1542. {
  1543. *pfBroken = fTrue;
  1544. lserr = FillPtboPbrkinf(plocchnk, itxtobjLast, iwchLast, /*itxtobjBefore,*/ iwchBefore,
  1545. brkkindPrev, &pbrkinf, ptbo);
  1546. if (lserr != lserrNone) return lserr;
  1547. }
  1548. }
  1549. else
  1550. {
  1551. Assert(iwchLast >= ptxtobjLast->iwchFirst);
  1552. if (brkcond == brkcondPlease ||
  1553. brkcond == brkcondCan && iwchLast != iwchBefore)
  1554. {
  1555. *pfBroken = fTrue;
  1556. lserr = FillPtboPbrkinf(plocchnk, itxtobjLast, iwchLast, /*itxtobjBefore,*/ iwchBefore,
  1557. brkkindPrev, &pbrkinf, ptbo);
  1558. if (lserr != lserrNone) return lserr;
  1559. }
  1560. }
  1561. break;
  1562. case txtkindNonBreakSpace:
  1563. case txtkindNonBreakHyphen:
  1564. case txtkindOptNonBreak:
  1565. break;
  1566. case txtkindHardHyphen:
  1567. lserr = TryBreakAtHardHyphen(plocchnk, itxtobjLast, iwchLast, brkkindPrev, pfBroken, ptbo);
  1568. if (lserr != lserrNone) return lserr;
  1569. break;
  1570. case txtkindOptBreak:
  1571. lserr = TryBreakAtOptBreak(plocchnk, itxtobjLast, brkkindPrev, pfBroken, ptbo);
  1572. if (lserr != lserrNone) return lserr;
  1573. break;
  1574. case txtkindNonReqHyphen:
  1575. lserr = TryBreakAtNonReqHyphen(plocchnk, itxtobjLast, brkkindPrev, pfBroken, ptbo);
  1576. if (lserr != lserrNone) return lserr;
  1577. break;
  1578. }
  1579. return lserrNone;
  1580. }
  1581. /* T R Y B R E A K B E F O R E C H U N K */
  1582. /*----------------------------------------------------------------------------
  1583. %%Function: TryBreakBeforeChunk
  1584. %%Contact: sergeyge
  1585. ----------------------------------------------------------------------------*/
  1586. static LSERR TryBreakBeforeChunk(PCLOCCHNK plocchnk, BRKCOND brkcond, BOOL* pfBroken, PBRKOUT ptbo)
  1587. {
  1588. LSERR lserr;
  1589. PILSOBJ pilsobj;
  1590. BRKCOND brkcondTemp;
  1591. pilsobj = ((PTXTOBJ)plocchnk->plschnk[0].pdobj)->plnobj->pilsobj;
  1592. *pfBroken = fFalse;
  1593. if (!(pilsobj->grpf & fTxtApplyBreakingRules))
  1594. *pfBroken = (brkcond == brkcondPlease);
  1595. else
  1596. {
  1597. lserr = CanBreakBeforeText(plocchnk, &brkcondTemp);
  1598. if (lserr != lserrNone) return lserr;
  1599. *pfBroken = (brkcond == brkcondPlease && brkcondTemp != brkcondNever ||
  1600. brkcond == brkcondCan && brkcondTemp == brkcondPlease);
  1601. }
  1602. if (*pfBroken)
  1603. {
  1604. memset(ptbo, 0, sizeof (*ptbo));
  1605. ptbo->fSuccessful = fTrue;
  1606. return lserrNone;
  1607. }
  1608. return lserrNone;
  1609. }
  1610. /* C A N B R E A K B E F O R E T E X T */
  1611. /*----------------------------------------------------------------------------
  1612. %%Function: CanBreakBeforeText
  1613. %%Contact: sergeyge
  1614. Checks if break before text chunk is possible.
  1615. ----------------------------------------------------------------------------*/
  1616. static LSERR CanBreakBeforeText(PCLOCCHNK plocchnk, BRKCOND* pbrktxt)
  1617. {
  1618. LSERR lserr;
  1619. PILSOBJ pilsobj;
  1620. PTXTOBJ ptxtobj;
  1621. WCHAR wch;
  1622. BRKCLS brkclsBefore;
  1623. BRKCLS brkclsJunk;
  1624. Assert(plocchnk->clschnk > 0);
  1625. ptxtobj = (PTXTOBJ)plocchnk->plschnk[0].pdobj;
  1626. pilsobj = ptxtobj->plnobj->pilsobj;
  1627. if (plocchnk->lsfgi.fFirstOnLine || !FRegularBreakableBeforeDobj(ptxtobj))
  1628. {
  1629. *pbrktxt = brkcondNever;
  1630. }
  1631. else
  1632. {
  1633. wch = pilsobj->pwchOrig[ptxtobj->iwchFirst];
  1634. if ( (wch == pilsobj->wchSpace || ptxtobj->txtkind == txtkindSpecSpace) &&
  1635. !(pilsobj->grpf & fTxtWrapAllSpaces) )
  1636. {
  1637. *pbrktxt = brkcondNever;
  1638. }
  1639. else
  1640. {
  1641. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols, plocchnk->plschnk[0].plsrun,
  1642. plocchnk->plschnk[0].cpFirst, wch, &brkclsJunk, &brkclsBefore);
  1643. if (lserr != lserrNone) return lserr;
  1644. lserr = (*pilsobj->plscbk->pfnCanBreakBeforeChar)(pilsobj->pols, brkclsBefore, pbrktxt);
  1645. if (lserr != lserrNone) return lserr;
  1646. }
  1647. }
  1648. return lserrNone;
  1649. }
  1650. /* C A N B R E A K A F T E R T E X T */
  1651. /*----------------------------------------------------------------------------
  1652. %%Function: CanBreakAfterText
  1653. %%Contact: sergeyge
  1654. Checks if break after text chunk is possible.
  1655. ----------------------------------------------------------------------------*/
  1656. static LSERR CanBreakAfterText(PCLOCCHNK plocchnk, BOOL fNonSpaceFound, long itxtobjBefore,
  1657. long iwchBefore, BRKCOND* pbrktxt)
  1658. {
  1659. LSERR lserr;
  1660. PILSOBJ pilsobj;
  1661. PTXTOBJ ptxtobj;
  1662. BRKCLS brkclsAfter;
  1663. BRKCLS brkclsJunk;
  1664. if (fNonSpaceFound)
  1665. {
  1666. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobjBefore].pdobj;
  1667. pilsobj = ptxtobj->plnobj->pilsobj;
  1668. Assert(ptxtobj->txtkind != txtkindTab &&
  1669. ptxtobj->txtkind != txtkindSpecSpace &&
  1670. ptxtobj->txtkind != txtkindEOL);
  1671. if (ptxtobj->txtkind == txtkindHardHyphen ||
  1672. ptxtobj->txtkind == txtkindOptBreak ||
  1673. ptxtobj->txtkind == txtkindNonReqHyphen)
  1674. {
  1675. *pbrktxt = brkcondPlease;
  1676. }
  1677. else if (ptxtobj->txtkind == txtkindNonBreakSpace ||
  1678. ptxtobj->txtkind == txtkindNonBreakHyphen ||
  1679. ptxtobj->txtkind == txtkindOptNonBreak)
  1680. {
  1681. *pbrktxt = brkcondNever;
  1682. }
  1683. else
  1684. {
  1685. Assert(ptxtobj->txtkind == txtkindRegular ||
  1686. ptxtobj->txtkind == txtkindYsrChar);
  1687. lserr =(*pilsobj->plscbk->pfnGetBreakingClasses)(pilsobj->pols,
  1688. plocchnk->plschnk[itxtobjBefore].plsrun,
  1689. plocchnk->plschnk[itxtobjBefore].cpFirst + (iwchBefore - ptxtobj->iwchFirst),
  1690. pilsobj->pwchOrig[iwchBefore], &brkclsAfter, &brkclsJunk);
  1691. if (lserr != lserrNone) return lserr;
  1692. lserr = (*pilsobj->plscbk->pfnCanBreakAfterChar)(pilsobj->pols, brkclsAfter, pbrktxt);
  1693. if (lserr != lserrNone) return lserr;
  1694. }
  1695. }
  1696. else
  1697. {
  1698. /* REVIEW sergeyge: check if it is correct */
  1699. *pbrktxt = brkcondPlease;
  1700. // *pbrktxt = brkcondNever;
  1701. }
  1702. return lserrNone;
  1703. }
  1704. /* F I L L P T B O P B R K I N F */
  1705. /*----------------------------------------------------------------------------
  1706. %%Function: FillPtboPbrkinf
  1707. %%Contact: sergeyge
  1708. Prepares output of the breaking procedure
  1709. ----------------------------------------------------------------------------*/
  1710. static LSERR FillPtboPbrkinf(PCLOCCHNK plocchnk, long itxtobj, long iwch,
  1711. /* long itxtobjBefore,*/ long iwchBefore, BRKKIND brkkind,
  1712. BREAKINFO** ppbrkinf, PBRKOUT ptbo)
  1713. {
  1714. LSERR lserr;
  1715. PILSOBJ pilsobj;
  1716. PTXTOBJ ptxtobj;
  1717. long dwchBreak;
  1718. long igindLim;
  1719. long dur;
  1720. ptxtobj = (PTXTOBJ)plocchnk->plschnk[itxtobj].pdobj;
  1721. pilsobj = ptxtobj->plnobj->pilsobj;
  1722. dwchBreak = iwch - ptxtobj->iwchFirst + 1;
  1723. igindLim = 0;
  1724. if (ptxtobj->txtf & txtfGlyphBased)
  1725. {
  1726. igindLim = IgindFirstFromIwch(ptxtobj, ptxtobj->iwchFirst + dwchBreak);
  1727. lserr = CalcPartWidthsGlyphs(ptxtobj, dwchBreak, &ptbo->objdim, &dur);
  1728. }
  1729. else
  1730. lserr = CalcPartWidths(ptxtobj, dwchBreak, &ptbo->objdim, &dur);
  1731. if (lserr != lserrNone) return lserr;
  1732. ptbo->fSuccessful = fTrue;
  1733. ptbo->objdim.dur = dur;
  1734. ptbo->posichnk.ichnk = itxtobj;
  1735. ptbo->posichnk.dcp = dwchBreak;
  1736. if (iwchBefore < ptxtobj->iwchFirst)
  1737. {
  1738. if (!(pilsobj->grpf & fTxtSpacesInfluenceHeight))
  1739. {
  1740. ptbo->objdim.heightsRef.dvMultiLineHeight = dvHeightIgnore;
  1741. ptbo->objdim.heightsPres.dvMultiLineHeight = dvHeightIgnore;
  1742. }
  1743. }
  1744. lserr = GetPbrkinf(pilsobj, (PDOBJ)ptxtobj, brkkind, ppbrkinf);
  1745. if (lserr != lserrNone) return lserr;
  1746. (*ppbrkinf)->pdobj = (PDOBJ)ptxtobj;
  1747. (*ppbrkinf)->brkkind = brkkind;
  1748. (*ppbrkinf)->dcp = (LSDCP)dwchBreak;
  1749. (*ppbrkinf)->u.normal.igindLim = igindLim;
  1750. Assert((*ppbrkinf)->brkt == brktNormal);
  1751. Assert((*ppbrkinf)->u.normal.durFix == 0);
  1752. return lserrNone;
  1753. }