Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

605 lines
18 KiB

  1. /* LSDNFIN.C */
  2. #include "lsdnfin.h"
  3. #include "lsidefs.h"
  4. #include "lsc.h"
  5. #include "getfmtst.h"
  6. #include "setfmtst.h"
  7. #include "dninfo.h"
  8. #include "lschp.h"
  9. #include "lsffi.h"
  10. #include "iobj.h"
  11. #include "dnutils.h"
  12. #include "lsfrun.h"
  13. #include "lsfetch.h"
  14. #include "qheap.h"
  15. #include "sublutil.h"
  16. #include "lsmem.h"
  17. #include "lscfmtfl.h"
  18. #include "ntiman.h"
  19. #ifdef DEBUG
  20. #define DebugMemset(a,b,c) if ((a) != NULL) memset(a,b,c); else
  21. #else
  22. #define DebugMemset(a,b,c) (void)(0)
  23. #endif
  24. #define IsLschpFlagsValid(plsc, plschp) fTrue
  25. /* Word violates condition bellow and it is not very important to us, so I deleted body of this macro,
  26. but not deleted macro itself to have a place where to put such checks later */
  27. // ((((plsc)->lsadjustcontext.lsbrj == lsbrjBreakWithCompJustify) || ((plsc)->lsadjustcontext.lskj == lskjSnapGrid)) ? \
  28. // fTrue :\
  29. // (!((plschp)->fCompressOnRun || (plschp)->fCompressSpace || (plschp)->fCompressTable)))
  30. /* L S D N F I N I S H R E G U L A R */
  31. /*----------------------------------------------------------------------------
  32. %%Function: LsdnFinishRegular
  33. %%Contact: igorzv
  34. Parameters:
  35. plsc - (IN) ptr to line services context
  36. lsdcp - (IN) dcp adopted
  37. plsrun - (IN) plsrun of dnode
  38. plschp - (IN) plschp of dnode
  39. pdobj - (IN) pdobj of dnode
  40. pobjdim - (IN) pobjdim of dnode
  41. Finish creating dnode
  42. ----------------------------------------------------------------------------*/
  43. LSERR WINAPI LsdnFinishRegular(
  44. PLSC plsc,
  45. LSDCP lsdcp,
  46. PLSRUN plsrun,
  47. PCLSCHP plschp,
  48. PDOBJ pdobj,
  49. PCOBJDIM pobjdim)
  50. {
  51. PLSDNODE plsdn;
  52. LSERR lserr;
  53. PLSSUBL plssubl;
  54. if (!FIsLSC(plsc)) return lserrInvalidParameter;
  55. if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled;
  56. /* all sublines should be closed */
  57. if (GetCurrentSubline(plsc) != NULL) return lserrFormattingFunctionDisabled;
  58. plsdn = GetDnodeToFinish(plsc);
  59. if (plsdn == NULL) return lserrFiniFunctionDisabled;
  60. plssubl = SublineFromDnode(plsdn);
  61. plsdn->u.real.pdobj = pdobj;
  62. /* if handler changed plsrun that we passed to him than we should release previous one */
  63. /* Attention: we have assumption here that new one has another plsrun */
  64. if (plsdn->u.real.plsrun != plsrun && !plsc->fDontReleaseRuns)
  65. {
  66. lserr = plsc->lscbk.pfnReleaseRun(plsc->pols, plsdn->u.real.plsrun);
  67. plsdn->u.real.plsrun = plsrun; /* to release it later */
  68. if (lserr != lserrNone)
  69. return lserr;
  70. }
  71. plsdn->dcp = lsdcp;
  72. plsdn->cpLimOriginal = plsdn->cpFirst + lsdcp;
  73. Assert(FIsDnodeReal(plsdn)); /* this is default value */
  74. Assert(pobjdim->dur >= 0);
  75. SetDnodeObjdimFmt(plsdn, *pobjdim);
  76. Assert(IsLschpFlagsValid(plsc, plschp));
  77. plsdn->u.real.lschp = *plschp;
  78. /* Special effects */
  79. plsc->plslineCur->lslinfo.EffectsFlags |= plschp->EffectsFlags;
  80. /* set flags for display */
  81. if (plschp->dvpPos != 0)
  82. TurnOnNonZeroDvpPosEncounted(plsc);
  83. AddToAggregatedDisplayFlags(plsc, plschp);
  84. if (FApplyNominalToIdeal(plschp))
  85. TurnOnNominalToIdealEncounted(plsc);
  86. if (plsdn->u.real.lschp.idObj == idObjTextChp)
  87. plsdn->u.real.lschp.idObj = (WORD) IobjTextFromLsc(&plsc->lsiobjcontext);
  88. AssertImplies(plsc->lsdocinf.fPresEqualRef,
  89. plsdn->u.real.objdim.heightsPres.dvAscent == plsdn->u.real.objdim.heightsRef.dvAscent);
  90. AssertImplies(plsc->lsdocinf.fPresEqualRef,
  91. plsdn->u.real.objdim.heightsPres.dvDescent == plsdn->u.real.objdim.heightsRef.dvDescent);
  92. AssertImplies(plsc->lsdocinf.fPresEqualRef,
  93. plsdn->u.real.objdim.heightsPres.dvMultiLineHeight
  94. == plsdn->u.real.objdim.heightsRef.dvMultiLineHeight);
  95. /* nobody can change current dnode after plsdn was constructed */
  96. Assert(GetCurrentDnodeSubl(plssubl) == plsdn->plsdnPrev);
  97. *(GetWhereToPutLinkSubl(plssubl, plsdn->plsdnPrev)) = plsdn;
  98. SetCurrentDnodeSubl(plssubl, plsdn);
  99. SetDnodeToFinish(plsc, NULL);
  100. AdvanceCurrentCpLimSubl(plssubl, lsdcp);
  101. AdvanceCurrentUrSubl(plssubl, pobjdim->dur);
  102. return lserrNone;
  103. }
  104. /* L S D N F I N I S H R E G U L A R A D D A D V A N C E D P E N */
  105. /*----------------------------------------------------------------------------
  106. %%Function: LsdnFinishRegularAddAdvancePen
  107. %%Contact: igorzv
  108. Parameters:
  109. plsc - (IN) ptr to line services context
  110. lsdcp - (IN) dcp adopted
  111. plsrun - (IN) plsrun of dnode
  112. plschp - (IN) plschp of dnode
  113. pdobj - (IN) pdobj of dnode
  114. pobjdim - (IN) pobjdim of dnode
  115. durPen - (IN) dur of advanced pen
  116. dvrPen - (IN) dvr of advanced pen
  117. dvpPen - (IN) dvp of advanced pen
  118. Finish creating dnode and add advanced pen after such dnode
  119. ----------------------------------------------------------------------------*/
  120. LSERR WINAPI LsdnFinishRegularAddAdvancePen(
  121. PLSC plsc, /* IN: Pointer to LS Context */
  122. LSDCP lsdcp, /* IN: dcp adopted */
  123. PLSRUN plsrun, /* IN: PLSRUN */
  124. PCLSCHP plschp, /* IN: CHP */
  125. PDOBJ pdobj, /* IN: PDOBJ */
  126. PCOBJDIM pobjdim, /* IN: OBJDIM */
  127. long durPen, /* IN: durPen */
  128. long dvrPen, /* IN: dvrPen */
  129. long dvpPen) /* IN: dvpPen */
  130. {
  131. LSERR lserr;
  132. PLSDNODE plsdnPrev;
  133. PLSDNODE plsdnPen;
  134. PLSSUBL plssubl;
  135. /* we don't have checks of parameters here because they are in LsdnFinishRegular */
  136. plsdnPrev = GetDnodeToFinish(plsc); /* we should store it before calling LsdnFinishRegular */
  137. plssubl = SublineFromDnode(plsdnPrev);
  138. lserr = LsdnFinishRegular(plsc, lsdcp, plsrun, plschp, pdobj, pobjdim);
  139. if (lserr != lserrNone)
  140. return lserr;
  141. /* create and fill in pen dnode */
  142. plsdnPen = PvNewQuick(GetPqhAllDNodes(plsc), sizeof *plsdnPen);
  143. if (plsdnPen == NULL)
  144. return lserrOutOfMemory;
  145. plsdnPen->tag = tagLSDNODE;
  146. plsdnPen->cpFirst = GetCurrentCpLimSubl(plssubl);
  147. plsdnPen->cpLimOriginal = plsdnPen->cpFirst;
  148. plsdnPen->plsdnPrev = plsdnPrev;
  149. plsdnPen->plsdnNext = NULL;
  150. plsdnPen->plssubl = plssubl;
  151. plsdnPen->dcp = 0;
  152. /* flush all flags, bellow check that result is what we expect */ \
  153. *((DWORD *) ((&(plsdnPen)->dcp)+1)) = 0;\
  154. Assert((plsdnPen)->fRigidDup == fFalse);\
  155. Assert((plsdnPen)->fTab == fFalse);\
  156. Assert((plsdnPen)->icaltbd == 0);\
  157. Assert((plsdnPen)->fBorderNode == fFalse);\
  158. Assert((plsdnPen)->fOpenBorder == fFalse);\
  159. Assert((plsdnPen)->fEndOfSection == fFalse); \
  160. Assert((plsdnPen)->fEndOfColumn == fFalse); \
  161. Assert((plsdnPen)->fEndOfPage == fFalse); \
  162. Assert((plsdnPen)->fEndOfPara == fFalse); \
  163. Assert((plsdnPen)->fAltEndOfPara == fFalse); \
  164. Assert((plsdnPen)->fSoftCR == fFalse); \
  165. Assert((plsdnPen)->fInsideBorder == fFalse); \
  166. Assert((plsdnPen)->fAutoDecTab == fFalse); \
  167. Assert((plsdnPen)->fTabForAutonumber == fFalse);
  168. plsdnPen->klsdn = klsdnPenBorder;
  169. plsdnPen->fAdvancedPen = fTrue;
  170. SetPenBorderDurFmt(plsdnPen, durPen);
  171. plsdnPen->u.pen.dvr = dvrPen;
  172. plsdnPen->u.pen.dvp = dvpPen;
  173. /* maintain list */
  174. plsdnPrev->plsdnNext = plsdnPen;
  175. SetCurrentDnodeSubl(plssubl, plsdnPen);
  176. AdvanceCurrentUrSubl(plssubl, durPen);
  177. AdvanceCurrentVrSubl(plssubl, dvrPen);
  178. if (durPen < 0)
  179. plsc->fAdvanceBack = fTrue;
  180. TurnOnNonRealDnodeEncounted(plsc);
  181. return lserrNone;
  182. }
  183. /* L S D N F I N I S H D E L E T E */
  184. /*----------------------------------------------------------------------------
  185. %%Function: LsdnFinishDelete
  186. %%Contact: igorzv
  187. Parameters:
  188. plsc - (IN) ptr to line services context
  189. lsdcp - (IN) dcp adopted
  190. Delete dnode due to the will of formater
  191. ----------------------------------------------------------------------------*/
  192. LSERR WINAPI LsdnFinishDelete(
  193. PLSC plsc, /* IN: Pointer to LS Context */
  194. LSDCP lsdcp) /* IN: dcp to add */
  195. {
  196. PLSDNODE plsdn;
  197. PLSSUBL plssubl;
  198. LSERR lserr;
  199. if (!FIsLSC(plsc)) return lserrInvalidParameter;
  200. if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled;
  201. /* all sublines should be closed */
  202. if (GetCurrentSubline(plsc) != NULL) return lserrFormattingFunctionDisabled;
  203. plsdn = GetDnodeToFinish(plsc);
  204. if (plsdn == NULL) return lserrFiniFunctionDisabled;
  205. plssubl = SublineFromDnode(plsdn);
  206. /* nobody can change current dnode after plsdn was constructed */
  207. Assert(GetCurrentDnodeSubl(plssubl) == plsdn->plsdnPrev);
  208. Assert(plsdn->plsdnNext == NULL);
  209. lserr = DestroyDnodeList (&plsc->lscbk, plsc->pols, &plsc->lsiobjcontext,
  210. plsdn, plsc->fDontReleaseRuns);
  211. if (lserr != lserrNone)
  212. return lserr;
  213. SetDnodeToFinish(plsc, NULL);
  214. AdvanceCurrentCpLimSubl(plssubl, lsdcp);
  215. return lserrNone;
  216. }
  217. /* L S D N F I N I S H P E N */
  218. /*----------------------------------------------------------------------------
  219. %%Function: LsdnFinishSimpleRegular
  220. %%Contact: igorzv
  221. Parameters:
  222. plsc - (IN) ptr to line services context
  223. lsdcp - (IN) dcp adopted
  224. plsrun - (IN) plsrun of dnode
  225. plschp - (IN) plschp of dnode
  226. dur, dvr, dvp - (IN) variables to put in pen dnode
  227. Finish dnode as a pen
  228. ----------------------------------------------------------------------------*/
  229. LSERR WINAPI LsdnFinishByPen(PLSC plsc, /* IN: Pointer to LS Context */
  230. LSDCP lsdcp, /* IN: dcp adopted */
  231. PLSRUN plsrun, /* IN: PLSRUN */
  232. PDOBJ pdobj, /* IN: PDOBJ */
  233. long durPen, /* IN: dur */
  234. long dvrPen, /* IN: dvr */
  235. long dvpPen) /* IN: dvp */
  236. {
  237. PLSDNODE plsdn;
  238. LSERR lserr;
  239. PLSSUBL plssubl;
  240. if (!FIsLSC(plsc)) return lserrInvalidParameter;
  241. if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled;
  242. /* all sublines should be closed */
  243. if (GetCurrentSubline(plsc) != NULL) return lserrFormattingFunctionDisabled;
  244. plsdn = GetDnodeToFinish(plsc);
  245. if (plsdn == NULL) return lserrFiniFunctionDisabled;
  246. plssubl = SublineFromDnode(plsdn);
  247. if (plsrun != NULL && !plsc->fDontReleaseRuns)
  248. {
  249. lserr = plsc->lscbk.pfnReleaseRun(plsc->pols, plsrun);
  250. if (lserr != lserrNone) return lserr;
  251. }
  252. /* caller pass pdobj to us only to destroy it*/
  253. if (pdobj != NULL)
  254. {
  255. Assert(plsdn->u.real.lschp.idObj != idObjTextChp);
  256. lserr = (PLsimFromLsc(&plsc->lsiobjcontext,
  257. plsdn->u.real.lschp.idObj))->pfnDestroyDObj (pdobj);
  258. if (lserr != lserrNone) return lserr;
  259. }
  260. plsdn->dcp = lsdcp;
  261. plsdn->cpLimOriginal = plsdn->cpFirst + lsdcp;
  262. plsdn->klsdn = klsdnPenBorder;
  263. plsdn->fBorderNode = fFalse;
  264. SetPenBorderDurFmt(plsdn, durPen);
  265. plsdn->u.pen.dvr = dvrPen;
  266. plsdn->u.pen.dvp = dvpPen;
  267. /* nobody can change current dnode after plsdn was constructed */
  268. Assert(GetCurrentDnodeSubl(plssubl) == plsdn->plsdnPrev);
  269. *(GetWhereToPutLinkSubl(plssubl, plsdn->plsdnPrev)) = plsdn;
  270. SetCurrentDnodeSubl(plssubl, plsdn);
  271. SetDnodeToFinish(plsc, NULL);
  272. AdvanceCurrentCpLimSubl(plssubl, lsdcp);
  273. AdvanceCurrentUrSubl(plssubl, durPen);
  274. AdvanceCurrentVrSubl(plssubl, dvrPen);
  275. TurnOnNonRealDnodeEncounted(plsc);
  276. return lserrNone;
  277. }
  278. /* L S D N F I N I S H B Y S U B L I N E*/
  279. /*----------------------------------------------------------------------------
  280. %%Function: LsdnFinishBySubline
  281. %%Contact: igorzv
  282. Parameters:
  283. plsc - (IN) ptr to line services context
  284. lsdcp - (IN) increase cp by this number before hanldler ends
  285. plssubl - (IN) subline to substitute dnode to finish
  286. Delete dnode and include child list in the upper level
  287. ----------------------------------------------------------------------------*/
  288. LSERR WINAPI LsdnFinishBySubline(PLSC plsc, /* IN: Pointer to LS Context */
  289. LSDCP lsdcp, /* IN: dcp adopted */
  290. PLSSUBL plssubl) /* IN: Subline context */
  291. {
  292. PLSDNODE plsdnParent;
  293. PLSDNODE plsdnChildFirst;
  294. PLSDNODE plsdnChildCurrent, plsdnChildPrevious;
  295. PLSSUBL plssublParent;
  296. LSERR lserr;
  297. if (!FIsLSC(plsc)) return lserrInvalidParameter;
  298. if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled;
  299. /* all sublines should be closed */
  300. if (GetCurrentSubline(plsc) != NULL) return lserrFormattingFunctionDisabled;
  301. plsdnParent = GetDnodeToFinish(plsc);
  302. if (plsdnParent == NULL) return lserrFiniFunctionDisabled;
  303. plssublParent = SublineFromDnode(plsdnParent);
  304. AdvanceCurrentCpLimSubl(plssublParent, lsdcp);
  305. plsdnChildFirst = plssubl->plsdnFirst;
  306. /* go through child list change subline and calculate resulting pen movement */
  307. plsdnChildCurrent = plsdnChildFirst;
  308. plsdnChildPrevious = NULL;
  309. while (plsdnChildPrevious != plssubl->plsdnLast)
  310. {
  311. plsdnChildCurrent->plssubl = plssublParent;
  312. AdvanceCurrentUrSubl(plssublParent, DurFromDnode(plsdnChildCurrent));
  313. AdvanceCurrentVrSubl(plssublParent, DvrFromDnode(plsdnChildCurrent));
  314. plsdnChildPrevious = plsdnChildCurrent;
  315. plsdnChildCurrent = plsdnChildCurrent->plsdnNext;
  316. }
  317. /* include subline's list to upper level */
  318. *(GetWhereToPutLinkSubl(plssublParent, plsdnParent->plsdnPrev)) = plsdnChildFirst;
  319. if (plsdnChildFirst != NULL && plsdnParent->plsdnPrev != NULL)
  320. plsdnChildFirst->plsdnPrev = plsdnParent->plsdnPrev;
  321. /* if subline's list is empty than dnode before parent should be made current */
  322. if (plsdnChildFirst == NULL)
  323. {
  324. /* if subline's list is empty than dnode before parent should be made current */
  325. SetCurrentDnodeSubl(plssublParent, plsdnParent->plsdnPrev);
  326. }
  327. else
  328. {
  329. /* else last dnode in subline is now current dnode */
  330. SetCurrentDnodeSubl(plssublParent, plssubl->plsdnLast);
  331. }
  332. /* delete parent dnode */
  333. lserr = DestroyDnodeList (&plsc->lscbk, plsc->pols, &plsc->lsiobjcontext,
  334. plsdnParent, plsc->fDontReleaseRuns);
  335. if (lserr != lserrNone)
  336. return lserr;
  337. /* set first dnode of subline to NULL and destroy subline will not erase dnodes that has
  338. been promoted to the upper level */
  339. plssubl->plsdnFirst = NULL;
  340. lserr = DestroySublineCore(plssubl,&plsc->lscbk, plsc->pols,
  341. &plsc->lsiobjcontext, plsc->fDontReleaseRuns);
  342. if (lserr != lserrNone)
  343. return lserr;
  344. SetDnodeToFinish(plsc, NULL);
  345. return lserrNone;
  346. }
  347. /* L S D N F I N I S H D E L E T E A L L*/
  348. /*----------------------------------------------------------------------------
  349. %%Function: LsdnFinishDeleteAll
  350. %%Contact: igorzv
  351. Parameters:
  352. plsc - (IN) ptr to line services context
  353. dcpToAdvance - (IN) increase cp by this number before hanldler ends
  354. Delete parent dnode and include child list in the upper level
  355. ----------------------------------------------------------------------------*/
  356. LSERR WINAPI LsdnFinishDeleteAll(PLSC plsc, /* IN: Pointer to LS Context */
  357. LSDCP lsdcp) /* IN: dcp adopted */
  358. {
  359. PLSDNODE plsdnParent;
  360. PLSDNODE plsdnFirstOnLine;
  361. PLSDNODE plsdnFirstInContents;
  362. PLSDNODE plsdnLastBeforeContents;
  363. LSERR lserr;
  364. long dvpPen;
  365. long durPen;
  366. long dvrPen;
  367. PLSSUBL plssublMain;
  368. if (!FIsLSC(plsc)) return lserrInvalidParameter;
  369. if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled;
  370. /* all sublines should be closed */
  371. if (GetCurrentSubline(plsc) != NULL) return lserrFormattingFunctionDisabled;
  372. plsdnParent = GetDnodeToFinish(plsc);
  373. if (plsdnParent == NULL) return lserrFiniFunctionDisabled;
  374. plssublMain = &plsc->plslineCur->lssubl;
  375. AdvanceCurrentCpLimSubl(plssublMain, lsdcp);
  376. plsdnFirstOnLine = plssublMain->plsdnFirst;
  377. plsdnFirstInContents = plsdnFirstOnLine;
  378. plsdnLastBeforeContents = NULL;
  379. while (plsdnFirstInContents != NULL && FIsNotInContent(plsdnFirstInContents))
  380. {
  381. plsdnLastBeforeContents = plsdnFirstInContents;
  382. plsdnFirstInContents = plsdnFirstInContents->plsdnNext;
  383. }
  384. /* restore state as it was before starting formatting content*/
  385. plsc->lstabscontext.plsdnPendingTab = NULL;
  386. plsc->plslineCur->lslinfo.fAdvanced = 0;
  387. plsc->plslineCur->lslinfo.EffectsFlags = 0;
  388. /* break link with contest*/
  389. if (plsdnFirstInContents != NULL)
  390. *(GetWhereToPutLinkSubl(plssublMain, plsdnFirstInContents->plsdnPrev)) = NULL;
  391. /* set dnode to append */
  392. SetCurrentDnodeSubl(plssublMain, plsdnLastBeforeContents);
  393. /* set current subline */
  394. SetCurrentSubline(plsc, plssublMain);
  395. /* recalculate current position */
  396. if (plsdnFirstInContents != NULL)
  397. {
  398. FindListFinalPenMovement(plsdnFirstInContents, plssublMain->plsdnLast,
  399. &durPen, &dvrPen, &dvpPen);
  400. AdvanceCurrentUrSubl(plssublMain, -durPen);
  401. AdvanceCurrentVrSubl(plssublMain, -dvrPen);
  402. }
  403. /* delete content before this parent dnode */
  404. if (plsdnFirstInContents != NULL)
  405. {
  406. lserr = DestroyDnodeList (&plsc->lscbk, plsc->pols, &plsc->lsiobjcontext,
  407. plsdnFirstInContents, plsc->fDontReleaseRuns);
  408. if (lserr != lserrNone)
  409. return lserr;
  410. }
  411. /* delete parent dnode and child list*/
  412. lserr = DestroyDnodeList (&plsc->lscbk, plsc->pols, &plsc->lsiobjcontext,
  413. plsdnParent, plsc->fDontReleaseRuns);
  414. if (lserr != lserrNone)
  415. return lserr;
  416. SetDnodeToFinish(plsc, NULL);
  417. return lserrNone;
  418. }
  419. LSERR WINAPI LsdnFinishByOneChar( /* allows replacement by simple DNODE only */
  420. PLSC plsc, /* IN: Pointer to LS Context */
  421. long urColumnMax, /* IN: urColumnMax */
  422. WCHAR ch, /* IN: character to replace */
  423. PCLSCHP plschp, /* IN: lschp for character */
  424. PLSRUN plsrun, /* IN: plsrun for character */
  425. FMTRES* pfmtres) /* OUT:Result of the Repl formatter*/
  426. {
  427. LSERR lserr;
  428. LSFRUN lsfrun;
  429. PLSDNODE plsdn;
  430. PLSSUBL plssubl;
  431. if (!FIsLSC(plsc)) return lserrInvalidParameter;
  432. if (!FFormattingAllowed(plsc)) return lserrFormattingFunctionDisabled;
  433. /* all sublines should be closed */
  434. if (GetCurrentSubline(plsc) != NULL) return lserrFormattingFunctionDisabled;
  435. plsdn = GetDnodeToFinish(plsc);
  436. if (plsdn == NULL) return lserrFiniFunctionDisabled;
  437. plssubl = SublineFromDnode(plsdn);
  438. /* nobody can change current dnode after plsdn was constructed */
  439. Assert(GetCurrentDnodeSubl(plssubl) == plsdn->plsdnPrev);
  440. if (plsdn->dcp != 1) return lserrWrongFiniFunction;
  441. lserr = LsdnFinishDelete(plsc, 0);
  442. if (lserr != lserrNone)
  443. return lserr;
  444. Assert(IsLschpFlagsValid(plsc, plschp));
  445. lsfrun.plschp = plschp;
  446. /* Special effects */
  447. plsc->plslineCur->lslinfo.EffectsFlags |= plschp->EffectsFlags;
  448. lsfrun.plsrun = plsrun;
  449. lsfrun.lpwchRun = &ch;
  450. lsfrun.cwchRun = 1;
  451. /* to ProcessOneRun work properly we need to temporarely restore current subline */
  452. SetCurrentSubline(plsc, plssubl);
  453. lserr = ProcessOneRun(plsc, urColumnMax, &lsfrun, NULL, 0, pfmtres);
  454. if (lserr != lserrNone)
  455. return lserr;
  456. SetCurrentSubline(plsc, NULL);
  457. return lserrNone;
  458. }