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.

2255 lines
73 KiB

  1. #include "lsmem.h" /* memset() */
  2. #include "lsidefs.h"
  3. #include "chnutils.h"
  4. #include "iobj.h"
  5. #include "dninfo.h"
  6. #include "locchnk.h"
  7. #include "posichnk.h"
  8. #include "plschcon.h"
  9. #include "lschcon.h"
  10. #include "lscbk.h"
  11. #include "limqmem.h"
  12. #include "lstext.h"
  13. #ifdef DEBUG
  14. #define DebugMemset(a,b,c) if ((a) != NULL) memset(a,b,c); else
  15. #else
  16. #define DebugMemset(a,b,c) (void)(0)
  17. #endif
  18. static LSERR SetChunkArraysSize(PLSCHUNKCONTEXT, DWORD);
  19. static LSERR IncreaseChunkArrays(PLSCHUNKCONTEXT);
  20. static LSERR IncreaseGroupChunkNonTextArrays(PLSCHUNKCONTEXT plschunkcontext);
  21. static LSERR ConvertChunkToGroupChunk(GRCHUNKEXT*, LSCP);
  22. static void LocateChunk(PLSCHUNKCONTEXT plschnukcontext,/* IN: LS chunk context */
  23. PLSDNODE plsdn, /* IN: dnode to collect chunk arround */
  24. LSTFLOW lstflow, /* IN: text flow */
  25. POINTUV* ppoint); /* IN: position of dnode */
  26. static LSERR FExpandBeforeNonTextObject(GRCHUNKEXT* pgrchunkext, DWORD cTextBeforePrevioustNonText,
  27. BOOL* pfExpand);
  28. static LSERR FExpandAfterNonTextObject(GRCHUNKEXT* pgrchunkext, DWORD cTextBeforeLastNonText,
  29. BOOL* pfExpand);
  30. typedef struct groupchunkiterator
  31. {
  32. COLLECTSUBLINES Purpose; /* what sublines to take from a complex object */
  33. PLSDNODE plsdnFirst; /* dnode from which we started collecting */
  34. PLSDNODE plsdnStart; /* dnode where to start search for next, if NULL then
  35. use plsdnFirst as first opportunity */
  36. LSCP cpLim; /* boundary for group chunk if we go forward */
  37. BOOL fForward; /* direction of traversing is forward otherwise it's backward*/
  38. }
  39. GROUPCHUNKITERATOR;
  40. static void CreateGroupChunkIterator(
  41. GROUPCHUNKITERATOR* pgroupchunkiterator, /* handler for iterator */
  42. COLLECTSUBLINES Purpose, /* what sublines to take from a complex object */
  43. PLSDNODE plsdnFirst, /* dnode from which we started collecting */
  44. LSCP cpLim, /* boundary for group chunk if we go forward */
  45. BOOL fForward); /* direction of traversing is forward otherwise it's backward*/
  46. static void DestroyGroupChunkIterator(
  47. GROUPCHUNKITERATOR* pgroupchunkiterator); /* handler for iterator */
  48. static PLSDNODE ContinueGroupChunk(
  49. GROUPCHUNKITERATOR* pgroupchunkiterator, /* handler for iterator */
  50. BOOL* pfSuccessful); /* OUT: do we find dnode */
  51. static PLSDNODE GetNextDnodeInGroupChunk(
  52. GROUPCHUNKITERATOR* pgroupchunkiterator, /* handler for iterator */
  53. BOOL* pfSuccessful); /* OUT: do we find dnode */
  54. #define LschnkeFromDnode(plschnke, plsdn) \
  55. (plschnke)->cpFirst = plsdn->cpFirst; \
  56. (plschnke)->dcp = (plsdn)->dcp; \
  57. (plschnke)->plschp = &((plsdn)->u.real.lschp); \
  58. (plschnke)->plsrun = (plsdn)->u.real.plsrun; \
  59. (plschnke)->pdobj = (plsdn)->u.real.pdobj;
  60. #define FIsGroupChunkBoundary(plsdn, cpLim, cpBase) \
  61. (FIsOutOfBoundary((plsdn), (cpLim)) \
  62. ||(FIsDnodePen(plsdn) && (!(plsdn)->fAdvancedPen)) \
  63. || ((plsdn)->fTab) \
  64. || (((cpBase) >= 0) ? ((plsdn)->cpFirst < 0) : ((plsdn)->cpFirst >= 0)))
  65. /* last check verifies that we are not crossing boundaries of autonumber */
  66. #define FIsGroupChunkStartBoundary(plsdn, cpBase) \
  67. (((plsdn) == NULL) \
  68. ||(FIsDnodePen(plsdn) && (!(plsdn)->fAdvancedPen)) \
  69. || ((plsdn)->fTab) \
  70. || (((cpBase) >= 0) ? ((plsdn)->cpFirst < 0) : ((plsdn)->cpFirst >= 0)))
  71. /* last check verifies that we are not crossing boundaries of autonumber */
  72. #define FIsGrchnkExtValid(plschunkcontext, pgrchunkext) \
  73. (((plschunkcontext) == (pgrchunkext)->plschunkcontext) &&\
  74. ((pgrchunkext)->lsgrchnk.plschnk == (plschunkcontext)->locchnkCurrent.plschnk) &&\
  75. ((pgrchunkext)->lsgrchnk.pcont == (plschunkcontext)->pcont) &&\
  76. ((pgrchunkext)->pplsdnNonText == (plschunkcontext)->pplsdnNonText) &&\
  77. ((pgrchunkext)->pfNonTextExpandAfter == (plschunkcontext)->pfNonTextExpandAfter) \
  78. )
  79. #define FDnodeInsideSubline(plssubl, plsdn) \
  80. (FDnodeBeforeCpLim(plsdn, (plssubl)->cpLim) \
  81. && FDnodeAfterCpFirst(plsdn, (plssubl)->cpFirst))
  82. #define FUseForPurpose(plsdn, purpose) \
  83. (*(&((plsdn)->u.real.pinfosubl->fUseForJustification) + (purpose -1)))
  84. #define FIsUsageFlagsCastWorks(plsdn) \
  85. ((plsdn)->u.real.pinfosubl->fUseForCompression == \
  86. FUseForPurpose(plsdn, CollectSublinesForCompression) && \
  87. (plsdn)->u.real.pinfosubl->fUseForJustification == \
  88. FUseForPurpose(plsdn, CollectSublinesForJustification) && \
  89. (plsdn)->u.real.pinfosubl->fUseForDisplay == \
  90. FUseForPurpose(plsdn, CollectSublinesForDisplay) && \
  91. (plsdn)->u.real.pinfosubl->fUseForDecimalTab == \
  92. FUseForPurpose(plsdn, CollectSublinesForDecimalTab) && \
  93. (plsdn)->u.real.pinfosubl->fUseForTrailingArea == \
  94. FUseForPurpose(plsdn, CollectSublinesForTrailingArea))
  95. #define GetSubmittedSublines(plsdn, purpose) \
  96. ((((purpose) == CollectSublinesNone) || \
  97. (Assert(FIsDnodeReal(plsdn)), (plsdn)->u.real.pinfosubl == NULL) || \
  98. ((plsdn)->u.real.pinfosubl->rgpsubl == NULL)) ? \
  99. NULL : (Assert(FIsUsageFlagsCastWorks(plsdn)), \
  100. (FUseForPurpose(plsdn, purpose)) ? \
  101. (plsdn)->u.real.pinfosubl->rgpsubl : NULL))
  102. #define GetNumberSubmittedSublines(plsdn) \
  103. (Assert((plsdn)->u.real.pinfosubl != NULL), (plsdn)->u.real.pinfosubl->cSubline)
  104. #define FColinearTflows(t1, t2) \
  105. (((t1) & fUVertical) == ((t2) & fUVertical))
  106. #define FSameSemiPlaneTflows(t1, t2) \
  107. (((t1) & fUDirection) == ((t2) & fUDirection))
  108. #define FParallelTflows(t1,t2) \
  109. Assert(FColinearTflows(t1, t2)), \
  110. FSameSemiPlaneTflows(t1, t2) // we assume here that they are colinear
  111. /* C O L L E C T C H U N K A R O U N D*/
  112. /*----------------------------------------------------------------------------
  113. %%Function: CollectChunkAround
  114. %%Contact: igorzv
  115. Parameters:
  116. plsc - (IN) chunk context
  117. plsdn - (IN) dnode to collect chunk arround
  118. lstflow - (IN) lstflow
  119. ppoint (IN) starting position of dnode
  120. Fill in cnunk elements array for chunk arround pposinline->plsdn
  121. Calculate location of the chunk
  122. ----------------------------------------------------------------------------*/
  123. LSERR CollectChunkAround(PLSCHUNKCONTEXT plschunkcontext, PLSDNODE plsdnInChunk,
  124. LSTFLOW lstflow, POINTUV* ppoint)
  125. {
  126. WORD idObjChnk;
  127. PLSDNODE plsdnNext;
  128. PLSDNODE plsdnCurrent;
  129. PLOCCHNK plocchnk;
  130. LSCHNKE* plschnke;
  131. DWORD clschnk;
  132. LSERR lserr;
  133. LSCP cpInChunk;
  134. Assert(FIsLSDNODE(plsdnInChunk));
  135. plocchnk = &(plschunkcontext->locchnkCurrent);
  136. clschnk = plocchnk->clschnk;
  137. plschnke = plocchnk->plschnk;
  138. plsdnCurrent = plsdnInChunk;
  139. cpInChunk = plsdnInChunk->cpFirst;
  140. /* check: has this chunk already collected? */
  141. /* chunk was already collected if there is some chunk and our dnode is within this chunk
  142. and nothing was added to list after chunk was collected */
  143. /* we turn off optimisation for dnodes with dcp=0 (ex. pens) because of a problem how
  144. to figure out that dnode is within chunk */
  145. if ((!plschunkcontext->FChunkValid) || (plschunkcontext->FGroupChunk)
  146. ||(plschnke[0].cpFirst > plsdnCurrent->cpFirst)
  147. || (plschnke[clschnk - 1].cpFirst < plsdnCurrent->cpFirst)
  148. || (plsdnCurrent->dcp == 0)
  149. || (plschnke[0].dcp == 0)
  150. || ((plschunkcontext->pplsdnChunk[clschnk - 1])->plsdnNext != NULL))
  151. {
  152. /* we need to recollect chunk */
  153. /* we don't allow caller to pass border as a plsdnInChunk */
  154. Assert(!FIsDnodeBorder(plsdnInChunk));
  155. if ( FIsDnodePen(plsdnInChunk) || plsdnInChunk->fTab || FIsDnodeSplat(plsdnInChunk))
  156. {
  157. /* for pens and tabs chunk consists of one element and we collect it right away */
  158. plocchnk->clschnk = 1;
  159. Assert(plocchnk->clschnk <= plschunkcontext->cchnkMax);
  160. LschnkeFromDnode((&(plschnke[0])), plsdnInChunk);
  161. plschunkcontext->pplsdnChunk[0] = plsdnInChunk;
  162. plschunkcontext->FChunkValid = fTrue;
  163. plschunkcontext->FLocationValid = fFalse;
  164. plschunkcontext->FGroupChunk = fFalse;
  165. /* we should here calculate width of border before dnode, the same way it done
  166. in FillChunkArray */
  167. plschunkcontext->pdurOpenBorderBefore[0] = 0;
  168. plschunkcontext->pdurCloseBorderAfter[0] = 0;
  169. plschunkcontext->FBorderInside = fFalse;
  170. plsdnCurrent = plsdnInChunk->plsdnPrev;
  171. if (plsdnCurrent != NULL && FIsDnodeOpenBorder(plsdnCurrent))
  172. {
  173. plschunkcontext->FBorderInside = fTrue;
  174. plschunkcontext->pdurOpenBorderBefore[0] += DurFromDnode(plsdnCurrent);
  175. }
  176. plsdnCurrent = plsdnInChunk->plsdnNext;
  177. if (plsdnCurrent != NULL && FIsDnodeCloseBorder(plsdnCurrent))
  178. {
  179. plschunkcontext->FBorderInside = fTrue;
  180. plschunkcontext->pdurCloseBorderAfter[0] += DurFromDnode(plsdnCurrent);
  181. }
  182. }
  183. else
  184. {
  185. idObjChnk = IdObjFromDnode(plsdnInChunk);
  186. /* go to the end of chunk */
  187. plsdnNext = plsdnCurrent->plsdnNext;
  188. while(!FIsChunkBoundary(plsdnNext, idObjChnk, cpInChunk))
  189. {
  190. plsdnCurrent = plsdnNext;
  191. plsdnNext = plsdnCurrent->plsdnNext;
  192. }
  193. lserr = FillChunkArray(plschunkcontext, plsdnCurrent);
  194. if (lserr != lserrNone)
  195. return lserr;
  196. }
  197. }
  198. /* check: is chunck located */
  199. if (!plschunkcontext->FLocationValid)
  200. {
  201. LocateChunk(plschunkcontext, plsdnInChunk, lstflow, ppoint);
  202. }
  203. return lserrNone;
  204. }
  205. /* L O C A T E C H U N K */
  206. /*----------------------------------------------------------------------------
  207. %%Function: CollectPreviousChunk
  208. %%Contact: igorzv
  209. Parameters:
  210. plsc - (IN) chunk context
  211. plsdn - (IN) dnode to collect chunk arround
  212. lstflow - (IN) lstflow
  213. ppoint (IN) starting position of dnode
  214. Calculates location of the chunk. We assume here that pointUv.u in locchunk
  215. contains before this procedure width of border before dnode.
  216. After procedure we put location there
  217. /*----------------------------------------------------------------------------*/
  218. static void LocateChunk(PLSCHUNKCONTEXT plschunkcontext, PLSDNODE plsdnInChunk,
  219. LSTFLOW lstflow, POINTUV* ppoint)
  220. {
  221. PLSDNODE plsdnFirst;
  222. PLOCCHNK plocchnk;
  223. PLSDNODE* pplsdnChunk;
  224. PLSDNODE plsdnCurrent;
  225. long urPen,vrPen;
  226. LONG i;
  227. PPOINTUV ppointUv;
  228. LONG* pdurOpenBorderBefore;
  229. LONG* pdurCloseBorderAfter;
  230. Assert(!FIsDnodeBorder(plsdnInChunk)); /* we don't allow border as in input */
  231. plocchnk = &(plschunkcontext->locchnkCurrent);
  232. plsdnFirst = plschunkcontext->pplsdnChunk[0];
  233. plocchnk->lsfgi.fFirstOnLine = FIsFirstOnLine(plsdnFirst)
  234. && FIsSubLineMain(SublineFromDnode(plsdnFirst));
  235. plocchnk->lsfgi.cpFirst = plsdnFirst->cpFirst;
  236. plocchnk->lsfgi.lstflow = lstflow;
  237. /* we can't set urColumnMax here, because during breaking object handler can change it */
  238. /* and we suppose that caller use for this purpose SetUrColumnMaxForChunks */
  239. pplsdnChunk = plschunkcontext->pplsdnChunk;
  240. ppointUv = plocchnk->ppointUvLoc;
  241. pdurOpenBorderBefore = plschunkcontext->pdurOpenBorderBefore;
  242. pdurCloseBorderAfter = plschunkcontext->pdurCloseBorderAfter;
  243. /* calculation of pen position before chunk */
  244. if (plsdnFirst->plsdnPrev == NULL) /* optimization */
  245. {
  246. urPen = plschunkcontext->urFirstChunk;
  247. vrPen = plschunkcontext->vrFirstChunk;
  248. }
  249. else
  250. {
  251. plsdnCurrent = plsdnInChunk;
  252. urPen = ppoint->u;
  253. vrPen = ppoint->v;
  254. for (i = 0; pplsdnChunk[i] != plsdnCurrent; i++)
  255. {
  256. Assert(i < (LONG) plocchnk->clschnk);
  257. urPen -= DurFromDnode(pplsdnChunk[i]);
  258. vrPen -= DvrFromDnode(pplsdnChunk[i]);
  259. /* substract also border before dnode */
  260. urPen -= pdurOpenBorderBefore[i];
  261. urPen -= pdurCloseBorderAfter[i];
  262. }
  263. /* and now open border before plsdnCurrent */
  264. urPen -= pdurOpenBorderBefore[i];
  265. }
  266. plocchnk->lsfgi.urPen = urPen;
  267. plocchnk->lsfgi.vrPen = vrPen;
  268. /* location of all dnodes */
  269. for (i = 0; i < (LONG) plocchnk->clschnk; i++)
  270. {
  271. urPen += pdurOpenBorderBefore[i]; /* count border */
  272. if (i != 0) urPen += pdurCloseBorderAfter[i - 1];
  273. ppointUv[i].u = urPen;
  274. ppointUv[i].v = vrPen;
  275. urPen += DurFromDnode(pplsdnChunk[i]);
  276. vrPen += DvrFromDnode(pplsdnChunk[i]);
  277. }
  278. plschunkcontext->FLocationValid = fTrue;
  279. }
  280. /* C O L L E C T P R E V I O U S C H U N K */
  281. /*----------------------------------------------------------------------------
  282. %%Function: CollectPreviousChunk
  283. %%Contact: igorzv
  284. Parameters:
  285. plschuncontext - (IN) chunk context
  286. pfSuccessful - (OUT) does previous chunk exist
  287. Check that we are in the begining of line,
  288. othewise call CollectChunkAround with the previous dnode
  289. ----------------------------------------------------------------------------*/
  290. LSERR CollectPreviousChunk(PLSCHUNKCONTEXT plschunkcontext,
  291. BOOL* pfSuccessful )
  292. {
  293. PLOCCHNK plocchnk;
  294. POINTUV point;
  295. PLSDNODE plsdn;
  296. plocchnk = &(plschunkcontext->locchnkCurrent);
  297. if (FIsFirstOnLine(plschunkcontext->pplsdnChunk[0]))
  298. {
  299. *pfSuccessful = fFalse;
  300. return lserrNone;
  301. }
  302. else
  303. {
  304. plsdn = plschunkcontext->pplsdnChunk[0]->plsdnPrev;
  305. point = plocchnk->ppointUvLoc[0];
  306. while (FIsDnodeBorder(plsdn))
  307. {
  308. point.u -= DurFromDnode(plsdn);
  309. point.v -= DvrFromDnode(plsdn);
  310. plsdn = plsdn->plsdnPrev;
  311. }
  312. point.u -= DurFromDnode(plsdn);
  313. point.v -= DvrFromDnode(plsdn);
  314. *pfSuccessful = fTrue;
  315. return CollectChunkAround(plschunkcontext, plsdn,
  316. plocchnk->lsfgi.lstflow, &point);
  317. }
  318. }
  319. /* C O L L E C T N E X T C H U N K */
  320. /*----------------------------------------------------------------------------
  321. %%Function: CollectNextChunk
  322. %%Contact: igorzv
  323. Parameters:
  324. plschuncontext - (IN) chunk context
  325. pfSuccessful - (OUT) does next chunk exist
  326. Check that we are in the end of list, in this case return *pfSuccessful and don't change chunk
  327. othewise call CollectChunkAround with the next dnode
  328. ----------------------------------------------------------------------------*/
  329. LSERR CollectNextChunk(PLSCHUNKCONTEXT plschunkcontext,
  330. BOOL* pfSuccessful )
  331. {
  332. PLOCCHNK plocchnk;
  333. DWORD clschnk;
  334. PLSDNODE* pplsdnChunk;
  335. POINTUV point;
  336. PLSDNODE plsdn;
  337. plocchnk = &(plschunkcontext->locchnkCurrent);
  338. clschnk = plocchnk->clschnk;
  339. Assert(clschnk > 0);
  340. pplsdnChunk = plschunkcontext->pplsdnChunk;
  341. point = plocchnk->ppointUvLoc[clschnk - 1];
  342. point.u += DurFromDnode(pplsdnChunk[clschnk - 1]);
  343. point.v += DvrFromDnode(pplsdnChunk[clschnk - 1]);
  344. plsdn = pplsdnChunk[clschnk - 1]->plsdnNext;
  345. /* skip borders */
  346. while (plsdn != NULL && FIsDnodeBorder(plsdn))
  347. {
  348. point.u += DurFromDnode(plsdn);
  349. point.v += DvrFromDnode(plsdn);
  350. plsdn = plsdn->plsdnNext;
  351. }
  352. if (plsdn == NULL)
  353. {
  354. *pfSuccessful = fFalse;
  355. return lserrNone;
  356. }
  357. else
  358. {
  359. *pfSuccessful = fTrue;
  360. return CollectChunkAround(plschunkcontext, plsdn,
  361. plocchnk->lsfgi.lstflow, &point);
  362. }
  363. }
  364. /* F I L L C H U N K A R R A Y*/
  365. /*----------------------------------------------------------------------------
  366. %%Function: FillChunkArray
  367. %%Contact: igorzv
  368. Parameters:
  369. plschuncontext - (IN) chunk context
  370. plsdnLast - (IN) last dnode in chunk
  371. Fill in chunk elements array for chunk before plsdnLast
  372. ----------------------------------------------------------------------------*/
  373. LSERR FillChunkArray(PLSCHUNKCONTEXT plschunkcontext,
  374. PLSDNODE plsdnLast)
  375. {
  376. PLSDNODE plsdnCurrent, plsdnPrev;
  377. WORD idObjChnk;
  378. PLOCCHNK plocchnk;
  379. LSCHNKE* plschnke;
  380. LONG clschnke;
  381. LSERR lserr;
  382. LONG i;
  383. LSCP cpInChunk;
  384. PPOINTUV ppointUv;
  385. LONG* pdurOpenBorderBefore;
  386. LONG* pdurCloseBorderAfter;
  387. Assert(FIsLSDNODE(plsdnLast));
  388. Assert(!plsdnLast->fTab); /* for optimization we assume that caller will resolve */
  389. Assert(! FIsDnodePen(plsdnLast)); /* pen and tabs */
  390. Assert(!FIsDnodeSplat(plsdnLast));
  391. plocchnk = &(plschunkcontext->locchnkCurrent);
  392. /* skip borders in the end of chunk to figure out what idObj this chunk has */
  393. while (FIsDnodeBorder(plsdnLast))
  394. {
  395. plsdnLast = plsdnLast->plsdnPrev;
  396. Assert(FIsLSDNODE(plsdnLast));
  397. }
  398. idObjChnk = IdObjFromDnode(plsdnLast);
  399. cpInChunk = plsdnLast->cpFirst;
  400. /* go to the begining of chunk calculating amount of elements */
  401. plsdnCurrent = plsdnLast;
  402. plsdnPrev = plsdnCurrent->plsdnPrev;
  403. clschnke = 1;
  404. while (!FIsChunkBoundary(plsdnPrev, idObjChnk, cpInChunk))
  405. {
  406. plsdnCurrent = plsdnPrev;
  407. plsdnPrev = plsdnCurrent->plsdnPrev;
  408. if (!FIsDnodeBorder(plsdnCurrent)) clschnke++; /* we don't put borders into array */
  409. }
  410. /* plsdnCurrent is first dnode in chunk, clschnke is amount of chnk elements */
  411. if (clschnke > (LONG) plschunkcontext->cchnkMax)
  412. {
  413. lserr = SetChunkArraysSize(plschunkcontext, clschnke);
  414. if (lserr != lserrNone)
  415. return lserr;
  416. }
  417. /* fill in array of chunk elements */
  418. FlushNominalToIdealState(plschunkcontext);
  419. plschnke = plocchnk->plschnk;
  420. plocchnk->clschnk = clschnke;
  421. ppointUv = plocchnk->ppointUvLoc;
  422. pdurOpenBorderBefore = plschunkcontext->pdurOpenBorderBefore;
  423. pdurCloseBorderAfter = plschunkcontext->pdurCloseBorderAfter;
  424. plschunkcontext->FBorderInside = fFalse;
  425. for (i=0; i < clschnke; i++)
  426. {
  427. Assert(!FIsChunkBoundary(plsdnCurrent, idObjChnk, cpInChunk));
  428. ppointUv[i].u = 0;
  429. pdurOpenBorderBefore[i] = 0;
  430. if (i != 0) pdurCloseBorderAfter[i - 1] = 0;
  431. while (FIsDnodeBorder(plsdnCurrent))
  432. {
  433. /* calculates border widths */
  434. plschunkcontext->FBorderInside = fTrue;
  435. if (FIsDnodeOpenBorder(plsdnCurrent))
  436. {
  437. pdurOpenBorderBefore[i] += DurFromDnode(plsdnCurrent);
  438. }
  439. else
  440. {
  441. if (i != 0) pdurCloseBorderAfter[i - 1] += DurFromDnode(plsdnCurrent);
  442. }
  443. plsdnCurrent = plsdnCurrent->plsdnNext;
  444. }
  445. LschnkeFromDnode(plschnke, plsdnCurrent);
  446. plschunkcontext->pplsdnChunk[i] = plsdnCurrent;
  447. SetNominalToIdealFlags(plschunkcontext, &(plsdnCurrent->u.real.lschp));
  448. plsdnCurrent = plsdnCurrent->plsdnNext;
  449. plschnke++;
  450. }
  451. /* closing border after chunk */
  452. if (plsdnCurrent != NULL && FIsDnodeCloseBorder(plsdnCurrent))
  453. {
  454. plschunkcontext->FBorderInside = fTrue;
  455. pdurCloseBorderAfter[clschnke - 1] = DurFromDnode(plsdnCurrent);
  456. }
  457. else
  458. {
  459. pdurCloseBorderAfter[clschnke - 1] = 0;
  460. }
  461. plschunkcontext->FChunkValid = fTrue;
  462. plschunkcontext->FLocationValid = fFalse; /* chunk we collected is not located and */
  463. plschunkcontext->FGroupChunk = fFalse; /* is not group */
  464. return lserrNone;
  465. }
  466. /* S E T P O S I N C H U N K */
  467. /*----------------------------------------------------------------------------
  468. %%Function: SetPosInChunk
  469. %%Contact: igorzv
  470. Parameters:
  471. plschunkcontext - (IN) LineServices context
  472. PLSDNODE plsdn - (IN) dnode
  473. LSDCP dcp - (IN) dcp
  474. pposichnk - (OUT) position in chunk to fill in
  475. Convert position in line to position in chunk
  476. ----------------------------------------------------------------------------*/
  477. void SetPosInChunk(PLSCHUNKCONTEXT plschunkcontext, PLSDNODE plsdn,
  478. LSDCP dcp, PPOSICHNK pposichnk)
  479. {
  480. LONG i;
  481. LONG clschnkMac;
  482. PLSDNODE* pplsdnChunk;
  483. Assert(FIsLSDNODE(plsdn));
  484. pplsdnChunk = plschunkcontext->pplsdnChunk;
  485. clschnkMac = plschunkcontext->locchnkCurrent.clschnk;
  486. for (i=0; (i < clschnkMac) && (plsdn != pplsdnChunk[i]) ; i++);
  487. Assert(i < clschnkMac);
  488. pposichnk->dcp = dcp;
  489. pposichnk->ichnk = i;
  490. }
  491. /* I N I T G R O U P C H U N K E X T */
  492. /*----------------------------------------------------------------------------
  493. %%Function: InitGroupChunkExt
  494. %%Contact: igorzv
  495. Parameters:
  496. plschunkcontext - (IN) chunkcontext context
  497. iobjText - (IN) idobj of text
  498. pgrchunkext - (OUT) structure to initialize
  499. Link GroupChunkExt with state
  500. Fill in default values
  501. ----------------------------------------------------------------------------*/
  502. void InitGroupChunkExt(PLSCHUNKCONTEXT plschunkcontext, DWORD iobjText,
  503. GRCHUNKEXT* pgrchunkext)
  504. {
  505. Assert(pgrchunkext != NULL);
  506. pgrchunkext->plschunkcontext = plschunkcontext;
  507. pgrchunkext->iobjText = iobjText;
  508. /* we don't need to flush everything here */
  509. /* we will do this in CollectGroupChunk procedures */
  510. pgrchunkext->lsgrchnk.plschnk = plschunkcontext->locchnkCurrent.plschnk;
  511. pgrchunkext->lsgrchnk.pcont = plschunkcontext->pcont;
  512. pgrchunkext->pfNonTextExpandAfter = plschunkcontext->pfNonTextExpandAfter;
  513. pgrchunkext->pplsdnNonText = plschunkcontext->pplsdnNonText;
  514. }
  515. /* C O L L E C T T E X T G R O U P C H U N K*/
  516. /*----------------------------------------------------------------------------
  517. %%Function: CollectTextGroupChunk
  518. %%Contact: igorzv
  519. Parameters:
  520. plsdnFirst - (IN) start dnode
  521. cpLim - (IN) boundary for group chunk
  522. Purpose - (IN) what subline to take from complex object
  523. pgrchunkext - (OUT) group chunk to fill in
  524. Fill in group chunk structure with text dnodes located from plsdFirst
  525. ----------------------------------------------------------------------------*/
  526. LSERR CollectTextGroupChunk(
  527. PLSDNODE plsdnFirst,
  528. LSCP cpLim,
  529. COLLECTSUBLINES Purpose,
  530. GRCHUNKEXT* pgrchunkext)
  531. {
  532. PLSCHUNKCONTEXT plschunkcontext = pgrchunkext->plschunkcontext;
  533. DWORD iobjText = pgrchunkext->iobjText;
  534. PLOCCHNK plocchnk;
  535. DWORD cChunk;
  536. PLSDNODE plsdnCurrent;
  537. BOOL fPreviousIsNonText = fFalse;
  538. LSERR lserr;
  539. LSCHNKE* plschnke;
  540. BOOL fSuccessful;
  541. BOOL fExpand;
  542. DWORD cTextBeforeLastNonText = 0;
  543. GROUPCHUNKITERATOR groupchunkiterator;
  544. PLSDNODE plsdnLastForTrailing;
  545. int cDnodesTrailing;
  546. LSDCP dcpStartTrailing;
  547. PLSDNODE plsdnTrailingObject;
  548. LSDCP dcpTrailingObject;
  549. Assert(FIsLSDNODE(plsdnFirst));
  550. Assert(FIsGrchnkExtValid(plschunkcontext, pgrchunkext));
  551. /* we try to optimize here in a case when group chunk consist of one (last in a line)
  552. chunk and this chunk has been already collected */
  553. plocchnk = &(plschunkcontext->locchnkCurrent);
  554. cChunk = plocchnk->clschnk;
  555. /* if we have text chunk without borders started with plsdnFirst
  556. and going up or beyond cpLim */
  557. if ((cChunk > 0) &&
  558. (plschunkcontext->FChunkValid) &&
  559. (!plschunkcontext->FGroupChunk) &&
  560. (!plschunkcontext->FBorderInside) &&
  561. (IdObjFromChnk(plocchnk) == pgrchunkext->iobjText) &&
  562. (plschunkcontext->pplsdnChunk[0] == plsdnFirst)
  563. && (!plsdnFirst->fTab)
  564. && (FIsOutOfBoundary((plschunkcontext->pplsdnChunk[cChunk - 1])->plsdnNext, cpLim)))
  565. {
  566. pgrchunkext->Purpose = Purpose;
  567. return ConvertChunkToGroupChunk(pgrchunkext, cpLim);
  568. }
  569. /* we have to go through general procedure */
  570. /* flush group chunk */
  571. pgrchunkext->plsdnFirst = plsdnFirst;
  572. pgrchunkext->durTotal = 0;
  573. pgrchunkext->durTextTotal = 0;
  574. pgrchunkext->dupNonTextTotal = 0;
  575. pgrchunkext->cNonTextObjects = 0;
  576. pgrchunkext->cNonTextObjectsExpand = 0;
  577. pgrchunkext->lsgrchnk.clsgrchnk = 0;
  578. pgrchunkext->plsdnNext = NULL;
  579. pgrchunkext->plsdnLastUsed = NULL;
  580. plschunkcontext->FGroupChunk = fTrue;
  581. plschunkcontext->FBorderInside = fFalse;
  582. pgrchunkext->Purpose = Purpose;
  583. CreateGroupChunkIterator(&groupchunkiterator,
  584. Purpose, plsdnFirst, cpLim, fTrue);
  585. plsdnCurrent = GetNextDnodeInGroupChunk(&groupchunkiterator, &fSuccessful);
  586. while(fSuccessful)
  587. {
  588. pgrchunkext->plsdnLastUsed = plsdnCurrent;
  589. /* fill in array of elements */
  590. if (FIsDnodeReal(plsdnCurrent) && !FIsDnodeSplat(plsdnCurrent)) /* not a pen border or splat*/
  591. {
  592. if (IdObjFromDnode(plsdnCurrent) == iobjText) /* is text */
  593. {
  594. pgrchunkext->lsgrchnk.clsgrchnk++;
  595. if (pgrchunkext->lsgrchnk.clsgrchnk > plschunkcontext->cchnkMax)
  596. {
  597. lserr = IncreaseChunkArrays(plschunkcontext);
  598. if (lserr != lserrNone)
  599. {
  600. DestroyGroupChunkIterator(&groupchunkiterator);
  601. return lserr;
  602. }
  603. pgrchunkext->lsgrchnk.plschnk = plschunkcontext->locchnkCurrent.plschnk;
  604. pgrchunkext->lsgrchnk.pcont = plschunkcontext->pcont;
  605. Assert(FIsGrchnkExtValid(plschunkcontext, pgrchunkext));
  606. }
  607. /* fill in group chunk element */
  608. plschnke = &(pgrchunkext->lsgrchnk.plschnk[pgrchunkext->lsgrchnk.clsgrchnk - 1]);
  609. LschnkeFromDnode(plschnke, plsdnCurrent);
  610. /* fill in array of dnodes in context */
  611. plschunkcontext->pplsdnChunk[pgrchunkext->lsgrchnk.clsgrchnk - 1] = plsdnCurrent;
  612. /* flash flags */
  613. pgrchunkext->lsgrchnk.pcont[pgrchunkext->lsgrchnk.clsgrchnk - 1] = 0;
  614. /* set flags */
  615. if (fPreviousIsNonText)
  616. {
  617. pgrchunkext->lsgrchnk.pcont[pgrchunkext->lsgrchnk.clsgrchnk - 1] |=
  618. fcontNonTextBefore;
  619. }
  620. fPreviousIsNonText = fFalse;
  621. /* calculate integrated information */
  622. pgrchunkext->durTextTotal += plsdnCurrent->u.real.objdim.dur;
  623. pgrchunkext->durTotal += plsdnCurrent->u.real.objdim.dur;
  624. }
  625. else
  626. {
  627. /* resolve expansion after previous non text */
  628. if (pgrchunkext->cNonTextObjects > 0)
  629. {
  630. lserr = FExpandAfterNonTextObject(pgrchunkext, cTextBeforeLastNonText,
  631. &fExpand);
  632. if (lserr != lserrNone)
  633. {
  634. DestroyGroupChunkIterator(&groupchunkiterator);
  635. return lserr;
  636. }
  637. pgrchunkext->pfNonTextExpandAfter[pgrchunkext->cNonTextObjects - 1] =
  638. fExpand;
  639. if (fExpand)
  640. {
  641. /* increase amount of expandable non text objects */
  642. pgrchunkext->cNonTextObjectsExpand++;
  643. /* it was text between two non texts */
  644. if (!fPreviousIsNonText)
  645. {
  646. Assert(pgrchunkext->lsgrchnk.clsgrchnk > cTextBeforeLastNonText);
  647. pgrchunkext->lsgrchnk.pcont[cTextBeforeLastNonText] |=
  648. fcontExpandBefore;
  649. }
  650. }
  651. }
  652. pgrchunkext->cNonTextObjects++;
  653. if (pgrchunkext->cNonTextObjects > plschunkcontext->cNonTextMax)
  654. {
  655. lserr = IncreaseGroupChunkNonTextArrays(plschunkcontext);
  656. if (lserr != lserrNone)
  657. {
  658. DestroyGroupChunkIterator(&groupchunkiterator);
  659. return lserr;
  660. }
  661. pgrchunkext->pplsdnNonText = plschunkcontext->pplsdnNonText;
  662. pgrchunkext->pfNonTextExpandAfter = plschunkcontext->pfNonTextExpandAfter;
  663. Assert(FIsGrchnkExtValid(plschunkcontext, pgrchunkext));
  664. }
  665. /* fill in array of non text dnodes in context */
  666. plschunkcontext->pplsdnNonText[pgrchunkext->cNonTextObjects - 1] = plsdnCurrent;
  667. /* set flags in previous text */
  668. if (!fPreviousIsNonText && pgrchunkext->lsgrchnk.clsgrchnk >= 1)
  669. {
  670. Assert(pgrchunkext->lsgrchnk.clsgrchnk >= 1);
  671. pgrchunkext->lsgrchnk.pcont[pgrchunkext->lsgrchnk.clsgrchnk - 1] |=
  672. (fcontNonTextAfter);
  673. /* resolve expansion before current non text */
  674. Assert(cTextBeforeLastNonText < pgrchunkext->lsgrchnk.clsgrchnk);
  675. lserr =FExpandBeforeNonTextObject(pgrchunkext, cTextBeforeLastNonText,
  676. &fExpand);
  677. if (lserr != lserrNone)
  678. {
  679. DestroyGroupChunkIterator(&groupchunkiterator);
  680. return lserr;
  681. }
  682. if (fExpand)
  683. {
  684. pgrchunkext->lsgrchnk.pcont[pgrchunkext->lsgrchnk.clsgrchnk - 1] |=
  685. fcontExpandAfter;
  686. }
  687. }
  688. fPreviousIsNonText = fTrue;
  689. cTextBeforeLastNonText = pgrchunkext->lsgrchnk.clsgrchnk;
  690. /* calculate integrated information */
  691. pgrchunkext->durTotal += DurFromRealDnode(plsdnCurrent);
  692. pgrchunkext->dupNonTextTotal += DupFromRealDnode(plsdnCurrent);
  693. } /* non -text */
  694. } /* real dnode */
  695. else
  696. { /* pen or border*/
  697. Assert(FIsDnodePen(plsdnCurrent) ||
  698. FIsDnodeBorder(plsdnCurrent) || FIsDnodeSplat(plsdnCurrent));
  699. Assert(FIsDnodeBorder(plsdnCurrent) || FIsDnodeSplat(plsdnCurrent) ||
  700. plsdnCurrent->fAdvancedPen); /* only advanced pens are allowed here */
  701. if (FIsDnodeBorder(plsdnCurrent))
  702. plschunkcontext->FBorderInside = fTrue;
  703. pgrchunkext->durTotal += DurFromDnode(plsdnCurrent);
  704. pgrchunkext->dupNonTextTotal += DupFromDnode(plsdnCurrent);
  705. }
  706. /* prepare next iteration */
  707. plsdnCurrent = GetNextDnodeInGroupChunk(&groupchunkiterator, &fSuccessful);
  708. }
  709. /* resolve expansion after previous non text */
  710. if (pgrchunkext->cNonTextObjects > 0)
  711. {
  712. lserr = FExpandAfterNonTextObject(pgrchunkext, cTextBeforeLastNonText,
  713. &fExpand);
  714. if (lserr != lserrNone)
  715. {
  716. DestroyGroupChunkIterator(&groupchunkiterator);
  717. return lserr;
  718. }
  719. pgrchunkext->pfNonTextExpandAfter[pgrchunkext->cNonTextObjects - 1] |=
  720. fExpand;
  721. if (fExpand)
  722. {
  723. /* increase amount of expandable non text objects */
  724. pgrchunkext->cNonTextObjectsExpand++;
  725. /* it was text between two non texts */
  726. if (!fPreviousIsNonText)
  727. {
  728. Assert(pgrchunkext->lsgrchnk.clsgrchnk > cTextBeforeLastNonText);
  729. pgrchunkext->lsgrchnk.pcont[cTextBeforeLastNonText] |=
  730. fcontExpandBefore;
  731. }
  732. }
  733. }
  734. pgrchunkext->plsdnNext = plsdnCurrent;
  735. DestroyGroupChunkIterator(&groupchunkiterator);
  736. /* because collecting of group chunk can be called before SetBreak, dcp of last
  737. dnode, if it come from lower level, should be cut using cpLim */
  738. if ((pgrchunkext->lsgrchnk.clsgrchnk > 0) &&
  739. (plschunkcontext->pplsdnChunk[pgrchunkext->lsgrchnk.clsgrchnk - 1]->cpLimOriginal
  740. > cpLim)
  741. )
  742. {
  743. pgrchunkext->lsgrchnk.plschnk[pgrchunkext->lsgrchnk.clsgrchnk - 1].dcp =
  744. cpLim -
  745. plschunkcontext->pplsdnChunk[pgrchunkext->lsgrchnk.clsgrchnk - 1]->cpFirst;
  746. }
  747. if (Purpose == CollectSublinesForJustification ||
  748. Purpose == CollectSublinesForCompression)
  749. {
  750. /* we should find here last dnode on the upper level before chunk boundary */
  751. if (pgrchunkext->plsdnLastUsed == NULL)
  752. {
  753. /* first dnode is already out of boundary, it can happened with tabs or pens */
  754. Assert(pgrchunkext->plsdnFirst == pgrchunkext->plsdnNext);
  755. plsdnLastForTrailing = pgrchunkext->plsdnFirst;
  756. }
  757. else if (pgrchunkext->plsdnNext != NULL)
  758. {
  759. plsdnLastForTrailing = pgrchunkext->plsdnNext->plsdnPrev;
  760. }
  761. else
  762. {
  763. plsdnLastForTrailing = (SublineFromDnode(pgrchunkext->plsdnFirst))->plsdnLast;
  764. }
  765. lserr = GetTrailingInfoForTextGroupChunk
  766. (plsdnLastForTrailing, plsdnLastForTrailing->dcp,
  767. iobjText, &(pgrchunkext->durTrailing), &(pgrchunkext->dcpTrailing),
  768. &(pgrchunkext->plsdnStartTrailing),
  769. &dcpStartTrailing,
  770. &cDnodesTrailing, &plsdnTrailingObject, &dcpTrailingObject,
  771. &(pgrchunkext->fClosingBorderStartsTrailing));
  772. if (lserr != lserrNone)
  773. {
  774. return lserr;
  775. }
  776. if (cDnodesTrailing == 0)
  777. {
  778. if (pgrchunkext->lsgrchnk.clsgrchnk != 0)
  779. {
  780. pgrchunkext->posichnkBeforeTrailing.ichnk = pgrchunkext->lsgrchnk.clsgrchnk - 1;
  781. pgrchunkext->posichnkBeforeTrailing.dcp = pgrchunkext->lsgrchnk.plschnk
  782. [pgrchunkext->posichnkBeforeTrailing.ichnk].dcp;
  783. }
  784. else
  785. {
  786. /* in this case posichnkBeforeTrailing doesn't make any sense and we can't use
  787. code above not to triger memory violation, so we put zeroes just to put something */
  788. pgrchunkext->posichnkBeforeTrailing.ichnk = 0;
  789. pgrchunkext->posichnkBeforeTrailing.dcp = 0;
  790. }
  791. }
  792. else
  793. {
  794. pgrchunkext->posichnkBeforeTrailing.ichnk = pgrchunkext->lsgrchnk.clsgrchnk
  795. - cDnodesTrailing;
  796. if (FIsDnodeReal(pgrchunkext->plsdnStartTrailing)
  797. && IdObjFromDnode(pgrchunkext->plsdnStartTrailing) == iobjText)
  798. {
  799. pgrchunkext->posichnkBeforeTrailing.dcp = dcpStartTrailing;
  800. }
  801. else
  802. {
  803. /* trailing area was interupted by non text, we report to text starting of trailing before
  804. previous text */
  805. Assert(pgrchunkext->plsdnStartTrailing->dcp == dcpStartTrailing);
  806. pgrchunkext->posichnkBeforeTrailing.dcp = 0;
  807. }
  808. }
  809. }
  810. return lserrNone;
  811. }
  812. /* C O N T I N U E G R O U P C H U N K*/
  813. /*----------------------------------------------------------------------------
  814. %%Function: ContinueGroupChunk
  815. %%Contact: igorzv
  816. Parameters:
  817. pgroupchunkiterator -(IN) handler for iterator
  818. pfSuccessful - (OUT) do we find dnode in this group chunk
  819. Start traversing list for collecting group chunk
  820. ----------------------------------------------------------------------------*/
  821. PLSDNODE ContinueGroupChunk(
  822. GROUPCHUNKITERATOR* pgroupchunkiterator,
  823. BOOL* pfSuccessful)
  824. {
  825. PLSSUBL plssubl;
  826. PLSSUBL* rgpsubl;
  827. PLSDNODE plsdnStart = pgroupchunkiterator->plsdnStart;
  828. BOOL fBoundaryCondition;
  829. int cSublines;
  830. /* we assume here that dnode out of group chunk boundary can happen only on main subline of
  831. the group chunk */
  832. fBoundaryCondition = pgroupchunkiterator->fForward ?
  833. FIsGroupChunkBoundary(plsdnStart, pgroupchunkiterator->cpLim,
  834. pgroupchunkiterator->plsdnFirst->cpFirst) :
  835. FIsGroupChunkStartBoundary(plsdnStart, pgroupchunkiterator->plsdnFirst->cpFirst) ;
  836. if (fBoundaryCondition) /* we out of limits */
  837. {
  838. AssertImplies(plsdnStart != NULL, FIsLSDNODE(plsdnStart));
  839. AssertImplies(plsdnStart != NULL,
  840. SublineFromDnode(plsdnStart) == SublineFromDnode(pgroupchunkiterator->plsdnFirst));
  841. *pfSuccessful = fFalse;
  842. return plsdnStart;
  843. }
  844. Assert(FIsLSDNODE(plsdnStart));
  845. plssubl = SublineFromDnode(plsdnStart);
  846. /* we assume here that here that plsnStart is valid dnode within subline*/
  847. Assert(!FIsOutOfBoundary(plsdnStart, plssubl->cpLim));
  848. *pfSuccessful = fTrue;
  849. if (FIsDnodeBorder(plsdnStart) || FIsDnodePen(plsdnStart))
  850. {
  851. return plsdnStart;
  852. }
  853. rgpsubl = GetSubmittedSublines(plsdnStart, pgroupchunkiterator->Purpose);
  854. if (rgpsubl == NULL)
  855. {
  856. return plsdnStart;
  857. }
  858. else
  859. {
  860. cSublines = GetNumberSubmittedSublines(plsdnStart);
  861. if (cSublines > 0)
  862. {
  863. plssubl = pgroupchunkiterator->fForward ?
  864. rgpsubl[0] : rgpsubl[cSublines - 1];
  865. /* we assume here that empty subline can not be submitted */
  866. Assert(!FIsOutOfBoundary(plssubl->plsdnFirst, plssubl->cpLim));
  867. plssubl->plsdnUpTemp = plsdnStart;
  868. pgroupchunkiterator->plsdnStart = pgroupchunkiterator->fForward ?
  869. plssubl->plsdnFirst : plssubl->plsdnLast;
  870. return ContinueGroupChunk(pgroupchunkiterator, pfSuccessful);
  871. }
  872. else
  873. {
  874. return plsdnStart;
  875. }
  876. }
  877. }
  878. /* G E T N E X T D N O D E I N G R O U P C H U N K*/
  879. /*----------------------------------------------------------------------------
  880. %%Function: GetNextDnodeInGroupChunk
  881. %%Contact: igorzv
  882. Parameters:
  883. pgroupchunkiterator -(IN) handler for iterator
  884. pfSuccessful - (OUT) do we find dnode in this group chunk
  885. Continue traversing list for collecting group chunk
  886. ----------------------------------------------------------------------------*/
  887. PLSDNODE GetNextDnodeInGroupChunk(
  888. GROUPCHUNKITERATOR* pgroupchunkiterator,
  889. BOOL* pfSuccessful)
  890. {
  891. LONG i;
  892. PLSSUBL plssubl;
  893. PLSDNODE plsdnNext;
  894. PLSDNODE plsdnUp;
  895. PLSSUBL* rgpsubl;
  896. LONG cSublines;
  897. PLSDNODE plsdnStart = pgroupchunkiterator->plsdnStart;
  898. if (plsdnStart == NULL) /* first iteration */
  899. {
  900. pgroupchunkiterator->plsdnStart = pgroupchunkiterator->plsdnFirst;
  901. return ContinueGroupChunk(pgroupchunkiterator, pfSuccessful);
  902. }
  903. Assert(FIsLSDNODE(plsdnStart));
  904. plssubl = plsdnStart->plssubl;
  905. plsdnNext = pgroupchunkiterator->fForward ?
  906. plsdnStart->plsdnNext : plsdnStart->plsdnPrev;
  907. /* we are in one of submitted sublines and this subline ended */
  908. if (plssubl != SublineFromDnode(pgroupchunkiterator->plsdnFirst) &&
  909. FIsOutOfBoundary(plsdnNext, plssubl->cpLim))
  910. {
  911. plsdnUp = plssubl->plsdnUpTemp;
  912. Assert(FIsLSDNODE(plsdnUp));
  913. /* flush temporary field */
  914. plssubl->plsdnUpTemp = NULL;
  915. rgpsubl = GetSubmittedSublines(plsdnUp, pgroupchunkiterator->Purpose);
  916. cSublines = GetNumberSubmittedSublines(plsdnUp);
  917. Assert(rgpsubl != NULL);
  918. Assert(cSublines > 0);
  919. /* find index in a array of submitted sublines */
  920. for (i=0; i < cSublines && plssubl != rgpsubl[i]; i++);
  921. Assert(i < cSublines);
  922. if ( (pgroupchunkiterator->fForward && i == cSublines - 1) ||
  923. (!pgroupchunkiterator->fForward && i == 0)
  924. )
  925. /* array ended: return to the upper level */
  926. {
  927. pgroupchunkiterator->plsdnStart = plsdnUp;
  928. return GetNextDnodeInGroupChunk(pgroupchunkiterator, pfSuccessful);
  929. }
  930. else
  931. {
  932. plssubl = pgroupchunkiterator->fForward ?
  933. rgpsubl[i + 1] : rgpsubl[i - 1];
  934. /* we assume here that empty subline can not be submitted */
  935. Assert(!FIsOutOfBoundary(plssubl->plsdnFirst, plssubl->cpLim));
  936. plssubl->plsdnUpTemp = plsdnUp;
  937. pgroupchunkiterator->plsdnStart = plssubl->plsdnFirst;
  938. return ContinueGroupChunk(pgroupchunkiterator, pfSuccessful);
  939. }
  940. }
  941. else /* we can continue with the same subline */
  942. {
  943. pgroupchunkiterator->plsdnStart = plsdnNext;
  944. return ContinueGroupChunk(pgroupchunkiterator, pfSuccessful);
  945. }
  946. }
  947. /* C R E A T E G R O U P C H U N K I T E R A T O R*/
  948. /*----------------------------------------------------------------------------
  949. %%Function: CreateGroupChunkIterator
  950. %%Contact: igorzv
  951. Parameters:
  952. pgroupchunkiterator -(IN) handler for iterator
  953. Purpose -(INI what sublines to take from a complex object
  954. plsdnFirst -(IN) dnode from which we started collecting
  955. cpLim -(IN) boundary for group chunk if we go forward
  956. fForward -(IN) direction of traversing is forward otherwise it's backward
  957. ----------------------------------------------------------------------------*/
  958. static void CreateGroupChunkIterator(
  959. GROUPCHUNKITERATOR* pgroupchunkiterator,
  960. COLLECTSUBLINES Purpose,
  961. PLSDNODE plsdnFirst,
  962. LSCP cpLim,
  963. BOOL fForward)
  964. {
  965. pgroupchunkiterator->Purpose = Purpose;
  966. pgroupchunkiterator->plsdnFirst = plsdnFirst;
  967. pgroupchunkiterator->plsdnStart = NULL;
  968. pgroupchunkiterator->cpLim = cpLim;
  969. pgroupchunkiterator->fForward = fForward;
  970. }
  971. /* D E S T R O Y G R O U P C H U N K I T E R A T O R*/
  972. /*----------------------------------------------------------------------------
  973. %%Function: DesroyGroupChunkIterator
  974. %%Contact: igorzv
  975. Parameters:
  976. pgroupchunkiterator -(IN) handler for iterator
  977. ----------------------------------------------------------------------------*/
  978. static void DestroyGroupChunkIterator(
  979. GROUPCHUNKITERATOR* pgroupchunkiterator)
  980. {
  981. PLSSUBL plssubl;
  982. PLSDNODE plsdn;
  983. if (pgroupchunkiterator->plsdnStart != NULL)
  984. {
  985. plssubl = SublineFromDnode(pgroupchunkiterator->plsdnStart);
  986. while (SublineFromDnode(pgroupchunkiterator->plsdnFirst) != plssubl)
  987. {
  988. plsdn = plssubl->plsdnUpTemp;
  989. Assert(FIsLSDNODE(plsdn));
  990. plssubl->plsdnUpTemp = NULL;
  991. plssubl = SublineFromDnode(plsdn);
  992. }
  993. }
  994. }
  995. /* F E X P A N D B E F O R E N O N T E X T O B J E C T*/
  996. /*----------------------------------------------------------------------------
  997. %%Function: FExpandBeforeNonTextObject
  998. %%Contact: igorzv
  999. Parameters:
  1000. pgrchunkext - (IN) group chunk
  1001. cTextBeforePreviousNonText - (IN) number of text before previous non text
  1002. to calculate contiguous chunk
  1003. pfExpand - (OUT) to expand dnode before non text
  1004. ----------------------------------------------------------------------------*/
  1005. static LSERR FExpandBeforeNonTextObject(GRCHUNKEXT* pgrchunkext, DWORD cTextBeforePrevioustNonText,
  1006. BOOL* pfExpand)
  1007. {
  1008. DWORD cTextBetween;
  1009. LSERR lserr;
  1010. BOOL fSuccessful;
  1011. WCHAR wchar;
  1012. PLSRUN plsrunText;
  1013. HEIGHTS heightsText;
  1014. MWCLS mwcls;
  1015. DWORD iobj;
  1016. LSIMETHODS* plsim;
  1017. PLSDNODE plsdnNonText;
  1018. *pfExpand = fTrue;
  1019. cTextBetween = pgrchunkext->lsgrchnk.clsgrchnk - cTextBeforePrevioustNonText;
  1020. if (cTextBetween)
  1021. {
  1022. lserr = GetLastCharInChunk(cTextBetween,
  1023. (pgrchunkext->lsgrchnk.plschnk + cTextBeforePrevioustNonText), &fSuccessful,
  1024. &wchar, &plsrunText, &heightsText, &mwcls);
  1025. if (lserr != lserrNone)
  1026. return lserr;
  1027. if (fSuccessful)
  1028. {
  1029. plsdnNonText = pgrchunkext->pplsdnNonText[pgrchunkext->cNonTextObjects - 1];
  1030. iobj = IdObjFromDnode(plsdnNonText);
  1031. plsim = PLsimFromLsc(pgrchunkext->plschunkcontext->plsiobjcontext, iobj);
  1032. if (plsim->pfnFExpandWithPrecedingChar != NULL)
  1033. {
  1034. lserr = plsim->pfnFExpandWithPrecedingChar(plsdnNonText->u.real.pdobj,
  1035. plsdnNonText->u.real.plsrun, plsrunText, wchar,
  1036. mwcls, pfExpand);
  1037. if (lserr != lserrNone)
  1038. return lserr;
  1039. } /* object has this method */
  1040. } /* call back from text was successful */
  1041. }
  1042. return lserrNone;
  1043. }
  1044. /* F E X P A N D A F T E R N O N T E X T O B J E C T*/
  1045. /*----------------------------------------------------------------------------
  1046. %%Function: FExpandAfterNonTextObject
  1047. %%Contact: igorzv
  1048. Parameters:
  1049. pgrchunkext - (IN) group chunk
  1050. cTextBeforeLastNonText - (IN) number of text before last non text
  1051. to calculate contiguous chunk
  1052. pfExpand - (OUT) to expand dnode before non text
  1053. ----------------------------------------------------------------------------*/
  1054. static LSERR FExpandAfterNonTextObject(GRCHUNKEXT* pgrchunkext, DWORD cTextBeforeLastNonText,
  1055. BOOL* pfExpand)
  1056. {
  1057. DWORD cTextBetween;
  1058. LSERR lserr;
  1059. BOOL fSuccessful;
  1060. WCHAR wchar;
  1061. PLSRUN plsrunText;
  1062. HEIGHTS heightsText;
  1063. MWCLS mwcls;
  1064. DWORD iobj;
  1065. LSIMETHODS* plsim;
  1066. PLSDNODE plsdnNonText;
  1067. *pfExpand = fTrue;
  1068. cTextBetween = pgrchunkext->lsgrchnk.clsgrchnk - cTextBeforeLastNonText;
  1069. if (cTextBetween)
  1070. {
  1071. lserr = GetFirstCharInChunk(cTextBetween,
  1072. (pgrchunkext->lsgrchnk.plschnk + cTextBeforeLastNonText), &fSuccessful,
  1073. &wchar, &plsrunText, &heightsText, &mwcls);
  1074. if (lserr != lserrNone)
  1075. return lserr;
  1076. if (fSuccessful)
  1077. {
  1078. plsdnNonText = pgrchunkext->pplsdnNonText[pgrchunkext->cNonTextObjects - 1];
  1079. iobj = IdObjFromDnode(plsdnNonText);
  1080. plsim = PLsimFromLsc(pgrchunkext->plschunkcontext->plsiobjcontext, iobj);
  1081. if (plsim->pfnFExpandWithFollowingChar != NULL)
  1082. {
  1083. lserr = plsim->pfnFExpandWithFollowingChar(plsdnNonText->u.real.pdobj,
  1084. plsdnNonText->u.real.plsrun, plsrunText, wchar,
  1085. mwcls, pfExpand);
  1086. if (lserr != lserrNone)
  1087. return lserr;
  1088. } /* object has this method */
  1089. } /* call back from text was successful */
  1090. }
  1091. return lserrNone;
  1092. }
  1093. /* C O L L E C T P R E V I O U S T E X T G R O U P C H U N K*/
  1094. /*----------------------------------------------------------------------------
  1095. %%Function: CollectPreviousTextGroupChunk
  1096. %%Contact: igorzv
  1097. Parameters:
  1098. plsdnEnd - (IN) end dnode
  1099. sublinnesToCollect (IN) what subline to take from complex object
  1100. pgrchunkext - (OUT) group chunk to fill in
  1101. Fill in group chunk structure with text dnodes located before plsdEnd
  1102. ----------------------------------------------------------------------------*/
  1103. LSERR CollectPreviousTextGroupChunk(
  1104. PLSDNODE plsdnEnd,
  1105. COLLECTSUBLINES Purpose,
  1106. BOOL fAllSimpleText,
  1107. GRCHUNKEXT* pgrchunkext)
  1108. {
  1109. LSCHUNKCONTEXT* plschunkcontext = pgrchunkext->plschunkcontext;
  1110. PLOCCHNK plocchnk;
  1111. DWORD cChunk;
  1112. LSCP cpLim;
  1113. PLSDNODE plsdn;
  1114. PLSDNODE plsdnPrev;
  1115. Assert(FIsLSDNODE(plsdnEnd));
  1116. Assert(FIsGrchnkExtValid(plschunkcontext, pgrchunkext));
  1117. /* we try to optimize here in a case when there is only text in line */
  1118. /* chunk of text has been already collected */
  1119. plocchnk = &(plschunkcontext->locchnkCurrent);
  1120. cChunk = plocchnk->clschnk;
  1121. cpLim = plsdnEnd->cpLimOriginal;
  1122. if (fAllSimpleText && cChunk > 0)
  1123. {
  1124. /* chunk goes up to the end of a line */
  1125. Assert((plschunkcontext->pplsdnChunk[cChunk - 1])->plsdnNext == NULL);
  1126. pgrchunkext->Purpose = Purpose;
  1127. return ConvertChunkToGroupChunk(pgrchunkext, cpLim);
  1128. }
  1129. /* go backward to the start of group chunk */
  1130. plsdn = plsdnEnd;
  1131. plsdnPrev = plsdn->plsdnPrev;
  1132. while (!FIsGroupChunkStartBoundary(plsdnPrev, plsdnEnd->cpFirst))
  1133. {
  1134. plsdn = plsdnPrev;
  1135. plsdnPrev = plsdn->plsdnPrev;
  1136. }
  1137. return CollectTextGroupChunk(plsdn, cpLim, Purpose, pgrchunkext);
  1138. }
  1139. /* C O N V E R T C H U N K T O G R O U P C H U N K*/
  1140. /*----------------------------------------------------------------------------
  1141. %%Function: ConvertChunkToGroupChunk
  1142. %%Contact: igorzv
  1143. Parameters:
  1144. cpLim - (IN) cpLim
  1145. pgrchunkext - (OUT) group chunk to fill in
  1146. Fill in group chunk structure with text dnodes located before plsdEnd
  1147. We assume here that chunk doesn't contain border.
  1148. ----------------------------------------------------------------------------*/
  1149. static LSERR ConvertChunkToGroupChunk(GRCHUNKEXT* pgrchunkext, LSCP cpLim)
  1150. {
  1151. DWORD clsgrchnkCollected = 0;
  1152. long durTotal = 0;
  1153. LSCHUNKCONTEXT* plschunkcontext = pgrchunkext->plschunkcontext;
  1154. PLOCCHNK plocchnk;
  1155. LONG cChunk;
  1156. LONG i;
  1157. BOOL fLineEnded;
  1158. PLSDNODE plsdn;
  1159. long durTrailingDnode;
  1160. LSDCP dcpTrailingDnode;
  1161. Assert(FIsGrchnkExtValid(plschunkcontext, pgrchunkext));
  1162. plocchnk = &(plschunkcontext->locchnkCurrent);
  1163. cChunk = (int) plocchnk->clschnk;
  1164. fLineEnded = fFalse;
  1165. for (i = 0; (i < cChunk) && !fLineEnded; i ++)
  1166. {
  1167. clsgrchnkCollected++;
  1168. pgrchunkext->lsgrchnk.pcont[i] = 0;
  1169. plsdn = plschunkcontext->pplsdnChunk[i];
  1170. durTotal += DurFromRealDnode(plsdn);
  1171. /* if we are in last dnode before cpLim there is possibility
  1172. that during break it was changed
  1173. so we should rewrite dcp in chunk element and quit */
  1174. if ((LSCP)(plsdn->cpLimOriginal) == cpLim)
  1175. {
  1176. plocchnk->plschnk[i].dcp = plsdn->dcp;
  1177. fLineEnded = fTrue;
  1178. }
  1179. }
  1180. /* fill in header of groupchunkext */
  1181. pgrchunkext->plsdnFirst = plschunkcontext->pplsdnChunk[0];;
  1182. pgrchunkext->plsdnLastUsed = plschunkcontext->pplsdnChunk[clsgrchnkCollected - 1];
  1183. pgrchunkext->plsdnNext = pgrchunkext->plsdnLastUsed->plsdnNext;
  1184. pgrchunkext->durTotal = durTotal;
  1185. pgrchunkext->durTextTotal = durTotal;
  1186. pgrchunkext->dupNonTextTotal = 0;
  1187. pgrchunkext->cNonTextObjects = 0;
  1188. pgrchunkext->cNonTextObjectsExpand = 0;
  1189. pgrchunkext->lsgrchnk.clsgrchnk = clsgrchnkCollected;
  1190. plschunkcontext->FGroupChunk = fTrue;
  1191. if (pgrchunkext->Purpose == CollectSublinesForJustification ||
  1192. pgrchunkext->Purpose == CollectSublinesForCompression)
  1193. {
  1194. Assert(clsgrchnkCollected > 0);
  1195. pgrchunkext->durTrailing = 0;
  1196. pgrchunkext->dcpTrailing = 0;
  1197. plsdn = NULL;
  1198. dcpTrailingDnode = 0;
  1199. pgrchunkext->fClosingBorderStartsTrailing = fFalse;
  1200. for (i = clsgrchnkCollected - 1; i >= 0; i--)
  1201. {
  1202. plsdn = plschunkcontext->pplsdnChunk[i];
  1203. GetTrailInfoText(PdobjFromDnode(plsdn), plsdn->dcp,
  1204. &dcpTrailingDnode, &durTrailingDnode);
  1205. pgrchunkext->durTrailing += durTrailingDnode;
  1206. pgrchunkext->dcpTrailing += dcpTrailingDnode;
  1207. /* add opening border before previous dnode */
  1208. if (i < (int) (clsgrchnkCollected - 1))
  1209. pgrchunkext->durTrailing += plschunkcontext->pdurOpenBorderBefore[i +1];
  1210. if (dcpTrailingDnode != 0)
  1211. /* add closing border after */
  1212. pgrchunkext->durTrailing += plschunkcontext->pdurCloseBorderAfter[i];
  1213. else
  1214. {
  1215. pgrchunkext->fClosingBorderStartsTrailing =
  1216. (plschunkcontext->pdurCloseBorderAfter[i] != 0);
  1217. }
  1218. if (plsdn->dcp != dcpTrailingDnode)
  1219. break;
  1220. }
  1221. pgrchunkext->plsdnStartTrailing = plsdn;
  1222. if (i == -1) i = 0;
  1223. pgrchunkext->posichnkBeforeTrailing.ichnk = i;
  1224. pgrchunkext->posichnkBeforeTrailing.dcp = plsdn->dcp - dcpTrailingDnode;
  1225. }
  1226. return lserrNone;
  1227. }
  1228. /* G E T T R A I L I N G I N F O F O R T E X T G R O U P C H U N K */
  1229. /*----------------------------------------------------------------------------
  1230. %%Function: GetTrailingInfoForTextGroupChunk
  1231. %%Contact: igorzv
  1232. Parameters:
  1233. plsdnLastDnode - (IN) dnode where to start calculation of trailing area
  1234. dcpLastDnode - (IN) dcp in this dnode
  1235. iobjText - (IN) iobj of text
  1236. pdurTrailing - (OUT) dur of trailing area in group chunk
  1237. pdcpTrailing - (OUT) dcp of trailing area in chunk
  1238. pplsdnStartTrailing - (OUT) dnode where trailing area starts
  1239. pdcpStartTrailing- (OUT) with pcDnodesTrailing defines last character in text before
  1240. trailing area
  1241. pcDnodesTrailing - (OUT) number of text dnodes participates in trailing area
  1242. pplsdnStartTrailingObject -(OUT) dnode on the upper level where trailing are starts
  1243. pdcpStartTrailingObject -(OUT) dcp in such dnode
  1244. pfClosingBorderStartsTrailing - (OUT) closing border located just before trailing area
  1245. ----------------------------------------------------------------------------*/
  1246. LSERR GetTrailingInfoForTextGroupChunk
  1247. (PLSDNODE plsdnLast, LSDCP dcpLastDnode, DWORD iobjText,
  1248. long* pdurTrailing, LSDCP* pdcpTrailing,
  1249. PLSDNODE* pplsdnStartTrailing, LSDCP* pdcpStartTrailing,
  1250. int* pcDnodesTrailing, PLSDNODE* pplsdnStartTrailingObject,
  1251. LSDCP* pdcpStartTrailingObject, BOOL* pfClosingBorderStartsTrailing)
  1252. {
  1253. PLSDNODE plsdn;
  1254. long durTrailingDnode;
  1255. LSDCP dcpTrailingDnode;
  1256. BOOL fSuccessful;
  1257. LSDCP dcpDnode;
  1258. GROUPCHUNKITERATOR groupchunkiterator;
  1259. LSCP cpLim;
  1260. LSCP cpLimTrail;
  1261. LSSUBL* plssubl;
  1262. long durPrevClosingBorder = 0;
  1263. *pdurTrailing = 0;
  1264. *pdcpTrailing = 0;
  1265. *pplsdnStartTrailing = plsdnLast;
  1266. *pdcpStartTrailing = dcpLastDnode;
  1267. *pcDnodesTrailing = 0;
  1268. if (plsdnLast->dcp == dcpLastDnode)
  1269. cpLim = plsdnLast->cpLimOriginal;
  1270. else
  1271. cpLim = plsdnLast->cpFirst + dcpLastDnode;
  1272. CreateGroupChunkIterator(&groupchunkiterator,
  1273. CollectSublinesForTrailingArea, plsdnLast,
  1274. cpLim, fFalse);
  1275. plsdn = GetNextDnodeInGroupChunk(&groupchunkiterator, &fSuccessful);
  1276. while(fSuccessful)
  1277. {
  1278. *pplsdnStartTrailing = plsdn;
  1279. /* this procedure can be called before SetBreak so we should calculate
  1280. dcp of last dnode in chunk using cpLim */
  1281. if (plsdn->cpLimOriginal > cpLim)
  1282. dcpDnode = cpLim - plsdn->cpFirst;
  1283. else
  1284. dcpDnode = plsdn->dcp;
  1285. *pdcpStartTrailing = dcpDnode;
  1286. if (FIsDnodeReal(plsdn) && !FIsDnodeSplat(plsdn)) /* not a pen border or splat*/
  1287. {
  1288. if (IdObjFromDnode(plsdn) == iobjText) /* is text */
  1289. {
  1290. GetTrailInfoText(PdobjFromDnode(plsdn), dcpDnode,
  1291. &dcpTrailingDnode, &durTrailingDnode);
  1292. (*pcDnodesTrailing)++;
  1293. if (dcpTrailingDnode == 0)
  1294. {
  1295. break;
  1296. }
  1297. *pdurTrailing += durTrailingDnode;
  1298. *pdcpTrailing += dcpTrailingDnode;
  1299. *pdcpStartTrailing -= dcpTrailingDnode;
  1300. *pdurTrailing += durPrevClosingBorder;
  1301. durPrevClosingBorder = 0;
  1302. if (dcpDnode != dcpTrailingDnode)
  1303. break;
  1304. }
  1305. else
  1306. {
  1307. /* object which did not submit subline for trailing */
  1308. break;
  1309. }
  1310. }
  1311. else
  1312. {
  1313. /* border or splat */
  1314. if (FIsDnodeCloseBorder(plsdn))
  1315. {
  1316. durPrevClosingBorder = DurFromDnode(plsdn);
  1317. }
  1318. else
  1319. {
  1320. *pdurTrailing += DurFromDnode(plsdn);
  1321. }
  1322. *pdcpTrailing += plsdn->dcp;
  1323. }
  1324. plsdn = GetNextDnodeInGroupChunk(&groupchunkiterator, &fSuccessful);
  1325. }
  1326. *pfClosingBorderStartsTrailing = (durPrevClosingBorder != 0);
  1327. if (*pcDnodesTrailing == 0)
  1328. {
  1329. *pplsdnStartTrailingObject = plsdnLast;
  1330. *pdcpStartTrailingObject = dcpLastDnode;
  1331. }
  1332. else if (SublineFromDnode(*pplsdnStartTrailing) ==
  1333. SublineFromDnode(plsdnLast))
  1334. {
  1335. *pplsdnStartTrailingObject = *pplsdnStartTrailing;
  1336. *pdcpStartTrailingObject = *pdcpStartTrailing;
  1337. }
  1338. /* the last dnode we've checked was on the lower level */
  1339. else if (fSuccessful) /* and we actually stopped on it */
  1340. {
  1341. if ((*pplsdnStartTrailing)->dcp == *pdcpStartTrailing)
  1342. cpLimTrail = (*pplsdnStartTrailing)->cpLimOriginal;
  1343. else
  1344. cpLimTrail = (*pplsdnStartTrailing)->cpFirst + *pdcpStartTrailing;
  1345. plsdn = *pplsdnStartTrailing;
  1346. plssubl = SublineFromDnode(plsdn);
  1347. while (SublineFromDnode(plsdnLast) != plssubl)
  1348. {
  1349. plsdn = plssubl->plsdnUpTemp;
  1350. Assert(FIsLSDNODE(plsdn));
  1351. plssubl = SublineFromDnode(plsdn);
  1352. }
  1353. *pplsdnStartTrailingObject = plsdn;
  1354. if (plsdn->cpLimOriginal > cpLimTrail)
  1355. *pdcpStartTrailingObject = cpLimTrail - plsdn->cpFirst;
  1356. else
  1357. *pdcpStartTrailingObject = plsdn->dcp;
  1358. }
  1359. else
  1360. {
  1361. /* we went through all group chunk and the last dnode under investigation was on lower level */
  1362. /* plsdn is dnode before group chunk */
  1363. if (plsdn == NULL) /* there is nothing before group chunk */
  1364. {
  1365. *pplsdnStartTrailingObject = (SublineFromDnode(plsdnLast))->plsdnFirst;
  1366. }
  1367. else
  1368. {
  1369. *pplsdnStartTrailingObject = plsdn->plsdnNext;
  1370. }
  1371. Assert(FIsLSDNODE(*pplsdnStartTrailingObject));
  1372. *pdcpStartTrailingObject = 0;
  1373. }
  1374. DestroyGroupChunkIterator(&groupchunkiterator);
  1375. return lserrNone;
  1376. }
  1377. /* A L L O C C H U N K A R R A Y S */
  1378. /*----------------------------------------------------------------------------
  1379. %%Function: AllocChunkArrays
  1380. %%Contact: igorzv
  1381. Parameters:
  1382. plschunkcontext - (IN) chunk context
  1383. plscbk - (IN) callbacks
  1384. pols - (IN) pols for callbacks
  1385. plsiobjcontext - (IN) pointer to a table of methods
  1386. ----------------------------------------------------------------------------*/
  1387. LSERR AllocChunkArrays(PLSCHUNKCONTEXT plschunkcontext, LSCBK* plscbk, POLS pols,
  1388. PLSIOBJCONTEXT plsiobjcontext)
  1389. {
  1390. plschunkcontext->pplsdnChunk = plscbk->pfnNewPtr(pols,
  1391. sizeof(PLSDNODE)*limAllDNodes);
  1392. plschunkcontext->pcont = plscbk->pfnNewPtr(pols,
  1393. sizeof(DWORD)*limAllDNodes);
  1394. plschunkcontext->locchnkCurrent.plschnk = plscbk->pfnNewPtr(pols,
  1395. sizeof(LSCHNKE)*limAllDNodes);
  1396. plschunkcontext->locchnkCurrent.ppointUvLoc = plscbk->pfnNewPtr(pols,
  1397. sizeof(POINTUV)*limAllDNodes);
  1398. plschunkcontext->pfNonTextExpandAfter = plscbk->pfnNewPtr(pols,
  1399. sizeof(BOOL)*limAllDNodes);
  1400. plschunkcontext->pplsdnNonText = plscbk->pfnNewPtr(pols,
  1401. sizeof(PLSDNODE)*limAllDNodes);
  1402. plschunkcontext->pdurOpenBorderBefore = plscbk->pfnNewPtr(pols,
  1403. sizeof(LONG)*limAllDNodes);
  1404. plschunkcontext->pdurCloseBorderAfter = plscbk->pfnNewPtr(pols,
  1405. sizeof(LONG)*limAllDNodes);
  1406. plschunkcontext->cchnkMax = limAllDNodes;
  1407. plschunkcontext->cNonTextMax = limAllDNodes;
  1408. plschunkcontext->plscbk = plscbk;
  1409. plschunkcontext->pols = pols;
  1410. plschunkcontext->plsiobjcontext = plsiobjcontext;
  1411. if (plschunkcontext->pplsdnChunk == NULL || plschunkcontext->pcont == NULL
  1412. || plschunkcontext->locchnkCurrent.plschnk == NULL
  1413. || plschunkcontext->locchnkCurrent.ppointUvLoc == NULL
  1414. || plschunkcontext->pfNonTextExpandAfter == NULL
  1415. || plschunkcontext->pplsdnNonText == NULL
  1416. ||plschunkcontext->pdurOpenBorderBefore == NULL
  1417. ||plschunkcontext->pdurCloseBorderAfter == NULL
  1418. )
  1419. {
  1420. return lserrOutOfMemory;
  1421. }
  1422. else
  1423. {
  1424. return lserrNone;
  1425. }
  1426. }
  1427. /* G E T U R P E N A T B E G I N I N G O F L A S T C H U N K */
  1428. /*----------------------------------------------------------------------------
  1429. %%Function: GetUrPenAtBeginingOfLastChunk
  1430. %%Contact: igorzv
  1431. Parameters:
  1432. plschunkcontext - (IN) chunk context
  1433. plsdnFirst - (IN) First dnode in a chunk (used for checks)
  1434. plsdnLast - (IN) last dnode in subline
  1435. point - (IN) point after last dnode
  1436. purPen - (OUT) ur before chunk
  1437. ----------------------------------------------------------------------------*/
  1438. LSERR GetUrPenAtBeginingOfLastChunk(PLSCHUNKCONTEXT plschunkcontext,PLSDNODE plsdnFirst,
  1439. PLSDNODE plsdnLast, POINTUV* ppoint,
  1440. long* purPen)
  1441. {
  1442. /* chunk must be already collected and has plsdnFirst as the first element */
  1443. Assert(plschunkcontext->locchnkCurrent.clschnk != 0);
  1444. Assert(!plschunkcontext->FGroupChunk);
  1445. Assert(plschunkcontext->pplsdnChunk[0]== plsdnFirst);
  1446. if (plschunkcontext->locchnkCurrent.clschnk == 0 ||
  1447. plschunkcontext->FGroupChunk ||
  1448. plschunkcontext->pplsdnChunk[0]!= plsdnFirst)
  1449. return lserrInvalidParameter;
  1450. /* calculate point before the last dnode */
  1451. ppoint->u -= DurFromDnode(plsdnLast);
  1452. ppoint->v -= DvrFromDnode(plsdnLast);
  1453. /* go back until first dnode in chunk */
  1454. while(plsdnLast != plsdnFirst)
  1455. {
  1456. plsdnLast = plsdnLast->plsdnPrev;
  1457. Assert(FIsLSDNODE(plsdnLast));
  1458. ppoint->u -= DurFromDnode(plsdnLast);
  1459. ppoint->v -= DvrFromDnode(plsdnLast);
  1460. }
  1461. /* locate chunk */
  1462. if (!plschunkcontext->FLocationValid)
  1463. {
  1464. LocateChunk(plschunkcontext, plsdnFirst, LstflowFromDnode(plsdnFirst), ppoint);
  1465. }
  1466. *purPen = plschunkcontext->locchnkCurrent.lsfgi.urPen;
  1467. return lserrNone;
  1468. }
  1469. /* F I N D P O I N T O F F S E T */
  1470. /*----------------------------------------------------------------------------
  1471. %%Function: FindPointOffset
  1472. %%Contact: igorzv
  1473. Parameters:
  1474. plsdnFirst - (IN) dnode from the boundaries of which to calculate offset
  1475. lsdev - (IN) presentation or reference device
  1476. lstflowBase - (IN) text flow to use for calculation
  1477. Purpose - (IN) what sublines to take from a complex object
  1478. plsdnContainsPoint - (IN) dnode contains point
  1479. duInDnode, - (IN) offset in the dnode
  1480. pduOffset - (OUT) offset from the starting point
  1481. ----------------------------------------------------------------------------*/
  1482. void FindPointOffset(PLSDNODE plsdnFirst, enum lsdevice lsdev,
  1483. LSTFLOW lstflowBase, COLLECTSUBLINES Purpose,
  1484. PLSDNODE plsdnContainsPoint, long duInDnode,
  1485. long* pduOffset)
  1486. {
  1487. PLSDNODE plsdnCurrent;
  1488. PLSSUBL plssubl;
  1489. LSTFLOW lstflow;
  1490. LSCP cpFirstDnode;
  1491. PLSSUBL* rgpsubl;
  1492. long cSublines;
  1493. long i;
  1494. long duOffsetSubline;
  1495. plssubl = SublineFromDnode(plsdnFirst);
  1496. lstflow = LstflowFromSubline(plssubl);
  1497. cpFirstDnode = plsdnContainsPoint->cpFirst;
  1498. *pduOffset = 0;
  1499. if (FParallelTflows(lstflow, lstflowBase))
  1500. {
  1501. for(plsdnCurrent = plsdnFirst;
  1502. plsdnCurrent->cpLimOriginal <= cpFirstDnode && (plsdnCurrent != plsdnContainsPoint);
  1503. /* second check is to catch situation when plsdnContainsPoint has dcp = 0 */
  1504. plsdnCurrent = plsdnCurrent->plsdnNext)
  1505. {
  1506. Assert(FIsLSDNODE(plsdnCurrent));
  1507. if (lsdev == lsdevReference)
  1508. {
  1509. *pduOffset += DurFromDnode(plsdnCurrent);
  1510. }
  1511. else
  1512. {
  1513. Assert(lsdev == lsdevPres);
  1514. *pduOffset += DupFromDnode(plsdnCurrent);
  1515. }
  1516. }
  1517. Assert(FIsLSDNODE(plsdnCurrent));
  1518. if (FIsDnodeReal(plsdnCurrent))
  1519. rgpsubl = GetSubmittedSublines(plsdnCurrent, Purpose);
  1520. else
  1521. rgpsubl = NULL;
  1522. if (rgpsubl == NULL)
  1523. {
  1524. Assert(plsdnCurrent == plsdnContainsPoint);
  1525. *pduOffset += duInDnode;
  1526. }
  1527. else
  1528. {
  1529. cSublines = GetNumberSubmittedSublines(plsdnCurrent);
  1530. /* if everything is correct we should always find subline in this loop,
  1531. check (i < cSublines) is just to avoid infinite loop and catch situation in a Assert */
  1532. for (i = 0; (i < cSublines) && !FDnodeInsideSubline(rgpsubl[i], plsdnContainsPoint); i++)
  1533. {
  1534. plssubl = rgpsubl[i];
  1535. Assert(FIsLSSUBL(plssubl));
  1536. for (plsdnCurrent = plssubl->plsdnFirst;
  1537. FDnodeBeforeCpLim(plsdnCurrent, plssubl->cpLim);
  1538. plsdnCurrent = plsdnCurrent->plsdnNext)
  1539. {
  1540. Assert(FIsLSDNODE(plsdnCurrent));
  1541. if (lsdev == lsdevReference)
  1542. {
  1543. *pduOffset += DurFromDnode(plsdnCurrent);
  1544. }
  1545. else
  1546. {
  1547. Assert(lsdev == lsdevPres);
  1548. *pduOffset += DupFromDnode(plsdnCurrent);
  1549. }
  1550. }
  1551. }
  1552. Assert(i != cSublines);
  1553. plssubl = rgpsubl[i];
  1554. Assert(FIsLSSUBL(plssubl));
  1555. FindPointOffset(plssubl->plsdnFirst, lsdev, lstflowBase,
  1556. Purpose, plsdnContainsPoint, duInDnode,
  1557. &duOffsetSubline);
  1558. *pduOffset += duOffsetSubline;
  1559. }
  1560. }
  1561. else
  1562. {
  1563. for(plsdnCurrent = plssubl->plsdnLast;
  1564. plsdnCurrent->cpFirst > cpFirstDnode && (plsdnCurrent != plsdnContainsPoint);
  1565. /* second check is to catch situation when plsdnContainsPoint has dcp = 0 */
  1566. plsdnCurrent = plsdnCurrent->plsdnPrev)
  1567. {
  1568. Assert(FIsLSDNODE(plsdnCurrent));
  1569. if (lsdev == lsdevReference)
  1570. {
  1571. *pduOffset += DurFromDnode(plsdnCurrent);
  1572. }
  1573. else
  1574. {
  1575. Assert(lsdev == lsdevPres);
  1576. *pduOffset += DupFromDnode(plsdnCurrent);
  1577. }
  1578. }
  1579. Assert(FIsLSDNODE(plsdnCurrent));
  1580. if (FIsDnodeReal(plsdnCurrent))
  1581. rgpsubl = GetSubmittedSublines(plsdnCurrent, Purpose);
  1582. else
  1583. rgpsubl = NULL;
  1584. if (rgpsubl == NULL)
  1585. {
  1586. Assert(plsdnCurrent == plsdnContainsPoint);
  1587. if (lsdev == lsdevReference)
  1588. {
  1589. *pduOffset += (DurFromDnode(plsdnCurrent) - duInDnode);
  1590. }
  1591. else
  1592. {
  1593. Assert(lsdev == lsdevPres);
  1594. *pduOffset += (DupFromDnode(plsdnCurrent) - duInDnode);
  1595. }
  1596. }
  1597. else
  1598. {
  1599. cSublines = GetNumberSubmittedSublines(plsdnCurrent);
  1600. /* if everything is correct we should always find subline in this loop,
  1601. check (i >= 0) is just to avoid infinite loop and catch situation in a Assert */
  1602. for (i = cSublines - 1; (i >= 0) && !FDnodeInsideSubline(rgpsubl[i], plsdnContainsPoint); i--)
  1603. {
  1604. plssubl = rgpsubl[i];
  1605. Assert(FIsLSSUBL(plssubl));
  1606. for (plsdnCurrent = plssubl->plsdnFirst;
  1607. FDnodeBeforeCpLim(plsdnCurrent, plssubl->cpLim);
  1608. plsdnCurrent = plsdnCurrent->plsdnNext)
  1609. {
  1610. Assert(FIsLSDNODE(plsdnCurrent));
  1611. if (lsdev == lsdevReference)
  1612. {
  1613. *pduOffset += DurFromDnode(plsdnCurrent);
  1614. }
  1615. else
  1616. {
  1617. Assert(lsdev == lsdevPres);
  1618. *pduOffset += DupFromDnode(plsdnCurrent);
  1619. }
  1620. }
  1621. }
  1622. Assert(i >= 0);
  1623. plssubl = rgpsubl[i];
  1624. Assert(FIsLSSUBL(plssubl));
  1625. FindPointOffset(plssubl->plsdnFirst, lsdev, lstflowBase,
  1626. Purpose, plsdnContainsPoint, duInDnode,
  1627. &duOffsetSubline);
  1628. *pduOffset += duOffsetSubline;
  1629. }
  1630. }
  1631. }
  1632. /* D I S P O S E C H U N K A R R A Y S */
  1633. /*----------------------------------------------------------------------------
  1634. %%Function: AllocChunkArrays
  1635. %%Contact: igorzv
  1636. Parameters:
  1637. plschunkcontext - (IN) chunk context
  1638. ----------------------------------------------------------------------------*/
  1639. void DisposeChunkArrays(PLSCHUNKCONTEXT plschunkcontext)
  1640. {
  1641. if (plschunkcontext->pplsdnChunk != NULL)
  1642. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1643. plschunkcontext->pplsdnChunk);
  1644. if (plschunkcontext->pcont != NULL)
  1645. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1646. plschunkcontext->pcont);
  1647. if (plschunkcontext->locchnkCurrent.plschnk != NULL)
  1648. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1649. plschunkcontext->locchnkCurrent.plschnk);
  1650. if (plschunkcontext->locchnkCurrent.ppointUvLoc != NULL)
  1651. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1652. plschunkcontext->locchnkCurrent.ppointUvLoc);
  1653. if (plschunkcontext->pplsdnNonText != NULL)
  1654. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1655. plschunkcontext->pplsdnNonText);
  1656. if (plschunkcontext->pfNonTextExpandAfter != NULL)
  1657. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1658. plschunkcontext->pfNonTextExpandAfter);
  1659. if (plschunkcontext->pdurOpenBorderBefore != NULL)
  1660. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1661. plschunkcontext->pdurOpenBorderBefore);
  1662. if (plschunkcontext->pdurCloseBorderAfter != NULL)
  1663. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1664. plschunkcontext->pdurCloseBorderAfter);
  1665. }
  1666. /* S E T C H U N K A R R A Y S S I Z E */
  1667. /*----------------------------------------------------------------------------
  1668. %%Function: SetChunkArraysSize
  1669. %%Contact: igorzv
  1670. Parameters:
  1671. plschunkcontext - (IN) chunk context
  1672. cchnkMax - (IN) new max size for array
  1673. ----------------------------------------------------------------------------*/
  1674. static LSERR SetChunkArraysSize(PLSCHUNKCONTEXT plschunkcontext, DWORD cchnkMax)
  1675. {
  1676. /* arrays pfNonTextExpandAfter and pplsdnNonText should not be touched here:
  1677. they are independable */
  1678. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1679. plschunkcontext->pplsdnChunk);
  1680. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1681. plschunkcontext->pcont);
  1682. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1683. plschunkcontext->locchnkCurrent.plschnk);
  1684. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1685. plschunkcontext->locchnkCurrent.ppointUvLoc);
  1686. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1687. plschunkcontext->pdurOpenBorderBefore);
  1688. plschunkcontext->plscbk->pfnDisposePtr(plschunkcontext->pols,
  1689. plschunkcontext->pdurCloseBorderAfter);
  1690. /* create arrays for chunks */
  1691. plschunkcontext->pplsdnChunk = plschunkcontext->plscbk->pfnNewPtr(plschunkcontext->pols,
  1692. sizeof(PLSDNODE)*cchnkMax);
  1693. plschunkcontext->pcont = plschunkcontext->plscbk->pfnNewPtr(plschunkcontext->pols,
  1694. sizeof(DWORD)*cchnkMax);
  1695. plschunkcontext->locchnkCurrent.plschnk = plschunkcontext->plscbk->pfnNewPtr(plschunkcontext->pols,
  1696. sizeof(LSCHNKE)*cchnkMax);
  1697. plschunkcontext->locchnkCurrent.ppointUvLoc = plschunkcontext->plscbk->pfnNewPtr(plschunkcontext->pols,
  1698. sizeof(POINTUV)*cchnkMax);
  1699. plschunkcontext->pdurOpenBorderBefore = plschunkcontext->plscbk->pfnNewPtr(plschunkcontext->pols,
  1700. sizeof(LONG)*cchnkMax);
  1701. plschunkcontext->pdurCloseBorderAfter = plschunkcontext->plscbk->pfnNewPtr(plschunkcontext->pols,
  1702. sizeof(LONG)*cchnkMax);
  1703. if (plschunkcontext->pplsdnChunk == NULL || plschunkcontext->pcont == NULL
  1704. || plschunkcontext->locchnkCurrent.plschnk == NULL
  1705. || plschunkcontext->locchnkCurrent.ppointUvLoc == NULL
  1706. || plschunkcontext->pdurOpenBorderBefore == NULL
  1707. || plschunkcontext->pdurCloseBorderAfter == NULL
  1708. )
  1709. return lserrOutOfMemory;
  1710. plschunkcontext->cchnkMax = cchnkMax;
  1711. return lserrNone;
  1712. }
  1713. /* I N C R E A S E C H U N K A R R A Y S S I Z E */
  1714. /*----------------------------------------------------------------------------
  1715. %%Function: IncreaseChunkArrays
  1716. %%Contact: igorzv
  1717. Parameters:
  1718. plschunkcontext - (IN) chunk context
  1719. The difference from previous function is that we don't now final size
  1720. and going to increase size step by step
  1721. ----------------------------------------------------------------------------*/
  1722. static LSERR IncreaseChunkArrays(PLSCHUNKCONTEXT plschunkcontext)
  1723. {
  1724. /* arrays pfNonTextExpandAfter and pplsdnNonText should not be touched here:
  1725. they are independable */
  1726. DWORD cchnkMax;
  1727. cchnkMax = plschunkcontext->cchnkMax + limAllDNodes;
  1728. /* create arrays for chunks */
  1729. plschunkcontext->pplsdnChunk = plschunkcontext->plscbk->pfnReallocPtr(plschunkcontext->pols,
  1730. plschunkcontext->pplsdnChunk,
  1731. sizeof(PLSDNODE)*cchnkMax);
  1732. plschunkcontext->pcont = plschunkcontext->plscbk->pfnReallocPtr(plschunkcontext->pols,
  1733. plschunkcontext->pcont,
  1734. sizeof(DWORD)*cchnkMax);
  1735. plschunkcontext->locchnkCurrent.plschnk = plschunkcontext->plscbk->pfnReallocPtr(plschunkcontext->pols,
  1736. plschunkcontext->locchnkCurrent.plschnk,
  1737. sizeof(LSCHNKE)*cchnkMax);
  1738. plschunkcontext->locchnkCurrent.ppointUvLoc = plschunkcontext->plscbk->pfnReallocPtr(plschunkcontext->pols,
  1739. plschunkcontext->locchnkCurrent.ppointUvLoc,
  1740. sizeof(POINTUV)*cchnkMax);
  1741. plschunkcontext->pdurOpenBorderBefore = plschunkcontext->plscbk->pfnReallocPtr(plschunkcontext->pols,
  1742. plschunkcontext->pdurOpenBorderBefore,
  1743. sizeof(LONG)*cchnkMax);
  1744. plschunkcontext->pdurCloseBorderAfter = plschunkcontext->plscbk->pfnReallocPtr(plschunkcontext->pols,
  1745. plschunkcontext->pdurCloseBorderAfter,
  1746. sizeof(LONG)*cchnkMax);
  1747. if (plschunkcontext->pplsdnChunk == NULL || plschunkcontext->pcont == NULL
  1748. || plschunkcontext->locchnkCurrent.plschnk == NULL
  1749. || plschunkcontext->locchnkCurrent.ppointUvLoc == NULL
  1750. || plschunkcontext->pdurOpenBorderBefore == NULL
  1751. || plschunkcontext->pdurCloseBorderAfter == NULL
  1752. )
  1753. return lserrOutOfMemory;
  1754. plschunkcontext->cchnkMax = cchnkMax;
  1755. return lserrNone;
  1756. }
  1757. /* D U P L I C A T E C H U N K C O N T E X T */
  1758. /*----------------------------------------------------------------------------
  1759. %%Function: DuplicateChunkContext
  1760. %%Contact: igorzv
  1761. Parameters:
  1762. plschunkcontextOld - (IN) chunk context to duplicate
  1763. pplschunkcontextNew - (OUT) new chunk context
  1764. ----------------------------------------------------------------------------*/
  1765. LSERR DuplicateChunkContext(PLSCHUNKCONTEXT plschunkcontextOld,
  1766. PLSCHUNKCONTEXT* pplschunkcontextNew)
  1767. {
  1768. *pplschunkcontextNew = plschunkcontextOld->plscbk->pfnNewPtr(plschunkcontextOld->pols,
  1769. sizeof(LSCHUNKCONTEXT));
  1770. if (*pplschunkcontextNew == NULL)
  1771. return lserrOutOfMemory;
  1772. memcpy(*pplschunkcontextNew, plschunkcontextOld, sizeof(LSCHUNKCONTEXT));
  1773. /* but we need to use new arrays */
  1774. /* create arrays for chunks */
  1775. (*pplschunkcontextNew)->pplsdnChunk = (*pplschunkcontextNew)->plscbk->pfnNewPtr((*pplschunkcontextNew)->pols,
  1776. sizeof(PLSDNODE) * ((*pplschunkcontextNew)->cchnkMax));
  1777. (*pplschunkcontextNew)->pcont = (*pplschunkcontextNew)->plscbk->pfnNewPtr((*pplschunkcontextNew)->pols,
  1778. sizeof(DWORD) * ((*pplschunkcontextNew)->cchnkMax));
  1779. (*pplschunkcontextNew)->locchnkCurrent.plschnk =
  1780. (*pplschunkcontextNew)->plscbk->pfnNewPtr((*pplschunkcontextNew)->pols,
  1781. sizeof(LSCHNKE) * ((*pplschunkcontextNew)->cchnkMax));
  1782. (*pplschunkcontextNew)->locchnkCurrent.ppointUvLoc =
  1783. (*pplschunkcontextNew)->plscbk->pfnNewPtr((*pplschunkcontextNew)->pols,
  1784. sizeof(POINTUV) * ((*pplschunkcontextNew)->cchnkMax));
  1785. (*pplschunkcontextNew)->pfNonTextExpandAfter =
  1786. (*pplschunkcontextNew)->plscbk->pfnNewPtr((*pplschunkcontextNew)->pols,
  1787. sizeof(BOOL) * ((*pplschunkcontextNew)->cNonTextMax));
  1788. (*pplschunkcontextNew)->pplsdnNonText =
  1789. (*pplschunkcontextNew)->plscbk->pfnNewPtr((*pplschunkcontextNew)->pols,
  1790. sizeof(PLSDNODE) * ((*pplschunkcontextNew)->cNonTextMax));
  1791. (*pplschunkcontextNew)->pdurOpenBorderBefore =
  1792. (*pplschunkcontextNew)->plscbk->pfnNewPtr((*pplschunkcontextNew)->pols,
  1793. sizeof(LONG) * ((*pplschunkcontextNew)->cchnkMax));
  1794. (*pplschunkcontextNew)->pdurCloseBorderAfter =
  1795. (*pplschunkcontextNew)->plscbk->pfnNewPtr((*pplschunkcontextNew)->pols,
  1796. sizeof(LONG) * ((*pplschunkcontextNew)->cchnkMax));
  1797. if ((*pplschunkcontextNew)->pplsdnChunk == NULL || (*pplschunkcontextNew)->pcont == NULL
  1798. || (*pplschunkcontextNew)->locchnkCurrent.plschnk == NULL
  1799. || (*pplschunkcontextNew)->locchnkCurrent.ppointUvLoc == NULL
  1800. || (*pplschunkcontextNew)->pfNonTextExpandAfter == NULL
  1801. || (*pplschunkcontextNew)->pplsdnNonText == NULL
  1802. || (*pplschunkcontextNew)->pdurOpenBorderBefore == NULL
  1803. || (*pplschunkcontextNew)->pdurCloseBorderAfter == NULL
  1804. )
  1805. return lserrOutOfMemory;
  1806. /* copy valid parts of the arrays */
  1807. memcpy ((*pplschunkcontextNew)->pplsdnChunk, plschunkcontextOld->pplsdnChunk,
  1808. plschunkcontextOld->locchnkCurrent.clschnk * sizeof(PLSDNODE));
  1809. memcpy ((*pplschunkcontextNew)->pcont, plschunkcontextOld->pcont,
  1810. plschunkcontextOld->locchnkCurrent.clschnk * sizeof(DWORD));
  1811. memcpy ((*pplschunkcontextNew)->locchnkCurrent.plschnk, plschunkcontextOld->locchnkCurrent.plschnk,
  1812. plschunkcontextOld->locchnkCurrent.clschnk * sizeof(LSCHNKE));
  1813. memcpy ((*pplschunkcontextNew)->locchnkCurrent.ppointUvLoc, plschunkcontextOld->locchnkCurrent.ppointUvLoc,
  1814. plschunkcontextOld->locchnkCurrent.clschnk * sizeof(POINTUV));
  1815. memcpy ((*pplschunkcontextNew)->pfNonTextExpandAfter, plschunkcontextOld->pfNonTextExpandAfter,
  1816. plschunkcontextOld->cNonTextMax * sizeof(BOOL));
  1817. memcpy ((*pplschunkcontextNew)->pplsdnNonText, plschunkcontextOld->pplsdnNonText,
  1818. plschunkcontextOld->cNonTextMax * sizeof(PLSDNODE));
  1819. memcpy ((*pplschunkcontextNew)->pdurOpenBorderBefore, plschunkcontextOld->pdurOpenBorderBefore,
  1820. plschunkcontextOld->locchnkCurrent.clschnk * sizeof(LONG));
  1821. memcpy ((*pplschunkcontextNew)->pdurCloseBorderAfter, plschunkcontextOld->pdurCloseBorderAfter,
  1822. plschunkcontextOld->locchnkCurrent.clschnk * sizeof(LONG));
  1823. return lserrNone;
  1824. }
  1825. /* D E S T R O Y C H U N K C O N T E X T */
  1826. /*----------------------------------------------------------------------------
  1827. %%Function: DestroyChunkContext
  1828. %%Contact: igorzv
  1829. Parameters:
  1830. plschunkcontext - (IN) chunk context to destroy
  1831. ----------------------------------------------------------------------------*/
  1832. void DestroyChunkContext(PLSCHUNKCONTEXT plschunkcontext)
  1833. {
  1834. POLS pols = plschunkcontext->pols;
  1835. LSCBK* plscbk = plschunkcontext->plscbk;
  1836. DisposeChunkArrays(plschunkcontext);
  1837. DebugMemset(plschunkcontext, 0xE9, sizeof(LSCHUNKCONTEXT));
  1838. plscbk->pfnDisposePtr(pols, plschunkcontext);
  1839. }
  1840. /* I N C R E A S E G R O U P C H U N K N O N T E X T A R R A Y S S I Z E */
  1841. /*----------------------------------------------------------------------------
  1842. %%Function: SetGroupChunkNonTextArraysSize
  1843. %%Contact: igorzv
  1844. Parameters:
  1845. plschunkcontext - (IN) chunk context
  1846. The difference from previous function is that we don't now final size
  1847. and going to increase size step by step
  1848. ----------------------------------------------------------------------------*/
  1849. static LSERR IncreaseGroupChunkNonTextArrays(PLSCHUNKCONTEXT plschunkcontext)
  1850. {
  1851. DWORD cNonTextMax;
  1852. cNonTextMax = plschunkcontext->cNonTextMax + limAllDNodes;
  1853. /* create arrays for chunks */
  1854. plschunkcontext->pplsdnNonText = plschunkcontext->plscbk->pfnReallocPtr(plschunkcontext->pols,
  1855. plschunkcontext->pplsdnNonText,
  1856. sizeof(PLSDNODE)*cNonTextMax);
  1857. plschunkcontext->pfNonTextExpandAfter = plschunkcontext->plscbk->pfnReallocPtr(plschunkcontext->pols,
  1858. plschunkcontext->pfNonTextExpandAfter,
  1859. sizeof(BOOL)*cNonTextMax);
  1860. if (plschunkcontext->pplsdnNonText == NULL || plschunkcontext->pfNonTextExpandAfter == NULL)
  1861. return lserrOutOfMemory;
  1862. plschunkcontext->cNonTextMax = cNonTextMax;
  1863. return lserrNone;
  1864. }