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.

726 lines
20 KiB

  1. #include "lsidefs.h"
  2. #include "dninfo.h"
  3. #include "tabutils.h"
  4. #include "lstbcon.h"
  5. #include "plstbcon.h"
  6. #include "lstabs.h"
  7. #include "lsktab.h"
  8. #include "lscaltbd.h"
  9. #include "lstext.h"
  10. #include "zqfromza.h"
  11. #include "iobj.h"
  12. #include "chnutils.h"
  13. #include "lscbk.h"
  14. #include "limqmem.h"
  15. #include "posichnk.h"
  16. #include <limits.h>
  17. static LSERR FillTabsContext(PLSTABSCONTEXT, LSTFLOW);
  18. static LSERR ItbdMergeTabs(PLSTABSCONTEXT plstabscontext, LSTFLOW lstflow, const LSTABS* plstabs,
  19. BOOL fHangingTab,
  20. long duaHangingTab,
  21. WCHAR wchHangingTabLeader, DWORD* picaltbdMac);
  22. static LSERR FindTab (PLSTABSCONTEXT plstabscontext, long urPen, BOOL fUseHangingTabAsDefault,
  23. BOOL fZeroWidthUserTab,
  24. DWORD* picaltbd, BOOL* pfBreakThroughTab);
  25. static LSERR IncreaseTabsArray(PLSTABSCONTEXT plstabscontext, DWORD ccaltbdMaxNew);
  26. /* G E T C U R T A B I N F O C O R E*/
  27. /*----------------------------------------------------------------------------
  28. %%Function: GetCurTabInfoCore
  29. %%Contact: igorzv
  30. Parameters:
  31. plstabscontext - (IN) pointer to tabs context
  32. plsdnTab - (IN) dnode with tab
  33. urTab - (IN) position before this tab
  34. fResolveAllTabsAsLeft(IN) switch all other tab to left
  35. plsktab - (OUT) type of current tab
  36. pfBreakThroughTab- (OUT)is break through tab occurs
  37. Provides information about nearest tab stop
  38. ----------------------------------------------------------------------------*/
  39. LSERR GetCurTabInfoCore(PLSTABSCONTEXT plstabscontext, PLSDNODE plsdnTab,
  40. long urTab, BOOL fResolveAllTabsAsLeft,
  41. LSKTAB* plsktab, BOOL* pfBreakThroughTab)
  42. {
  43. LSERR lserr;
  44. LSCALTBD* plscaltbd;
  45. DWORD icaltbd;
  46. long durTab;
  47. BOOL fUseHangingTabAsDefault = fFalse;
  48. BOOL fZeroWidthUserTab = fFalse;
  49. long urToFindTabStop;
  50. Assert(plsktab != NULL);
  51. Assert(FIsLSDNODE(plsdnTab));
  52. Assert(plsdnTab->fTab);
  53. Assert(FIsDnodeReal(plsdnTab));
  54. // Assert(plstabscontext->plsdnPendingTab == NULL);
  55. /* first tab on line */
  56. if (!plstabscontext->fTabsInitialized)
  57. {
  58. lserr = FillTabsContext(plstabscontext, LstflowFromDnode(plsdnTab));
  59. if (lserr != lserrNone)
  60. return lserr;
  61. }
  62. urToFindTabStop = urTab;
  63. if (plstabscontext->fResolveTabsAsWord97 ) /* such strange behaviour was in Word97 */
  64. {
  65. if (plsdnTab->fTabForAutonumber)
  66. {
  67. fZeroWidthUserTab = fTrue;
  68. fUseHangingTabAsDefault = fTrue;
  69. }
  70. else
  71. {
  72. urToFindTabStop++;
  73. }
  74. }
  75. /* find tab in tabs table */
  76. lserr = FindTab(plstabscontext, urToFindTabStop, fUseHangingTabAsDefault,
  77. fZeroWidthUserTab, &icaltbd, pfBreakThroughTab);
  78. if (lserr != lserrNone)
  79. return lserr;
  80. plsdnTab->icaltbd = icaltbd;
  81. plscaltbd = &(plstabscontext->pcaltbd[icaltbd]);
  82. /* ask text to set tab leader in his structures */
  83. if (plscaltbd->wchTabLeader != 0)
  84. {
  85. lserr = SetTabLeader(plsdnTab->u.real.pdobj, plscaltbd->wchTabLeader);
  86. if (lserr != lserrNone)
  87. return lserr;
  88. }
  89. *plsktab = plscaltbd->lskt;
  90. if (fResolveAllTabsAsLeft)
  91. *plsktab = lsktLeft;
  92. /* offset calculation for left tab , register pending tab for all others */
  93. switch (*plsktab)
  94. {
  95. default:
  96. NotReached();
  97. break;
  98. case lsktLeft:
  99. durTab = plscaltbd->ur - urTab;
  100. Assert(durTab >= 0);
  101. SetDnodeDurFmt(plsdnTab, durTab);
  102. break;
  103. case lsktRight:
  104. case lsktCenter:
  105. case lsktDecimal:
  106. case lsktChar:
  107. plstabscontext->plsdnPendingTab = plsdnTab;
  108. plstabscontext->urBeforePendingTab = urTab;
  109. break;
  110. }
  111. return lserrNone;
  112. }
  113. /* R E S O L V E P R E V T A B C O R E*/
  114. /*----------------------------------------------------------------------------
  115. %%Function: ResolvePrevTabCore
  116. %%Contact: igorzv
  117. Parameters:
  118. plstabscontext - (IN) pointer to tabs context
  119. plsdnCurrent - (IN) current dnode
  120. urCurrentPen - (IN) current pen position
  121. pdurPendingTab - (OUT)offset because of pending tab
  122. Resolves if exists previous pending tab (right, decimal or center)
  123. ----------------------------------------------------------------------------*/
  124. LSERR ResolvePrevTabCore(PLSTABSCONTEXT plstabscontext, PLSDNODE plsdnCurrent,
  125. long urCurrentPen, long* pdurPendingTab)
  126. {
  127. PLSDNODE plsdnPendingTab;
  128. LSCALTBD* plscaltbd;
  129. long urTabStop, durTab, durSeg;
  130. PLSDNODE plsdn;
  131. long durTrail;
  132. GRCHUNKEXT grchnkext;
  133. DWORD index;
  134. long durToDecimalPoint;
  135. LSERR lserr;
  136. PLSCHUNKCONTEXT plschunkcontext;
  137. DWORD cchTrail;
  138. PLSDNODE plsdnStartTrail;
  139. LSDCP dcpStartTrailingText;
  140. PLSDNODE plsdnTrailingObject;
  141. LSDCP dcpTrailingObject;
  142. int cDnodesTrailing;
  143. BOOL fClosingBorderStartsTrailing;
  144. PLSDNODE plsdnDecimalPoint;
  145. *pdurPendingTab = 0;
  146. plsdnPendingTab = plstabscontext->plsdnPendingTab;
  147. if (plsdnPendingTab == NULL ||
  148. plsdnPendingTab->cpFirst >= plsdnCurrent->cpFirst)
  149. /* this second condition can happen after break when because of increased margin
  150. we fetch pending tab but later break was found before */
  151. {
  152. /* no business for us */
  153. return lserrNone;
  154. }
  155. /* pending in an other subline */
  156. if (SublineFromDnode(plsdnCurrent) != SublineFromDnode(plsdnPendingTab))
  157. {
  158. /* cancell pending tab */
  159. CancelPendingTab(plstabscontext);
  160. return lserrNone;
  161. }
  162. Assert(FIsLSDNODE(plsdnCurrent));
  163. plschunkcontext = PlschunkcontextFromSubline(SublineFromDnode(plsdnCurrent));
  164. Assert(plstabscontext->fTabsInitialized);
  165. Assert(FIsLSDNODE(plsdnPendingTab));
  166. Assert(plsdnPendingTab->fTab);
  167. Assert(FIsDnodeReal(plsdnPendingTab));
  168. plscaltbd = &(plstabscontext->pcaltbd[plsdnPendingTab->icaltbd]);
  169. urTabStop = plscaltbd->ur;
  170. durSeg = urCurrentPen - plstabscontext->urBeforePendingTab;
  171. /* find durTrail */
  172. /* collect last chunk */
  173. plsdn = plsdnCurrent;
  174. /* If we resolve pending tab because of other tab we should
  175. use previous dnode to calculate correct group chunk . We also must
  176. be careful keeping in mind that line can be stopped right after pending tab */
  177. if ((plsdn->fTab && plsdn != plsdnPendingTab))
  178. plsdn = plsdn->plsdnPrev;
  179. Assert(FIsLSDNODE(plsdn));
  180. Assert(!FIsNotInContent(plsdn));
  181. lserr = GetTrailingInfoForTextGroupChunk(plsdn,
  182. plsdn->dcp, IdObjFromDnode(plsdnPendingTab),
  183. &durTrail, &cchTrail, &plsdnStartTrail,
  184. &dcpStartTrailingText, &cDnodesTrailing,
  185. &plsdnTrailingObject, &dcpTrailingObject, &fClosingBorderStartsTrailing);
  186. if (lserr != lserrNone)
  187. return lserr;
  188. switch (plscaltbd->lskt)
  189. {
  190. default:
  191. case lsktLeft:
  192. NotReached();
  193. break;
  194. case lsktRight:
  195. case lsktCenter:
  196. durSeg -= durTrail;
  197. if (plscaltbd->lskt == lsktCenter)
  198. durSeg /= 2;
  199. break;
  200. case lsktDecimal:
  201. case lsktChar:
  202. InitGroupChunkExt(plschunkcontext, IdObjFromDnode(plsdnPendingTab), &grchnkext);
  203. plsdn = plsdnPendingTab->plsdnNext;
  204. Assert(FIsLSDNODE(plsdn));
  205. lserr = CollectTextGroupChunk(plsdn, plsdnCurrent->cpLimOriginal,
  206. CollectSublinesForDecimalTab, &grchnkext);
  207. if (lserr != lserrNone)
  208. return lserr;
  209. if (grchnkext.plsdnLastUsed == NULL)
  210. {
  211. /* there are now dnodes between tabs */
  212. durSeg = 0;
  213. }
  214. else
  215. {
  216. if (grchnkext.lsgrchnk.clsgrchnk > 0)
  217. {
  218. if (plscaltbd->lskt == lsktDecimal)
  219. {
  220. lserr = LsGetDecimalPoint(&(grchnkext.lsgrchnk), lsdevReference,
  221. &index, &durToDecimalPoint);
  222. if (lserr != lserrNone)
  223. return lserr;
  224. }
  225. else
  226. {
  227. Assert(plscaltbd->lskt == lsktChar);
  228. lserr = LsGetCharTab(&(grchnkext.lsgrchnk), plscaltbd->wchCharTab, lsdevReference,
  229. &index, &durToDecimalPoint);
  230. if (lserr != lserrNone)
  231. return lserr;
  232. }
  233. }
  234. else
  235. {
  236. index = idobjOutside;
  237. durToDecimalPoint = 0;
  238. }
  239. if (index != idobjOutside) /* decimal point has been found */
  240. {
  241. plsdnDecimalPoint = grchnkext.plschunkcontext->pplsdnChunk[index];
  242. }
  243. else
  244. {
  245. /* we allign end of the last logical cp to the tab stop */
  246. plsdnDecimalPoint = grchnkext.plsdnLastUsed;
  247. durToDecimalPoint = DurFromDnode(plsdnDecimalPoint);
  248. }
  249. FindPointOffset(plsdn, lsdevReference, LstflowFromDnode(plsdn),
  250. CollectSublinesForDecimalTab,
  251. plsdnDecimalPoint,
  252. durToDecimalPoint, &durSeg);
  253. }
  254. break;
  255. }
  256. durTab = urTabStop - plstabscontext->urBeforePendingTab - durSeg;
  257. if (urTabStop < plstabscontext->urColumnMax &&
  258. (durTab + urCurrentPen - durTrail > plstabscontext->urColumnMax))
  259. {
  260. /* this code is for compatibility with Word: when we are not in a situation
  261. of break through tab we dont allow line to leap right margin after we resolve
  262. pending tab */
  263. durTab = plstabscontext->urColumnMax - urCurrentPen + durTrail;
  264. }
  265. if (durTab > 0)
  266. {
  267. SetDnodeDurFmt(plsdnPendingTab, durTab);
  268. *pdurPendingTab = durTab;
  269. }
  270. plstabscontext->plsdnPendingTab = NULL;
  271. return lserrNone;
  272. }
  273. /* F I L L T A B S C O N T E X T*/
  274. /*----------------------------------------------------------------------------
  275. %%Function: FillTabsContext
  276. %%Contact: igorzv
  277. Parameters:
  278. plstabscontext - (IN) pointer to tabs context
  279. lstflow - (IN) text flow of the line
  280. Initializes tabs context using clients callback FetchTabs
  281. ----------------------------------------------------------------------------*/
  282. LSERR FillTabsContext(PLSTABSCONTEXT plstabscontext, LSTFLOW lstflow)
  283. {
  284. LSTABS lstabs;
  285. BOOL fHangingTab;
  286. long uaHangingTab;
  287. WCHAR wchHangingTabLeader;
  288. LSERR lserr;
  289. lserr = plstabscontext->plscbk->pfnFetchTabs(plstabscontext->pols, plstabscontext->cpInPara,
  290. &lstabs, &fHangingTab, &uaHangingTab, &wchHangingTabLeader);
  291. if (lserr != lserrNone)
  292. return lserr;
  293. plstabscontext->durIncrementalTab = UrFromUa(lstflow, &(plstabscontext->plsdocinf->lsdevres), lstabs.duaIncrementalTab);
  294. /* Copy tabs from LSTABS to rgcaltbd[], inserting a hanging tab if
  295. * required.
  296. */
  297. if (fHangingTab || lstabs.iTabUserDefMac > 0)
  298. {
  299. lserr = ItbdMergeTabs(plstabscontext, lstflow,
  300. &lstabs, fHangingTab,
  301. uaHangingTab, wchHangingTabLeader, &plstabscontext->icaltbdMac);
  302. if (lserr != lserrNone)
  303. return lserr;
  304. }
  305. else
  306. {
  307. plstabscontext->icaltbdMac = 0;
  308. }
  309. plstabscontext->fTabsInitialized = fTrue;
  310. return lserrNone;
  311. }
  312. /* I N I T T A B S C O N T E X T F O R A U T O D E C I M A L T A B*/
  313. /*----------------------------------------------------------------------------
  314. %%Function: InitTabsContextForAutoDecimalTab
  315. %%Contact: igorzv
  316. Parameters:
  317. plstabscontext - (IN) pointer to tabs context
  318. durAutoDecimalTab- (IN) tab stop for autodecimal tab
  319. Creates tabs context that consists of one tab stop - auto decimal
  320. ----------------------------------------------------------------------------*/
  321. LSERR InitTabsContextForAutoDecimalTab(PLSTABSCONTEXT plstabscontext, long durAutoDecimalTab)
  322. {
  323. LSCALTBD* pcaltbd;
  324. pcaltbd = plstabscontext->pcaltbd;
  325. Assert(plstabscontext->ccaltbdMax >= 1);
  326. if (!plstabscontext->fTabsInitialized)
  327. {
  328. plstabscontext->icaltbdMac = 1;
  329. pcaltbd->lskt = lsktDecimal;
  330. pcaltbd->ur = durAutoDecimalTab;
  331. pcaltbd->wchTabLeader = 0;
  332. plstabscontext->fTabsInitialized = fTrue;
  333. }
  334. else
  335. {
  336. /* tab is already there because of autonumber */
  337. Assert(plstabscontext->icaltbdMac == 1);
  338. Assert(pcaltbd->lskt == lsktDecimal);
  339. Assert(pcaltbd->ur == durAutoDecimalTab);
  340. }
  341. return lserrNone;
  342. }
  343. /* I T B D M E R G E T A B S */
  344. /*----------------------------------------------------------------------------
  345. %%Function: ItbdMergeTabs
  346. %%Contact: igorzv
  347. Parameters:
  348. plstabscontext - (IN) pointer to tabs context
  349. lstflow - (IN) text flow of the line
  350. plstabs - (IN) tabs array provided by client
  351. fHangingTab - (IN) does paragraph have hanging tab
  352. uaHangingTab - (IN) position of hanging tab
  353. wchHangingTabLeader-(IN) leader for hanging tab
  354. picaltbdMac (OUT) amount of tabs in array
  355. Copies tabs from LSPAP into ptbd[], inserting a hanging tab where
  356. required.
  357. ----------------------------------------------------------------------------*/
  358. static LSERR ItbdMergeTabs(PLSTABSCONTEXT plstabscontext, LSTFLOW lstflow,
  359. const LSTABS* plstabs, BOOL fHangingTab,
  360. long uaHangingTab, WCHAR wchHangingTabLeader, DWORD* picaltbdMac)
  361. {
  362. long uaPrevTab, uaCurrentTab;
  363. DWORD itbdOut, itbdIn, itbdLimIn;
  364. LSCALTBD* plscaltbd;
  365. DWORD ccaltbdMax;
  366. LSERR lserr;
  367. /* check that have enough room*/
  368. ccaltbdMax = plstabs->iTabUserDefMac;
  369. if (fHangingTab)
  370. ccaltbdMax++;
  371. if (ccaltbdMax >= plstabscontext->ccaltbdMax)
  372. {
  373. lserr = IncreaseTabsArray(plstabscontext, ccaltbdMax + limCaltbd);
  374. if (lserr != lserrNone)
  375. return lserr;
  376. }
  377. plscaltbd = plstabscontext->pcaltbd;
  378. itbdLimIn = plstabs->iTabUserDefMac;
  379. uaPrevTab = LONG_MAX;
  380. itbdOut = 0;
  381. if (fHangingTab)
  382. {
  383. /* If no user tabs, or hanging tab is before 0th user tab,
  384. * make hanging tab the 0th member of ptbd[].
  385. */
  386. if (itbdLimIn == 0 || uaHangingTab < plstabs->pTab[0].ua)
  387. {
  388. plscaltbd[0].lskt = lsktLeft;
  389. plscaltbd[0].ur = UrFromUa(lstflow,
  390. &(plstabscontext->plsdocinf->lsdevres), uaHangingTab);
  391. plscaltbd[0].wchTabLeader = wchHangingTabLeader;
  392. plscaltbd[0].fDefault = fFalse;
  393. plscaltbd[0].fHangingTab = fTrue;
  394. uaPrevTab = uaHangingTab;
  395. itbdOut = 1;
  396. }
  397. }
  398. else
  399. {
  400. uaHangingTab = LONG_MAX;
  401. }
  402. /* Copy user defined tabs, checking each time for hanging tab.
  403. */
  404. for (itbdIn = 0; itbdIn < itbdLimIn; itbdOut++, itbdIn++)
  405. {
  406. uaCurrentTab = plstabs->pTab[itbdIn].ua;
  407. /* If hanging tab is between previous tab and this tab,
  408. * insert hanging tab into ptbd[] here and revisit "this"
  409. * tab again during next loop iteration.
  410. */
  411. if (uaPrevTab < uaHangingTab && uaHangingTab < uaCurrentTab)
  412. {
  413. plscaltbd[itbdOut].lskt = lsktLeft;
  414. plscaltbd[itbdOut].ur = UrFromUa(lstflow, &(plstabscontext->plsdocinf->lsdevres),
  415. uaHangingTab);
  416. plscaltbd[itbdOut].wchTabLeader = wchHangingTabLeader;
  417. plscaltbd[itbdOut].fDefault = fFalse;
  418. plscaltbd[itbdOut].fHangingTab = fTrue;
  419. itbdIn -= 1;
  420. uaPrevTab = uaHangingTab;
  421. }
  422. else
  423. {
  424. plscaltbd[itbdOut].lskt = plstabs->pTab[itbdIn].lskt;
  425. plscaltbd[itbdOut].ur = UrFromUa(lstflow, &(plstabscontext->plsdocinf->lsdevres),
  426. plstabs->pTab[itbdIn].ua);
  427. plscaltbd[itbdOut].wchTabLeader = plstabs->pTab[itbdIn].wchTabLeader;
  428. plscaltbd[itbdOut].wchCharTab = plstabs->pTab[itbdIn].wchCharTab;
  429. plscaltbd[itbdOut].fDefault = fFalse;
  430. plscaltbd[itbdOut].fHangingTab = fFalse;
  431. uaPrevTab = uaCurrentTab;
  432. }
  433. }
  434. /* If hanging tab is after final user tab, make hanging tab the
  435. * final member of ptbd[]
  436. */
  437. if (uaPrevTab < uaHangingTab && uaHangingTab < LONG_MAX)
  438. {
  439. plscaltbd[itbdOut].lskt = lsktLeft;
  440. plscaltbd[itbdOut].ur = UrFromUa(lstflow,
  441. &(plstabscontext->plsdocinf->lsdevres), uaHangingTab);
  442. plscaltbd[itbdOut].wchTabLeader = wchHangingTabLeader;
  443. plscaltbd[itbdOut].fDefault = fFalse;
  444. plscaltbd[itbdOut].fHangingTab = fTrue;
  445. itbdOut += 1;
  446. }
  447. *picaltbdMac = itbdOut;
  448. return lserrNone;
  449. }
  450. /* F I N D T A B*/
  451. /*----------------------------------------------------------------------------
  452. %%Function: FindTab
  453. %%Contact: igorzv
  454. Parameters:
  455. plstabscontext - (IN) pointer to tabs context
  456. urPen - (IN) position before this tab
  457. fUseHangingTabAsDefault - (IN) usually hanging tab is used as user defined tab,
  458. but in one case for compstibility with Word97 it's treated as
  459. user default tab
  460. fZeroWidthUserTab- (IN) for compatibility with Word97
  461. picaltbd - (OUT)pointer to a record describing tab stop
  462. pfBreakThroughTab- (OUT)is break through tab occurs
  463. Procedure findes fist tab stop after current pen position. In the case when
  464. it is a default tab stop program adds record to an array of tab stops.
  465. This procedure also resolves breakthrouhtab logic.
  466. ----------------------------------------------------------------------------*/
  467. static LSERR FindTab (PLSTABSCONTEXT plstabscontext, long urPen, BOOL fUseHangingTabAsDefault,
  468. BOOL fZeroWidthUserTab,
  469. DWORD* picaltbd, BOOL* pfBreakThroughTab)
  470. {
  471. DWORD icaltbdMac = plstabscontext->icaltbdMac;
  472. LSCALTBD* pcaltbd = plstabscontext->pcaltbd;
  473. long durIncTab, durDelta;
  474. DWORD i;
  475. LSERR lserr;
  476. int iHangingTab = -1;
  477. long urDefaultTab;
  478. long urPenForUserTab = urPen;
  479. *pfBreakThroughTab = fFalse;
  480. if (fZeroWidthUserTab)
  481. urPenForUserTab--;
  482. for (i = 0; i < icaltbdMac &&
  483. (urPenForUserTab >= (pcaltbd[i].ur) /* if fUseHangingTabAsDefault we skip it */
  484. || (fUseHangingTabAsDefault && pcaltbd[i].fHangingTab));
  485. i++)
  486. {
  487. if (fUseHangingTabAsDefault && pcaltbd[i].fHangingTab)
  488. iHangingTab = i;
  489. }
  490. if (i == icaltbdMac)
  491. {
  492. /* We deleted strange calculation of tab stop which was there due to compatibility with
  493. Word97. Compatibility we are solving when calling this procedure */
  494. durIncTab = plstabscontext->durIncrementalTab;
  495. if (durIncTab == 0)
  496. durIncTab = 1;
  497. durDelta = durIncTab;
  498. if (urPen < 0)
  499. durDelta = 0;
  500. urDefaultTab = ((urPen + durDelta) / durIncTab) * durIncTab;
  501. if (fUseHangingTabAsDefault && iHangingTab != -1 &&
  502. pcaltbd[iHangingTab].ur > urPen &&
  503. pcaltbd[iHangingTab].ur <= urDefaultTab)
  504. {
  505. /* in this case hanging tab is the nearesr default tab */
  506. i = iHangingTab;
  507. }
  508. else
  509. {
  510. icaltbdMac++;
  511. if (icaltbdMac >= plstabscontext->ccaltbdMax)
  512. {
  513. lserr = IncreaseTabsArray(plstabscontext, 0);
  514. if (lserr != lserrNone)
  515. return lserr;
  516. pcaltbd = plstabscontext->pcaltbd;
  517. }
  518. plstabscontext->icaltbdMac = icaltbdMac;
  519. pcaltbd[i].lskt = lsktLeft;
  520. pcaltbd[i].wchTabLeader = 0; /* REVIEW (igorzv) do we need wchSpace as tab leader in this case */
  521. pcaltbd[i].fDefault = fTrue;
  522. pcaltbd[i].fHangingTab = fFalse;
  523. pcaltbd[i].ur = urDefaultTab;
  524. }
  525. }
  526. else
  527. {
  528. if (urPen < plstabscontext->urColumnMax &&
  529. pcaltbd[i].ur >= plstabscontext->urColumnMax)
  530. /* tab we found is user defined behind right margin */
  531. /* it is important to check also that we are not already behind right margin,
  532. opposite can happens because of exceeded right margin */
  533. {
  534. *pfBreakThroughTab = fTrue;
  535. }
  536. }
  537. *picaltbd = i;
  538. return lserrNone;
  539. }
  540. /* I N C R E A S E T A B S A R R A Y*/
  541. /*----------------------------------------------------------------------------
  542. %%Function: IncreaseTabsArray
  543. %%Contact: igorzv
  544. Parameters:
  545. plsc - (IN) ptr to line services context
  546. ccaltbdMaxNew - (IN) new value for array size if 0 then add limCaltbd
  547. Relocate tabs array and set new values in context
  548. ----------------------------------------------------------------------------*/
  549. static LSERR IncreaseTabsArray(PLSTABSCONTEXT plstabscontext, DWORD ccaltbdMaxNew)
  550. {
  551. DWORD ccaltbdMax;
  552. if (ccaltbdMaxNew > 0)
  553. ccaltbdMax = ccaltbdMaxNew;
  554. else
  555. ccaltbdMax = plstabscontext->ccaltbdMax + limCaltbd;
  556. /* create new array for tabs */
  557. plstabscontext->pcaltbd = plstabscontext->plscbk->pfnReallocPtr(plstabscontext->pols,
  558. plstabscontext->pcaltbd,
  559. sizeof(LSCALTBD)*ccaltbdMax);
  560. if (plstabscontext->pcaltbd == NULL )
  561. return lserrOutOfMemory;
  562. plstabscontext->ccaltbdMax = ccaltbdMax;
  563. return lserrNone;
  564. }
  565. /* G E T M A R G I N A F T E R B R E A K T H R O U G H T A B*/
  566. /*----------------------------------------------------------------------------
  567. %%Function: GetMarginAfterBreakThroughTab
  568. %%Contact: igorzv
  569. Parameters:
  570. plsc - (IN) ptr to line services context
  571. plsdnTab - (IN) tab which triggered breakthrough tab
  572. purNewMargin - (OUT) new margin because of breakthrough tab
  573. ----------------------------------------------------------------------------*/
  574. LSERR GetMarginAfterBreakThroughTab(PLSTABSCONTEXT plstabscontext,
  575. PLSDNODE plsdnTab, long* purNewMargin)
  576. {
  577. LSERR lserr;
  578. long uaNewMargin;
  579. lserr = plstabscontext->plscbk->pfnGetBreakThroughTab(plstabscontext->pols,
  580. UaFromUr(LstflowFromDnode(plsdnTab), &(plstabscontext->plsdocinf->lsdevres),
  581. plstabscontext->urColumnMax),
  582. UaFromUr(LstflowFromDnode(plsdnTab), &(plstabscontext->plsdocinf->lsdevres),
  583. plstabscontext->pcaltbd[plsdnTab->icaltbd].ur),
  584. &uaNewMargin);
  585. if (lserr != lserrNone)
  586. return lserr;
  587. *purNewMargin = UrFromUa(LstflowFromDnode(plsdnTab), &(plstabscontext->plsdocinf->lsdevres),
  588. uaNewMargin);
  589. return lserrNone;
  590. }