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.

476 lines
14 KiB

  1. #include "lsidefs.h"
  2. #include "pilsobj.h"
  3. #include "plsline.h"
  4. #include "lstext.h"
  5. #include "lscbk.h"
  6. #include "lsc.h"
  7. #include "lscontxt.h"
  8. #include "limqmem.h"
  9. #include "qheap.h"
  10. #include "lsline.h"
  11. #include "lsdnode.h"
  12. #include "iobj.h"
  13. #include "chnutils.h"
  14. #include "autonum.h"
  15. #include "lsmem.h" /* memset() */
  16. static LSERR CannotCreateLsContext(PLSC, LSERR);
  17. static LSERR InitObject(PLSC plsc, DWORD iobj, const LSIMETHODS* plsim);
  18. static LSERR RemoveContextObjects(PLSC plsc);
  19. #ifdef DEBUG
  20. #ifdef LSTEST_ASSERTSTOP
  21. /* We use it to run debug LS with ship build of WORD */
  22. int nZero = 0;
  23. void AssertFailedStop (char* pzstrMsg, char* pzstrFile, int nLine)
  24. {
  25. Unreferenced (pzstrMsg);
  26. Unreferenced (pzstrFile);
  27. Unreferenced (nLine);
  28. nZero = nZero / nZero;
  29. return;
  30. }
  31. #endif
  32. #endif
  33. /* L S C R E A T E C O N T E X T */
  34. /*----------------------------------------------------------------------------
  35. %%Function: LsCreateContext
  36. %%Contact: igorzv
  37. Parameters:
  38. plsci - (IN) structure which contains clients setings
  39. pplsc - (OUT) pointer to created contexts (opaque to clients)
  40. Creates a Line Services context.
  41. Typically called once, at the beginning of time.
  42. ----------------------------------------------------------------------------*/
  43. LSERR WINAPI LsCreateContext(const LSCONTEXTINFO* plsci, PLSC* pplsc)
  44. {
  45. static LSIMETHODS const lsimText =
  46. {
  47. CreateILSObjText,
  48. DestroyILSObjText,
  49. SetDocText,
  50. CreateLNObjText,
  51. DestroyLNObjText,
  52. FmtText,
  53. NULL,
  54. NULL,
  55. NULL,
  56. TruncateText,
  57. FindPrevBreakText,
  58. FindNextBreakText,
  59. ForceBreakText,
  60. SetBreakText,
  61. NULL,
  62. NULL,
  63. NULL,
  64. CalcPresentationText,
  65. QueryPointPcpText,
  66. QueryCpPpointText,
  67. EnumObjText,
  68. DisplayText,
  69. DestroyDObjText,
  70. };
  71. static LSIMETHODS const lsimAutonum =
  72. {
  73. AutonumCreateILSObj,
  74. AutonumDestroyILSObj,
  75. AutonumSetDoc,
  76. AutonumCreateLNObj,
  77. AutonumDestroyLNObj,
  78. AutonumFmt,
  79. NULL,
  80. NULL,
  81. NULL,
  82. AutonumTruncateChunk,
  83. AutonumFindPrevBreakChunk,
  84. AutonumFindNextBreakChunk,
  85. AutonumForceBreakChunk,
  86. AutonumSetBreak,
  87. AutonumGetSpecialEffectsInside,
  88. NULL,
  89. NULL,
  90. AutonumCalcPresentation,
  91. AutonumQueryPointPcp,
  92. AutonumQueryCpPpoint,
  93. AutonumEnumerate,
  94. AutonumDisplay,
  95. AutonumDestroyDobj,
  96. };
  97. DWORD const iobjText = plsci->cInstalledHandlers;
  98. DWORD const iobjAutonum = plsci->cInstalledHandlers + 1;
  99. DWORD const iobjMac = iobjText + 2;
  100. POLS const pols = plsci->pols;
  101. const LSIMETHODS* const plsim = plsci->pInstalledHandlers;
  102. DWORD iobj;
  103. PLSC plsc;
  104. LSERR lserr;
  105. #ifdef DEBUG
  106. #ifdef LSTEST_ASSERTSTOP
  107. /* We use this option when run debug LS with ship WORD */
  108. pfnAssertFailed = AssertFailedStop;
  109. #else
  110. pfnAssertFailed = plsci->lscbk.pfnAssertFailed;
  111. #endif
  112. #endif
  113. if (pplsc == NULL)
  114. return lserrNullOutputParameter;
  115. *pplsc = NULL;
  116. /* Allocate memory for the context and clean it
  117. */
  118. plsc = plsci->lscbk.pfnNewPtr(pols, cbRep(struct lscontext, lsiobjcontext.rgobj, iobjMac));
  119. if (plsc == NULL)
  120. return lserrOutOfMemory;
  121. memset(plsc, 0, cbRep(struct lscontext, lsiobjcontext.rgobj, iobjMac));
  122. /* Initialize the fixed-size part of the context
  123. */
  124. plsc->tag = tagLSC;
  125. plsc->pols = pols;
  126. plsc->lscbk = plsci->lscbk;
  127. plsc->fDontReleaseRuns = plsci->fDontReleaseRuns;
  128. plsc->cLinesActive = 0;
  129. plsc->plslineCur = NULL;
  130. plsc->lsstate = LsStateCreatingContext;
  131. plsc->pqhLines = CreateQuickHeap(plsc, limLines,
  132. cbRep(struct lsline, rgplnobj, iobjMac), fFalse);
  133. plsc->pqhAllDNodesRecycled = CreateQuickHeap(plsc, limAllDNodes,
  134. sizeof (struct lsdnode), fTrue);
  135. if (plsc->pqhLines == NULL || plsc->pqhAllDNodesRecycled == NULL )
  136. {
  137. return CannotCreateLsContext(plsc, lserrOutOfMemory);
  138. }
  139. /* create arrays for chunks */
  140. lserr = AllocChunkArrays(&plsc->lschunkcontextStorage, &plsc->lscbk, plsc->pols,
  141. &plsc->lsiobjcontext);
  142. if (lserr != lserrNone)
  143. return CannotCreateLsContext(plsc, lserr);
  144. /* create array for tabs */
  145. plsc->lstabscontext.pcaltbd = plsci->lscbk.pfnNewPtr(pols,
  146. sizeof(LSCALTBD)*limCaltbd);
  147. plsc->lstabscontext.ccaltbdMax = limCaltbd;
  148. if (plsc->lstabscontext.pcaltbd == NULL )
  149. {
  150. return CannotCreateLsContext(plsc, lserrOutOfMemory);
  151. }
  152. /* set links in lstabscontext */
  153. plsc->lstabscontext.plscbk = &plsc->lscbk;
  154. plsc->lstabscontext.pols = plsc->pols;
  155. plsc->lstabscontext.plsdocinf = &plsc->lsdocinf;
  156. /* ****************************************************************** */
  157. /* Initialize the "static" array part of the context
  158. * "Text" is the last element of the array
  159. */
  160. plsc->lsiobjcontext.iobjMac = iobjMac;
  161. for (iobj = 0; iobj < iobjText; iobj++)
  162. {
  163. lserr = InitObject(plsc, iobj, &plsim[iobj]);
  164. if (lserr != lserrNone)
  165. return CannotCreateLsContext(plsc, lserr);
  166. }
  167. lserr = InitObject(plsc, iobjText, &lsimText);
  168. if (lserr != lserrNone)
  169. return CannotCreateLsContext(plsc, lserr);
  170. /* Set text Config */
  171. lserr = SetTextConfig(PilsobjFromLsc(&plsc->lsiobjcontext, iobjText), &(plsci->lstxtcfg));
  172. if (lserr != lserrNone)
  173. return CannotCreateLsContext(plsc, lserr);
  174. lserr = InitObject(plsc, iobjAutonum, &lsimAutonum);
  175. if (lserr != lserrNone)
  176. return CannotCreateLsContext(plsc, lserr);
  177. /* Set text Config */
  178. lserr = SetAutonumConfig(PilsobjFromLsc(&plsc->lsiobjcontext, iobjAutonum),
  179. &(plsci->lstxtcfg));
  180. if (lserr != lserrNone)
  181. return CannotCreateLsContext(plsc, lserr);
  182. plsc->lsstate = LsStateNotReady; /* nobody can use context before LsSetDoc */
  183. /* we set other variavles by memset, bellow we check that we get what we want */
  184. Assert(plsc->cLinesActive == 0);
  185. Assert(plsc->plslineCur == NULL);
  186. Assert(plsc->fIgnoreSplatBreak == 0);
  187. Assert(plsc->fLimSplat == fFalse);
  188. Assert(plsc->fHyphenated == fFalse);
  189. Assert(plsc->fAdvanceBack == fFalse);
  190. Assert(plsc->grpfManager == 0);
  191. Assert(plsc->urRightMarginBreak == 0);
  192. Assert(plsc->lMarginIncreaseCoefficient == 0);
  193. Assert(plsc->lsdocinf.fDisplay == fFalse);
  194. Assert(plsc->lsdocinf.fPresEqualRef == fFalse);
  195. Assert(plsc->lsdocinf.lsdevres.dxpInch == 0);
  196. Assert(plsc->lsdocinf.lsdevres.dxrInch == 0);
  197. Assert(plsc->lsdocinf.lsdevres.dypInch == 0);
  198. Assert(plsc->lsdocinf.lsdevres.dyrInch == 0);
  199. Assert(plsc->lstabscontext.fTabsInitialized == fFalse);
  200. Assert(plsc->lstabscontext.durIncrementalTab == 0);
  201. Assert(plsc->lstabscontext.urBeforePendingTab == 0);
  202. Assert(plsc->lstabscontext.plsdnPendingTab == NULL);
  203. Assert(plsc->lstabscontext.icaltbdMac == 0);
  204. Assert(plsc->lstabscontext.urColumnMax == 0);
  205. Assert(plsc->lstabscontext.fResolveTabsAsWord97 == fFalse);
  206. Assert(plsc->lsadjustcontext.fLineCompressed == fFalse);
  207. Assert(plsc->lsadjustcontext.fLineContainsAutoNumber == fFalse);
  208. Assert(plsc->lsadjustcontext.fUnderlineTrailSpacesRM == fFalse);
  209. Assert(plsc->lsadjustcontext.fForgetLastTabAlignment == fFalse);
  210. Assert(plsc->lsadjustcontext.fNominalToIdealEncounted == fFalse);
  211. Assert(plsc->lsadjustcontext.fForeignObjectEncounted == fFalse);
  212. Assert(plsc->lsadjustcontext.fTabEncounted == fFalse);
  213. Assert(plsc->lsadjustcontext.fNonLeftTabEncounted == fFalse);
  214. Assert(plsc->lsadjustcontext.fSubmittedSublineEncounted == fFalse);
  215. Assert(plsc->lsadjustcontext.fAutodecimalTabPresent == fFalse);
  216. Assert(plsc->lsadjustcontext.lskj == lskjNone);
  217. Assert(plsc->lsadjustcontext.lskalign == lskalLeft);
  218. Assert(plsc->lsadjustcontext.lsbrj == lsbrjBreakJustify);
  219. Assert(plsc->lsadjustcontext.urLeftIndent == 0);
  220. Assert(plsc->lsadjustcontext.urStartAutonumberingText == 0);
  221. Assert(plsc->lsadjustcontext.urStartMainText == 0);
  222. Assert(plsc->lsadjustcontext.urRightMarginJustify == 0);
  223. Assert(plsc->lschunkcontextStorage.FChunkValid == fFalse);
  224. Assert(plsc->lschunkcontextStorage.FLocationValid == fFalse);
  225. Assert(plsc->lschunkcontextStorage.FGroupChunk == fFalse);
  226. Assert(plsc->lschunkcontextStorage.FBorderInside == fFalse);
  227. Assert(plsc->lschunkcontextStorage.grpfTnti == 0);
  228. Assert(plsc->lschunkcontextStorage.fNTIAppliedToLastChunk == fFalse);
  229. Assert(plsc->lschunkcontextStorage.locchnkCurrent.clschnk == 0);
  230. Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.fFirstOnLine == fFalse);
  231. Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.cpFirst == fFalse);
  232. Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.urPen == 0);
  233. Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.vrPen == 0);
  234. Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.urColumnMax == 0);
  235. Assert(plsc->lschunkcontextStorage.locchnkCurrent.lsfgi.lstflow == 0);
  236. Assert(plsc->lslistcontext.plsdnToFinish == NULL);
  237. Assert(plsc->lslistcontext.plssublCurrent == NULL);
  238. Assert(plsc->lslistcontext.nDepthFormatLineCurrent == 0);
  239. /* Everything worked, so set the output parameter and return success
  240. */
  241. *pplsc = plsc;
  242. return lserrNone;
  243. }
  244. /* C A N N O T C R E A T E L S C O N T E X T */
  245. /*----------------------------------------------------------------------------
  246. %%Function: CannotCreateLsContext
  247. %%Contact: igorzv
  248. Parameters:
  249. plsc - partually created context
  250. lseReturn - error code
  251. Utility function called when an error occurs when an LSC is
  252. partially created.
  253. ----------------------------------------------------------------------------*/
  254. static LSERR CannotCreateLsContext(PLSC plsc, LSERR lseReturn)
  255. {
  256. plsc->lsstate = LsStateFree; /* otherwise destroy will not work */
  257. (void) LsDestroyContext(plsc);
  258. return lseReturn;
  259. }
  260. /* L S D E S T R O Y C O N T E X T */
  261. /*----------------------------------------------------------------------------
  262. %%Function: LsDestroyContext
  263. %%Contact: igorzv
  264. Parameters:
  265. plsc - (IN) ptr to line services context
  266. Frees all resources associated with a Line Services context,
  267. which was created by CreateLsContext.
  268. ----------------------------------------------------------------------------*/
  269. LSERR WINAPI LsDestroyContext(PLSC plsc)
  270. {
  271. LSERR lserr = lserrNone;
  272. if (plsc != NULL)
  273. {
  274. if (!FIsLSC(plsc))
  275. return lserrInvalidContext;
  276. if (plsc->cLinesActive != 0 || FIsLSCBusy(plsc))
  277. return lserrContextInUse;
  278. plsc->lsstate = LsStateDestroyingContext;
  279. DestroyQuickHeap(plsc->pqhLines);
  280. Assert(plsc->pqhAllDNodesRecycled != NULL);
  281. DestroyQuickHeap(plsc->pqhAllDNodesRecycled);
  282. DisposeChunkArrays(&plsc->lschunkcontextStorage);
  283. plsc->lscbk.pfnDisposePtr(plsc->pols, plsc->lstabscontext.pcaltbd);
  284. lserr = RemoveContextObjects(plsc);
  285. plsc->tag = tagInvalid;
  286. plsc->lscbk.pfnDisposePtr(plsc->pols, plsc);
  287. }
  288. return lserr;
  289. }
  290. static LSERR InitObject(PLSC plsc, DWORD iobj, const LSIMETHODS* plsim)
  291. {
  292. struct OBJ *pobj;
  293. LSERR lserr;
  294. Assert(FIsLSC(plsc));
  295. Assert(plsc->lsstate == LsStateCreatingContext);
  296. Assert(iobj < plsc->lsiobjcontext.iobjMac);
  297. pobj = &(plsc->lsiobjcontext.rgobj[iobj]);
  298. pobj->lsim = *plsim;
  299. Assert(pobj->pilsobj == NULL);
  300. lserr = pobj->lsim.pfnCreateILSObj(plsc->pols, plsc, &(plsc->lscbk), iobj, &(pobj->pilsobj));
  301. if (lserr != lserrNone)
  302. {
  303. if (pobj->pilsobj != NULL)
  304. {
  305. pobj->lsim.pfnDestroyILSObj(pobj->pilsobj);
  306. pobj->pilsobj = NULL;
  307. }
  308. return lserr;
  309. }
  310. return lserrNone;
  311. }
  312. /* R E M O V E C O N T E X T O B J E C T S */
  313. /*----------------------------------------------------------------------------
  314. %%Function: RemoveContextObjects
  315. %%Contact: igorzv
  316. Parameter:
  317. plsc - (IN) ptr to line services context
  318. Removes a set of installed objects from an LSC.
  319. Destroy all ilsobj
  320. ----------------------------------------------------------------------------*/
  321. LSERR RemoveContextObjects(PLSC plsc)
  322. {
  323. DWORD iobjMac;
  324. LSERR lserr, lserrFinal = lserrNone;
  325. DWORD iobj;
  326. PILSOBJ pilsobj;
  327. Assert(FIsLSC(plsc));
  328. Assert(plsc->lsstate == LsStateDestroyingContext);
  329. iobjMac = plsc->lsiobjcontext.iobjMac;
  330. for (iobj = 0; iobj < iobjMac; iobj++)
  331. {
  332. pilsobj = plsc->lsiobjcontext.rgobj[iobj].pilsobj;
  333. if (pilsobj != NULL)
  334. {
  335. lserr = plsc->lsiobjcontext.rgobj[iobj].lsim.pfnDestroyILSObj(pilsobj);
  336. plsc->lsiobjcontext.rgobj[iobj].pilsobj = NULL;
  337. if (lserr != lserrNone)
  338. lserrFinal = lserr;
  339. }
  340. }
  341. return lserrFinal;
  342. }
  343. #ifdef DEBUG
  344. /* F I S L S C O N T E X T V A L I D*/
  345. /*----------------------------------------------------------------------------
  346. %%Function: FIsLsContextValid
  347. %%Contact: igorzv
  348. Parameters:
  349. plsc - (IN) ptr to line services context
  350. this function verify that nobody spoiled context, all reasonable integrity checks
  351. should be here
  352. ----------------------------------------------------------------------------*/
  353. BOOL FIsLsContextValid(PLSC plsc)
  354. {
  355. DWORD iobjText = IobjTextFromLsc(&plsc->lsiobjcontext);
  356. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnCreateILSObj ==CreateILSObjText);
  357. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnDestroyILSObj == DestroyILSObjText);
  358. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnSetDoc == SetDocText);
  359. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnCreateLNObj == CreateLNObjText);
  360. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnDestroyLNObj == DestroyLNObjText);
  361. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnTruncateChunk == TruncateText);
  362. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnFindPrevBreakChunk == FindPrevBreakText);
  363. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnFindNextBreakChunk == FindNextBreakText);
  364. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnForceBreakChunk == ForceBreakText);
  365. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnDisplay == DisplayText);
  366. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnQueryPointPcp == QueryPointPcpText);
  367. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnQueryCpPpoint == QueryCpPpointText);
  368. Assert(plsc->lsiobjcontext.rgobj[iobjText].lsim.pfnDestroyDObj == DestroyDObjText);
  369. Assert(plsc->lschunkcontextStorage.pcont != NULL);
  370. Assert(plsc->lschunkcontextStorage.pplsdnChunk != NULL);
  371. Assert(plsc->lschunkcontextStorage.locchnkCurrent.plschnk != NULL);
  372. Assert(plsc->lschunkcontextStorage.pplsdnNonText != NULL);
  373. Assert(plsc->lschunkcontextStorage.pfNonTextExpandAfter != NULL);
  374. Assert(plsc->lschunkcontextStorage.pdurOpenBorderBefore != NULL);
  375. Assert(plsc->lschunkcontextStorage.pdurCloseBorderAfter != NULL);
  376. return fTrue; /* if we here than everything OK */
  377. }
  378. #endif