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.

1566 lines
42 KiB

  1. #include "lsmem.h"
  2. #include "limits.h"
  3. #include "lscbk.h"
  4. #include "lsdevres.h"
  5. #include "pdobj.h"
  6. #include "objdim.h"
  7. #include "plssubl.h"
  8. #include "plsdnode.h"
  9. #include "pilsobj.h"
  10. #include "lscrsubl.h"
  11. #include "lssubset.h"
  12. #include "lsdnset.h"
  13. #include "lsdocinf.h"
  14. #include "lsidefs.h"
  15. #include "fmti.h"
  16. #include "posichnk.h"
  17. #include "locchnk.h"
  18. #include "lsdnfin.h"
  19. #include "brko.h"
  20. #include "lspap.h"
  21. #include "plspap.h"
  22. #include "lsqsubl.h"
  23. #include "dispi.h"
  24. #include "lsdssubl.h"
  25. #include "lsems.h"
  26. #include "lstfset.h"
  27. #include "plnobj.h"
  28. #include "plocchnk.h"
  29. #include "lsimeth.h"
  30. #include "robj.h"
  31. #include "lsidefs.h"
  32. #include "brkpos.h"
  33. #include "objhelp.h"
  34. #include "lssubset.h"
  35. typedef enum breaksublinetype
  36. {
  37. breakSublineAfter,
  38. breakSublineInside
  39. } BREAKSUBLINETYPE;
  40. struct ilsobj
  41. {
  42. POLS pols;
  43. LSCBK lscbk;
  44. PLSC plsc;
  45. DWORD idobj;
  46. LSESC lsesc;
  47. PFNREVERSEGETINFO pfnReverseGetInfo;
  48. PFNREVERSEENUM pfnReverseEnum;
  49. };
  50. typedef struct rbreakrec
  51. {
  52. BOOL fValid; /* Is this break record contains valid info? */
  53. BREAKSUBLINETYPE breakSublineType; /* After / Inside */
  54. LSCP cpBreak; /* CpLim of the break */
  55. } RBREAKREC;
  56. struct dobj
  57. {
  58. PILSOBJ pilsobj; /* ILS object */
  59. LSTFLOW lstflowL; /* flow of line input */
  60. LSTFLOW lstflowO; /* flow of this object */
  61. BOOL fDoNotBreakAround; /* Break around robj as "can" */
  62. BOOL fSuppressTrailingSpaces;
  63. /* Kill trailing space when robj is
  64. alone on the line & broken */
  65. BOOL fFirstOnLine; /* If first on line -- required for
  66. fSuppressTrailingSpaces */
  67. PLSDNODE plsdnTop; /* Parent dnode */
  68. LSCP cpStart; /* Starting LS cp for object */
  69. LSCP cpStartObj; /* cp for start of object can be different
  70. than cpStart if object is broken. */
  71. LSCP cpFirstSubline; /* cpFirst of the subline; will be
  72. equal to cpStart when object is broken and
  73. equal to cpStart+1 when it isnot broken */
  74. LSDCP dcpSubline; /* Number of characters in the subline */
  75. LSDCP dcp; /* Number of characters in object */
  76. PLSSUBL plssubl; /* Subline formatted RTL */
  77. OBJDIM objdimAll; /* Objdim for entire object */
  78. long dup; /* dup of object */
  79. RBREAKREC breakRecord [NBreaksToSave];
  80. /* Last 3 break records for each break */
  81. };
  82. static LSTFLOW rlstflowReverse[8] =
  83. {
  84. lstflowWS, /* Reverse lstflowES */
  85. lstflowWN, /* Reverse lstflowEN */
  86. lstflowNE, /* Reverse lstflowSE */
  87. lstflowNW, /* Reverse lstflowSW */
  88. lstflowES, /* Reverse lstflowWS */
  89. lstflowEN, /* Reverse lstflowWN */
  90. lstflowSE, /* Reverse lstflowNE */
  91. lstflowSW /* Reverse lstflowNW */
  92. };
  93. /* R E V E R S E S A V E B R E A K R E C O R D */
  94. /*----------------------------------------------------------------------------
  95. %%Function: RobjSaveBreakRecord
  96. %%Contact: antons
  97. Save break record in DOBJ.
  98. ----------------------------------------------------------------------------*/
  99. static void ReverseSaveBreakRecord (
  100. PDOBJ pdobj,
  101. BRKKIND brkkindWhatBreak,
  102. BREAKSUBLINETYPE breakSublineType,
  103. LSCP cpBreak)
  104. {
  105. DWORD ind = GetBreakRecordIndex (brkkindWhatBreak);
  106. pdobj->breakRecord [ind].fValid = TRUE;
  107. pdobj->breakRecord [ind].breakSublineType = breakSublineType;
  108. pdobj->breakRecord [ind].cpBreak = cpBreak;
  109. }
  110. /* R E V E R S E G E T B R E A K R E C O R D */
  111. /*----------------------------------------------------------------------------
  112. %%Function: ReverseGetBreakRecord
  113. %%Contact: antons
  114. Read break record from DOBJ.
  115. ----------------------------------------------------------------------------*/
  116. static void ReverseGetBreakRecord (
  117. PDOBJ pdobj,
  118. BRKKIND brkkindWhatBreak,
  119. BREAKSUBLINETYPE *breakSublineType,
  120. LSCP * pcpBreak )
  121. {
  122. DWORD ind = GetBreakRecordIndex (brkkindWhatBreak);
  123. Assert (pdobj->breakRecord [ind].fValid);
  124. *breakSublineType = pdobj->breakRecord [ind].breakSublineType;
  125. *pcpBreak = pdobj->breakRecord [ind].cpBreak;
  126. }
  127. /* F R E E D O B J */
  128. /*----------------------------------------------------------------------------
  129. %%Function: ReverseFreeDobj
  130. %%Contact: antons
  131. Free all resources associated with this Reverse dobj.
  132. ----------------------------------------------------------------------------*/
  133. static LSERR ReverseFreeDobj(PDOBJ pdobj)
  134. {
  135. LSERR lserr = lserrNone;
  136. PILSOBJ pilsobj = pdobj->pilsobj;
  137. if (pdobj->plssubl != NULL)
  138. {
  139. lserr = LsDestroySubline(pdobj->plssubl);
  140. }
  141. pilsobj->lscbk.pfnDisposePtr(pilsobj->pols, pdobj);
  142. return lserr;
  143. }
  144. /* R E V E R S E F M T F A I L E D */
  145. /*----------------------------------------------------------------------------
  146. %%Function: ReverseFmtFailed
  147. %%Contact: antons
  148. Could not create Reverse DOBJ due to error.
  149. ----------------------------------------------------------------------------*/
  150. static LSERR ReverseFmtFailed (PDOBJ pdobj, LSERR lserr)
  151. {
  152. if (pdobj != NULL) ReverseFreeDobj (pdobj); /* Works with parially-filled DOBJ */
  153. return lserr;
  154. }
  155. /* T R A N S L A T E C P L I M S U B L I N E T O D C P E X T E R N A L
  156. /*----------------------------------------------------------------------------
  157. %%Function: TranslateCpLimSublineToDcpExternal
  158. %%Contact: antons
  159. Translates position (CpLim) in the subline to dcp of
  160. the reverse object.
  161. ----------------------------------------------------------------------------*/
  162. /* REVIEW (antons): Is old name OK for new behavior? */
  163. LSDCP TranslateCpLimSublineToDcpExternal (PDOBJ pdobj, LSCP cpLim)
  164. {
  165. Unreferenced (pdobj);
  166. Assert (cpLim <= pdobj->cpStart + (long) pdobj->dcp);
  167. Assert (cpLim >= pdobj->cpStart);
  168. Assert (pdobj->cpStart <= pdobj->cpFirstSubline);
  169. Assert (pdobj->cpStart + pdobj->dcp >= pdobj->cpFirstSubline + pdobj->dcpSubline);
  170. return cpLim - pdobj->cpStart;
  171. }
  172. /* T R A N S L A T E D C P E X T E R N A L T O C P L I M S U B L I N E
  173. /*----------------------------------------------------------------------------
  174. %%Function: TranslateCpLimInternalToExternal
  175. %%Contact: antons
  176. Translates position (dcp) in reverse object to cpLim of
  177. the subline.
  178. ----------------------------------------------------------------------------*/
  179. LSCP TranslateDcpExternalToCpLimSubline (PDOBJ pdobj, LSDCP dcp)
  180. {
  181. Unreferenced (pdobj);
  182. Assert (dcp <= pdobj->dcp);
  183. Assert (pdobj->cpStart <= pdobj->cpFirstSubline);
  184. Assert (pdobj->cpStart + pdobj->dcp >= pdobj->cpFirstSubline + pdobj->dcpSubline);
  185. return pdobj->cpStart + dcp;
  186. }
  187. /* F I N I S H B R E A K R E G U L A R */
  188. /*----------------------------------------------------------------------------
  189. %%Function: FinishBreakRegular
  190. %%Contact: antons
  191. Set up breaking information for proposed break point.
  192. Caller must save break record by hiself!
  193. ----------------------------------------------------------------------------*/
  194. static LSERR FinishBreakRegular (
  195. DWORD ichnk, /* (IN): chunk id */
  196. PDOBJ pdobj, /* (IN): object for break */
  197. LSCP cpBreak, /* (IN): cp - break to report outside */
  198. POBJDIM pobjdimSubline, /* (IN): objdim for subline at proposed break */
  199. PBRKOUT pbrkout) /* (OUT): break info for Line Services */
  200. {
  201. Assert (ichnk != ichnkOutside);
  202. pbrkout->fSuccessful = fTrue;
  203. pbrkout->posichnk.dcp = TranslateCpLimSublineToDcpExternal (pdobj, cpBreak);
  204. pbrkout->posichnk.ichnk = ichnk;
  205. pbrkout->objdim = *pobjdimSubline;
  206. return lserrNone;
  207. }
  208. /* P U T B R E A K A T E N D O F O B J E C T */
  209. /*----------------------------------------------------------------------------
  210. %%Function: PutBreakAtEndOfObject
  211. %%Contact: antons
  212. Fill in break output record for the end of the object.
  213. ----------------------------------------------------------------------------*/
  214. static void PutBreakAtEndOfObject (
  215. DWORD ichnk, /* (IN): index in chunk */
  216. PCLOCCHNK pclocchnk, /* (IN): locchnk to find break */
  217. PBRKOUT pbrkout) /* (OUT): results of breaking */
  218. {
  219. PDOBJ pdobj = pclocchnk->plschnk[ichnk].pdobj;
  220. Assert (ichnk != ichnkOutside);
  221. pbrkout->fSuccessful = fTrue;
  222. pbrkout->posichnk.dcp = pdobj->dcp;
  223. pbrkout->posichnk.ichnk = ichnk;
  224. pbrkout->objdim = pdobj->objdimAll;
  225. }
  226. /* P U T B R E A K B E F O R E O B J E C T */
  227. /*----------------------------------------------------------------------------
  228. %%Function: PutBreakBeforeObject
  229. %%Contact: antons
  230. Fill in break output record for break before object.
  231. ----------------------------------------------------------------------------*/
  232. static void PutBreakBeforeObject (
  233. DWORD ichnk, /* (IN): index in chunk */
  234. PCLOCCHNK pclocchnk, /* (IN): locchnk to find break */
  235. PBRKOUT pbrkout) /* (OUT): results of breaking */
  236. {
  237. Unreferenced (pclocchnk);
  238. Assert (ichnk != ichnkOutside);
  239. pbrkout->fSuccessful = fTrue;
  240. pbrkout->posichnk.dcp = 0;
  241. pbrkout->posichnk.ichnk = ichnk;
  242. ZeroMemory (&pbrkout->objdim, sizeof(pbrkout->objdim));
  243. }
  244. /* P U T B R E A K U N S U C C E S S F U L */
  245. /*----------------------------------------------------------------------------
  246. %%Function: PutBreakUnsuccessful
  247. %%Contact: antons
  248. Fill in break output record for unsuccessful break of ROBJ
  249. ----------------------------------------------------------------------------*/
  250. static void PutBreakUnsuccessful (PDOBJ pdobj, PBRKOUT pbrkout)
  251. {
  252. pbrkout->fSuccessful = FALSE;
  253. if (pdobj->fDoNotBreakAround) pbrkout->brkcond = brkcondCan;
  254. else
  255. pbrkout->brkcond = brkcondPlease;
  256. }
  257. /* I N I T D O B J */
  258. /*----------------------------------------------------------------------------
  259. %%Function: InitDobj
  260. %%Contact: ricksa
  261. Allocate and initialize DOBJ with basic information.
  262. ----------------------------------------------------------------------------*/
  263. static LSERR InitDobj(
  264. PILSOBJ pilsobj, /* (IN): ilsobj */
  265. PCFMTIN pcfmtin, /* (IN): formatting input */
  266. PDOBJ *ppdobj) /* (OUT): initialized dobj */
  267. {
  268. /* Assume failure */
  269. LSERR lserr;
  270. PDOBJ pdobj = (PDOBJ)
  271. pilsobj->lscbk.pfnNewPtr(pilsobj->pols, sizeof(*pdobj));
  272. if (pdobj != NULL)
  273. {
  274. int iBreakRec;
  275. ZeroMemory(pdobj, sizeof(*pdobj));
  276. pdobj->pilsobj = pilsobj;
  277. pdobj->cpStart = pcfmtin->lsfgi.cpFirst;
  278. pdobj->lstflowL = pcfmtin->lsfgi.lstflow;
  279. pdobj->lstflowO = rlstflowReverse[(int) pcfmtin->lsfgi.lstflow];
  280. pdobj->cpStartObj = pcfmtin->lsfgi.cpFirst;
  281. for (iBreakRec = 0; iBreakRec < NBreaksToSave; iBreakRec++)
  282. {
  283. pdobj->breakRecord [iBreakRec].fValid = FALSE;
  284. };
  285. *ppdobj = pdobj;
  286. lserr = lserrNone;
  287. }
  288. else
  289. {
  290. lserr = lserrOutOfMemory;
  291. }
  292. return lserr;
  293. }
  294. /* F I N I S H F M T */
  295. /*----------------------------------------------------------------------------
  296. %%Function: FinishFmt
  297. %%Contact: ricksa
  298. Helper for ReverseFmt & ReverseFmtResume that completes work
  299. for formatting.
  300. ----------------------------------------------------------------------------*/
  301. static LSERR FinishFmt(
  302. PDOBJ pdobj, /* (IN): dobj for reverse */
  303. PILSOBJ pilsobj, /* (IN): ILS object for Reverse */
  304. PCFMTIN pcfmtin, /* (IN): formatting input */
  305. LSCP cpFirstMain, /* (IN): cp first of reverse subline */
  306. LSCP cpLast, /* (IN): cp output from formatting subline */
  307. FMTRES fmtres) /* (IN): final format state */
  308. {
  309. LSERR lserr;
  310. /* Set cpFirst and cpLim for reverse subline */
  311. pdobj->cpFirstSubline = cpFirstMain;
  312. pdobj->dcpSubline = cpLast - pdobj->cpFirstSubline;
  313. /* Set dcp for whole object */
  314. pdobj->dcp = cpLast - pdobj->cpStart;
  315. if (fmtres != fmtrExceededMargin)
  316. {
  317. /* Note: +1 for the escape character at the end of the object. */
  318. pdobj->dcp++;
  319. }
  320. lserr = LsdnSubmitSublines(pilsobj->plsc, pcfmtin->plsdnTop, 1,
  321. &pdobj->plssubl, TRUE, FALSE, TRUE, TRUE, FALSE);
  322. if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
  323. return LsdnFinishRegular(pilsobj->plsc, pdobj->dcp,
  324. pcfmtin->lsfrun.plsrun, pcfmtin->lsfrun.plschp, pdobj,
  325. &pdobj->objdimAll);
  326. }
  327. /* R E V E R S E C R E A T E I L S O B J */
  328. /*----------------------------------------------------------------------------
  329. %%Function: ReverseCreateILSObj
  330. %%Contact: ricksa
  331. CreateILSObj
  332. Create the ILS object for all Reverse objects.
  333. ----------------------------------------------------------------------------*/
  334. LSERR WINAPI ReverseCreateILSObj(
  335. POLS pols, /* (IN): client application context */
  336. PLSC plsc, /* (IN): LS context */
  337. PCLSCBK pclscbk, /* (IN): callbacks to client application */
  338. DWORD idObj, /* (IN): id of the object */
  339. PILSOBJ *ppilsobj) /* (OUT): object ilsobj */
  340. {
  341. PILSOBJ pilsobj;
  342. REVERSEINIT reverseinit;
  343. LSERR lserr;
  344. *ppilsobj = NULL; /* in case of error */
  345. /* Get initialization data */
  346. reverseinit.dwVersion = REVERSE_VERSION;
  347. lserr = pclscbk->pfnGetObjectHandlerInfo(pols, idObj, &reverseinit);
  348. if (lserr != lserrNone) return lserr;
  349. pilsobj = (PILSOBJ) pclscbk->pfnNewPtr(pols, sizeof(*pilsobj));
  350. if (NULL == pilsobj) return lserrOutOfMemory;
  351. pilsobj->pols = pols;
  352. pilsobj->lscbk = *pclscbk;
  353. pilsobj->plsc = plsc;
  354. pilsobj->idobj = idObj;
  355. pilsobj->lsesc.wchFirst = reverseinit.wchEndReverse;
  356. pilsobj->lsesc.wchLast = reverseinit.wchEndReverse;
  357. pilsobj->pfnReverseEnum = reverseinit.pfnEnum;
  358. pilsobj->pfnReverseGetInfo = reverseinit.pfnGetRobjInfo;
  359. *ppilsobj = pilsobj;
  360. return lserrNone;
  361. }
  362. /* R E V E R S E D E S T R O Y I L S O B J */
  363. /*----------------------------------------------------------------------------
  364. %%Function: ReverseDestroyILSObj
  365. %%Contact: ricksa
  366. DestroyILSObj
  367. Free all resources assocaiated with Reverse ILS object.
  368. ----------------------------------------------------------------------------*/
  369. LSERR WINAPI ReverseDestroyILSObj(
  370. PILSOBJ pilsobj) /* (IN): object ilsobj */
  371. {
  372. pilsobj->lscbk.pfnDisposePtr(pilsobj->pols, pilsobj);
  373. return lserrNone;
  374. }
  375. /* R E V E R S E S E T D O C */
  376. /*----------------------------------------------------------------------------
  377. %%Function: ReverseSetDoc
  378. %%Contact: ricksa
  379. SetDoc
  380. Keep track of device information for scaling purposes.
  381. ----------------------------------------------------------------------------*/
  382. LSERR WINAPI ReverseSetDoc(
  383. PILSOBJ pilsobj, /* (IN): object ilsobj */
  384. PCLSDOCINF pclsdocinf) /* (IN): initialization data of the document level */
  385. {
  386. Unreferenced(pilsobj);
  387. Unreferenced(pclsdocinf);
  388. return lserrNone;
  389. }
  390. /* R E V E R S E C R E A T E L N O B J */
  391. /*----------------------------------------------------------------------------
  392. %%Function: ReverseCreateLNObj
  393. %%Contact: ricksa
  394. CreateLNObj
  395. Create the Line Object for the Reverse. No real need for a line
  396. object so don't allocated it.
  397. ----------------------------------------------------------------------------*/
  398. LSERR WINAPI ReverseCreateLNObj(
  399. PCILSOBJ pcilsobj, /* (IN): object ilsobj */
  400. PLNOBJ *pplnobj) /* (OUT): object lnobj */
  401. {
  402. *pplnobj = (PLNOBJ) pcilsobj;
  403. return lserrNone;
  404. }
  405. /* R E V E R S E D E S T R O Y L N O B J */
  406. /*----------------------------------------------------------------------------
  407. %%Function: ReverseDestroyLNObj
  408. %%Contact: ricksa
  409. DestroyLNObj
  410. Frees resources associated with the Reverse line object. Since
  411. there isn't any this is a no-op.
  412. ----------------------------------------------------------------------------*/
  413. LSERR WINAPI ReverseDestroyLNObj(
  414. PLNOBJ plnobj) /* (OUT): object lnobj */
  415. {
  416. Unreferenced(plnobj);
  417. return lserrNone;
  418. }
  419. /* R E V E R S E F M T */
  420. /*----------------------------------------------------------------------------
  421. %%Function: ReverseFmt
  422. %%Contact: ricksa
  423. Fmt
  424. Format the Reverse object.
  425. ----------------------------------------------------------------------------*/
  426. LSERR WINAPI ReverseFmt(
  427. PLNOBJ plnobj, /* (IN): object lnobj */
  428. PCFMTIN pcfmtin, /* (IN): formatting input */
  429. FMTRES *pfmtres) /* (OUT): formatting result */
  430. {
  431. PDOBJ pdobj;
  432. LSERR lserr;
  433. PILSOBJ pilsobj = (PILSOBJ) plnobj;
  434. LSCP cpStartMain = pcfmtin->lsfgi.cpFirst + 1;
  435. LSCP cpOut;
  436. lserr = InitDobj(pilsobj, pcfmtin, &pdobj);
  437. // Assert (pilsobj->pfnReverseGetInfo != NULL);
  438. if (pilsobj->pfnReverseGetInfo != NULL)
  439. {
  440. lserr = pilsobj->pfnReverseGetInfo (pilsobj->pols,
  441. pcfmtin->lsfgi.cpFirst,
  442. pcfmtin->lsfrun.plsrun,
  443. &pdobj->fDoNotBreakAround,
  444. &pdobj->fSuppressTrailingSpaces);
  445. if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
  446. };
  447. if (lserr != lserrNone) return lserrNone;
  448. pdobj->fFirstOnLine = pcfmtin->lsfgi.fFirstOnLine;
  449. pdobj->plsdnTop = pcfmtin->plsdnTop;
  450. // Format the text to the maximum remaining in the column
  451. lserr = FormatLine(pilsobj->plsc, cpStartMain,
  452. pcfmtin->lsfgi.urColumnMax - pcfmtin->lsfgi.urPen,
  453. pdobj->lstflowO, &pdobj->plssubl, 1, &pilsobj->lsesc,
  454. &pdobj->objdimAll, &cpOut, NULL, NULL, pfmtres);
  455. if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
  456. return FinishFmt(pdobj, pilsobj, pcfmtin, cpStartMain, cpOut, *pfmtres);
  457. }
  458. /* R E V E R S E F M T R E S U M E */
  459. /*----------------------------------------------------------------------------
  460. %%Function: ReverseFmtResume
  461. %%Contact: ricksa
  462. Fmt
  463. Format a broken Reverse object.
  464. ----------------------------------------------------------------------------*/
  465. LSERR WINAPI ReverseFmtResume(
  466. PLNOBJ plnobj, /* (IN): object lnobj */
  467. const BREAKREC *rgBreakRecord, /* (IN): array of break records */
  468. DWORD nBreakRecord, /* (IN): size of the break records array */
  469. PCFMTIN pcfmtin, /* (IN): formatting input */
  470. FMTRES *pfmtres) /* (OUT): formatting result */
  471. {
  472. PDOBJ pdobj;
  473. LSERR lserr;
  474. PILSOBJ pilsobj = (PILSOBJ) plnobj;
  475. LSCP cpStartMain = pcfmtin->lsfgi.cpFirst;
  476. LSCP cpOut;
  477. lserr = InitDobj(pilsobj, pcfmtin, &pdobj);
  478. if (lserr != lserrNone) return lserr;
  479. /* InitDobj sets cpStartObj to start of text. Because we are resuming,
  480. we need to set this to the real start of the object. */
  481. pdobj->cpStartObj = rgBreakRecord->cpFirst;
  482. // Assert (pilsobj->pfnReverseGetInfo != NULL);
  483. if (pilsobj->pfnReverseGetInfo != NULL)
  484. {
  485. lserr = pilsobj->pfnReverseGetInfo (pilsobj->pols, pcfmtin->lsfgi.cpFirst,
  486. pcfmtin->lsfrun.plsrun,
  487. &pdobj->fDoNotBreakAround,
  488. &pdobj->fSuppressTrailingSpaces);
  489. if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
  490. };
  491. pdobj->fFirstOnLine = pcfmtin->lsfgi.fFirstOnLine;
  492. pdobj->plsdnTop = pcfmtin->plsdnTop;
  493. /* Format the text to the maximum remaining in the column */
  494. lserr = FormatResumedLine(pilsobj->plsc, cpStartMain,
  495. pcfmtin->lsfgi.urColumnMax - pcfmtin->lsfgi.urPen,
  496. pdobj->lstflowO, &pdobj->plssubl, 1, &pilsobj->lsesc,
  497. &pdobj->objdimAll, &cpOut, NULL, NULL, pfmtres,
  498. &rgBreakRecord[1], nBreakRecord - 1);
  499. if (lserr != lserrNone) return ReverseFmtFailed (pdobj, lserr);
  500. return FinishFmt(pdobj, pilsobj, pcfmtin, cpStartMain, cpOut, *pfmtres);
  501. }
  502. /* R E V E R S E T R U N C A T E C H U N K */
  503. /*----------------------------------------------------------------------------
  504. %%Function: ReverseTruncateChunk
  505. %%Contact: ricksa
  506. ----------------------------------------------------------------------------*/
  507. LSERR WINAPI ReverseTruncateChunk(
  508. PCLOCCHNK plocchnk, /* (IN): locchnk to truncate */
  509. PPOSICHNK posichnk) /* (OUT): truncation point */
  510. {
  511. long urColumnMax = plocchnk->lsfgi.urColumnMax;
  512. long ur = plocchnk->ppointUvLoc[0].u;
  513. PDOBJ pdobj = NULL;
  514. DWORD i;
  515. LSCP cp;
  516. LSERR lserr;
  517. AssertSz(plocchnk->ppointUvLoc[0].u <= urColumnMax,
  518. "ReverseTruncateChunk - pen greater than column max");
  519. /* Look for chunk to truncate */
  520. for (i = 0; ur <= urColumnMax; i++)
  521. {
  522. AssertSz((i < plocchnk->clschnk), "ReverseTruncateChunk exceeded group of chunks");
  523. ur = plocchnk->ppointUvLoc[i].u;
  524. AssertSz(ur <= urColumnMax,
  525. "ReverseTruncateChunk - pen pos past column max");
  526. pdobj = plocchnk->plschnk[i].pdobj;
  527. ur += pdobj->objdimAll.dur;
  528. }
  529. /* Found the object where truncation is to occur */
  530. AssertSz(pdobj != NULL, "ReverseTruncateChunk - pdobj is NULL");
  531. /* Get the truncation point from the subline */
  532. lserr = LsTruncateSubline(pdobj->plssubl,
  533. urColumnMax - (ur - pdobj->objdimAll.dur), &cp);
  534. if (lserr != lserrNone) return lserr;
  535. /* Format return result */
  536. posichnk->ichnk = i - 1;
  537. posichnk->dcp = TranslateCpLimSublineToDcpExternal (pdobj, cp + 1);
  538. return lserrNone;
  539. }
  540. /* R E V E R S E F I N D P R E V B R E A K C O R E*/
  541. /*----------------------------------------------------------------------------
  542. %%Function: ReverseFindPrevBreakCore
  543. %%Contact: antons
  544. ----------------------------------------------------------------------------*/
  545. LSERR ReverseFindPrevBreakCore (
  546. PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
  547. DWORD ichnk, /* (IN): object to start looking for break */
  548. BOOL fDcpOutside, /* (IN): when true, start looking from outside */
  549. LSDCP dcp, /* (IN): starting dcp; valid only when fDcpOutside=False */
  550. BRKCOND brkcond, /* (IN): recommmendation about the break before ichnk */
  551. PBRKOUT pbrkout) /* (OUT): result of breaking */
  552. {
  553. LSERR lserr;
  554. PDOBJ pdobj = pclocchnk->plschnk[ichnk].pdobj;
  555. if (fDcpOutside)
  556. {
  557. if ( brkcond != brkcondNever &&
  558. ! (pdobj->fDoNotBreakAround && brkcond == brkcondCan) )
  559. {
  560. /* Can break after ichnk */
  561. PutBreakAtEndOfObject(ichnk, pclocchnk, pbrkout);
  562. ReverseSaveBreakRecord (pdobj, brkkindPrev, breakSublineAfter, pdobj->cpStart + pdobj->dcp);
  563. return lserrNone;
  564. }
  565. else
  566. {
  567. /* Try to break ichnk */
  568. return ReverseFindPrevBreakCore ( pclocchnk,
  569. ichnk,
  570. fFalse,
  571. pclocchnk->plschnk[ichnk].dcp - 1,
  572. brkcond,
  573. pbrkout );
  574. }
  575. }
  576. else
  577. {
  578. LSCP cpTruncateSubline = TranslateDcpExternalToCpLimSubline (pdobj, dcp - 1);
  579. BOOL fSuccessful;
  580. LSCP cpBreak;
  581. OBJDIM objdimSubline;
  582. BRKPOS brkpos;
  583. Assert (dcp >= 1 && dcp <= pdobj->dcp);
  584. /* REVIEW (antons): I do not think that passing pclocchnk->lsfgi.urColumnMax is correct... */
  585. /* need to be confirmed with IgorZv */
  586. lserr = LsFindPrevBreakSubline (
  587. pdobj->plssubl,
  588. pclocchnk->lsfgi.fFirstOnLine,
  589. cpTruncateSubline,
  590. pclocchnk->lsfgi.urColumnMax,
  591. &fSuccessful,
  592. &cpBreak,
  593. &objdimSubline,
  594. &brkpos);
  595. if (lserr != lserrNone) return lserr;
  596. /* 1. Unsuccessful or break before first DNode */
  597. if (!fSuccessful || (fSuccessful && brkpos == brkposBeforeFirstDnode))
  598. {
  599. if (ichnk == 0)
  600. {
  601. /* First in the chunk => return UnSuccessful */
  602. PutBreakUnsuccessful (pdobj, pbrkout);
  603. return lserrNone;
  604. }
  605. else
  606. {
  607. /* Break between objects */
  608. if (pdobj->fDoNotBreakAround)
  609. {
  610. return ReverseFindPrevBreakCore ( pclocchnk,
  611. ichnk - 1,
  612. fTrue,
  613. 0,
  614. brkcondCan,
  615. pbrkout );
  616. }
  617. else
  618. {
  619. pdobj = pclocchnk->plschnk[ichnk-1].pdobj;
  620. PutBreakAtEndOfObject(ichnk - 1, pclocchnk, pbrkout);
  621. ReverseSaveBreakRecord (
  622. pclocchnk->plschnk[ichnk-1].pdobj,
  623. brkkindPrev,
  624. breakSublineAfter, pdobj->cpStart + pdobj->dcp);
  625. return lserrNone;
  626. };
  627. };
  628. }
  629. /* 2. Successful break after last DNode */
  630. else if (brkpos == brkposAfterLastDnode)
  631. {
  632. if (brkcond == brkcondNever) /* Can not reset dcp */
  633. {
  634. /* We are not allowed to break "after", */
  635. /* so we are trying another previous break if possible */
  636. return ReverseFindPrevBreakCore ( pclocchnk,
  637. ichnk,
  638. fFalse,
  639. dcp-1,
  640. brkcondCan,
  641. pbrkout );
  642. }
  643. else /* Can reset dcp */
  644. {
  645. /* We reset dcp of the break so it happends after object but in break
  646. record we remember that we should call SetBreakSubline with brkkindPrev */
  647. ReverseSaveBreakRecord ( pdobj, brkkindPrev, breakSublineInside,
  648. pdobj->cpStart + pdobj->dcp );
  649. return FinishBreakRegular ( ichnk,
  650. pdobj,
  651. pdobj->cpStart + pdobj->dcp,
  652. & objdimSubline,
  653. pbrkout );
  654. } ;
  655. }
  656. else
  657. {
  658. /* 3. Successful break inside subline */
  659. ReverseSaveBreakRecord (pdobj, brkkindPrev, breakSublineInside,
  660. cpBreak );
  661. return FinishBreakRegular ( ichnk,
  662. pdobj,
  663. cpBreak,
  664. &objdimSubline,
  665. pbrkout );
  666. };
  667. };
  668. }
  669. /* R E V E R S E F I N D P R E V B R E A K C H U N K */
  670. /*----------------------------------------------------------------------------
  671. %%Function: ReverseFindPrevBreakChunk
  672. %%Contact: antons
  673. ----------------------------------------------------------------------------*/
  674. LSERR WINAPI ReverseFindPrevBreakChunk (
  675. PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
  676. PCPOSICHNK pcpoischnk, /* (IN): place to start looking for break */
  677. BRKCOND brkcond, /* (IN): recommmendation about the break after chunk */
  678. PBRKOUT pbrkout) /* (OUT): results of breaking */
  679. {
  680. if (pcpoischnk->ichnk == ichnkOutside)
  681. {
  682. return ReverseFindPrevBreakCore ( pclocchnk,
  683. pclocchnk->clschnk - 1,
  684. fTrue,
  685. 0,
  686. brkcond,
  687. pbrkout );
  688. }
  689. else
  690. {
  691. return ReverseFindPrevBreakCore ( pclocchnk,
  692. pcpoischnk->ichnk,
  693. fFalse,
  694. pcpoischnk->dcp,
  695. brkcondPlease,
  696. pbrkout );
  697. };
  698. }
  699. /* R E V E R S E F I N D N E X T B R E A K C O R E*/
  700. /*----------------------------------------------------------------------------
  701. %%Function: ReverseFindNextBreakCore
  702. %%Contact: antons
  703. ----------------------------------------------------------------------------*/
  704. LSERR ReverseFindNextBreakCore (
  705. PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
  706. DWORD ichnk, /* (IN): object to start looking for break */
  707. BOOL fDcpOutside, /* (IN): when true, start looking from outside */
  708. LSDCP dcp, /* (IN): starting dcp; valid only when fDcpOutside=False */
  709. BRKCOND brkcond, /* (IN): recommmendation about the break before ichnk */
  710. PBRKOUT pbrkout ) /* (OUT): result of breaking */
  711. {
  712. LSERR lserr;
  713. PDOBJ pdobj = pclocchnk->plschnk[ichnk].pdobj;
  714. if (fDcpOutside)
  715. {
  716. if ( brkcond != brkcondNever &&
  717. ! (pdobj->fDoNotBreakAround && brkcond == brkcondCan) )
  718. {
  719. /* Can break before ichnk */
  720. PutBreakBeforeObject (ichnk, pclocchnk, pbrkout);
  721. return lserrNone;
  722. }
  723. else
  724. {
  725. /* Try to break ichnk */
  726. return ReverseFindNextBreakCore (pclocchnk, ichnk, fFalse, 1, brkcond, pbrkout );
  727. }
  728. }
  729. else
  730. {
  731. /* Dcp is inside ichnk */
  732. LSCP cpTruncateSubline = TranslateDcpExternalToCpLimSubline (pdobj, dcp - 1);
  733. BOOL fSuccessful;
  734. LSCP cpBreak;
  735. OBJDIM objdimSubline;
  736. BRKPOS brkpos;
  737. Assert (dcp >= 1 && dcp <= pdobj->dcp);
  738. /* REVIEW (antons): I do not think that passing pclocchnk->lsfgi.urColumnMax is correct... */
  739. /* need to be confirmed with IgorZv */
  740. lserr = LsFindNextBreakSubline (
  741. pdobj->plssubl,
  742. pclocchnk->lsfgi.fFirstOnLine,
  743. cpTruncateSubline,
  744. pclocchnk->lsfgi.urColumnMax,
  745. &fSuccessful,
  746. &cpBreak,
  747. &objdimSubline,
  748. &brkpos);
  749. if (lserr != lserrNone) return lserr;
  750. if (!fSuccessful)
  751. {
  752. /* Unsuccessful break */
  753. if (ichnk == pclocchnk->clschnk-1) /* Last object in chunk */
  754. {
  755. /* Review (AntonS): Better would be take objdimSubline */
  756. pbrkout->objdim = pclocchnk->plschnk[ichnk].pdobj->objdimAll;
  757. PutBreakUnsuccessful (pdobj, pbrkout);
  758. /* Break condition is not next => have to store break record */
  759. ReverseSaveBreakRecord ( pdobj,
  760. brkkindNext,
  761. breakSublineAfter, pdobj->cpStart + pdobj->dcp );
  762. return lserrNone;
  763. }
  764. else if (pdobj->fDoNotBreakAround)
  765. {
  766. /* Try to break next object */
  767. return ReverseFindNextBreakCore (
  768. pclocchnk,
  769. ichnk+1,
  770. fTrue,
  771. 0,
  772. brkcondCan,
  773. pbrkout );
  774. }
  775. else
  776. {
  777. /* Break after ichnk */
  778. PutBreakAtEndOfObject(ichnk, pclocchnk, pbrkout);
  779. ReverseSaveBreakRecord ( pclocchnk->plschnk[ichnk].pdobj,
  780. brkkindNext,
  781. breakSublineAfter,
  782. pclocchnk->plschnk[ichnk].pdobj->cpStart +
  783. pclocchnk->plschnk[ichnk].pdobj->dcp );
  784. return lserrNone;
  785. };
  786. }
  787. else if (brkpos == brkposAfterLastDnode)
  788. {
  789. /* Break after last dnode => reset dcp and break afetr ichnk */
  790. ReverseSaveBreakRecord (pdobj, brkkindNext, breakSublineInside, pdobj->cpStart + pdobj->dcp);
  791. return FinishBreakRegular ( ichnk,
  792. pdobj,
  793. pdobj->cpStart + pdobj->dcp,
  794. & objdimSubline,
  795. pbrkout );
  796. }
  797. else
  798. {
  799. /* 3. Successful break inside subline */
  800. ReverseSaveBreakRecord (pdobj, brkkindNext, breakSublineInside, cpBreak);
  801. return FinishBreakRegular ( ichnk,
  802. pdobj,
  803. cpBreak,
  804. & objdimSubline,
  805. pbrkout);
  806. };
  807. }
  808. } /* End of ReverseFindNextBreakCore */
  809. /* R E V E R S E F I N D N E X T B R E A K C H U N K */
  810. /*----------------------------------------------------------------------------
  811. %%Function: ReverseFindNextBreakChunk
  812. %%Contact: antons
  813. ----------------------------------------------------------------------------*/
  814. LSERR WINAPI ReverseFindNextBreakChunk (
  815. PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
  816. PCPOSICHNK pcpoischnk, /* (IN): place to start looking for break */
  817. BRKCOND brkcond, /* (IN): recommmendation about the break after chunk */
  818. PBRKOUT pbrkout) /* (OUT): results of breaking */
  819. {
  820. LSERR lserr;
  821. if (pcpoischnk->ichnk == ichnkOutside)
  822. {
  823. lserr = ReverseFindNextBreakCore ( pclocchnk,
  824. 0,
  825. fTrue,
  826. 0,
  827. brkcond,
  828. pbrkout );
  829. }
  830. else
  831. {
  832. lserr = ReverseFindNextBreakCore ( pclocchnk,
  833. pcpoischnk->ichnk,
  834. fFalse,
  835. pcpoischnk->dcp,
  836. brkcondPlease,
  837. pbrkout );
  838. };
  839. return lserr;
  840. }
  841. /* R E V E R S E F O R C E B R E A K C H U N K */
  842. /*----------------------------------------------------------------------------
  843. %%Function: ReverseForceBreak
  844. %%Contact: antons
  845. ----------------------------------------------------------------------------*/
  846. LSERR WINAPI ReverseForceBreakChunk (
  847. PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
  848. PCPOSICHNK pcposichnkIn, /* (IN): place to start looking for break */
  849. PBRKOUT pbrkout) /* (OUT): results of breaking */
  850. {
  851. POSICHNK posichnk = * pcposichnkIn;
  852. LSERR lserr;
  853. LSCP cpTruncateSubline;
  854. LSCP cpBreak;
  855. OBJDIM objdimSubline;
  856. PDOBJ pdobj;
  857. BRKPOS brkpos;
  858. if (posichnk.ichnk == ichnkOutside)
  859. {
  860. /* When left indent is bigger then Right Margin */
  861. posichnk.ichnk = 0;
  862. posichnk.dcp = 1;
  863. };
  864. Assert (posichnk.ichnk != ichnkOutside);
  865. pdobj = pclocchnk->plschnk[posichnk.ichnk].pdobj;
  866. if (pclocchnk->lsfgi.fFirstOnLine && (posichnk.ichnk == 0))
  867. {
  868. /* Object is the first on line (can not break before) */
  869. LSDCP dcp = posichnk.dcp;
  870. BOOL fEmpty;
  871. Assert (dcp >= 1 && dcp <= pdobj->dcp);
  872. lserr = LssbFIsSublineEmpty (pdobj->plssubl, &fEmpty);
  873. if (lserr != lserrNone) return lserr;
  874. if (fEmpty)
  875. {
  876. /* Can not ForceBreak empty subline */
  877. Assert (posichnk.ichnk == 0);
  878. PutBreakAtEndOfObject(0, pclocchnk, pbrkout);
  879. ReverseSaveBreakRecord ( pclocchnk->plschnk[0].pdobj,
  880. brkkindForce,
  881. breakSublineAfter,
  882. pclocchnk->plschnk[0].pdobj->cpStart +
  883. pclocchnk->plschnk[0].pdobj->dcp );
  884. return lserrNone;
  885. };
  886. /* Subline is not empty => do force break */
  887. /* REVIEW (antons): The same as in Prev & Next Break */
  888. cpTruncateSubline = TranslateDcpExternalToCpLimSubline (pdobj, dcp - 1);
  889. lserr = LsForceBreakSubline (
  890. pdobj->plssubl,
  891. pclocchnk->lsfgi.fFirstOnLine,
  892. cpTruncateSubline,
  893. pclocchnk->lsfgi.urColumnMax,
  894. &cpBreak,
  895. &objdimSubline,
  896. &brkpos );
  897. if (lserr != lserrNone) return lserr;
  898. /* REVIEW (antons): Check with IgorZv that Assert is correct ;-) */
  899. Assert (brkpos != brkposBeforeFirstDnode);
  900. if (brkpos == brkposAfterLastDnode)
  901. {
  902. /* We reset dcp so that closing brace stays on the same line */
  903. ReverseSaveBreakRecord (pdobj, brkkindForce, breakSublineInside, pdobj->cpStart + pdobj->dcp);
  904. return FinishBreakRegular ( posichnk.ichnk,
  905. pdobj,
  906. pdobj->cpStart + pdobj->dcp,
  907. &objdimSubline,
  908. pbrkout );
  909. }
  910. else
  911. {
  912. /* "Regular" ;-) ForceBreak inside subline */
  913. ReverseSaveBreakRecord (pdobj, brkkindForce, breakSublineInside, cpBreak);
  914. return FinishBreakRegular ( posichnk.ichnk,
  915. pdobj,
  916. cpBreak,
  917. &objdimSubline,
  918. pbrkout );
  919. }
  920. }
  921. else
  922. {
  923. /* Can break before ichnk */
  924. PutBreakBeforeObject (posichnk.ichnk, pclocchnk, pbrkout);
  925. /* Do not need to save break record when break "before", because it will be
  926. translated by manager to SetBreak (previous_dnode, ImposeAfter) */
  927. /* REVIEW (antons): It is strange that I have difference between break "before"
  928. not-first ichnk element and break "after" not-last. And only
  929. in the second case I remember break record */
  930. return lserrNone;
  931. };
  932. } /* ReverseForceBreakChunk */
  933. /* R E V E R S E S E T B R E A K */
  934. /*----------------------------------------------------------------------------
  935. %%Function: ReverseSetBreak
  936. %%Contact: antons
  937. ----------------------------------------------------------------------------*/
  938. LSERR WINAPI ReverseSetBreak(
  939. PDOBJ pdobj, /* (IN): dobj which is broken */
  940. BRKKIND brkkind, /* (IN): Prev / Next / Force / Impose After */
  941. DWORD cBreakRecord, /* (IN): size of array */
  942. BREAKREC *rgBreakRecord, /* (IN): array of break records */
  943. DWORD *pcActualBreakRecord) /* (IN): actual number of used elements in array */
  944. {
  945. LSERR lserr = lserrNone;
  946. if (cBreakRecord < 1) return lserrInsufficientBreakRecBuffer;
  947. if (pdobj->fSuppressTrailingSpaces && pdobj->fFirstOnLine)
  948. {
  949. /* Robj is alone on the line => submit for trailing spaces */
  950. if (brkkind != brkkindImposedAfter)
  951. {
  952. BREAKSUBLINETYPE breakSublineType;
  953. LSCP cpBreak;
  954. ReverseGetBreakRecord (pdobj, brkkind, &breakSublineType, &cpBreak);
  955. if (cpBreak < (LSCP) (pdobj->cpStart + pdobj->dcp))
  956. {
  957. lserr = LsdnSubmitSublines(pdobj->pilsobj->plsc, pdobj->plsdnTop, 1,
  958. &pdobj->plssubl, TRUE, TRUE, TRUE, TRUE, TRUE);
  959. if (lserr != lserrNone) return lserr;
  960. };
  961. };
  962. };
  963. if (brkkind == brkkindImposedAfter)
  964. {
  965. /* Break is imposed ater DNODE */
  966. lserr = LsSetBreakSubline ( pdobj->plssubl,
  967. brkkindImposedAfter,
  968. cBreakRecord-1,
  969. & rgBreakRecord [1],
  970. pcActualBreakRecord );
  971. if (lserr != lserrNone) return lserr;
  972. Assert (*pcActualBreakRecord == 0);
  973. return lserrNone;
  974. }
  975. else
  976. {
  977. BREAKSUBLINETYPE breakSublineType;
  978. LSCP cpBreak;
  979. /* Result of previous Prev / Next or Force - used stored break record */
  980. ReverseGetBreakRecord (pdobj, brkkind, &breakSublineType, &cpBreak);
  981. Assert (breakSublineType == breakSublineAfter || breakSublineType == breakSublineInside);
  982. if (breakSublineType == breakSublineAfter)
  983. {
  984. /* type = breakSublineAfter */
  985. lserr = LsSetBreakSubline ( pdobj->plssubl,
  986. brkkindImposedAfter,
  987. cBreakRecord-1,
  988. & rgBreakRecord [1],
  989. pcActualBreakRecord );
  990. if (lserr != lserrNone) return lserr;
  991. Assert (*pcActualBreakRecord == 0);
  992. return lserrNone;
  993. }
  994. else
  995. {
  996. /* type = breakSublineInside */
  997. lserr = LsSetBreakSubline ( pdobj->plssubl,
  998. brkkind,
  999. cBreakRecord-1,
  1000. & rgBreakRecord [1],
  1001. pcActualBreakRecord );
  1002. if (lserr != lserrNone) return lserr;
  1003. /* Still possible to have break after object */
  1004. if (cpBreak == (LSCP) (pdobj->cpStart + pdobj->dcp))
  1005. {
  1006. Assert (*pcActualBreakRecord == 0);
  1007. return lserrNone;
  1008. }
  1009. else
  1010. {
  1011. (*pcActualBreakRecord) += 1;
  1012. rgBreakRecord[0].idobj = pdobj->pilsobj->idobj;
  1013. rgBreakRecord[0].cpFirst = pdobj->cpStartObj;
  1014. return lserrNone;
  1015. }
  1016. };
  1017. };
  1018. }
  1019. /* R E V E R S E G E T S P E C I A L E F F E C T S I N S I D E */
  1020. /*----------------------------------------------------------------------------
  1021. %%Function: ReverseGetSpecialEffectsInside
  1022. %%Contact: ricksa
  1023. GetSpecialEffectsInside
  1024. .
  1025. ----------------------------------------------------------------------------*/
  1026. LSERR WINAPI ReverseGetSpecialEffectsInside(
  1027. PDOBJ pdobj, /* (IN): dobj */
  1028. UINT *pEffectsFlags) /* (OUT): Special effects for this object */
  1029. {
  1030. return LsGetSpecialEffectsSubline(pdobj->plssubl, pEffectsFlags);
  1031. }
  1032. /* R E V E R S E C A L C P R E S E N T A T I O N */
  1033. /*----------------------------------------------------------------------------
  1034. %%Function: ReverseCalcPresentation
  1035. %%Contact: ricksa
  1036. CalcPresentation
  1037. ----------------------------------------------------------------------------*/
  1038. LSERR WINAPI ReverseCalcPresentation(
  1039. PDOBJ pdobj, /* (IN): dobj */
  1040. long dup, /* (IN): dup of dobj */
  1041. LSKJUST lskjust, /* (IN): Justification type */
  1042. BOOL fLastVisibleOnLine ) /* (IN): Is this object last visible on line? */
  1043. {
  1044. LSERR lserr;
  1045. BOOL fDone;
  1046. Unreferenced (lskjust);
  1047. Unreferenced (fLastVisibleOnLine);
  1048. pdobj->dup = dup;
  1049. /* Make sure that justification line has been made ready for presentation */
  1050. lserr = LssbFDonePresSubline(pdobj->plssubl, &fDone);
  1051. if ((lserrNone == lserr) && !fDone)
  1052. {
  1053. lserr = LsMatchPresSubline(pdobj->plssubl);
  1054. }
  1055. return lserr;
  1056. }
  1057. /* R E V E R S E Q U E R Y P O I N T P C P */
  1058. /*----------------------------------------------------------------------------
  1059. %%Function: ReverseQueryPointPcp
  1060. %%Contact: ricksa
  1061. Map dup to dcp
  1062. ----------------------------------------------------------------------------*/
  1063. LSERR WINAPI ReverseQueryPointPcp(
  1064. PDOBJ pdobj, /*(IN): dobj to query */
  1065. PCPOINTUV ppointuvQuery, /*(IN): query point (uQuery,vQuery) */
  1066. PCLSQIN plsqin, /*(IN): query input */
  1067. PLSQOUT plsqout) /*(OUT): query output */
  1068. {
  1069. Unreferenced(ppointuvQuery);
  1070. return CreateQueryResult(pdobj->plssubl, pdobj->dup - 1, 0, plsqin, plsqout);
  1071. }
  1072. /* R E V E R S E Q U E R Y C P P P O I N T */
  1073. /*----------------------------------------------------------------------------
  1074. %%Function: ReverseQueryCpPpoint
  1075. %%Contact: ricksa
  1076. Map dcp to dup
  1077. ----------------------------------------------------------------------------*/
  1078. LSERR WINAPI ReverseQueryCpPpoint(
  1079. PDOBJ pdobj, /*(IN): dobj to query, */
  1080. LSDCP dcp, /*(IN): dcp for the query */
  1081. PCLSQIN plsqin, /*(IN): query input */
  1082. PLSQOUT plsqout) /*(OUT): query output */
  1083. {
  1084. Unreferenced(dcp);
  1085. return CreateQueryResult(pdobj->plssubl, pdobj->dup - 1, 0, plsqin, plsqout);
  1086. }
  1087. /* R E V E R S E D I S P L A Y */
  1088. /*----------------------------------------------------------------------------
  1089. %%Function: ReverseDisplay
  1090. %%Contact: ricksa
  1091. Display
  1092. This calculates the positions of the various lines for the
  1093. display and then displays them.
  1094. ----------------------------------------------------------------------------*/
  1095. LSERR WINAPI ReverseDisplay(
  1096. PDOBJ pdobj,
  1097. PCDISPIN pcdispin)
  1098. {
  1099. POINTUV pointuv;
  1100. POINT pt;
  1101. BOOL fDisplayed;
  1102. LSERR lserr = LssbFDoneDisplay(pdobj->plssubl, &fDisplayed);
  1103. if (lserr != lserrNone)
  1104. {
  1105. return lserr;
  1106. }
  1107. if (fDisplayed)
  1108. {
  1109. return lserrNone;
  1110. }
  1111. /* Calculate point to start displaying the subline. */
  1112. pointuv.u = pdobj->dup - 1;
  1113. pointuv.v = 0;
  1114. LsPointXYFromPointUV(&pcdispin->ptPen, pdobj->lstflowL, &pointuv, &pt);
  1115. /* display the Reverse line */
  1116. return LsDisplaySubline(pdobj->plssubl, &pt, pcdispin->kDispMode, pcdispin->prcClip);
  1117. }
  1118. /* R E V E R S E D E S T R O Y D O B J */
  1119. /*----------------------------------------------------------------------------
  1120. %%Function: ReverseDestroyDobj
  1121. %%Contact: ricksa
  1122. DestroyDobj
  1123. Free all resources connected with the input dobj.
  1124. ----------------------------------------------------------------------------*/
  1125. LSERR WINAPI ReverseDestroyDobj(
  1126. PDOBJ pdobj)
  1127. {
  1128. return ReverseFreeDobj(pdobj);
  1129. }
  1130. /* R E V E R S E E N U M */
  1131. /*----------------------------------------------------------------------------
  1132. %%Function: ReverseEnum
  1133. %%Contact: ricksa
  1134. Enum
  1135. Enumeration callback - passed to client.
  1136. ----------------------------------------------------------------------------*/
  1137. LSERR WINAPI ReverseEnum(
  1138. PDOBJ pdobj, /*(IN): dobj to enumerate */
  1139. PLSRUN plsrun, /*(IN): from DNODE */
  1140. PCLSCHP plschp, /*(IN): from DNODE */
  1141. LSCP cp, /*(IN): from DNODE */
  1142. LSDCP dcp, /*(IN): from DNODE */
  1143. LSTFLOW lstflow, /*(IN): text flow*/
  1144. BOOL fReverse, /*(IN): enumerate in reverse order */
  1145. BOOL fGeometryNeeded, /*(IN): */
  1146. const POINT *pt, /*(IN): starting position (top left), iff fGeometryNeeded */
  1147. PCHEIGHTS pcheights, /*(IN): from DNODE, relevant iff fGeometryNeeded */
  1148. long dupRun) /*(IN): from DNODE, relevant iff fGeometryNeeded */
  1149. {
  1150. return pdobj->pilsobj->pfnReverseEnum(pdobj->pilsobj->pols, plsrun, plschp,
  1151. cp, dcp, lstflow, fReverse, fGeometryNeeded, pt, pcheights, dupRun,
  1152. pdobj->lstflowO, pdobj->plssubl);
  1153. }
  1154. /* L S G E T R E V E R S E L S I M E T H O D S */
  1155. /*----------------------------------------------------------------------------
  1156. %%Function: LsGetReverseLsimethods
  1157. %%Contact: ricksa
  1158. Initialize object handler for client.
  1159. ----------------------------------------------------------------------------*/
  1160. LSERR WINAPI LsGetReverseLsimethods(
  1161. LSIMETHODS *plsim)
  1162. {
  1163. plsim->pfnCreateILSObj = ReverseCreateILSObj;
  1164. plsim->pfnDestroyILSObj = ReverseDestroyILSObj;
  1165. plsim->pfnSetDoc = ReverseSetDoc;
  1166. plsim->pfnCreateLNObj = ReverseCreateLNObj;
  1167. plsim->pfnDestroyLNObj = ReverseDestroyLNObj;
  1168. plsim->pfnFmt = ReverseFmt;
  1169. plsim->pfnFmtResume = ReverseFmtResume;
  1170. plsim->pfnGetModWidthPrecedingChar = ObjHelpGetModWidthChar;
  1171. plsim->pfnGetModWidthFollowingChar = ObjHelpGetModWidthChar;
  1172. plsim->pfnTruncateChunk = ReverseTruncateChunk;
  1173. plsim->pfnFindPrevBreakChunk = ReverseFindPrevBreakChunk;
  1174. plsim->pfnFindNextBreakChunk = ReverseFindNextBreakChunk;
  1175. plsim->pfnForceBreakChunk = ReverseForceBreakChunk;
  1176. plsim->pfnSetBreak = ReverseSetBreak;
  1177. plsim->pfnGetSpecialEffectsInside = ReverseGetSpecialEffectsInside;
  1178. plsim->pfnFExpandWithPrecedingChar = ObjHelpFExpandWithPrecedingChar;
  1179. plsim->pfnFExpandWithFollowingChar = ObjHelpFExpandWithFollowingChar;
  1180. plsim->pfnCalcPresentation = ReverseCalcPresentation;
  1181. plsim->pfnQueryPointPcp = ReverseQueryPointPcp;
  1182. plsim->pfnQueryCpPpoint = ReverseQueryCpPpoint;
  1183. plsim->pfnDisplay = ReverseDisplay;
  1184. plsim->pfnDestroyDObj = ReverseDestroyDobj;
  1185. plsim->pfnEnum = ReverseEnum;
  1186. return lserrNone;
  1187. }