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.

4519 lines
127 KiB

  1. /* ---------------------------------------------------------------
  2. : LineServices 3.0
  3. :
  4. : WARICHU ("Two lines in one" in Winword)
  5. :
  6. : Object Handler Routines
  7. :
  8. : Contact: AntonS
  9. :
  10. ------------------------------------------------------------------ */
  11. #include "lsmem.h"
  12. #include "limits.h"
  13. #include "warichu.h"
  14. #include "objhelp.h"
  15. #include "lsesc.h"
  16. #include "lscbk.h"
  17. #include "lsdevres.h"
  18. #include "pdobj.h"
  19. #include "objdim.h"
  20. #include "plssubl.h"
  21. #include "plsdnode.h"
  22. #include "pilsobj.h"
  23. #include "lscrsubl.h"
  24. #include "lssubset.h"
  25. #include "lsdnset.h"
  26. #include "zqfromza.h"
  27. #include "lstfset.h"
  28. #include "lsdocinf.h"
  29. #include "fmti.h"
  30. #include "posichnk.h"
  31. #include "locchnk.h"
  32. #include "lsdnfin.h"
  33. #include "brko.h"
  34. #include "lspap.h"
  35. #include "plspap.h"
  36. #include "lsqsubl.h"
  37. #include "dispi.h"
  38. #include "lsdssubl.h"
  39. #include "dispmisc.h"
  40. #include "lstfset.h"
  41. #include "brkkind.h"
  42. #include "lschp.h"
  43. /* REVIEW (antons):
  44. - Assert that FormatUntilCpBreak fSuccessful
  45. - Assimetry between Prev and Next BreakWarichuDobj: it looks like
  46. right margin as input to Next break may also optimize truncation.
  47. - In ForceBreak it may happen that dur < 0: What is the correct thing to do?
  48. - Invalid pdobj.wlayout when wwhole is not finished: dur must be
  49. set correctly.
  50. - Can I assert that if subline was stopped at fmtrExceededMargin,
  51. dur > RM.
  52. - Should ForceBreak return correct previous break if possible?
  53. - I rely on the following axiom:
  54. If Warichu returned fmtrExceedMargin, it must be broken
  55. inside (brkkind != brkkindImposedAfter)
  56. - Mod width: check method(s); should I count m-w in Warichu Truncation / Breaking
  57. - Optimization of allocating WBRKREC
  58. - To have function GetDcpWarichu (additionally to GetCpLimOfWLayout)
  59. - Do something with FOpenBraceWLayout
  60. - Queries: callback to client saying where to snap?
  61. - Sergey: Assert in AdjustText & submitted sublines.
  62. */
  63. /**********************************/
  64. /* */
  65. /* WARICHU Array of break records */
  66. /* */
  67. /**********************************/
  68. typedef struct wbrkarray
  69. {
  70. DWORD nBreakRec; /* Actual number of break records in the array */
  71. DWORD nBreakRecMax; /* Size of allocated array */
  72. BREAKREC * rgBreakRec; /* Ls array of break records */
  73. /* Note: Field nBreakRec is maintained by clients of this structure
  74. and it must be <= nBreakRecMax. nBreakRecMax and rgBreakRec
  75. are set during allocation */
  76. } WBRKARRAY;
  77. typedef WBRKARRAY *PWBRKARRAY;
  78. /****************************/
  79. /* */
  80. /* WARICHU Installed LS Obj */
  81. /* */
  82. /****************************/
  83. typedef struct ilsobj
  84. {
  85. POLS pols;
  86. struct lscbk lscbk;
  87. PLSC plsc;
  88. DWORD idobj;
  89. LSDEVRES lsdevres;
  90. LSESC lsescBraceOpen;
  91. LSESC lsescText;
  92. LSESC lsescBraceClose;
  93. WARICHUCBK warichucbk; /* Callbacks to client application */
  94. BOOL fContiguousFetch; /* This flag was added to fix Word 9 bug */
  95. } ILSOBJ;
  96. /****************************/
  97. /* */
  98. /* WARICHU Internal Subline */
  99. /* */
  100. /****************************/
  101. typedef struct wsubline
  102. {
  103. PLSSUBL plssubl; /* Pointer to LS Subline */
  104. OBJDIM objdim; /* Dimensions of this subline */
  105. LSCP cpFirst; /* cp where formatting of this subline started */
  106. LSCP cpLim; /* cp-lim after formatting */
  107. /* Note: One exception when objdim & cpLim does not correspond to the
  108. dimensions of the subline is the second subline in the Broken Warichu
  109. before SetBreak. We lie putting objdim & cpLim of
  110. already broken subline. Durig Warichu SetBreak we call
  111. LsSetBreakSubline (plssubl...) and the lie turnes into the truth
  112. */
  113. } WSUBLINE;
  114. typedef WSUBLINE *PWSUBLINE;
  115. /****************************/
  116. /* */
  117. /* WARICHU Formatted Brace */
  118. /* */
  119. /****************************/
  120. typedef struct wbrace
  121. {
  122. PLSSUBL plssubl; /* Pointer to Ls subline with brace */
  123. OBJDIM objdim; /* Dimensions of the subline */
  124. LSCP cpFirst; /* cp-start formatting */
  125. LSCP cpLim; /* cp-lim after formatting */
  126. LSCP cpLimAfterEsc; /* cp-lim after brace ESC character (in our case cpLim + 1) */
  127. } WBRACE;
  128. typedef WBRACE *PBRACE;
  129. /**********************/
  130. /* */
  131. /* WARICHU Dimensions */
  132. /* */
  133. /**********************/
  134. typedef struct wdim
  135. {
  136. OBJDIM objdimAll; /* Dimensions of the whole Warichu */
  137. long dvpDescentReserved; /* Received from client together with objdimAll */
  138. /* REVIEW (antons): Clean this logic of calculating
  139. relative positions of warichu sublines */
  140. } WDIM;
  141. /************************/
  142. /* */
  143. /* WARICHU Layout */
  144. /* */
  145. /************************/
  146. typedef struct wlayout
  147. {
  148. WSUBLINE wsubline1; /* First subline in the layout (NULL if layout not valid) */
  149. WSUBLINE wsubline2; /* Second subline in the layout (NULL if no second line) */
  150. BOOL fBroken; /* Broken or whole Warichu? */
  151. BRKKIND brkkind; /* Kind of break to set at the end of second line if "Broken" */
  152. /* Note: Although the following fields can be calculated using above data
  153. and DOBJ, it is filled by FinishObjDimLayout and nobody has the right
  154. to recalc it on his own way after it has been set.
  155. */
  156. WDIM wdim; /* Dimensions of the whole Warichu */
  157. } WLAYOUT;
  158. typedef WLAYOUT *PWLAYOUT;
  159. /****************************/
  160. /* */
  161. /* WARICHU Kind of break */
  162. /* */
  163. /****************************/
  164. typedef enum wbreaktype
  165. {
  166. wbreaktypeInside,
  167. wbreaktypeAfter,
  168. wbreaktypeInvalid
  169. } WBREAKTYPE;
  170. /******************************************/
  171. /* */
  172. /* Presentation Data for Warichu sublines */
  173. /* */
  174. /******************************************/
  175. typedef struct wdispsubl
  176. {
  177. long dup; /* Dup of subline */
  178. POINTUV duvStart; /* Relative (from object start) position of subline */
  179. /* (in lstflow of the parent) */
  180. } WDISPSUBL;
  181. typedef WDISPSUBL *PWDISPSUBL;
  182. /******************************************/
  183. /* */
  184. /* Presentation Data for Warichu braces */
  185. /* */
  186. /******************************************/
  187. typedef WDISPSUBL WDISPBRACE; /* Same as display information for sublines */
  188. typedef WDISPBRACE *PWDISPBRACE;
  189. /*****************************/
  190. /* */
  191. /* WARICHU Presentation Data */
  192. /* */
  193. /*****************************/
  194. typedef struct wdisplay
  195. {
  196. WDISPSUBL wdispsubl1; /* Display information about Warichu first subline */
  197. WDISPSUBL wdispsubl2; /* Display information about Warichu second subline */
  198. WDISPBRACE wdispbraceOpen; /* Display information about Open brace */
  199. WDISPBRACE wdispbraceClose; /* Display information about Closing brace */
  200. long dvpBetween; /* REVIEW (antons): Do I need to store this? ;-) */
  201. long dupAll; /* REVIEW (antons): Do I need to store this? ;-) */
  202. } WDISPLAY;
  203. /****************************/
  204. /* */
  205. /* WARICHU Whole subline */
  206. /* */
  207. /****************************/
  208. typedef struct wwhole
  209. {
  210. PLSSUBL plssubl; /* Whole formatted subline */
  211. LSCP cpFirst; /* Cp first of the subline */
  212. LSCP cpLim; /* Cp lim of the subline */
  213. OBJDIM objdim; /* Dimensions of the formatted subline */
  214. long urColumnMax; /* Column Max until we formatted the WHOLE line */
  215. /* REVIEW (antons): Do we need this? */
  216. BOOL fFinished; /* If we have reached ESC character during formatting */
  217. /* REVIEW (antons): It seems now I can leave without cpTruncate at all */
  218. LSCP cpTruncate; /* Truncation point at urColumnMax if fFinished = FALSE */
  219. LSCP cpLimAfterEsc; /* First character after ESC if fFinished = TRUE */
  220. BOOL fJisRangeKnown; /* Did we calculate cpJisRangeFirst & cpJisRangeLim? */
  221. /* The following two variables are valid only when "fJisRangeKnown == TRUE" */
  222. LSCP cpJisRangeFirst; /* 4-th cpBreak break from the start of the WWhole subline */
  223. LSCP cpJisRangeLim; /* 4-th cpBreak break from the end of WWhole subline */
  224. /* Note 1: Jis Range empty when cpJisRangeFirst >= cpJisRangeLim */
  225. /* Note 2: Jis Range defines possible set of Warichu breaks according
  226. to JIS rule about 4 break opportunities before / after break.
  227. If cp belong to JisRange (cpJisRangeFirst <= cp < cpJisRangeLim)
  228. it means that there are 4 break opportunities before / after cp. */
  229. /* Note 3: Jis Range is calculated only when neccesary (during breaking). After
  230. formatting fJisRangeKnown==FALSE. When someone need Jis Range during
  231. breaking, he should call CalcJisRange().
  232. */
  233. } WWHOLE;
  234. typedef WWHOLE *PWWHOLE;
  235. /***************************/
  236. /* */
  237. /* WARICHU DOBJ structure */
  238. /* */
  239. /***************************/
  240. struct dobj
  241. {
  242. /* 1. Dobj life-time constant data */
  243. PILSOBJ pilsobj; /* Pointer to ILS object */
  244. PLSDNODE plsdnTop; /* Warichu parent DNode */
  245. LSCP cpStart; /* Starting LS cp for object */
  246. LSCP cpStartObj; /* Starting cp for object. If not Resumed => cpStartObj == cpStart */
  247. BOOL fResumed; /* If Warichu was resumed */
  248. /* REVIEW (antons): Can I assert that fResumed == (cpStart == cpStartObj) */
  249. LSTFLOW lstflowParent; /* Lstflow of the parent subline */
  250. /* 2. Formattig + Breaking + Displaying */
  251. WLAYOUT wlayout; /* Current layout after Formatting / SetBreak */
  252. WBRACE wbraceOpen; /* Opening brace */
  253. WBRACE wbraceClose; /* Closing brace */
  254. /* 3. Breaking */
  255. WBRKARRAY wbrkarrayAtStart;
  256. /* Break records at line start */
  257. /* (if !fResumed => zero # of break records) */
  258. WWHOLE wwhole; /* Structure containing warichu whole subline */
  259. WLAYOUT wlayoutBreak [NBreaksToSave];
  260. /* 3 break records for Prev / Next / Force */
  261. WLAYOUT wlayoutTruncate; /* Optimization: we save the layout after Truncation */
  262. WBREAKTYPE wbreaktype [NBreaksToSave];
  263. /* 4. Displaying */
  264. WDISPLAY wdisplay; /* Presentation info for current layout (valid after CalcPres) */
  265. } DOBJ;
  266. /***************************/
  267. /* */
  268. /* Some macors */
  269. /* */
  270. /***************************/
  271. #define INT_UNDEFINED 0xFFFFFFFF
  272. #define CP_MAX LONG_MAX
  273. #define abs(x) ((x)<0 ? -(x) : (x))
  274. #define max(a,b) ((a) > (b) ? (a) : (b))
  275. #define ZeroObjDim(pobjdim) memset ((pobjdim), 0, sizeof(OBJDIM));
  276. #define NOT !
  277. /* O V E R F L O W S A F E A R I T H M E T I C S */
  278. /*----------------------------------------------------------------------------
  279. %%Functions: ADDLongSafe, MULLongSafe
  280. %%Contact: antons
  281. Calculations with urColumnMax require special treatment because
  282. of possible overflow. Two functions below implement overflow-safe
  283. arithmetics for ADD and MUL on positive (>=0) numbers.
  284. ----------------------------------------------------------------------------*/
  285. /* ADDLongSafe: X + Y */
  286. long ADDLongSafe (long x, long y)
  287. {
  288. Assert (x >= 0 && y >= 0);
  289. if (x > LONG_MAX - y) return LONG_MAX;
  290. else
  291. return x + y;
  292. }
  293. /* MULLongSafe: X * Y */
  294. long MULLongSafe (long x, long y)
  295. {
  296. Assert (x >= 0 && y >= 0);
  297. if (y == 0) return 0;
  298. else if (x > LONG_MAX / y) return LONG_MAX;
  299. else
  300. return x * y;
  301. }
  302. /* W A F I N D N E X T B R E A K S U B L I N E */
  303. /*----------------------------------------------------------------------------
  304. %%Function: WaFindNextBreakSubline
  305. %%Contact: antons
  306. Wrapper to LsFindNextBreakSubline () API. It makes sure that result is
  307. monotonous.
  308. ----------------------------------------------------------------------------*/
  309. LSERR WaFindNextBreakSubline (
  310. PLSSUBL plssubl,
  311. LSCP cpTruncate,
  312. long urColumnMax,
  313. BOOL * pfSuccessful,
  314. LSCP * pcpBreak,
  315. POBJDIM pobjdimSubline )
  316. {
  317. BRKPOS brkpos;
  318. LSERR lserr = LsFindNextBreakSubline ( plssubl,
  319. TRUE,
  320. cpTruncate,
  321. urColumnMax,
  322. pfSuccessful,
  323. pcpBreak,
  324. pobjdimSubline,
  325. & brkpos );
  326. if (lserr != lserrNone) return lserr;
  327. if (* pfSuccessful)
  328. {
  329. /* REVIEW (antons): Maybe still better have a loop for crazy case? */
  330. Assert (*pcpBreak > cpTruncate);
  331. /* REVIEW (antons): Check this Assert with Igor */
  332. Assert (brkpos != brkposBeforeFirstDnode);
  333. if (brkpos == brkposAfterLastDnode) *pfSuccessful = FALSE;
  334. };
  335. return lserrNone;
  336. }
  337. /* W A F I N D N E X T B R E A K S U B L I N E */
  338. /*----------------------------------------------------------------------------
  339. %%Function: WaFindPrevBreakSubline
  340. %%Contact: antons
  341. Wrapper to LsForceBreakSubline () API. It makes sure that result is
  342. monotonous.
  343. ----------------------------------------------------------------------------*/
  344. LSERR WaFindPrevBreakSubline (
  345. PLSSUBL plssubl,
  346. LSCP cpTruncate,
  347. long urColumnMax,
  348. BOOL * pfSuccessful,
  349. LSCP * pcpBreak,
  350. POBJDIM pobjdimSubline )
  351. {
  352. BRKPOS brkpos;
  353. LSCP cpTruncateLoop;
  354. LSERR lserr = LsFindPrevBreakSubline ( plssubl,
  355. TRUE,
  356. cpTruncate,
  357. urColumnMax,
  358. pfSuccessful,
  359. pcpBreak,
  360. pobjdimSubline,
  361. & brkpos );
  362. if (lserr != lserrNone) return lserr;
  363. if (! *pfSuccessful) return lserrNone;
  364. /* Successful => check monotonous and break "after"*/
  365. cpTruncateLoop = cpTruncate;
  366. while (brkpos == brkposAfterLastDnode || *pcpBreak > cpTruncate)
  367. {
  368. /* Break is to the right from truncation point or
  369. after the subline. Have to try another Prev Break
  370. */
  371. /* REVIEW (antons): Can I ever repeat this loop more then once? */
  372. cpTruncateLoop --;
  373. lserr = LsFindPrevBreakSubline ( plssubl,
  374. TRUE,
  375. cpTruncateLoop,
  376. urColumnMax,
  377. pfSuccessful,
  378. pcpBreak,
  379. pobjdimSubline,
  380. & brkpos );
  381. if (! *pfSuccessful) return lserrNone;
  382. };
  383. if (brkpos == brkposBeforeFirstDnode)
  384. {
  385. *pfSuccessful = FALSE;
  386. return lserrNone;
  387. };
  388. Assert (*pfSuccessful);
  389. Assert (brkpos == brkposInside);
  390. Assert (*pcpBreak <= cpTruncate);
  391. return lserrNone;
  392. }
  393. /* W A F O R C E B R E A K S U B L I N E */
  394. /*----------------------------------------------------------------------------
  395. %%Function: WaForceForceBreakSubline
  396. %%Contact: antons
  397. Wrapper to LsForceBreakSubline () API.
  398. ----------------------------------------------------------------------------*/
  399. LSERR WaForceBreakSubline ( PLSSUBL plssubl,
  400. LSCP cpTruncate,
  401. long dur,
  402. LSCP * cpEnd,
  403. BRKPOS * pbrkpos,
  404. POBJDIM pobjdim )
  405. {
  406. LSERR lserr;
  407. lserr = LsForceBreakSubline ( plssubl, TRUE, cpTruncate, dur, cpEnd, pobjdim,
  408. pbrkpos );
  409. return lserr;
  410. }
  411. /* W A D E S T R O Y S U B L I N E */
  412. /*----------------------------------------------------------------------------
  413. %%Function: WaDestroySubline
  414. %%Contact: antons
  415. Wrapper to LsDestroySubline () API.
  416. ----------------------------------------------------------------------------*/
  417. LSERR WaDestroySubline (PLSSUBL plssubl)
  418. {
  419. if (plssubl != NULL) return LsDestroySubline (plssubl);
  420. else
  421. return lserrNone;
  422. }
  423. /* W A M A T C H P R E S S U B L I N E */
  424. /*----------------------------------------------------------------------------
  425. %%Function: WaMatchPresSubline
  426. %%Contact: antons
  427. Wrapper to LsMatchPresSubline () API.
  428. ----------------------------------------------------------------------------*/
  429. LSERR WaMatchPresSubline (PLSSUBL plssubl, long *pdup)
  430. {
  431. LSERR lserr;
  432. BOOL fDone;
  433. LSTFLOW lstflowUnused;
  434. lserr = LssbFDonePresSubline (plssubl, &fDone);
  435. if (lserr != lserrNone) return lserr;
  436. if (!fDone) lserr = LsMatchPresSubline (plssubl);
  437. if (lserr != lserrNone) return lserr; /* ;-) */
  438. lserr = LssbGetDupSubline (plssubl, &lstflowUnused, pdup);
  439. return lserr;
  440. }
  441. /* W A E X P A N D S U B L I N E */
  442. /*----------------------------------------------------------------------------
  443. %%Function: WaExpandSubline
  444. %%Contact: antons
  445. Wrapper to LsExpandSubline () API.
  446. ----------------------------------------------------------------------------*/
  447. LSERR WaExpandSubline ( PLSSUBL plssubl,
  448. LSKJUST lskjust,
  449. long dupExpand,
  450. long * pdupSubline )
  451. {
  452. LSERR lserr;
  453. LSTFLOW lstflowUnused;
  454. Unreferenced (dupExpand);
  455. Unreferenced (lskjust);
  456. lserr = LsExpandSubline (plssubl, lskjust, dupExpand);
  457. if (lserr != lserrNone) return lserr;
  458. lserr = LssbGetDupSubline (plssubl, &lstflowUnused, pdupSubline);
  459. return lserr;
  460. }
  461. /* S E T B R E A K W S U B L I N E */
  462. /*----------------------------------------------------------------------------
  463. %%Function: SetBreakWSubline
  464. %%Contact: antons
  465. Wrapper to LsSetBreakSubline () API for wsubline. Procedure changes
  466. objdim and cpLim of wsubline.
  467. ----------------------------------------------------------------------------*/
  468. static LSERR SetBreakWSubline (
  469. PWSUBLINE pwsubline, /* (IN): Subline to set break */
  470. BRKKIND brkkind, /* (IN): Kind of break to set */
  471. LSCP cpLimBreak, /* (IN): Cp-lim of the broken subline */
  472. POBJDIM pobjdimBreak, /* (IN): Dimensions of the broken subline */
  473. PWBRKARRAY pwbrkarray) /* (OUT): Array of break records */
  474. {
  475. LSERR lserr;
  476. lserr = LsSetBreakSubline ( pwsubline->plssubl,
  477. brkkind,
  478. pwbrkarray->nBreakRecMax,
  479. pwbrkarray->rgBreakRec,
  480. & pwbrkarray->nBreakRec );
  481. pwsubline->objdim = * pobjdimBreak;
  482. pwsubline->cpLim = cpLimBreak;
  483. #ifdef DEBUG
  484. /* Check that pobjdimBreak contains correct dimensions of the broken subline */
  485. {
  486. OBJDIM objdimSubline;
  487. LSTFLOW lstflowSubline;
  488. lserr = LssbGetObjDimSubline (pwsubline->plssubl, &lstflowSubline, &objdimSubline);
  489. if (lserr != lserrNone) return lserr;
  490. Assert (memcmp (&objdimSubline, pobjdimBreak, sizeof(OBJDIM)) == 0);
  491. }
  492. #endif // DEBUG
  493. return lserr;
  494. }
  495. /* C L E A R ... */
  496. /*----------------------------------------------------------------------------
  497. %%Function: Clear...
  498. %%Contact: antons
  499. Set of procedures to clear all references from different warichu
  500. data structures.
  501. ----------------------------------------------------------------------------*/
  502. #define ClearWSubline(pwsubline) (pwsubline)->plssubl = NULL;
  503. #define ClearWBrkArray(pwbrkarray) (pwbrkarray)->rgBreakRec = NULL;
  504. #define ClearWBrace(pwbrace) (pwbrace)->plssubl = NULL;
  505. #define ClearWWhole(pwwhole) (pwwhole)->plssubl = NULL;
  506. static void ClearWLayout (PWLAYOUT pwlayout)
  507. {
  508. ClearWSubline (&pwlayout->wsubline1);
  509. ClearWSubline (&pwlayout->wsubline2);
  510. }
  511. #define FWLayoutValid(pwlayout) ((pwlayout)->wsubline1.plssubl != NULL)
  512. #define InvalidateWLayout(pwlayout) (pwlayout)->wsubline1.plssubl = NULL;
  513. /* REVIEW (antons): Maybe we should have more clean def of "invalid" wlayout? */
  514. /* Note: I do not have ClearDobj () because Warichu Dobj gets cleaned in NewDobj */
  515. /* N E W W B R K A R R A Y C O P Y */
  516. /*----------------------------------------------------------------------------
  517. %%Function: NewWBrkArrayCopy
  518. %%Contact: antons
  519. Copy constructor for WBrkArray. Receives array of break records to
  520. store in WBrkArray structure. Important: There is another constructor
  521. of WBrkArray so any change here may require adjusting of another
  522. procedure.
  523. ----------------------------------------------------------------------------*/
  524. static LSERR NewWBrkArrayCopy (
  525. PDOBJ pdobj, /* (IN): Warichu Dobj */
  526. DWORD nBreakRec, /* (IN): Number of break records in array */
  527. const BREAKREC
  528. * rgBreakRec, /* (IN): Array of break records */
  529. PWBRKARRAY pwbrkarray ) /* (OUT): Initialized (allocated) structure */
  530. {
  531. PILSOBJ pilsobj = pdobj->pilsobj;
  532. if (nBreakRec != 0)
  533. {
  534. pwbrkarray->rgBreakRec = AllocateMemory (pilsobj, nBreakRec * sizeof(BREAKREC));
  535. if (pwbrkarray->rgBreakRec == NULL)
  536. {
  537. return lserrOutOfMemory;
  538. };
  539. pwbrkarray->nBreakRecMax = nBreakRec;
  540. pwbrkarray->nBreakRec = nBreakRec;
  541. /* Copy contents of the input array to the WBrkArray data structure */
  542. memcpy (pwbrkarray->rgBreakRec, rgBreakRec, nBreakRec * sizeof(BREAKREC));
  543. }
  544. else
  545. {
  546. /* nBreakRec == 0 */
  547. pwbrkarray->rgBreakRec = NULL;
  548. pwbrkarray->nBreakRecMax = 0;
  549. pwbrkarray->nBreakRec = 0;
  550. };
  551. return lserrNone;
  552. }
  553. /* N E W W B R K A R R A Y */
  554. /*----------------------------------------------------------------------------
  555. %%Function: NewWBreakArray
  556. %%Contact: antons
  557. Constructor for WBrkArray. Allocate number of break records according
  558. to LsdnGetFormatDepth (...). Important: There is another constructor
  559. of WBrkArray so any change here may require adjusting of another procedure.
  560. ----------------------------------------------------------------------------*/
  561. static LSERR NewWBrkArray (
  562. PDOBJ pdobj, /* (IN): Warichu Dobj */
  563. PWBRKARRAY pwbrarray ) /* (OUT): Initialized (allocated) structure */
  564. {
  565. LSERR lserr;
  566. PILSOBJ pilsobj = pdobj->pilsobj;
  567. DWORD nBreakRecMax;
  568. lserr = LsdnGetFormatDepth (pilsobj->plsc, & nBreakRecMax);
  569. if (lserr != lserrNone)
  570. {
  571. pwbrarray->rgBreakRec = NULL;
  572. return lserr;
  573. };
  574. pwbrarray->rgBreakRec = AllocateMemory (pilsobj, nBreakRecMax * sizeof(BREAKREC));
  575. if (pwbrarray->rgBreakRec == NULL) return lserrOutOfMemory;
  576. pwbrarray->nBreakRecMax = nBreakRecMax;
  577. pwbrarray->nBreakRec = 0; /* Initialization - no b.r. */
  578. return lserrNone;
  579. }
  580. /* D E S T R O Y W B R K A R R A Y */
  581. /*----------------------------------------------------------------------------
  582. %%Function: DestroyWBrkArray
  583. %%Contact: antons
  584. Destroy WBRKARRAY structure.
  585. ----------------------------------------------------------------------------*/
  586. static void DestroyWBrkArray (PDOBJ pdobj, PWBRKARRAY pwbrkarray)
  587. {
  588. PILSOBJ pilsobj = pdobj->pilsobj;
  589. if (pwbrkarray->rgBreakRec != NULL)
  590. {
  591. FreeMemory (pilsobj, pwbrkarray->rgBreakRec);
  592. pwbrkarray->rgBreakRec = NULL;
  593. };
  594. }
  595. /* D E S T R O Y W L A Y O U T */
  596. /*----------------------------------------------------------------------------
  597. %%Function: Destroywlayout
  598. %%Contact: antons
  599. Destroy sublines stored in the layout record
  600. ----------------------------------------------------------------------------*/
  601. static LSERR DestroyWLayout (PWLAYOUT pwlayout)
  602. {
  603. LSERR lserr1, lserr2;
  604. lserr1 = WaDestroySubline (pwlayout->wsubline1.plssubl);
  605. lserr2 = WaDestroySubline (pwlayout->wsubline2.plssubl);
  606. ClearWLayout (pwlayout);
  607. if (lserr1 != lserrNone) return lserr1;
  608. else return lserr2;
  609. }
  610. /* N E W D O B J */
  611. /*----------------------------------------------------------------------------
  612. %%Function: NewDobj
  613. %%Contact: antons
  614. Allocate new Dobj and initialize it.
  615. ----------------------------------------------------------------------------*/
  616. static LSERR NewDobj (
  617. PILSOBJ pilsobj, /* (IN): Ilsobj for object */
  618. PLSDNODE plsdnTop, /* (IN): Parent Dnode */
  619. LSCP cpStart, /* (IN): Cp-start of the Warichu */
  620. LSCP cpStartObj, /* (IN): Cp-start from break record if fResumed */
  621. BOOL fResumed, /* (IN): FormatResume? */
  622. DWORD nBreakRec, /* (IN): fResumed => size of the break records array */
  623. const BREAKREC
  624. * rgBreakRec, /* (IN): fResumed => array of break records */
  625. LSTFLOW lstflowParent, /* (IN): Lstflow of the parent subline */
  626. PDOBJ *ppdobj) /* (OUT): allocated dobj */
  627. {
  628. LSERR lserr;
  629. PDOBJ pdobj = AllocateMemory (pilsobj, sizeof(DOBJ));
  630. if (pdobj == NULL)
  631. {
  632. *ppdobj = NULL;
  633. return lserrOutOfMemory;
  634. };
  635. #ifdef DEBUG
  636. Undefined (pdobj); /* Put some garbage into all dobj bytes */
  637. #endif
  638. pdobj->cpStart = cpStart;
  639. pdobj->cpStartObj = cpStartObj;
  640. pdobj->pilsobj = pilsobj;
  641. pdobj->plsdnTop = plsdnTop;
  642. pdobj->fResumed = fResumed;
  643. pdobj->lstflowParent = lstflowParent;
  644. ClearWLayout (&pdobj->wlayout);
  645. ClearWLayout (&pdobj->wlayoutBreak [0]); /* prev */
  646. ClearWLayout (&pdobj->wlayoutBreak [1]); /* next */
  647. ClearWLayout (&pdobj->wlayoutBreak [2]); /* force */
  648. ClearWLayout (&pdobj->wlayoutTruncate); /* OPT: Layout after truncation */
  649. Assert (NBreaksToSave == 3);
  650. pdobj->wbreaktype [0] = wbreaktypeInvalid; /* prev */
  651. pdobj->wbreaktype [1] = wbreaktypeInvalid; /* next */
  652. pdobj->wbreaktype [2] = wbreaktypeInvalid; /* force */
  653. ClearWBrace (&pdobj->wbraceOpen);
  654. ClearWBrace (&pdobj->wbraceClose);
  655. ClearWWhole (&pdobj->wwhole);
  656. *ppdobj = pdobj;
  657. if (fResumed)
  658. {
  659. /* RESUMED => Allocate array of break records in wwhole & store there rgBreakRec */
  660. lserr = NewWBrkArrayCopy (pdobj, nBreakRec, rgBreakRec, &pdobj->wbrkarrayAtStart);
  661. if (lserr != lserrNone) return lserr;
  662. }
  663. else
  664. {
  665. /* ! RESUMED => Allocate 0 break records */
  666. lserr = NewWBrkArrayCopy (pdobj, 0, NULL, &pdobj->wbrkarrayAtStart);
  667. if (lserr != lserrNone) return lserr;
  668. /* Note: even if ! Resumed, I will use Resumed formatting just because
  669. I do not want to see at fResumed each time I format subline */
  670. };
  671. return lserrNone;
  672. }
  673. /* D E S T R O Y D O B J */
  674. /*----------------------------------------------------------------------------
  675. %%Function: DestroyDobj
  676. %%Contact: antons
  677. Release all resources associated with dobj for Warichu.
  678. ----------------------------------------------------------------------------*/
  679. static LSERR DestroyDobj (PDOBJ pdobj)
  680. {
  681. LSERR rglserr [8];
  682. int i;
  683. rglserr [0] = WaDestroySubline (pdobj->wbraceOpen.plssubl);
  684. rglserr [1] = WaDestroySubline (pdobj->wbraceClose.plssubl);
  685. rglserr [2] = DestroyWLayout (&pdobj->wlayout);
  686. rglserr [3] = DestroyWLayout (&pdobj->wlayoutBreak [0]);
  687. rglserr [4] = DestroyWLayout (&pdobj->wlayoutBreak [1]);
  688. rglserr [5] = DestroyWLayout (&pdobj->wlayoutBreak [2]);
  689. rglserr [6] = WaDestroySubline (pdobj->wwhole.plssubl);
  690. rglserr [7] = DestroyWLayout (&pdobj->wlayoutTruncate);
  691. DestroyWBrkArray (pdobj, &pdobj->wbrkarrayAtStart);
  692. FreeMemory (pdobj->pilsobj, pdobj);
  693. /* REVIEW (antons): return last error instead of first? */
  694. for (i = 0; i < 8; i++)
  695. {
  696. if (rglserr [i] != lserrNone) return rglserr [i];
  697. };
  698. return lserrNone;
  699. }
  700. /* F O R M A T B R A C E O F W A R I C H U */
  701. /*----------------------------------------------------------------------------
  702. %%Function: FormatBraceOfWarichu
  703. %%Contact: antons
  704. Create a line for beginning or ending bracket for Warichu.
  705. ----------------------------------------------------------------------------*/
  706. typedef enum wbracekind {wbracekindOpen, wbracekindClose} WBRACEKIND;
  707. static LSERR FormatBraceOfWarichu (
  708. PDOBJ pdobj, /* (IN): Warichu Dobj */
  709. LSCP cpFirst, /* (IN): Cp to start formatting */
  710. WBRACEKIND wbracekind, /* (IN): Open or Close */
  711. WBRACE *wbrace) /* (OUT): Brace data structure */
  712. {
  713. LSERR lserr;
  714. LSCP cpLimSubline;
  715. FMTRES fmtres;
  716. LSESC * plsEscape;
  717. Assert (wbracekind == wbracekindOpen || wbracekind == wbracekindClose);
  718. plsEscape = ( wbracekind == wbracekindOpen ? &pdobj->pilsobj->lsescBraceOpen
  719. : &pdobj->pilsobj->lsescBraceClose );
  720. lserr = FormatLine( pdobj->pilsobj->plsc,
  721. cpFirst,
  722. LONG_MAX,
  723. pdobj->lstflowParent,
  724. & wbrace->plssubl,
  725. 1,
  726. plsEscape,
  727. & wbrace->objdim,
  728. & cpLimSubline,
  729. NULL,
  730. NULL,
  731. & fmtres );
  732. if (lserr != lserrNone) return lserr;
  733. Assert (fmtres == fmtrCompletedRun); /* Hit esc character */
  734. wbrace->cpFirst = cpFirst;
  735. wbrace->cpLim = cpLimSubline;
  736. wbrace->cpLimAfterEsc = cpLimSubline + 1; /* Skip 1 esc character */
  737. return lserrNone;
  738. }
  739. /* F O R M A T W W H O L E S U B L I N E */
  740. /*----------------------------------------------------------------------------
  741. %%Function: FormatWWholeSubline
  742. %%Contact: antons
  743. Formats the whole subline of Warichu (field "wwhole" in DOBJ).
  744. ----------------------------------------------------------------------------*/
  745. static LSERR FormatWWholeSubline (
  746. PDOBJ pdobj, /* (IN): Warichu Dobj */
  747. LSCP cpFirst, /* (IN): Where to start formatting */
  748. long urColumnMax, /* (IN): RM to limit formatting */
  749. PWBRKARRAY pwbrkarrayAtStart,
  750. /* (IN): array of break records at wwhole start */
  751. PWWHOLE pwwhole ) /* (OUT): Strucure with the whole subline */
  752. {
  753. LSERR lserr;
  754. LSCP cpLimSubline;
  755. FMTRES fmtres;
  756. ClearWWhole (pwwhole); /* For the case of error */
  757. Assert (pdobj->fResumed || (pdobj->wbrkarrayAtStart.nBreakRec == 0));
  758. lserr = FormatResumedLine (
  759. pdobj->pilsobj->plsc,
  760. cpFirst,
  761. urColumnMax,
  762. pdobj->lstflowParent,
  763. & pwwhole->plssubl,
  764. 1,
  765. & pdobj->pilsobj->lsescText,
  766. & pwwhole->objdim,
  767. & cpLimSubline,
  768. NULL,
  769. NULL,
  770. & fmtres,
  771. pwbrkarrayAtStart->rgBreakRec,
  772. pwbrkarrayAtStart->nBreakRec );
  773. if (lserr != lserrNone) return lserr;
  774. Assert (pwwhole->plssubl != NULL);
  775. pwwhole->cpFirst = cpFirst;
  776. pwwhole->cpLim = cpLimSubline;
  777. pwwhole->urColumnMax = urColumnMax;
  778. Assert (fmtres == fmtrCompletedRun || fmtres == fmtrExceededMargin);
  779. if (fmtres == fmtrCompletedRun)
  780. {
  781. /* Formatting stopped at ESC character */
  782. pwwhole->fFinished = TRUE;
  783. pwwhole->cpLimAfterEsc = cpLimSubline + 1;
  784. Undefined (&pwwhole->cpTruncate);
  785. }
  786. else
  787. {
  788. /* Formatting stopped because of Exceeding RM */
  789. pwwhole->fFinished = FALSE;
  790. lserr = LsTruncateSubline (pwwhole->plssubl, urColumnMax, & pwwhole->cpTruncate);
  791. if (lserr != lserrNone)
  792. {
  793. WaDestroySubline (pwwhole->plssubl); /* Do not need to check error code */
  794. pwwhole->plssubl = NULL;
  795. return lserr;
  796. };
  797. Undefined (&pwwhole->cpLimAfterEsc);
  798. };
  799. pwwhole->fJisRangeKnown = FALSE;
  800. return lserrNone;
  801. }
  802. /* F O R M A T W S U B L I N E U N T I L C P B R E A K */
  803. /*----------------------------------------------------------------------------
  804. %%Function: FormatWSublineUntilCpBreak
  805. %%Contact: antons
  806. Format subline until known break opportunity.
  807. ----------------------------------------------------------------------------*/
  808. static LSERR FormatWSublineUntilCpBreak (
  809. PDOBJ pdobj, /* (IN): Warichu Dobj */
  810. LSCP cpFirst, /* (IN): Cp to start formatting */
  811. PWBRKARRAY pwbrkArray, /* (IN): Break records at start */
  812. LSCP cpBreak, /* (IN): Cp-break to find */
  813. long urFormatEstimate, /* (IN): Estimated RM for formatting */
  814. long urTruncateEstimate, /* (IN): Estimated RM for truncation */
  815. BOOL * pfSuccessful, /* (OUT): Did we find it? */
  816. WSUBLINE * pwsubl, /* (OUT): Warichu subline if found */
  817. OBJDIM * pobjdimBreak, /* (OUT): Dimensions of the break */
  818. BRKKIND * pbrkkind ) /* (OUT): Kind of break to set in the subline */
  819. {
  820. LSERR lserr;
  821. LSCP cpLimSubline;
  822. OBJDIM objdimSubline;
  823. OBJDIM objdimBreak;
  824. PLSSUBL plssubl;
  825. FMTRES fmtres;
  826. BOOL fContinue;
  827. LSCP cpTruncate;
  828. long urFormatCurrent;
  829. Assert (urFormatEstimate >= urTruncateEstimate);
  830. pwsubl->plssubl = NULL; /* in case of error */
  831. /* Loop initialization */
  832. urFormatCurrent = urFormatEstimate;
  833. fContinue = TRUE;
  834. /* Loop until we have fetched enough */
  835. /* REVIEW (antons): do-while instead of regular while to avoid
  836. VC++ 6.0 warning message */
  837. do /* while (fContinue) at the end */
  838. {
  839. lserr = FormatResumedLine ( pdobj->pilsobj->plsc,
  840. cpFirst,
  841. urFormatCurrent,
  842. pdobj->lstflowParent,
  843. & plssubl,
  844. 1,
  845. & pdobj->pilsobj->lsescText,
  846. & objdimSubline,
  847. & cpLimSubline,
  848. NULL,
  849. NULL,
  850. & fmtres,
  851. pwbrkArray->rgBreakRec,
  852. pwbrkArray->nBreakRec );
  853. if (lserr != lserrNone) return lserr;
  854. Assert (fmtres == fmtrCompletedRun || fmtres == fmtrExceededMargin);
  855. /* REVIEW (antons): here I wrote "<=" because currently in our
  856. definition, break "after" subline is not a break opportunity.
  857. This place need to verifyed more carefully */
  858. if (cpLimSubline <= cpBreak)
  859. {
  860. /* Did not fetch enough CPs, try again with bigger RM */
  861. Assert (fmtres == fmtrExceededMargin);
  862. lserr = LsDestroySubline (plssubl);
  863. if (lserr != lserrNone) return lserr;
  864. /* REVIEW (antons): Is coefficient 1.5 OK? */
  865. /* REVIEW (antons): The following Assert is against infinite loop */
  866. Assert (urFormatCurrent < ADDLongSafe (urFormatCurrent, urFormatCurrent / 2));
  867. urFormatCurrent = ADDLongSafe (urFormatCurrent, urFormatCurrent / 2);
  868. }
  869. else
  870. {
  871. fContinue = FALSE;
  872. };
  873. } while (fContinue);
  874. Assert (cpBreak < cpLimSubline);
  875. lserr = LsTruncateSubline (plssubl, urTruncateEstimate, & cpTruncate);
  876. if (lserr != lserrNone)
  877. {
  878. WaDestroySubline (plssubl); return lserr;
  879. };
  880. /* Going prev and next break to find required break point */
  881. if (cpTruncate < cpBreak)
  882. {
  883. /* Go forward with Next Break */
  884. LSCP cpLastBreak = cpTruncate;
  885. BOOL fBreakSuccessful = TRUE;
  886. do /* while (cpLastBreak < cpBreak && fBreakSuccessful) */
  887. {
  888. lserr = WaFindNextBreakSubline ( plssubl, cpLastBreak,
  889. LONG_MAX,
  890. & fBreakSuccessful,
  891. & cpLastBreak,
  892. & objdimBreak );
  893. if (lserr != lserrNone)
  894. {
  895. WaDestroySubline (plssubl); return lserr;
  896. };
  897. } while (cpLastBreak < cpBreak && fBreakSuccessful);
  898. if (! fBreakSuccessful || cpLastBreak > cpBreak)
  899. {
  900. lserr = LsDestroySubline (plssubl);
  901. if (lserr != lserrNone) return lserr;
  902. *pfSuccessful = FALSE;
  903. }
  904. else
  905. {
  906. Assert (cpLastBreak == cpBreak && fBreakSuccessful);
  907. pwsubl->plssubl = plssubl;
  908. pwsubl->cpFirst = cpFirst;
  909. pwsubl->cpLim = cpBreak;
  910. pwsubl->objdim = objdimSubline;
  911. *pobjdimBreak = objdimBreak;
  912. *pfSuccessful = TRUE;
  913. *pbrkkind = brkkindNext;
  914. };
  915. }
  916. else /* cpTruncate >= cpBreak */
  917. {
  918. /* Go backward with Prev Break */
  919. LSCP cpLastBreak = cpTruncate + 1;
  920. BOOL fBreakSuccessful = TRUE;
  921. do /* while (cpBreak < cpLastBreak && fBreakSuccessful) at the end */
  922. {
  923. lserr = WaFindPrevBreakSubline ( plssubl, cpLastBreak - 1,
  924. LONG_MAX,
  925. & fBreakSuccessful,
  926. & cpLastBreak,
  927. & objdimBreak );
  928. if (lserr != lserrNone)
  929. {
  930. WaDestroySubline (plssubl); return lserr;
  931. };
  932. } while (cpBreak < cpLastBreak && fBreakSuccessful);
  933. if (! fBreakSuccessful || cpBreak > cpLastBreak)
  934. {
  935. lserr = LsDestroySubline (plssubl);
  936. if (lserr != lserrNone) return lserr;
  937. *pfSuccessful = FALSE;
  938. }
  939. else
  940. {
  941. Assert (cpLastBreak == cpBreak && fBreakSuccessful);
  942. pwsubl->plssubl = plssubl;
  943. pwsubl->cpFirst = cpFirst;
  944. pwsubl->cpLim = cpBreak;
  945. pwsubl->objdim = objdimSubline;
  946. *pobjdimBreak = objdimBreak;
  947. *pbrkkind = brkkindPrev;
  948. *pfSuccessful = TRUE;
  949. };
  950. }; /* End If (cpTruncate < cpBreak) Then ... Else ... */
  951. return lserrNone;
  952. } /* FormatWSublineUntilCpBreak */
  953. /* F O R M A T W S U B L I N E U N T I L R M */
  954. /*----------------------------------------------------------------------------
  955. %%Function: FormatWSublineUntilRM
  956. %%Contact: antons
  957. Format until given right margin - wrapper to FormatLine ()
  958. ----------------------------------------------------------------------------*/
  959. static LSERR FormatWSublineUntilRM (
  960. PDOBJ pdobj, /* (IN): Warichu Dobj */
  961. LSCP cpFirst, /* (IN): Where to start formatting */
  962. long urColumnMax, /* (IN): Right margin to format to */
  963. PWBRKARRAY pwbrkarray, /* (IN): Array of break rec at subline start */
  964. BOOL * fFinished, /* (OUT): Subline finished at Escape? */
  965. WSUBLINE * pwsubl ) /* (OUT): Formatted WSubline */
  966. {
  967. LSERR lserr;
  968. FMTRES fmtr;
  969. lserr = FormatResumedLine ( pdobj->pilsobj->plsc,
  970. cpFirst,
  971. urColumnMax,
  972. pdobj->lstflowParent,
  973. & pwsubl->plssubl, /* out */
  974. 1,
  975. & pdobj->pilsobj->lsescText,
  976. & pwsubl->objdim, /* out */
  977. & pwsubl->cpLim, /* out */
  978. NULL,
  979. NULL,
  980. & fmtr,
  981. pwbrkarray->rgBreakRec,
  982. pwbrkarray->nBreakRec );
  983. if (lserr != lserrNone) return lserr;
  984. *fFinished = (fmtr == fmtrCompletedRun); /* out */
  985. pwsubl->cpFirst = cpFirst; /* out */
  986. Assert (fmtr == fmtrCompletedRun || fmtr == fmtrExceededMargin);
  987. return lserrNone;
  988. }
  989. /* F O R M A T W S U B L I N E U N T I L E S C A P E */
  990. /*----------------------------------------------------------------------------
  991. %%Function: FormatWSublineUntilEscape
  992. %%Contact: antons
  993. Format subline until escape character - wrapper to FormatLine ()
  994. ----------------------------------------------------------------------------*/
  995. static LSERR FormatWSublineUntilEscape (
  996. PDOBJ pdobj, /* (IN): Warichu Dobj */
  997. LSCP cpFirst, /* (IN): Where to start formatting */
  998. PWBRKARRAY pwbrkarray, /* (IN): Array of break rec at subline start */
  999. WSUBLINE * pwsubl, /* (OUT): Formatted WSubline */
  1000. long * cpLimAfterEsc) /* (OUT): CpLim after Esc characters */
  1001. {
  1002. FMTRES fmtres;
  1003. LSERR lserr = FormatResumedLine ( pdobj->pilsobj->plsc,
  1004. cpFirst,
  1005. LONG_MAX, /* urColumnMax */
  1006. pdobj->lstflowParent,
  1007. & pwsubl->plssubl, /* out */
  1008. 1,
  1009. & pdobj->pilsobj->lsescText,
  1010. & pwsubl->objdim, /* out */
  1011. & pwsubl->cpLim, /* out */
  1012. NULL,
  1013. NULL,
  1014. & fmtres,
  1015. pwbrkarray->rgBreakRec,
  1016. pwbrkarray->nBreakRec );
  1017. if (lserr != lserrNone) return lserr;
  1018. * cpLimAfterEsc = pwsubl->cpLim + 1; /* out */
  1019. pwsubl->cpFirst = cpFirst; /* out */
  1020. Assert (fmtres == fmtrCompletedRun);
  1021. return lserrNone;
  1022. }
  1023. /* C H O O S E N E A R E S T B R E A K */
  1024. /*----------------------------------------------------------------------------
  1025. %%Function: ChooseNearestBreak
  1026. %%Contact: antons
  1027. Choose nearest between prev and next breaks from the given
  1028. truncation Ur. If prev and next are on the same distance =>
  1029. we choose next.
  1030. ----------------------------------------------------------------------------*/
  1031. static LSERR ChooseNearestBreak (
  1032. PLSSUBL plssubl, /* (IN): Subline to find break */
  1033. long urTruncate2, /* (IN): Truncation point multiplied by 2
  1034. /* (we *2 to avoid rounding erros) */
  1035. LSCP cpLookBefore, /* (IN): Result must be before this cp */
  1036. BOOL *pfSuccessful, /* (OUT): Did we find any break ? */
  1037. LSCP *pcpBreak, /* (OUT): Cp of break */
  1038. OBJDIM *pobjdimBreak, /* (OUT): Dimensions of the broken subline */
  1039. BRKKIND *pbrkkind) /* (OUT): Break to set in the subline */
  1040. {
  1041. LSERR lserr;
  1042. LSCP cpTruncate;
  1043. OBJDIM objdimNext, objdimPrev;
  1044. LSCP cpBreakNext, cpBreakPrev;
  1045. BOOL fSuccessfulNext, fSuccessfulPrev;
  1046. lserr = LsTruncateSubline (plssubl, urTruncate2 / 2, & cpTruncate);
  1047. if (lserr != lserrNone) return lserr;
  1048. lserr = WaFindNextBreakSubline ( plssubl, cpTruncate, LONG_MAX,
  1049. & fSuccessfulNext, & cpBreakNext,
  1050. & objdimNext );
  1051. if (lserr != lserrNone) return lserr;
  1052. lserr = WaFindPrevBreakSubline ( plssubl, cpTruncate, LONG_MAX,
  1053. & fSuccessfulPrev, & cpBreakPrev,
  1054. & objdimPrev );
  1055. if (lserr != lserrNone) return lserr;
  1056. fSuccessfulNext = fSuccessfulNext && cpBreakNext <= cpLookBefore;
  1057. fSuccessfulPrev = fSuccessfulPrev && cpBreakPrev <= cpLookBefore;
  1058. if (fSuccessfulNext &&
  1059. (!fSuccessfulPrev || abs (objdimNext.dur * 2 - urTruncate2) <=
  1060. abs (objdimPrev.dur * 2 - urTruncate2) ) )
  1061. {
  1062. /* CHOOSING NEXT */
  1063. * pfSuccessful = TRUE;
  1064. * pcpBreak = cpBreakNext;
  1065. * pobjdimBreak = objdimNext;
  1066. * pbrkkind = brkkindNext;
  1067. }
  1068. else if (fSuccessfulPrev)
  1069. {
  1070. /* CHOOSING PREV */
  1071. * pfSuccessful = TRUE;
  1072. * pcpBreak = cpBreakPrev;
  1073. * pobjdimBreak = objdimPrev;
  1074. * pbrkkind = brkkindPrev;
  1075. }
  1076. else
  1077. {
  1078. /* Did not find any ;-( */
  1079. * pfSuccessful = FALSE;
  1080. };
  1081. return lserrNone;
  1082. } /* ChooseNearestBreak */
  1083. /* G E T D U R B R A C E S */
  1084. /*----------------------------------------------------------------------------
  1085. %%Function: GetDurBraces
  1086. %%Contact: antons
  1087. ----------------------------------------------------------------------------*/
  1088. #define FOpenBraceInWLayout(pdobj,pwlayout) (! (pdobj)->fResumed)
  1089. #define FCloseBraceInWLayout(pdobj,pwlayout) (! (pwlayout)->fBroken)
  1090. static void GetDurBraces (
  1091. PDOBJ pdobj, /* (IN): Warichu DOBJ */
  1092. BOOL fBroken, /* (IN): Is it broken? */
  1093. BOOL *pfOpenPresent, /* (OUT): Open brace present */
  1094. long *pdurOpen, /* (OUT): dur of the open brace, 0 if no brace */
  1095. BOOL *pfClosePresent,/* (OUT): Close brace present */
  1096. long *pdurClose) /* (OUT): dur of the close brace 0 if no brace */
  1097. {
  1098. if (! pdobj->fResumed)
  1099. {
  1100. Assert (pdobj->wbraceOpen.plssubl != NULL);
  1101. * pdurOpen = pdobj->wbraceOpen.objdim.dur;
  1102. * pfOpenPresent = TRUE;
  1103. }
  1104. else
  1105. {
  1106. * pdurOpen = 0;
  1107. * pfOpenPresent = FALSE;
  1108. };
  1109. if (! fBroken)
  1110. {
  1111. Assert (pdobj->wbraceClose.plssubl != NULL);
  1112. * pdurClose = pdobj->wbraceClose.objdim.dur;
  1113. * pfClosePresent = TRUE;
  1114. }
  1115. else
  1116. {
  1117. * pdurClose = 0;
  1118. * pfClosePresent = FALSE;
  1119. };
  1120. } /* CalcDurBraces */
  1121. /* F I N I S H O B J D I M W L A Y O U T */
  1122. /*----------------------------------------------------------------------------
  1123. %%Function: FinishObjDimWLayout
  1124. %%Contact: antons
  1125. Complete calculations of the Warichu layout. This procedure
  1126. fills WLAYOUT.wdim data structure. The calculations are based on
  1127. the dimensions of Warichu sublines stored in WLAYOUT and the result
  1128. of GetWarichuInfo callback.
  1129. ----------------------------------------------------------------------------*/
  1130. static LSERR FinishObjDimWLayout (
  1131. PDOBJ pdobj, /* (IN): Warichu DOBJ */
  1132. WLAYOUT * pwlayout) /* (IN): Break record (layout) of the Warichu */
  1133. {
  1134. LSERR lserr;
  1135. OBJDIM objdimAll;
  1136. long dvpDescentReserved;
  1137. long durOpen, durClose;
  1138. BOOL fOpenBrace, fCloseBrace;
  1139. PILSOBJ pilsobj = pdobj->pilsobj;
  1140. Assert (pwlayout->wsubline1.plssubl != NULL);
  1141. lserr = pilsobj->warichucbk.pfnGetWarichuInfo ( pilsobj->pols,
  1142. pdobj->cpStartObj,
  1143. pdobj->lstflowParent,
  1144. & pwlayout->wsubline1.objdim,
  1145. & pwlayout->wsubline2.objdim,
  1146. & objdimAll.heightsRef,
  1147. & objdimAll.heightsPres,
  1148. & dvpDescentReserved );
  1149. if (lserr != lserrNone) return lserr;
  1150. GetDurBraces (pdobj, pwlayout->fBroken,
  1151. &fOpenBrace, &durOpen, &fCloseBrace, &durClose);
  1152. objdimAll.dur = durOpen + durClose +
  1153. max (pwlayout->wsubline1.objdim.dur, pwlayout->wsubline2.objdim.dur);
  1154. pwlayout->wdim.objdimAll = objdimAll;
  1155. pwlayout->wdim.dvpDescentReserved = dvpDescentReserved;
  1156. return lserrNone;
  1157. }
  1158. /* F I N I S H W L A Y O U T S I N G L E L I N E */
  1159. /*----------------------------------------------------------------------------
  1160. %%Function: FinishWLayoutSingleLine
  1161. %%Contact: antons
  1162. Finishes layout of warichu as it were only one line (of course, not broken)
  1163. ----------------------------------------------------------------------------*/
  1164. static LSERR FinishWLayoutSingleLine (PDOBJ pdobj, PWLAYOUT pwlayout)
  1165. {
  1166. pwlayout->fBroken = FALSE;
  1167. pwlayout->wsubline2.plssubl = NULL;
  1168. /* REVIEW (antons): Does anybody use cpFirst & cpLim I set here? */
  1169. pwlayout->wsubline2.cpFirst = pwlayout->wsubline1.cpLim;
  1170. pwlayout->wsubline2.cpLim = pwlayout->wsubline1.cpLim;
  1171. ZeroObjDim (& pwlayout->wsubline2.objdim);
  1172. return FinishObjDimWLayout (pdobj, pwlayout);
  1173. }
  1174. /* P R O C E S S M O D W I D T H */
  1175. /*----------------------------------------------------------------------------
  1176. %%Function: ProcessModWidth
  1177. %%Contact: antons
  1178. Ask client how much widths should be modified for lead or end
  1179. bracket for the Warichu. Then modify the Warichu to reflect the
  1180. change in size.
  1181. ----------------------------------------------------------------------------*/
  1182. static LSERR ProcessModWidth (
  1183. PDOBJ pdobj, /* (IN): dobj */
  1184. enum warichucharloc wloc, /* (IN): location of mod width request */
  1185. PLSRUN plsrun, /* (IN): plsrun of the object */
  1186. PLSRUN plsrunText, /* (IN): plsrun of the preceding char */
  1187. WCHAR wchar, /* (IN): preceding character */
  1188. MWCLS mwcls, /* (IN): ModWidth class of preceding character */
  1189. long *pdurChange) /* (OUT): amount by which width of the preceding char is to be changed */
  1190. {
  1191. PILSOBJ pilsobj = pdobj->pilsobj;
  1192. LSERR lserr;
  1193. long durWChange;
  1194. lserr = pilsobj->warichucbk.pfnFetchWarichuWidthAdjust(pilsobj->pols,
  1195. pdobj->cpStartObj, wloc, plsrunText, wchar, mwcls, plsrun, pdurChange,
  1196. &durWChange);
  1197. AssertSz(durWChange >= 0,
  1198. "ProcessModWidth - invalid return from FetchWidthAdjust");
  1199. if (durWChange < 0)
  1200. {
  1201. durWChange = 0;
  1202. }
  1203. *pdurChange += durWChange;
  1204. return lserr;
  1205. }
  1206. /* S U B M I T W L A Y O U T S U B L I N E S */
  1207. /*----------------------------------------------------------------------------
  1208. %%Function: SubmitWLayoutSublines
  1209. %%Contact: antons
  1210. Submit sublines from the given layout for justification. We call
  1211. it after formatting and during SetBreak.
  1212. ----------------------------------------------------------------------------*/
  1213. static LSERR SubmitWLayoutSublines (PDOBJ pdobj, PWLAYOUT pwlayout)
  1214. {
  1215. PLSSUBL rgsublSubmit [3]; /* Array of psublines to submit */
  1216. DWORD nSubmit; /* Number of sublines to submit */
  1217. LSERR lserr;
  1218. BOOL fOpenBrace, fCloseBrace;
  1219. long durOpen, durClose;
  1220. GetDurBraces (pdobj, pwlayout->fBroken, &fOpenBrace, &durOpen, &fCloseBrace, &durClose);
  1221. nSubmit = 0;
  1222. /* Submit open brace */
  1223. if (fOpenBrace)
  1224. {
  1225. BOOL fSublineEmpty;
  1226. lserr = LssbFIsSublineEmpty (pdobj->wbraceOpen.plssubl, &fSublineEmpty);
  1227. if (lserr != lserrNone) return lserr;
  1228. if (! fSublineEmpty) /* Can not submit empty subline */
  1229. {
  1230. rgsublSubmit [nSubmit++] = pdobj->wbraceOpen.plssubl;
  1231. }
  1232. };
  1233. /* Submit longest subline */
  1234. /* REVIEW (antons): If first is empty & second is not empty but ZW,
  1235. I do not submit neither */
  1236. /* REVIEW (antons): Can it ever happen what I wrote before? */
  1237. if (pwlayout->wsubline1.objdim.dur >= pwlayout->wsubline2.objdim.dur)
  1238. {
  1239. BOOL fSublineEmpty;
  1240. lserr = LssbFIsSublineEmpty (pwlayout->wsubline1.plssubl, &fSublineEmpty);
  1241. if (lserr != lserrNone) return lserr;
  1242. if (! fSublineEmpty) /* Can not submit empty subline */
  1243. {
  1244. rgsublSubmit [nSubmit++] = pwlayout->wsubline1.plssubl;
  1245. };
  1246. }
  1247. else
  1248. {
  1249. BOOL fSublineEmpty;
  1250. Assert (pwlayout->wsubline2.plssubl != NULL);
  1251. lserr = LssbFIsSublineEmpty (pwlayout->wsubline2.plssubl, &fSublineEmpty);
  1252. if (lserr != lserrNone) return lserr;
  1253. if (! fSublineEmpty) /* Can not submit empty subline */
  1254. {
  1255. rgsublSubmit [nSubmit++] = pwlayout->wsubline2.plssubl;
  1256. }
  1257. };
  1258. /* Submit closing brace */
  1259. if (fCloseBrace)
  1260. {
  1261. BOOL fSublineEmpty;
  1262. lserr = LssbFIsSublineEmpty (pdobj->wbraceClose.plssubl, &fSublineEmpty);
  1263. if (lserr != lserrNone) return lserr;
  1264. if (! fSublineEmpty) /* Can not submit empty subline */
  1265. {
  1266. rgsublSubmit [nSubmit++] = pdobj->wbraceClose.plssubl;
  1267. }
  1268. };
  1269. /* REVIEW (antons): This deletes previously submitted subline. Question:
  1270. should we better have additional procedure to "clear" submition?
  1271. */
  1272. lserr = LsdnSubmitSublines ( pdobj->pilsobj->plsc,
  1273. pdobj->plsdnTop,
  1274. nSubmit, rgsublSubmit,
  1275. TRUE, /* Justification */
  1276. FALSE, /* Compression */
  1277. FALSE, /* Display */
  1278. FALSE, /* Decimal tab */
  1279. FALSE ); /* Trailing spaces */
  1280. return lserr;
  1281. }
  1282. /* W A R I C H U C R E A T E I L S O B J */
  1283. /*----------------------------------------------------------------------------
  1284. %%Function: WarichuCreateILSObj
  1285. %%Contact: ricksa
  1286. Create main object for Warichu handlers.
  1287. ----------------------------------------------------------------------------*/
  1288. LSERR WINAPI WarichuCreateILSObj (
  1289. POLS pols, /* (IN): client application context */
  1290. PLSC pclsc, /* (IN): LS context */
  1291. PCLSCBK pclscbk, /* (IN): callbacks to client application */
  1292. DWORD idobj, /* (IN): id of the object */
  1293. PILSOBJ * ppilsobj ) /* (OUT): object ilsobj */
  1294. {
  1295. PILSOBJ pilsobj;
  1296. LSERR lserr;
  1297. WARICHUINIT warichuinit;
  1298. warichuinit.dwVersion = WARICHU_VERSION;
  1299. /* Get initialization data */
  1300. lserr = pclscbk->pfnGetObjectHandlerInfo(pols, idobj, &warichuinit);
  1301. if (lserr != lserrNone)
  1302. {
  1303. return lserr;
  1304. }
  1305. /* Build ILS object */
  1306. pilsobj = pclscbk->pfnNewPtr(pols, sizeof(*pilsobj));
  1307. if (NULL == pilsobj) return lserrOutOfMemory;
  1308. ZeroMemory(pilsobj, sizeof(*pilsobj));
  1309. pilsobj->pols = pols;
  1310. pilsobj->idobj = idobj;
  1311. pilsobj->lscbk = *pclscbk;
  1312. pilsobj->plsc = pclsc;
  1313. pilsobj->lsescBraceOpen.wchFirst = warichuinit.wchEndFirstBracket;
  1314. pilsobj->lsescBraceOpen.wchLast = warichuinit.wchEndFirstBracket;
  1315. pilsobj->lsescText.wchFirst = warichuinit.wchEndText;
  1316. pilsobj->lsescText.wchLast = warichuinit.wchEndText;
  1317. pilsobj->lsescBraceClose.wchFirst = warichuinit.wchEndWarichu;
  1318. pilsobj->lsescBraceClose.wchLast = warichuinit.wchEndWarichu;
  1319. pilsobj->warichucbk = warichuinit.warichcbk;
  1320. pilsobj->fContiguousFetch = warichuinit.fContiguousFetch;
  1321. *ppilsobj = pilsobj;
  1322. return lserrNone;
  1323. }
  1324. /* W A R I C H U D E S T R O Y I L S O B J */
  1325. /*----------------------------------------------------------------------------
  1326. %%Function: WarichuDestroyILSObj
  1327. %%Contact: antons
  1328. Free all resources connected with Warichu main object.
  1329. ----------------------------------------------------------------------------*/
  1330. LSERR WINAPI WarichuDestroyILSObj(PILSOBJ pilsobj)
  1331. {
  1332. FreeMemory (pilsobj, pilsobj);
  1333. return lserrNone;
  1334. }
  1335. /* W A R I C H U S E T D O C */
  1336. /*----------------------------------------------------------------------------
  1337. %%Function: WarichuSetDoc
  1338. %%Contact: antons
  1339. Save the device resolution for later scaling.
  1340. ----------------------------------------------------------------------------*/
  1341. LSERR WINAPI WarichuSetDoc(
  1342. PILSOBJ pilsobj, /* (IN): object ilsobj */
  1343. PCLSDOCINF pclsdocinf) /* (IN): initialization data of the document level */
  1344. {
  1345. pilsobj->lsdevres = pclsdocinf->lsdevres;
  1346. return lserrNone;
  1347. }
  1348. /* W A R I C H U C R E A T E L N O B J */
  1349. /*----------------------------------------------------------------------------
  1350. %%Function: WarichuCreateLNObj
  1351. %%Contact: antons
  1352. ----------------------------------------------------------------------------*/
  1353. LSERR WINAPI WarichuCreateLNObj (PCILSOBJ pcilsobj, PLNOBJ *pplnobj)
  1354. {
  1355. *pplnobj = (PLNOBJ) pcilsobj;
  1356. return lserrNone;
  1357. }
  1358. /* W A R I C H U D E S T R O Y L N O B J */
  1359. /*----------------------------------------------------------------------------
  1360. %%Function: WarichuDestroyLNObj
  1361. %%Contact: antons
  1362. ----------------------------------------------------------------------------*/
  1363. LSERR WINAPI WarichuDestroyLNObj (PLNOBJ plnobj)
  1364. {
  1365. Unreferenced(plnobj);
  1366. return lserrNone;
  1367. }
  1368. /* G E T C P L I M O F W L A Y O U T */
  1369. /*----------------------------------------------------------------------------
  1370. %%Function: GetCpLimOfWLayout
  1371. %%Contact: antons
  1372. Return cp-lim for the given Warichu layout.
  1373. ----------------------------------------------------------------------------*/
  1374. static LSCP GetCpLimOfWLayout (PDOBJ pdobj, WLAYOUT *pwlayout)
  1375. {
  1376. Unreferenced (pdobj);
  1377. Assert (FWLayoutValid (pwlayout));
  1378. if (pwlayout->fBroken)
  1379. {
  1380. Assert (pwlayout->wsubline2.plssubl != NULL);
  1381. return pwlayout->wsubline2.cpLim;
  1382. }
  1383. else
  1384. {
  1385. Assert (pdobj->wbraceClose.plssubl != NULL);
  1386. return pdobj->wbraceClose.cpLimAfterEsc;
  1387. };
  1388. }
  1389. /* R E F O R M A T C L O S I N G B R A C E F O R W O R D 9
  1390. /*----------------------------------------------------------------------------
  1391. %%Function: ReformatClosingBraceForWord9
  1392. %%Contact: antons
  1393. REVIEW (antons):
  1394. THIS IS HACK WHICH WAS REQUESTED BY WORD 9, BECAUSE THEY
  1395. DID NOT WANT TO FIX THEIR BUG IN CODE WHICH INSERTS BRACES
  1396. ON-THE-FLY. IT MUST BE REMOVED AS SOON AS POSSIBLE, BECAUSE
  1397. IT MAY SLOWS DOWN WARICHU FORMATTING SIGNIFICANTLY.
  1398. ----------------------------------------------------------------------------*/
  1399. #define min(a,b) ((a)<(b) ? (a) : (b))
  1400. LSERR ReformatClosingBraceForWord9 (PDOBJ pdobj)
  1401. {
  1402. DWORD cwchRun;
  1403. WCHAR * lpwchRun;
  1404. BOOL fHidden;
  1405. LSCHP lschp;
  1406. PLSRUN plsrun;
  1407. LSCP cpFetch;
  1408. LSCP cpLimFetch;
  1409. LSERR lserr;
  1410. if (pdobj->pilsobj->fContiguousFetch)
  1411. {
  1412. if (! FWLayoutValid (&pdobj->wlayout)) return lserrNone;
  1413. cpFetch = pdobj->wwhole.cpFirst;
  1414. cpLimFetch = min (pdobj->wwhole.cpLim, GetCpLimOfWLayout (pdobj, &pdobj->wlayout));
  1415. while (cpFetch < cpLimFetch)
  1416. {
  1417. lserr = pdobj->pilsobj->lscbk.pfnFetchRun ( pdobj->pilsobj->pols,
  1418. cpFetch, & lpwchRun, & cwchRun,
  1419. & fHidden, & lschp, & plsrun );
  1420. if (lserr != lserrNone) return lserr;
  1421. lserr = pdobj->pilsobj->lscbk.pfnReleaseRun (pdobj->pilsobj->pols, plsrun);
  1422. if (lserr != lserrNone) return lserr;
  1423. Assert (cwchRun > 0);
  1424. if (cwchRun == 0) return lserrInvalidDcpFetched;
  1425. cpFetch = cpFetch + cwchRun;
  1426. };
  1427. cpFetch = cpLimFetch;
  1428. cpLimFetch = GetCpLimOfWLayout (pdobj, &pdobj->wlayout);
  1429. while (cpFetch < cpLimFetch)
  1430. {
  1431. lserr = pdobj->pilsobj->lscbk.pfnFetchRun ( pdobj->pilsobj->pols,
  1432. cpFetch, & lpwchRun, & cwchRun,
  1433. & fHidden, & lschp, & plsrun );
  1434. if (lserr != lserrNone) return lserr;
  1435. lserr = pdobj->pilsobj->lscbk.pfnReleaseRun (pdobj->pilsobj->pols, plsrun);
  1436. if (lserr != lserrNone) return lserr;
  1437. Assert (cwchRun > 0);
  1438. if (cwchRun == 0) return lserrInvalidDcpFetched;
  1439. cpFetch = cpFetch + cwchRun;
  1440. };
  1441. };
  1442. return lserrNone;
  1443. }
  1444. /* F I N D W L A Y O U T O F U N B R O K E N W A R I C H U */
  1445. /*----------------------------------------------------------------------------
  1446. %%Function: FindWLayoutOfUnbrokenWarichu
  1447. %%Contact: antons
  1448. Find layout of the Warichu which is not broken. This procedure
  1449. returns structure WLAYOUT.
  1450. ----------------------------------------------------------------------------*/
  1451. static LSERR FindWLayoutOfUnbrokenWarichu (PDOBJ pdobj, WLAYOUT *pwlayout)
  1452. {
  1453. LSERR lserr;
  1454. BOOL fSuccessful;
  1455. LSCP cpBreakFirstLine;
  1456. OBJDIM objdimUnused;
  1457. OBJDIM objdimFirstLine;
  1458. BRKKIND brkkindUnused;
  1459. LSCP cpLimUnused;
  1460. Assert (pdobj->wwhole.plssubl != NULL);
  1461. /* This should not be called when wwhole was not finished */
  1462. Assert (pdobj->wwhole.fFinished);
  1463. ClearWLayout (pwlayout); /* For the case of error */
  1464. if (pdobj->wwhole.objdim.dur == 0)
  1465. {
  1466. /* Either empty or zero-width subline */
  1467. /* The only thing we can do is to create single-line Warichu */
  1468. LSCP cpLimAfterEscUnused;
  1469. lserr = FormatWSublineUntilEscape ( pdobj, pdobj->wwhole.cpFirst,
  1470. & pdobj->wbrkarrayAtStart,
  1471. & pwlayout->wsubline1,
  1472. & cpLimAfterEscUnused );
  1473. if (lserr != lserrNone) return lserr;
  1474. Assert (pwlayout->wsubline1.objdim.dur == 0);
  1475. return FinishWLayoutSingleLine (pdobj, pwlayout);
  1476. };
  1477. lserr = ChooseNearestBreak ( pdobj->wwhole.plssubl,
  1478. pdobj->wwhole.objdim.dur,
  1479. CP_MAX,
  1480. & fSuccessful,
  1481. & cpBreakFirstLine,
  1482. & objdimUnused,
  1483. & brkkindUnused );
  1484. if (lserr != lserrNone) return lserr;
  1485. if (! fSuccessful)
  1486. {
  1487. /* Not a single break in the whole Warichu line */
  1488. LSCP cpLimAfterEscUnused;
  1489. lserr = FormatWSublineUntilEscape ( pdobj, pdobj->wwhole.cpFirst,
  1490. & pdobj->wbrkarrayAtStart,
  1491. & pwlayout->wsubline1,
  1492. & cpLimAfterEscUnused );
  1493. if (lserr != lserrNone) return lserr;
  1494. return FinishWLayoutSingleLine (pdobj, pwlayout);
  1495. }
  1496. else
  1497. {
  1498. /* Yes, we have break between lines */
  1499. BOOL fSuccessful;
  1500. BRKKIND brkkind;
  1501. WBRKARRAY wbrkarray;
  1502. lserr = FormatWSublineUntilCpBreak ( pdobj, pdobj->wwhole.cpFirst,
  1503. & pdobj->wbrkarrayAtStart,
  1504. cpBreakFirstLine,
  1505. LONG_MAX, pdobj->wwhole.objdim.dur / 2, /* REVIEW THIS ! */
  1506. & fSuccessful,
  1507. & pwlayout->wsubline1, & objdimFirstLine, & brkkind );
  1508. if (lserr != lserrNone) return lserr;
  1509. Assert (fSuccessful); /* Something crazy inside Warichu */
  1510. lserr = NewWBrkArray (pdobj, &wbrkarray);
  1511. if (lserr != lserrNone) return lserr;
  1512. lserr = SetBreakWSubline (&pwlayout->wsubline1, brkkind, cpBreakFirstLine,
  1513. &objdimFirstLine, &wbrkarray);
  1514. lserr = FormatWSublineUntilEscape ( pdobj, pwlayout->wsubline1.cpLim,
  1515. & wbrkarray, & pwlayout->wsubline2,
  1516. & cpLimUnused );
  1517. if (lserr != lserrNone) return lserr;
  1518. DestroyWBrkArray (pdobj, &wbrkarray);
  1519. };
  1520. pwlayout->fBroken = FALSE; /* This warichu is not broken ;-) */
  1521. lserr = FinishObjDimWLayout (pdobj, pwlayout);
  1522. return lserr;
  1523. }
  1524. /* F O R M A T W A R I C H U C O R E */
  1525. /*----------------------------------------------------------------------------
  1526. %%Function: FormatWarichuCore
  1527. %%Contact: antons
  1528. Format Warichu Object (called from methods WarichuFmt and WarichuFmtResumt)
  1529. ----------------------------------------------------------------------------*/
  1530. static LSERR FormatWarichuCore (
  1531. PLNOBJ plnobj, /* (IN): Warichu LNOBJ */
  1532. PCFMTIN pcfmtin, /* (IN): Formatting input */
  1533. BOOL fResumed, /* (IN): Resumed? */
  1534. DWORD nBreakRec, /* (IN): fResumed => size of the break records array */
  1535. const BREAKREC
  1536. * rgBreakRec, /* (IN): fResumed => array of break records */
  1537. FMTRES * pfmtres ) /* (OUT): formatting result */
  1538. {
  1539. LSERR lserr;
  1540. PILSOBJ pilsobj = (PILSOBJ) plnobj; /* They are the same */
  1541. PDOBJ pdobj;
  1542. long urColumnMax = pcfmtin->lsfgi.urColumnMax;
  1543. /* REVIEW (antons): Can we optimize for case 0? */
  1544. long durAvailable = max (0, pcfmtin->lsfgi.urColumnMax - pcfmtin->lsfgi.urPen);
  1545. /* :: CREATE DOBJ WITH INITIAL OBJECT DATA */
  1546. if (! fResumed)
  1547. {
  1548. /* Not Resumed */
  1549. lserr = NewDobj ( pilsobj,
  1550. pcfmtin->plsdnTop,
  1551. pcfmtin->lsfgi.cpFirst,
  1552. pcfmtin->lsfgi.cpFirst,
  1553. FALSE, /* fResumed */
  1554. 0,
  1555. NULL,
  1556. pcfmtin->lsfgi.lstflow,
  1557. & pdobj );
  1558. }
  1559. else
  1560. {
  1561. /* Resumed */
  1562. Assert (nBreakRec > 0);
  1563. Assert (rgBreakRec [0].idobj == pilsobj->idobj);
  1564. lserr = NewDobj ( pilsobj,
  1565. pcfmtin->plsdnTop,
  1566. pcfmtin->lsfgi.cpFirst,
  1567. rgBreakRec [0].cpFirst,
  1568. TRUE, /* fResumed */
  1569. nBreakRec-1,
  1570. & rgBreakRec [1],
  1571. pcfmtin->lsfgi.lstflow,
  1572. & pdobj );
  1573. };
  1574. if (lserr != lserrNone) return lserr;
  1575. /* :: FORMAT WARICHU OPEN BRACE IF not RESUMED*/
  1576. if (!fResumed)
  1577. {
  1578. lserr = FormatBraceOfWarichu ( pdobj, pdobj->cpStart + 1 /* Skip 1 Esc */,
  1579. wbracekindOpen, & pdobj->wbraceOpen );
  1580. if (lserr != lserrNone)
  1581. {
  1582. DestroyDobj (pdobj); return lserr;
  1583. };
  1584. }
  1585. else
  1586. pdobj->wbraceOpen.plssubl = NULL; /* No open brace */
  1587. /* :: FORMAT THE WHOLE WARICHU LINE */
  1588. {
  1589. /* REVIEW (antons): Check with Igor that he is not playing with RM, because
  1590. if he is, the following estimations of durFormatWhole are
  1591. not correct */
  1592. /* To be able to check JIS rule, warichu needs to format the whole subline
  1593. far ehough to be able to count 4 break opportunities from break-point.
  1594. We estimate it like
  1595. 2 * durAvailable + 2 * urColumnMax
  1596. */
  1597. /* REVIEW (antons): I want to be sure that final line break does not depend on
  1598. whatever estimations we use here */
  1599. /* REVIEW (antons): Is that correct to return lserrUnsufficientFetch if there is
  1600. no 4 breaks after (JIS rule) when wwhole is not finished? */
  1601. /* REVIEW (antons): Can something like 5 * durAvailable may be better */
  1602. long urFormatWhole = MULLongSafe (ADDLongSafe (durAvailable, urColumnMax), 2);
  1603. LSCP cpStartFormatWhole = (fResumed ? pdobj->cpStart :
  1604. pdobj->wbraceOpen.cpLimAfterEsc);
  1605. lserr = FormatWWholeSubline ( pdobj,
  1606. cpStartFormatWhole,
  1607. urFormatWhole,
  1608. & pdobj->wbrkarrayAtStart,
  1609. & pdobj->wwhole );
  1610. if (lserr != lserrNone)
  1611. {
  1612. DestroyDobj (pdobj); return lserr;
  1613. };
  1614. };
  1615. /* :: CHECK IF THE WHOLE SUBLINE WAS NOT FINISHED */
  1616. if (! pdobj->wwhole.fFinished)
  1617. {
  1618. /* Not finished => return fmtrExceedMargin */
  1619. Assert (pdobj->wwhole.objdim.dur / 2 > durAvailable);
  1620. InvalidateWLayout (&pdobj->wlayout); /* Invalidate layout */
  1621. /* REVIEW (antons) */
  1622. pdobj->wlayout.wdim.objdimAll = pdobj->wwhole.objdim;
  1623. /* Must have correct objdim */
  1624. /* REVIEW (antons): Check - we return dcp of the fetched range */
  1625. /* REVIEW (antons): Check - we return objdim of the whole line */
  1626. lserr = LsdnFinishRegular ( pilsobj->plsc,
  1627. pdobj->wwhole.cpLim - pdobj->cpStart,
  1628. pcfmtin->lsfrun.plsrun,
  1629. pcfmtin->lsfrun.plschp,
  1630. pdobj,
  1631. & pdobj->wwhole.objdim );
  1632. if (lserr != lserrNone) { DestroyDobj (pdobj); return lserr; };
  1633. * pfmtres = fmtrExceededMargin;
  1634. return lserrNone;
  1635. };
  1636. /* :: FORMAT THE CLOSING BRACE */
  1637. lserr = FormatBraceOfWarichu (pdobj, pdobj->wwhole.cpLimAfterEsc,
  1638. wbracekindClose, &pdobj->wbraceClose);
  1639. if (lserr != lserrNone) { DestroyDobj (pdobj); return lserr; };
  1640. /* :: FIND LAYOUT OF WARICHU AS IF IT IS NOT BROKEN AND FINISH FORMATTING */
  1641. lserr = FindWLayoutOfUnbrokenWarichu (pdobj, &pdobj->wlayout);
  1642. if (lserr != lserrNone) { DestroyDobj (pdobj); return lserr; };
  1643. /* :: SUBMIT WARICHU SUBLINES */
  1644. /* REVIEW (antons): MOVE SUBMITTION BELOW LSDNFINISHREGULAR WHEN
  1645. WE ALIMINATE HACK WITH REFORMATTING ")" FOR SG */
  1646. lserr = SubmitWLayoutSublines (pdobj, &pdobj->wlayout);
  1647. if (lserr != lserrNone) { DestroyDobj (pdobj); return lserr; };
  1648. ReformatClosingBraceForWord9 (pdobj);
  1649. lserr = LsdnFinishRegular ( pilsobj->plsc,
  1650. GetCpLimOfWLayout (pdobj, &pdobj->wlayout)-pdobj->cpStart,
  1651. pcfmtin->lsfrun.plsrun,
  1652. pcfmtin->lsfrun.plschp,
  1653. pdobj,
  1654. & pdobj->wlayout.wdim.objdimAll );
  1655. if (lserr != lserrNone) { DestroyDobj (pdobj); return lserr; };
  1656. /* :: CHECK IF WE CROSSED RIGHT MARGIN AND RETURN */
  1657. if (pdobj->wlayout.wdim.objdimAll.dur > durAvailable)
  1658. {
  1659. * pfmtres = fmtrExceededMargin;
  1660. }
  1661. else
  1662. {
  1663. * pfmtres = fmtrCompletedRun;
  1664. };
  1665. return lserrNone;
  1666. } /* FormatWarichuCore */
  1667. /* W A R I C H U F M T */
  1668. /*----------------------------------------------------------------------------
  1669. %%Function: Warichu::Fmt
  1670. %%Contact: antons
  1671. Warichu FMT method entry point
  1672. ----------------------------------------------------------------------------*/
  1673. LSERR WINAPI WarichuFmt ( PLNOBJ plnobj, /* (IN): object lnobj */
  1674. PCFMTIN pcfmtin, /* (IN): formatting input */
  1675. FMTRES * pfmtres ) /* (OUT): formatting result */
  1676. {
  1677. return FormatWarichuCore ( plnobj,
  1678. pcfmtin,
  1679. FALSE, /* fResumed = false */
  1680. 0,
  1681. NULL,
  1682. pfmtres );
  1683. }
  1684. /* W A R I C H U F M T R E S U M E */
  1685. /*----------------------------------------------------------------------------
  1686. %%Function: Warichu::FmtResume
  1687. %%Contact: anton
  1688. Warichu FMT-RESUME method entry point
  1689. ----------------------------------------------------------------------------*/
  1690. LSERR WINAPI WarichuFmtResume (
  1691. PLNOBJ plnobj, /* (IN): object lnobj */
  1692. const BREAKREC * rgBreakRecord, /* (IN): array of break records */
  1693. DWORD nBreakRecord, /* (IN): size of the break records array */
  1694. PCFMTIN pcfmtin, /* (IN): formatting input */
  1695. FMTRES * pfmtres ) /* (OUT): formatting result */
  1696. {
  1697. return FormatWarichuCore ( plnobj,
  1698. pcfmtin,
  1699. TRUE, /* fResumed = true */
  1700. nBreakRecord,
  1701. rgBreakRecord,
  1702. pfmtres );
  1703. }
  1704. /* W A R I C H U G E T M O D W I D T H P R E C E D I N G C H A R */
  1705. /*----------------------------------------------------------------------------
  1706. %%Function: WarichuGetModWidthPrecedingChar
  1707. %%Contact: ricksa
  1708. .
  1709. ----------------------------------------------------------------------------*/
  1710. LSERR WINAPI WarichuGetModWidthPrecedingChar(
  1711. PDOBJ pdobj, /* (IN): dobj */
  1712. PLSRUN plsrun, /* (IN): plsrun of the object */
  1713. PLSRUN plsrunText, /* (IN): plsrun of the preceding char */
  1714. PCHEIGHTS pcheightsRef, /* (IN): height info about character */
  1715. WCHAR wchar, /* (IN): preceding character */
  1716. MWCLS mwcls, /* (IN): ModWidth class of preceding character */
  1717. long *pdurChange) /* (OUT): amount by which width of the preceding char is to be changed */
  1718. {
  1719. Unreferenced(pcheightsRef);
  1720. return ProcessModWidth(pdobj, warichuBegin, plsrun, plsrunText,
  1721. wchar, mwcls, pdurChange);
  1722. }
  1723. /* W A R I C H U G E T M O D W I D T H F O L L O W I N G C H A R */
  1724. /*----------------------------------------------------------------------------
  1725. %%Function: WarichuGetModWidthFollowingChar
  1726. %%Contact: ricksa
  1727. .
  1728. ----------------------------------------------------------------------------*/
  1729. LSERR WINAPI WarichuGetModWidthFollowingChar(
  1730. PDOBJ pdobj, /* (IN): dobj */
  1731. PLSRUN plsrun, /* (IN): plsrun of the object */
  1732. PLSRUN plsrunText, /* (IN): plsrun of the following char */
  1733. PCHEIGHTS pcheightsRef, /* (IN): height info about character */
  1734. WCHAR wchar, /* (IN): following character */
  1735. MWCLS mwcls, /* (IN): ModWidth class of the following character */
  1736. long *pdurChange) /* (OUT): amount by which width of the following char is to be changed */
  1737. {
  1738. Unreferenced(pcheightsRef);
  1739. return ProcessModWidth(pdobj, warichuEnd, plsrun, plsrunText,
  1740. wchar, mwcls, pdurChange);
  1741. }
  1742. /* T R Y B R E A K W A R I C H U A T C P */
  1743. /*----------------------------------------------------------------------------
  1744. %%Function: TryBreakWarichuAtCp
  1745. %%Contact: antons
  1746. Given break-point in the whole line, find break of Warichu which
  1747. ends at this break-point. For optimization during Truncation I added
  1748. urColumnMax and special result type trybreakkindExceedMargin.
  1749. This is the major breakig procedure which is called from Truncation,
  1750. Prev / Next Breaks and probably Force break.
  1751. ----------------------------------------------------------------------------*/
  1752. typedef enum trybreakwarichu
  1753. {
  1754. trybreakwarichuSuccessful,
  1755. trybreakwarichuExceedMargin,
  1756. trybreakwarichuCanNotFinishAtCp
  1757. } TRYBREAKWARICHU;
  1758. LSERR TryBreakWarichuAtCp (
  1759. PDOBJ pdobj, /* (IN): Warichu DOBJ */
  1760. LSCP cpBreakCandidate, /* (IN): Candidate cpLim of broken Warichu */
  1761. long durBreakCandidate, /* (IN): dur of break-point in the whole line */
  1762. long urColumnMax, /* (IN): max width of broken warichu (for OPT only!) */
  1763. TRYBREAKWARICHU * ptrybreakwarichu, /* (OUT): Successful | ExceededRM | Bad Candidate */
  1764. PWLAYOUT pwlayout) /* (OUT): Layout of broken Warichu if Successful */
  1765. {
  1766. LSERR lserr;
  1767. BOOL fSuccessful;
  1768. LSCP cpBreakFirst;
  1769. BRKKIND brkkindUnused;
  1770. OBJDIM objdimBreakFirst;
  1771. OBJDIM objdimBreakSecond;
  1772. BRKKIND brkkindFirst;
  1773. BRKKIND brkkindSecond;
  1774. WBRKARRAY wbrkarrayAtFirstEnd; /* WBreakArray at the end of first subline */
  1775. long durOpen, durClose;
  1776. BOOL boolUnused1, boolUnused2;
  1777. pwlayout->wsubline1.plssubl = NULL;
  1778. pwlayout->wsubline2.plssubl = NULL; /* In case of error */
  1779. GetDurBraces (pdobj, TRUE, &boolUnused1, &durOpen, &boolUnused2, &durClose);
  1780. /* REVIEW (antons): Hidden text at "cpBreakCandidate - 1" */
  1781. lserr = ChooseNearestBreak ( pdobj->wwhole.plssubl,
  1782. durBreakCandidate,
  1783. cpBreakCandidate - 1,
  1784. & fSuccessful,
  1785. & cpBreakFirst,
  1786. & objdimBreakFirst,
  1787. & brkkindUnused );
  1788. if (lserr != lserrNone) return lserr;
  1789. Assert (fSuccessful); /* REVIEW (antons): Should not we provide special ret code? */
  1790. /* Optimization check */
  1791. /* REVIEW (antons): I do not like this check, calculation must be done in special function */
  1792. if (durOpen + durClose + objdimBreakFirst.dur > urColumnMax)
  1793. {
  1794. * ptrybreakwarichu = trybreakwarichuExceedMargin;
  1795. lserr = DestroyWLayout (pwlayout);
  1796. return lserrNone;
  1797. };
  1798. /* Format first line */
  1799. lserr = FormatWSublineUntilCpBreak ( pdobj,
  1800. pdobj->wwhole.cpFirst,
  1801. & pdobj->wbrkarrayAtStart,
  1802. cpBreakFirst,
  1803. objdimBreakFirst.dur, /* REVIEW (antons): urColumnMax */
  1804. objdimBreakFirst.dur, /* REVIEW (antons): urTuncate */
  1805. & fSuccessful,
  1806. & pwlayout->wsubline1,
  1807. & objdimBreakFirst,
  1808. & brkkindFirst );
  1809. if (lserr != lserrNone) return lserr;
  1810. /* REVIEW (antons): Maybe we should leave this assert? */
  1811. /* Assert (fSuccessful); */
  1812. if (!fSuccessful) /* Incorrect object inside Warichu, but we can handle it */
  1813. {
  1814. * ptrybreakwarichu = trybreakwarichuCanNotFinishAtCp;
  1815. lserr = DestroyWLayout (pwlayout);
  1816. return lserr;
  1817. };
  1818. /* Create new WBreakArray */
  1819. lserr = NewWBrkArray (pdobj, & wbrkarrayAtFirstEnd);
  1820. if (lserr != lserrNone) {DestroyWLayout (pwlayout); return lserr;};
  1821. /* Set break at the end of first line and fill WBreakArray */
  1822. lserr = SetBreakWSubline (& pwlayout->wsubline1, brkkindFirst,
  1823. cpBreakFirst, & objdimBreakFirst, & wbrkarrayAtFirstEnd);
  1824. if (lserr != lserrNone)
  1825. {
  1826. DestroyWLayout (pwlayout);
  1827. DestroyWBrkArray (pdobj, &wbrkarrayAtFirstEnd);
  1828. return lserr;
  1829. };
  1830. /* REVIEW (antons): Check the following assumption! */
  1831. Assert (durBreakCandidate >= objdimBreakFirst.dur);
  1832. /* Format second line */
  1833. lserr = FormatWSublineUntilCpBreak ( pdobj,
  1834. cpBreakFirst,
  1835. & wbrkarrayAtFirstEnd,
  1836. cpBreakCandidate,
  1837. durBreakCandidate - objdimBreakFirst.dur, /* REVIEW (antons): urColumnMax */
  1838. durBreakCandidate - objdimBreakFirst.dur, /* REVIEW (antons): urTuncate */
  1839. & fSuccessful,
  1840. & pwlayout->wsubline2,
  1841. & objdimBreakSecond,
  1842. & brkkindSecond );
  1843. if (lserr != lserrNone)
  1844. {
  1845. DestroyWLayout ( pwlayout);
  1846. DestroyWBrkArray (pdobj, &wbrkarrayAtFirstEnd);
  1847. return lserr;
  1848. };
  1849. /* We do not need wBreakArrayAtFirstEnd any more, so we release it */
  1850. DestroyWBrkArray (pdobj, & wbrkarrayAtFirstEnd);
  1851. /* If not Successful => result "Can not Finish At Cp" */
  1852. if (!fSuccessful)
  1853. {
  1854. DestroyWLayout (pwlayout);
  1855. * ptrybreakwarichu = trybreakwarichuCanNotFinishAtCp;
  1856. return lserrNone;
  1857. };
  1858. /* Here comes a small cheating ;-)
  1859. We do not want to Set Break at the end of second line, but have to
  1860. store objdim & cpLim as if after SetBreak. Maybe in the future I will
  1861. get rid of this checting (hope it is the only one left in Warichu ;-)
  1862. but today I change cpLim and objdim manually & also store
  1863. kind of break to set at second line end (playout->brkkind).
  1864. */
  1865. pwlayout->wsubline2.cpLim = cpBreakCandidate;
  1866. pwlayout->wsubline2.objdim = objdimBreakSecond;
  1867. pwlayout->brkkind = brkkindSecond;
  1868. pwlayout->fBroken = TRUE;
  1869. lserr = FinishObjDimWLayout (pdobj, pwlayout);
  1870. if (lserr != lserrNone) {DestroyWLayout (pwlayout); return lserr;};
  1871. /* Again, check for right Margin */
  1872. if (pwlayout->wdim.objdimAll.dur > urColumnMax)
  1873. {
  1874. * ptrybreakwarichu = trybreakwarichuExceedMargin;
  1875. lserr = DestroyWLayout (pwlayout);
  1876. return lserr;
  1877. }
  1878. else
  1879. {
  1880. * ptrybreakwarichu = trybreakwarichuSuccessful;
  1881. return lserrNone;
  1882. };
  1883. }
  1884. /* C A L C J I S R A N G E */
  1885. /*----------------------------------------------------------------------------
  1886. %%Function: CalcJisRange
  1887. %%Contact: antons
  1888. Calculate cpJisRangeFisrt and cpJisRangeLim as 4th break opportunities
  1889. from the beginning and from the end of Whole subline. If range is empty,
  1890. * pfJisRangeEmpty = FALSE and cps are undefined.
  1891. ----------------------------------------------------------------------------*/
  1892. static LSERR CalcJisRange (
  1893. PDOBJ pdobj,
  1894. BOOL *pfJisRangeEmpty,
  1895. LSCP *pcpJisRangeFirst,
  1896. LSCP *pcpJisRangeLim )
  1897. {
  1898. LSERR lserr;
  1899. OBJDIM objdimUnused;
  1900. WWHOLE * pwwhole = &pdobj->wwhole;
  1901. Assert (pwwhole->plssubl != NULL);
  1902. if (!pwwhole->fJisRangeKnown) /* Have to calculate */
  1903. {
  1904. /* Searching 4 breaks from WWHOLE start */
  1905. LSCP cpTruncateBefore = pdobj->wwhole.cpFirst;
  1906. BOOL fSuccessful = TRUE;
  1907. long nFound = 0;
  1908. while (fSuccessful && nFound < 4)
  1909. {
  1910. lserr = WaFindNextBreakSubline ( pwwhole->plssubl,
  1911. cpTruncateBefore,
  1912. LONG_MAX,
  1913. & fSuccessful,
  1914. & cpTruncateBefore,
  1915. & objdimUnused );
  1916. if (lserr != lserrNone) return lserr;
  1917. if (fSuccessful) nFound ++;
  1918. };
  1919. if (fSuccessful)
  1920. {
  1921. /* Searching 4 breaks from WWHOLE end */
  1922. LSCP cpTruncateAfter;
  1923. BOOL fSuccessful = TRUE;
  1924. long nFound = 0;
  1925. if (pwwhole->fFinished)
  1926. {
  1927. /* Subline was finished at Esc char, so we can start from cpLim */
  1928. cpTruncateAfter = pwwhole->cpLim;
  1929. }
  1930. else
  1931. {
  1932. /* Subline was stopped at RM => start at RM truncation point */
  1933. cpTruncateAfter = pwwhole->cpTruncate+1;
  1934. };
  1935. /* REVIEW (antons): To reduce check above maybe we can lie about
  1936. cp-lim of the whole subline when it was not finished? */
  1937. while (fSuccessful && nFound < 4)
  1938. {
  1939. lserr = WaFindPrevBreakSubline ( pwwhole->plssubl,
  1940. cpTruncateAfter-1,
  1941. LONG_MAX,
  1942. & fSuccessful,
  1943. & cpTruncateAfter,
  1944. & objdimUnused );
  1945. if (lserr != lserrNone) return lserr;
  1946. if (fSuccessful) nFound ++;
  1947. };
  1948. if (fSuccessful)
  1949. {
  1950. /* Jis Range is not empty */
  1951. pwwhole->cpJisRangeFirst = cpTruncateBefore;
  1952. pwwhole->cpJisRangeLim = cpTruncateAfter + 1;
  1953. }
  1954. else
  1955. {
  1956. /* Empty range */
  1957. pwwhole->cpJisRangeFirst = 0;
  1958. pwwhole->cpJisRangeLim = 0;
  1959. };
  1960. }
  1961. else
  1962. {
  1963. /* Empty range */
  1964. pwwhole->cpJisRangeFirst = 0;
  1965. pwwhole->cpJisRangeLim = 0;
  1966. };
  1967. pwwhole->fJisRangeKnown = TRUE; /* Yes, now we know it */
  1968. }
  1969. else
  1970. /* Nothing - already know ;-) */ ;
  1971. Assert (pwwhole->fJisRangeKnown);
  1972. *pfJisRangeEmpty = pwwhole->cpJisRangeFirst >= pwwhole->cpJisRangeLim;
  1973. *pcpJisRangeFirst = pwwhole->cpJisRangeFirst;
  1974. *pcpJisRangeLim = pwwhole->cpJisRangeLim;
  1975. return lserrNone;
  1976. }
  1977. /* S A V E B R E A K I N S I D E W A R I C H U */
  1978. /*----------------------------------------------------------------------------
  1979. %%Function: SaveBreakInsideWarichu
  1980. %%Contact: antons
  1981. Store layout for Prev / Next / Force break in dobj. This procedure
  1982. also Invalidates pointers in input layout after copying.
  1983. ----------------------------------------------------------------------------*/
  1984. static void SaveBreakInsideWarichu (
  1985. PDOBJ pdobj, /* (IN): Warichu Dobj */
  1986. BRKKIND brkkind, /* (IN): Kind of break happened */
  1987. WLAYOUT * pwlayout ) /* (IN/OUT): Layout to store */
  1988. {
  1989. int ind = GetBreakRecordIndex (brkkind);
  1990. /* Destroy previously saved layout */
  1991. DestroyWLayout (& pdobj->wlayoutBreak [ind]);
  1992. /* Copy input layout to pdobj */
  1993. pdobj->wlayoutBreak [ind] = *pwlayout;
  1994. pdobj->wbreaktype [ind] = wbreaktypeInside;
  1995. /* Invalidate input layout */
  1996. InvalidateWLayout (pwlayout);
  1997. }
  1998. /* S A V E B R E A K A F T E R */
  1999. /*----------------------------------------------------------------------------
  2000. %%Function: SaveBreakAfter
  2001. %%Contact: antons
  2002. Changes break information so it says "After current layout"
  2003. ----------------------------------------------------------------------------*/
  2004. static void SaveBreakAfterWarichu (
  2005. PDOBJ pdobj, /* (IN): Warichu Dobj */
  2006. BRKKIND brkkind ) /* (IN): Kind of break happened */
  2007. {
  2008. int ind = GetBreakRecordIndex (brkkind);
  2009. /* Destroy previously saved layout */
  2010. DestroyWLayout (& pdobj->wlayoutBreak [ind]);
  2011. pdobj->wbreaktype [ind] = wbreaktypeAfter;
  2012. }
  2013. /* F I N D P R E V B R E A K W A R I C H U D O B J */
  2014. /*----------------------------------------------------------------------------
  2015. %%Function: FindPrevBreakWarichuDobj
  2016. %%Contact: antons
  2017. Important: This procedure has a twin "FindNextBreakWarichuDobj". Any
  2018. change here may require adjusting of the code in another procedure
  2019. as well.
  2020. ----------------------------------------------------------------------------*/
  2021. static LSERR FindPrevBreakWarichuDobj (
  2022. PDOBJ pdobj,
  2023. LSCP cpTruncate,
  2024. long urColumnMax, /* Only for optimization from Truncate */
  2025. BOOL * pfSuccessful,
  2026. BOOL * pfNextAfterColumnMax, /* (OUT): TRUE if we know that next break is
  2027. after urColumnMax for sure */
  2028. LSCP * pcpBreak,
  2029. OBJDIM * pobjdimBreak,
  2030. WLAYOUT * pwlayout ) /* (OUT): Layout of broken Warichu */
  2031. {
  2032. LSERR lserr;
  2033. LSCP cpJisRangeFirst, cpJisRangeLim;
  2034. BOOL fJisRangeEmpty;
  2035. InvalidateWLayout (pwlayout); /* Unsuccessful & error */
  2036. lserr = CalcJisRange (pdobj, &fJisRangeEmpty, &cpJisRangeFirst, &cpJisRangeLim);
  2037. if (lserr != lserrNone) return lserr;
  2038. if (fJisRangeEmpty || (cpTruncate < cpJisRangeFirst))
  2039. {
  2040. * pfSuccessful = FALSE;
  2041. return lserrNone;
  2042. }
  2043. else
  2044. {
  2045. LSCP cpBreak = cpTruncate+1;
  2046. * pfNextAfterColumnMax = FALSE;
  2047. /* REVIEW (antons): Is not it dangerous start from cpJisLim-1 ? */
  2048. /* Snap to the end of Jis region */
  2049. if (cpBreak > cpJisRangeLim) cpBreak = cpJisRangeLim;
  2050. for (;;)
  2051. {
  2052. TRYBREAKWARICHU trybreakwarichuKind;
  2053. BOOL fSuccessful;
  2054. OBJDIM objdim;
  2055. lserr = WaFindPrevBreakSubline ( pdobj->wwhole.plssubl, cpBreak-1, LONG_MAX,
  2056. & fSuccessful, & cpBreak, & objdim );
  2057. if (lserr != lserrNone) return lserr;
  2058. if (! fSuccessful || cpBreak < cpJisRangeFirst)
  2059. {
  2060. Assert (fSuccessful); /* Catch against crazy objects inside Warichu, can continue */
  2061. * pfSuccessful = FALSE;
  2062. return lserrNone;
  2063. };
  2064. Assert (cpBreak < cpJisRangeLim);
  2065. lserr = TryBreakWarichuAtCp (pdobj, cpBreak, objdim.dur,
  2066. urColumnMax, & trybreakwarichuKind, pwlayout );
  2067. if (lserr != lserrNone) return lserr;
  2068. if (trybreakwarichuKind== trybreakwarichuSuccessful)
  2069. {
  2070. /* Found Warichu Break */
  2071. * pcpBreak = GetCpLimOfWLayout (pdobj, pwlayout);
  2072. * pfSuccessful = TRUE;
  2073. * pobjdimBreak = pwlayout->wdim.objdimAll;
  2074. return lserr;
  2075. };
  2076. Assert (trybreakwarichuKind == trybreakwarichuExceedMargin ||
  2077. trybreakwarichuKind == trybreakwarichuCanNotFinishAtCp);
  2078. if (trybreakwarichuKind == trybreakwarichuExceedMargin)
  2079. {
  2080. /* Could not break because or Exceeding RM */
  2081. * pfNextAfterColumnMax = TRUE;
  2082. };
  2083. /* Continue loop */
  2084. };
  2085. };
  2086. /* Unreachable code */
  2087. }
  2088. /* F I N D N E X T B R E A K W A R I C H U D O B J */
  2089. /*----------------------------------------------------------------------------
  2090. %%Function: FindNextBreakWarichuDobj
  2091. %%Contact: antons
  2092. Important: This procedure has a twin "FindNextBreakWarichuDobj". Any
  2093. change here may require adjusting of the code in another procedure
  2094. as well.
  2095. ----------------------------------------------------------------------------*/
  2096. static LSERR FindNextBreakWarichuDobj (
  2097. PDOBJ pdobj,
  2098. LSCP cpTruncate,
  2099. BOOL * pfSuccessful,
  2100. LSCP * pcpBreak,
  2101. OBJDIM * pobjdimBreak,
  2102. WLAYOUT * pwlayout ) /* (OUT): Layout of broken Warichu */
  2103. {
  2104. LSERR lserr;
  2105. LSCP cpJisRangeFirst, cpJisRangeLim;
  2106. BOOL fJisRangeEmpty;
  2107. InvalidateWLayout (pwlayout); /* Unsuccessful & error */
  2108. lserr = CalcJisRange (pdobj, &fJisRangeEmpty, &cpJisRangeFirst, &cpJisRangeLim);
  2109. if (lserr != lserrNone) return lserr;
  2110. if (fJisRangeEmpty || (cpTruncate >= cpJisRangeLim-1))
  2111. {
  2112. * pfSuccessful = FALSE;
  2113. return lserrNone;
  2114. }
  2115. else
  2116. {
  2117. LSCP cpBreak = cpTruncate;
  2118. /* REVIEW (antons): Is not it dangerous start from cpJisLim-1 ? */
  2119. if (cpBreak < cpJisRangeFirst) cpBreak = cpJisRangeFirst-1; /* snap to the end of Jis region */
  2120. for (;;)
  2121. {
  2122. TRYBREAKWARICHU trybreakwarichuKind;
  2123. BOOL fSuccessful;
  2124. OBJDIM objdim;
  2125. lserr = WaFindNextBreakSubline ( pdobj->wwhole.plssubl, cpBreak, LONG_MAX,
  2126. & fSuccessful, & cpBreak, & objdim );
  2127. if (lserr != lserrNone) return lserr;
  2128. if (! fSuccessful || cpBreak >= cpJisRangeLim)
  2129. {
  2130. Assert (fSuccessful); /* Catch against crazy objects inside Warichu, can continue */
  2131. * pfSuccessful = FALSE;
  2132. return lserrNone;
  2133. };
  2134. Assert (cpBreak >= cpJisRangeFirst);
  2135. lserr = TryBreakWarichuAtCp (pdobj, cpBreak, objdim.dur,
  2136. LONG_MAX, & trybreakwarichuKind, pwlayout );
  2137. if (lserr != lserrNone) return lserr;
  2138. if (trybreakwarichuKind == trybreakwarichuSuccessful)
  2139. {
  2140. /* Found Warichu Break */
  2141. * pcpBreak = GetCpLimOfWLayout (pdobj, pwlayout);
  2142. * pfSuccessful = TRUE;
  2143. * pobjdimBreak = pwlayout->wdim.objdimAll;
  2144. return lserrNone;
  2145. };
  2146. Assert (trybreakwarichuKind == trybreakwarichuExceedMargin ||
  2147. trybreakwarichuKind == trybreakwarichuCanNotFinishAtCp);
  2148. /* Continue loop */
  2149. };
  2150. };
  2151. /* Unreachable code */
  2152. }
  2153. /* W A T R U N C A T E P R E V F O R C E */
  2154. /*----------------------------------------------------------------------------
  2155. %%Function: WaTruncatePrevForce
  2156. %%Contact: antons
  2157. ----------------------------------------------------------------------------*/
  2158. static LSERR WaTruncatePrevForce (
  2159. PLSSUBL plssubl,
  2160. long urColumnMax,
  2161. BRKKIND * pbrkkind, /* (OUT): Kind of break: Prev or Force */
  2162. LSCP * pcpBreak,
  2163. BRKPOS * pbrkpos,
  2164. POBJDIM pobjdimSubline )
  2165. {
  2166. LSERR lserr;
  2167. BOOL fSuccessful;
  2168. LSCP cpTruncate;
  2169. lserr = LsTruncateSubline (plssubl, urColumnMax, &cpTruncate);
  2170. if (lserr != lserrNone) return lserr;
  2171. lserr = WaFindPrevBreakSubline ( plssubl, cpTruncate, urColumnMax,
  2172. & fSuccessful, pcpBreak, pobjdimSubline );
  2173. if (lserr != lserrNone) return lserr;
  2174. if (fSuccessful)
  2175. {
  2176. * pbrkkind = brkkindPrev;
  2177. * pbrkpos = brkposInside; /* REVIEW (antons) */
  2178. }
  2179. else
  2180. {
  2181. lserr = WaForceBreakSubline ( plssubl, cpTruncate, urColumnMax,
  2182. pcpBreak, pbrkpos, pobjdimSubline );
  2183. if (lserr != lserrNone) return lserr;
  2184. Assert (* pbrkpos != brkposBeforeFirstDnode); /* REVIEW (antons): Check with Igor */
  2185. * pbrkkind = brkkindForce;
  2186. * pbrkpos = * pbrkpos;
  2187. };
  2188. return lserrNone;
  2189. }
  2190. /* F O R C E B R E A K W A R I C H U C O R E */
  2191. /*----------------------------------------------------------------------------
  2192. %%Function: ForceBreakWarichuDobjCore
  2193. %%Contact: antons
  2194. ----------------------------------------------------------------------------*/
  2195. static LSERR ForceBreakWarichuDobjCore (
  2196. PDOBJ pdobj,
  2197. long urColumnMax,
  2198. BOOL fBrokenWarichu, /* (IN): Which Warichu to produce: broken or not */
  2199. BOOL fLeaveSpaceForCloseBrace,
  2200. BOOL * pfSuccessful,
  2201. LSCP * pcpBreak,
  2202. OBJDIM * pobjdimBreak,
  2203. WLAYOUT * pwlayout ) /* (OUT): Layout of broken Warichu */
  2204. {
  2205. LSERR lserr;
  2206. long durOpen, durClose;
  2207. BOOL fBraceOpen, fBraceClose;
  2208. long durAvailable;
  2209. BOOL fFinished;
  2210. BRKPOS brkpos;
  2211. LSCP cpBreak;
  2212. BRKKIND brkkind;
  2213. OBJDIM objdimBreak;
  2214. WBRKARRAY wbrkarrayAtFirstEnd;
  2215. InvalidateWLayout (pwlayout); /* error and unsuccessful */
  2216. /* REVIEW (antons): HACK HACK HACK */
  2217. if (! fLeaveSpaceForCloseBrace)
  2218. {
  2219. GetDurBraces (pdobj, fBrokenWarichu, &fBraceOpen, &durOpen, &fBraceClose, &durClose);
  2220. durAvailable = urColumnMax - durOpen - durClose;
  2221. }
  2222. else
  2223. {
  2224. GetDurBraces (pdobj, FALSE, &fBraceOpen, &durOpen, &fBraceClose, &durClose);
  2225. durAvailable = urColumnMax - durOpen - durClose;
  2226. };
  2227. if (durAvailable <= 0)
  2228. {
  2229. if (! fBrokenWarichu)
  2230. {
  2231. * pfSuccessful = FALSE;
  2232. return lserrNone;
  2233. }
  2234. else
  2235. {
  2236. durAvailable = 0;
  2237. }
  2238. };
  2239. lserr = FormatWSublineUntilRM (pdobj, pdobj->wwhole.cpFirst, durAvailable,
  2240. &pdobj->wbrkarrayAtStart, &fFinished,
  2241. &pwlayout->wsubline1);
  2242. if (lserr != lserrNone) return lserr;
  2243. if (fFinished && pwlayout->wsubline1.objdim.dur <= durAvailable)
  2244. {
  2245. /* REVIEW (antons): Im I right that this assert shows possible error in
  2246. breaking inside Warichu? */
  2247. AssertSz (FALSE, "This should not happen in real life, but we handle it");
  2248. Assert (! fBrokenWarichu); /* REVIEW (antons) */
  2249. lserr = FinishWLayoutSingleLine (pdobj, pwlayout);
  2250. if (lserr != lserrNone) { DestroyWLayout (pwlayout); return lserr;};
  2251. * pfSuccessful = TRUE;
  2252. * pcpBreak = GetCpLimOfWLayout (pdobj, pwlayout);
  2253. * pobjdimBreak = pwlayout->wdim.objdimAll;
  2254. return lserrNone;
  2255. };
  2256. /* Break first subline at durAvailable */
  2257. lserr = WaTruncatePrevForce ( pwlayout->wsubline1.plssubl,
  2258. durAvailable,
  2259. & brkkind,
  2260. & cpBreak,
  2261. & brkpos,
  2262. & objdimBreak );
  2263. if (lserr != lserrNone) { DestroyWLayout (pwlayout); return lserr;};
  2264. lserr = NewWBrkArray (pdobj, &wbrkarrayAtFirstEnd);
  2265. if (lserr != lserrNone) { DestroyWLayout (pwlayout); return lserr;};
  2266. lserr = SetBreakWSubline ( & pwlayout->wsubline1, brkkind, cpBreak,
  2267. & objdimBreak, & wbrkarrayAtFirstEnd );
  2268. if (lserr != lserrNone)
  2269. {
  2270. DestroyWBrkArray (pdobj, &wbrkarrayAtFirstEnd);
  2271. DestroyWLayout (pwlayout); return lserr;
  2272. };
  2273. /* Continue to format second line */
  2274. lserr = FormatWSublineUntilRM ( pdobj, cpBreak, durAvailable,
  2275. & wbrkarrayAtFirstEnd, & fFinished,
  2276. & pwlayout->wsubline2 );
  2277. if (lserr != lserrNone)
  2278. {
  2279. DestroyWBrkArray (pdobj, &wbrkarrayAtFirstEnd);
  2280. DestroyWLayout (pwlayout); return lserr;
  2281. };
  2282. DestroyWBrkArray (pdobj, &wbrkarrayAtFirstEnd);
  2283. if (fFinished && pwlayout->wsubline2.objdim.dur <= durAvailable)
  2284. {
  2285. /* Second subline stopped before RM */
  2286. Assert (pdobj->wwhole.fFinished);
  2287. pwlayout->fBroken = FALSE; /* Closing brace can not stand alone */
  2288. pwlayout->brkkind = brkkindImposedAfter; /* in the case of fBroken */
  2289. lserr = FinishObjDimWLayout (pdobj, pwlayout);
  2290. if (lserr != lserrNone) { DestroyWLayout (pwlayout); return lserr;};
  2291. * pfSuccessful = TRUE;
  2292. * pcpBreak = GetCpLimOfWLayout (pdobj, pwlayout);
  2293. * pobjdimBreak = pwlayout->wdim.objdimAll;
  2294. return lserrNone;
  2295. };
  2296. /* Break at the end of second line... */
  2297. lserr = WaTruncatePrevForce ( pwlayout->wsubline2.plssubl,
  2298. durAvailable,
  2299. & brkkind,
  2300. & cpBreak,
  2301. & brkpos,
  2302. & objdimBreak );
  2303. if (lserr != lserrNone) { DestroyWLayout (pwlayout); return lserr;};
  2304. if (brkpos == brkposAfterLastDnode)
  2305. {
  2306. /* Second subline broken "After" */
  2307. Assert (pdobj->wwhole.fFinished);
  2308. pwlayout->fBroken = FALSE; /* Closing brace can not stand alone */
  2309. pwlayout->brkkind = brkkind; /* in the case of fBroken */
  2310. lserr = FinishObjDimWLayout (pdobj, pwlayout);
  2311. if (lserr != lserrNone) { DestroyWLayout (pwlayout); return lserr;};
  2312. * pfSuccessful = TRUE;
  2313. * pcpBreak = GetCpLimOfWLayout (pdobj, pwlayout);
  2314. * pobjdimBreak = pwlayout->wdim.objdimAll;
  2315. return lserrNone;
  2316. };
  2317. if (fBrokenWarichu)
  2318. {
  2319. /* REVIEW (antons) */
  2320. /* Our cheating to postpone SetBreakSubline until WarichuSetBreak */
  2321. pwlayout->wsubline2.cpLim = cpBreak;
  2322. pwlayout->wsubline2.objdim = objdimBreak;
  2323. pwlayout->brkkind = brkkind;
  2324. pwlayout->fBroken = TRUE;
  2325. lserr = FinishObjDimWLayout (pdobj, pwlayout);
  2326. if (lserr != lserrNone) { DestroyWLayout (pwlayout); return lserr;};
  2327. * pfSuccessful = TRUE;
  2328. * pcpBreak = GetCpLimOfWLayout (pdobj, pwlayout);
  2329. * pobjdimBreak = pwlayout->wdim.objdimAll;
  2330. return lserrNone;
  2331. }
  2332. else
  2333. {
  2334. /* Have to return Unsuccessful */
  2335. * pfSuccessful = FALSE;
  2336. lserr = DestroyWLayout (pwlayout); /* Not to loose memory */
  2337. return lserrNone;
  2338. }
  2339. }
  2340. /* F O R C E B R E A K W A R I C H U D O B J */
  2341. /*----------------------------------------------------------------------------
  2342. %%Function: ForceBreakWarichuDobj
  2343. %%Contact: antons
  2344. ----------------------------------------------------------------------------*/
  2345. static LSERR ForceBreakWarichuDobj (
  2346. PDOBJ pdobj,
  2347. long urColumnMax,
  2348. BOOL * pfSuccessful,
  2349. LSCP * pcpBreak,
  2350. OBJDIM * pobjdimBreak,
  2351. WLAYOUT * pwlayout )/* (OUT): Layout of broken Warichu */
  2352. {
  2353. LSERR lserr;
  2354. BOOL fSuccessful = FALSE;
  2355. /* 1. TRY FORCE BREAK WITHOUT BREAKING OF WARICHU */
  2356. if (pdobj->wwhole.fFinished)
  2357. {
  2358. /* Without breaking can be only when closing brace fetched */
  2359. lserr = ForceBreakWarichuDobjCore ( pdobj, urColumnMax, FALSE, FALSE, & fSuccessful,
  2360. pcpBreak, pobjdimBreak, pwlayout );
  2361. if (lserr != lserrNone) return lserr;
  2362. };
  2363. if (! fSuccessful)
  2364. {
  2365. /* 2. TRY FORCE BREAK WITH POSSIBLE BREAKING OF WARICHU */
  2366. lserr = ForceBreakWarichuDobjCore ( pdobj, urColumnMax, TRUE, FALSE, & fSuccessful,
  2367. pcpBreak, pobjdimBreak, pwlayout );
  2368. if (lserr != lserrNone) return lserr;
  2369. /* Euristic solution for the case when we exceed RM because we added closing brace */
  2370. if (fSuccessful && pdobj->wwhole.fFinished && urColumnMax < pobjdimBreak->dur)
  2371. {
  2372. lserr = DestroyWLayout (pwlayout);
  2373. if (lserr != lserrNone) return lserr;
  2374. lserr = ForceBreakWarichuDobjCore ( pdobj, urColumnMax, TRUE, TRUE, & fSuccessful,
  2375. pcpBreak, pobjdimBreak, pwlayout );
  2376. if (lserr != lserrNone) return lserr;
  2377. };
  2378. };
  2379. * pfSuccessful = fSuccessful;
  2380. return lserrNone;
  2381. }
  2382. /* T R U N C A T E W A R I C H U D O B J */
  2383. /*----------------------------------------------------------------------------
  2384. %%Function: TruncateWarichuDobj
  2385. %%Contact: antons
  2386. ----------------------------------------------------------------------------*/
  2387. static LSERR TruncateWarichuDobj (
  2388. PDOBJ pdobj, /* (IN): Warichu DOBJ */
  2389. long urColumnMax, /* (IN): ColumnMax to fix warichu before */
  2390. BOOL * pfSuccessful, /* (OUT): Successful? */
  2391. LSCP * pcpBreak, /* (OUT): Cp of broken Warichu if fSuccessful */
  2392. OBJDIM * pobjdimBreak, /* (OUT): Dim of broken Warichu if fSuccessful */
  2393. WLAYOUT * pwlayout ) /* (OUT): Layout of broken Warichu if fSuccessful */
  2394. {
  2395. LSERR lserr;
  2396. long durOpen;
  2397. long durClose;
  2398. BOOL boolUnused1, boolUnused2;
  2399. BOOL fSuccessful;
  2400. BOOL fNextAfterColumnMax;
  2401. LSCP cpBreakCandidate;
  2402. LSCP cpTruncateWhole;
  2403. OBJDIM objdimCandidate;
  2404. ClearWLayout (pwlayout); /* in case of error or ! fSuccessful */
  2405. GetDurBraces (pdobj, TRUE, &boolUnused1, &durOpen, &boolUnused2, &durClose);
  2406. /* REVIEW (antons): Move this check to a separate function */
  2407. if (urColumnMax <= durOpen + durClose)
  2408. {
  2409. /* Optimization: in this case we know for sure there is no break */
  2410. *pfSuccessful = FALSE;
  2411. return lserrNone;
  2412. };
  2413. /* Estimate truncation point in WWHOLE (find cpTruncateWhole) */
  2414. {
  2415. /* We want to estimate truncation point on WWHOLE as 2*(urColumnMax-durOpen-durClose),
  2416. but unfortunately it is not always possible. Here we check if can truncate
  2417. WWHOLE at this urTruncateWhole or, if we can not, take last possible cp in the
  2418. whole subline. Situation depends on whether we finished WWHOLE or not */
  2419. long urTruncateWhole = MULLongSafe (urColumnMax - durOpen - durClose, 2);
  2420. /* REVIEW (antons): Can we optimize if we know durs of JIS range? */
  2421. /* REVIEW (antons): Check all situation when I may come to "else" */
  2422. /* REVIEW (antons): Should the second part (starting with "NOT") ever cause "else"? */
  2423. if ( ( pdobj->wwhole.fFinished && urTruncateWhole < pdobj->wwhole.objdim.dur) ||
  2424. (NOT pdobj->wwhole.fFinished && urTruncateWhole < pdobj->wwhole.urColumnMax ) )
  2425. {
  2426. lserr = LsTruncateSubline (pdobj->wwhole.plssubl, urTruncateWhole,
  2427. & cpTruncateWhole);
  2428. if (lserr != lserrNone) return lserr;
  2429. }
  2430. else if (pdobj->wwhole.fFinished)
  2431. {
  2432. cpTruncateWhole = pdobj->wwhole.cpLim;
  2433. }
  2434. else
  2435. {
  2436. cpTruncateWhole = pdobj->wwhole.cpTruncate;
  2437. };
  2438. }
  2439. /* REVIEW (antos): Here and later in this proc I use pwayout as a candidate for
  2440. truncation. Should I better use local structure? */
  2441. lserr = FindPrevBreakWarichuDobj ( pdobj, cpTruncateWhole, urColumnMax, & fSuccessful,
  2442. & fNextAfterColumnMax, & cpBreakCandidate, & objdimCandidate,
  2443. pwlayout );
  2444. if (lserr != lserrNone) return lserr;
  2445. if (fSuccessful && fNextAfterColumnMax)
  2446. {
  2447. /* Candidate is OK */
  2448. * pfSuccessful = TRUE;
  2449. * pcpBreak = cpBreakCandidate;
  2450. * pobjdimBreak = objdimCandidate;
  2451. return lserrNone;
  2452. };
  2453. if (!fSuccessful)
  2454. {
  2455. /* Prev break Dobj is not found (or beyond RM) => try next break as a candidate */
  2456. lserr = FindNextBreakWarichuDobj ( pdobj, cpTruncateWhole, & fSuccessful,
  2457. & cpBreakCandidate, & objdimCandidate, pwlayout );
  2458. if (lserr != lserrNone) return lserr;
  2459. if (!fSuccessful)
  2460. {
  2461. /* NEXT break is not found */
  2462. * pfSuccessful = FALSE;
  2463. return lserrNone;
  2464. }
  2465. else if (objdimCandidate.dur > urColumnMax)
  2466. {
  2467. /* NEXT break is found but it is beyond RM */
  2468. * pfSuccessful = FALSE;
  2469. lserr = DestroyWLayout (pwlayout);
  2470. return lserr;
  2471. };
  2472. };
  2473. /* At this point we have break candidate: (pwlayout, cpBreakCandidate, objdimCandidate) */
  2474. /* Now we shall go forward to make sure we have last possible break before RM */
  2475. {
  2476. BOOL fContinue;
  2477. Assert (objdimCandidate.dur <= urColumnMax);
  2478. fContinue = TRUE;
  2479. while (fContinue)
  2480. {
  2481. WLAYOUT wlayoutNext;
  2482. OBJDIM objdimNext;
  2483. LSCP cpBreakNext;
  2484. BOOL fSuccessful;
  2485. lserr = FindNextBreakWarichuDobj ( pdobj, cpBreakCandidate, & fSuccessful,
  2486. & cpBreakNext, & objdimNext, &wlayoutNext );
  2487. if (lserr != lserrNone) {DestroyWLayout (pwlayout); return lserr;};
  2488. if (!fSuccessful)
  2489. {
  2490. /* Next not found => Candidate is OK */
  2491. fContinue = FALSE;
  2492. }
  2493. else if (objdimNext.dur > urColumnMax)
  2494. {
  2495. /* Next found, but exceeds RM => Candidate OK */
  2496. /* Destroy wlayoutNext, because we do not need it */
  2497. lserr = DestroyWLayout (&wlayoutNext);
  2498. if (lserr != lserrNone) {DestroyWLayout (pwlayout); return lserr;};
  2499. fContinue = FALSE;
  2500. }
  2501. else
  2502. {
  2503. /* Next found and before RM => Is is a new Candidate */
  2504. /* Destroy layout of the candidate, because we do not need it */
  2505. lserr = DestroyWLayout (pwlayout); /* Destroy old candidate */
  2506. if (lserr != lserrNone) {DestroyWLayout (&wlayoutNext); return lserr;};
  2507. * pwlayout = wlayoutNext;
  2508. cpBreakCandidate = cpBreakNext; /* Next break also before RM */
  2509. objdimCandidate = objdimNext;
  2510. }
  2511. }; /* While (fContinue */
  2512. * pfSuccessful = TRUE;
  2513. * pcpBreak = cpBreakCandidate;
  2514. * pobjdimBreak = objdimCandidate;
  2515. /* pwlayout contains correct candiate layout */
  2516. Assert (pwlayout->wdim.objdimAll.dur == objdimCandidate.dur); /* Sanity check */
  2517. return lserrNone;
  2518. };
  2519. } /* TruncateWarichuDobj */
  2520. /* P U T B R E A K A T W A R I C H U E N D */
  2521. /*----------------------------------------------------------------------------
  2522. %%Function: PutBreakAtWarichuEnd
  2523. %%Contact: antons
  2524. Fill in break output record for the end of the Warichu
  2525. ----------------------------------------------------------------------------*/
  2526. static void PutBreakAtWarichuEnd (
  2527. DWORD ichnk, /* (IN): index in chunk */
  2528. PCLOCCHNK pclocchnk, /* (IN): locchnk to find break */
  2529. PBRKOUT pbrkout) /* (OUT): results of breaking */
  2530. {
  2531. PDOBJ pdobj = pclocchnk->plschnk[ichnk].pdobj;
  2532. pbrkout->fSuccessful = TRUE;
  2533. pbrkout->posichnk.dcp = GetCpLimOfWLayout (pdobj, &pdobj->wlayout) - pdobj->cpStart;
  2534. /* REVIEW (antons) */
  2535. pbrkout->posichnk.ichnk = ichnk;
  2536. pbrkout->objdim = pdobj->wlayout.wdim.objdimAll;
  2537. }
  2538. /* P U T B R E A K A T W A R I C H U B E G I N */
  2539. /*----------------------------------------------------------------------------
  2540. %%Function: PutBreakAtWarichuBegin
  2541. %%Contact: antons
  2542. Fill in break output record for break before Warichu.
  2543. ----------------------------------------------------------------------------*/
  2544. static void PutBreakAtWarichuBegin (
  2545. DWORD ichnk, /* (IN): index in chunk */
  2546. PCLOCCHNK pclocchnk, /* (IN): locchnk to find break */
  2547. PBRKOUT pbrkout ) /* (OUT): results of breaking */
  2548. {
  2549. Unreferenced (pclocchnk);
  2550. pbrkout->fSuccessful = TRUE;
  2551. pbrkout->posichnk.dcp = 0;
  2552. pbrkout->posichnk.ichnk = ichnk;
  2553. ZeroObjDim (&pbrkout->objdim);
  2554. }
  2555. /* P U T B R E A K W A R I C H U U N S U C C E S S F U L */
  2556. /*----------------------------------------------------------------------------
  2557. %%Function: PutBreakWarichuUnsuccessful
  2558. %%Contact: antons
  2559. ----------------------------------------------------------------------------*/
  2560. static void PutBreakWarichuUnsuccessful (PBRKOUT pbrkout)
  2561. {
  2562. pbrkout->fSuccessful = FALSE;
  2563. pbrkout->brkcond = brkcondPlease;
  2564. /* Hack to fix crash before we eliminate posichnkBeforeTrailing */
  2565. }
  2566. /* P U T B R E A K W A R I C H U D O B J */
  2567. /*----------------------------------------------------------------------------
  2568. %%Function: PutBreakWarichuDobj
  2569. %%Contact: antons
  2570. ----------------------------------------------------------------------------*/
  2571. static void PutBreakAtWarichuDobj (
  2572. DWORD ichnk,
  2573. PCLOCCHNK pclocchnk,
  2574. LSCP cpBreak,
  2575. OBJDIM *pobjdimBreak,
  2576. PBRKOUT pbrkout)
  2577. {
  2578. PDOBJ pdobj = pclocchnk->plschnk[ichnk].pdobj;
  2579. pbrkout->fSuccessful = TRUE;
  2580. pbrkout->posichnk.dcp = cpBreak - pdobj->cpStart;
  2581. pbrkout->posichnk.ichnk = ichnk;
  2582. pbrkout->objdim = *pobjdimBreak;
  2583. Assert (pbrkout->posichnk.dcp > 0);
  2584. }
  2585. /* W A R I C H U T R U N C A T E C H U N K */
  2586. /*----------------------------------------------------------------------------
  2587. %%Function: WarichuTruncateChunk
  2588. %%Contact: antons
  2589. ----------------------------------------------------------------------------*/
  2590. LSERR WINAPI WarichuTruncateChunk (PCLOCCHNK plocchnk, PPOSICHNK pposichnk)
  2591. {
  2592. LSERR lserr;
  2593. long urColumnMax = plocchnk->lsfgi.urColumnMax;
  2594. DWORD ichnk = 0;
  2595. BOOL fFound = FALSE;
  2596. /* Find object containing RM */
  2597. while (!fFound)
  2598. {
  2599. Assert (ichnk < plocchnk->clschnk);
  2600. Assert (plocchnk->ppointUvLoc[ichnk].u <= urColumnMax);
  2601. fFound = plocchnk->ppointUvLoc[ichnk].u +
  2602. plocchnk->plschnk[ichnk].pdobj->wlayout.wdim.objdimAll.dur > urColumnMax;
  2603. if (!fFound) ichnk++;
  2604. };
  2605. Assert (ichnk < plocchnk->clschnk);
  2606. /* Element ichnk contains RM, try to prev break it to find correct tr point */
  2607. {
  2608. LSCP cpBreak;
  2609. BOOL fSuccessful;
  2610. OBJDIM objdimBreak;
  2611. WLAYOUT wlayoutBreak;
  2612. PDOBJ pdobj = plocchnk->plschnk[ichnk].pdobj;
  2613. lserr = TruncateWarichuDobj ( pdobj,
  2614. urColumnMax - plocchnk->ppointUvLoc[ichnk].u,
  2615. & fSuccessful,
  2616. & cpBreak,
  2617. & objdimBreak,
  2618. & wlayoutBreak );
  2619. if (lserr != lserrNone) return lserr;
  2620. ReformatClosingBraceForWord9 (pdobj);
  2621. if (fSuccessful) /* Found break before RM */
  2622. {
  2623. /* REVIEW (antons): Move this before call to TruncateWarichuDobj */
  2624. lserr = DestroyWLayout (&pdobj->wlayoutTruncate);
  2625. if (lserr != lserrNone) return lserr;
  2626. pdobj->wlayoutTruncate = wlayoutBreak;
  2627. pposichnk->ichnk = ichnk;
  2628. pposichnk->dcp = cpBreak - pdobj->cpStart + 1; /* +1 because dcp is always lim */
  2629. return lserrNone;
  2630. }
  2631. else
  2632. {
  2633. /* Break before RM not found => dcpTruncate := 1 */
  2634. pposichnk->ichnk = ichnk;
  2635. pposichnk->dcp = 1;
  2636. return lserrNone;
  2637. };
  2638. };
  2639. }
  2640. /* W A R I C H U F I N D P R E V B R E A K C H U N K */
  2641. /*----------------------------------------------------------------------------
  2642. %%Function: WarichuFindPrevBreakChunk
  2643. %%Contact: antons
  2644. Important: This procedure is similar to "WarichuFindPrevBreakChunk".
  2645. Any change here may require to change another procedure as well.
  2646. ----------------------------------------------------------------------------*/
  2647. LSERR WINAPI WarichuFindPrevBreakChunk (
  2648. PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
  2649. PCPOSICHNK pcpoischnk, /* (IN): place to start looking for break */
  2650. BRKCOND brkcond, /* (IN): recommmendation about the break after chunk */
  2651. PBRKOUT pbrkout) /* (OUT): results of breaking */
  2652. {
  2653. LSERR lserr;
  2654. PDOBJ pdobj;
  2655. WLAYOUT wlayoutBreak;
  2656. BOOL fSuccessful;
  2657. LSCP cpBreak;
  2658. LSCP cpTruncate;
  2659. OBJDIM objdimBreak;
  2660. BOOL fNextBeforeColumnMaxUnused;
  2661. POSICHNK posichnk = *pcpoischnk; /* position to start looking for break */
  2662. if (posichnk.ichnk == ichnkOutside)
  2663. {
  2664. if (brkcond != brkcondNever)
  2665. {
  2666. /* Can break after chunk */
  2667. pdobj = pclocchnk->plschnk [pclocchnk->clschnk - 1].pdobj;
  2668. SaveBreakAfterWarichu (pdobj, brkkindPrev);
  2669. PutBreakAtWarichuEnd (pclocchnk->clschnk - 1, pclocchnk, pbrkout);
  2670. return lserrNone;
  2671. }
  2672. else
  2673. {
  2674. /* Can not break after chunk, will try to break last Warichu */
  2675. PDOBJ pdobj = pclocchnk->plschnk[pclocchnk->clschnk - 1].pdobj;
  2676. posichnk.ichnk = pclocchnk->clschnk - 1;
  2677. posichnk.dcp = GetCpLimOfWLayout (pdobj, &pdobj->wlayout) - pdobj->cpStart;
  2678. };
  2679. };
  2680. /* Call routing which breaks Warichu */
  2681. pdobj = pclocchnk->plschnk[posichnk.ichnk].pdobj;
  2682. cpTruncate = pdobj->cpStart + posichnk.dcp - 1;
  2683. if (FWLayoutValid (&pdobj->wlayoutTruncate) &&
  2684. cpTruncate == GetCpLimOfWLayout (pdobj, &pdobj->wlayoutTruncate))
  2685. {
  2686. /* Optimization: we can take WLayout saved during Truncation */
  2687. PutBreakAtWarichuDobj (posichnk.ichnk, pclocchnk, cpTruncate,
  2688. & pdobj->wlayoutTruncate.wdim.objdimAll, pbrkout);
  2689. SaveBreakInsideWarichu (pdobj, brkkindPrev, &pdobj->wlayoutTruncate);
  2690. ClearWLayout (&pdobj->wlayoutTruncate);
  2691. return lserrNone;
  2692. }
  2693. lserr = FindPrevBreakWarichuDobj ( pdobj, cpTruncate,
  2694. LONG_MAX, & fSuccessful, & fNextBeforeColumnMaxUnused,
  2695. & cpBreak, & objdimBreak, & wlayoutBreak );
  2696. if (lserr != lserrNone) return lserr;
  2697. ReformatClosingBraceForWord9 (pdobj);
  2698. /* Check result */
  2699. if (fSuccessful)
  2700. {
  2701. /* Successful => Break inside Watichu */
  2702. Assert (cpBreak <= pdobj->cpStart + (long)posichnk.dcp - 1); /* Monotinous axiom */
  2703. SaveBreakInsideWarichu (pdobj, brkkindPrev, &wlayoutBreak);
  2704. PutBreakAtWarichuDobj (posichnk.ichnk, pclocchnk, cpBreak, &objdimBreak, pbrkout);
  2705. }
  2706. else if (posichnk.ichnk > 0)
  2707. {
  2708. /* Can break between Warichus */
  2709. pdobj = pclocchnk->plschnk [posichnk.ichnk-1].pdobj;
  2710. SaveBreakAfterWarichu (pdobj, brkkindPrev);
  2711. PutBreakAtWarichuEnd (posichnk.ichnk-1, pclocchnk, pbrkout);
  2712. }
  2713. else
  2714. {
  2715. /* Unsuccessful */
  2716. PutBreakWarichuUnsuccessful (pbrkout);
  2717. };
  2718. return lserrNone;
  2719. }
  2720. /* W A R I C H U F I N D N E X T B R E A K C H U N K */
  2721. /*----------------------------------------------------------------------------
  2722. %%Function: WarichuFindNextBreakChunk
  2723. %%Contact: antons
  2724. Important: This procedure is similar to "WarichuFindNextBreakChunk".
  2725. Any change here may require to change another procedure as well.
  2726. ----------------------------------------------------------------------------*/
  2727. LSERR WINAPI WarichuFindNextBreakChunk (
  2728. PCLOCCHNK pclocchnk, /* (IN): locchnk to break */
  2729. PCPOSICHNK pcpoischnk, /* (IN): place to start looking for break */
  2730. BRKCOND brkcond, /* (IN): recommendation about the break before chunk */
  2731. PBRKOUT pbrkout) /* (OUT): results of breaking */
  2732. {
  2733. LSERR lserr;
  2734. PDOBJ pdobj;
  2735. WLAYOUT wlayoutBreak;
  2736. BOOL fSuccessful;
  2737. LSCP cpBreak;
  2738. OBJDIM objdimBreak;
  2739. POSICHNK posichnk = *pcpoischnk; /* position to start looking for break */
  2740. if (posichnk.ichnk == ichnkOutside)
  2741. {
  2742. if (brkcond != brkcondNever)
  2743. {
  2744. /* Can break before chunk */
  2745. PutBreakAtWarichuBegin (0, pclocchnk, pbrkout);
  2746. return lserrNone;
  2747. }
  2748. else
  2749. {
  2750. /* Can not break before chunk, will try to break first Warichu */
  2751. posichnk.ichnk = 0;
  2752. posichnk.dcp = 1; /* REVIEW (antons): Check this dcp assigment */
  2753. };
  2754. };
  2755. /* Call routing which breaks Warichu */
  2756. pdobj = pclocchnk->plschnk[posichnk.ichnk].pdobj;
  2757. lserr = FindNextBreakWarichuDobj ( pdobj, pdobj->cpStart + posichnk.dcp - 1,
  2758. & fSuccessful, & cpBreak,
  2759. & objdimBreak, & wlayoutBreak );
  2760. if (lserr != lserrNone) return lserr;
  2761. ReformatClosingBraceForWord9 (pdobj);
  2762. /* Check result */
  2763. if (fSuccessful)
  2764. {
  2765. /* Break inside Watichu */
  2766. Assert (cpBreak > pdobj->cpStart + (long)posichnk.dcp - 1); /* Monotinous axiom */
  2767. SaveBreakInsideWarichu (pdobj, brkkindNext, &wlayoutBreak);
  2768. PutBreakAtWarichuDobj (posichnk.ichnk, pclocchnk, cpBreak, &objdimBreak, pbrkout);
  2769. }
  2770. else if (posichnk.ichnk < (long)pclocchnk->clschnk - 1)
  2771. {
  2772. /* Can break between Warichus */
  2773. pdobj = pclocchnk->plschnk [posichnk.ichnk].pdobj;
  2774. SaveBreakAfterWarichu (pdobj, brkkindNext);
  2775. PutBreakAtWarichuEnd (posichnk.ichnk, pclocchnk, pbrkout);
  2776. }
  2777. else
  2778. {
  2779. /* Unsuccessful */
  2780. pbrkout->objdim = pclocchnk->plschnk[pclocchnk->clschnk - 1].pdobj->wlayout.wdim.objdimAll;
  2781. SaveBreakAfterWarichu (pdobj, brkkindNext);
  2782. PutBreakWarichuUnsuccessful (pbrkout);
  2783. };
  2784. return lserrNone;
  2785. }
  2786. /* W A R I C H U F O R C E B R E A K C H U N K */
  2787. /*----------------------------------------------------------------------------
  2788. %%Function: WarichuForceBreakChunk
  2789. %%Contact: antons
  2790. ----------------------------------------------------------------------------*/
  2791. LSERR WINAPI WarichuForceBreakChunk (
  2792. PCLOCCHNK pclocchnk, /* (IN): Locchnk to break */
  2793. PCPOSICHNK pcposichnk, /* (IN): Place to start looking for break */
  2794. PBRKOUT pbrkout) /* (OUT): Results of breaking */
  2795. {
  2796. /* This procedure must be called with same arguments passed to Truncation.
  2797. If this is violated, Warichu may appear beyond RM */
  2798. /* REVIEW (antons): Should I assert agains violations? */
  2799. LSERR lserr;
  2800. BOOL fSuccessful;
  2801. LSCP cpBreak;
  2802. OBJDIM objdimBreak;
  2803. WLAYOUT wlayoutBreak;
  2804. DWORD ichnk = pcposichnk->ichnk;
  2805. PDOBJ pdobj;
  2806. if (ichnk == ichnkOutside) ichnk = 0; /* When left indent is bigger then RM */
  2807. Assert (ichnk != ichnkOutside);
  2808. if (ichnk > 0)
  2809. {
  2810. /* Can break after previous Warichu */
  2811. pdobj = pclocchnk->plschnk [ichnk-1].pdobj;
  2812. SaveBreakAfterWarichu (pdobj, brkkindForce);
  2813. PutBreakAtWarichuEnd (ichnk-1, pclocchnk, pbrkout);
  2814. }
  2815. else if (!pclocchnk->lsfgi.fFirstOnLine)
  2816. {
  2817. /* Can break before first chunk element, because !fFirstOnLine */
  2818. Assert (ichnk == 0);
  2819. PutBreakAtWarichuBegin (0, pclocchnk, pbrkout);
  2820. }
  2821. else
  2822. {
  2823. /* We are the only on the line */
  2824. /* REVIEW (antons): Check it and if this is correct make same changes in ROBJ etc. */
  2825. long urAvailable = pclocchnk->lsfgi.urColumnMax -
  2826. pclocchnk->ppointUvLoc [ichnk].u;
  2827. pdobj = pclocchnk->plschnk [ichnk].pdobj;
  2828. /* Try to force break Warichi */
  2829. lserr = ForceBreakWarichuDobj ( pdobj, urAvailable, & fSuccessful,
  2830. & cpBreak, & objdimBreak, &wlayoutBreak );
  2831. if (lserr != lserrNone) return lserr;
  2832. ReformatClosingBraceForWord9 (pdobj);
  2833. if (fSuccessful)
  2834. {
  2835. /* Yes, we can force break Warichu */
  2836. Assert (cpBreak > pdobj->cpStart);
  2837. SaveBreakInsideWarichu (pdobj, brkkindForce, &wlayoutBreak);
  2838. PutBreakAtWarichuDobj ( ichnk, pclocchnk, cpBreak,
  2839. &objdimBreak, pbrkout);
  2840. }
  2841. else
  2842. {
  2843. /* Nothing to do... have to break "after" and go beyond RM */
  2844. pdobj = pclocchnk->plschnk [ichnk].pdobj;
  2845. SaveBreakAfterWarichu (pdobj, brkkindForce);
  2846. PutBreakAtWarichuEnd (ichnk, pclocchnk, pbrkout);
  2847. }
  2848. };
  2849. Assert (pbrkout->fSuccessful); /* Force break always successful */
  2850. return lserrNone;
  2851. }
  2852. /* W A R I C H U S E T B R E A K */
  2853. /*----------------------------------------------------------------------------
  2854. %%Function: WarichuSetBreak
  2855. %%Contact: antons
  2856. --------------------------------------------------------------------------*/
  2857. LSERR WINAPI WarichuSetBreak (
  2858. PDOBJ pdobj, /* (IN): Dobj which is broken */
  2859. BRKKIND brkkind, /* (IN): Kind of break */
  2860. DWORD cBreakRecord, /* (IN): Size of array */
  2861. BREAKREC *rgBreakRecord, /* (IN): Array of break records */
  2862. DWORD *pcActualBreakRecord) /* (IN): Actual number of used elements in array */
  2863. {
  2864. LSERR lserr;
  2865. /* REVIEW (antons): Should we destroy formatting layout forever? */
  2866. /* REVIEW (antons): Should we release info about other previous breaks? */
  2867. if (brkkind == brkkindImposedAfter)
  2868. {
  2869. /* Looks like we are doing nothing */
  2870. *pcActualBreakRecord = 0; /* Break after Warichu, so it is terminate */
  2871. return lserrNone;
  2872. }
  2873. else
  2874. {
  2875. /* Prev | Next | Force */
  2876. int ind = GetBreakRecordIndex (brkkind);
  2877. WLAYOUT * pwlayout = & pdobj->wlayout;
  2878. if (pdobj->wbreaktype [ind] == wbreaktypeAfter)
  2879. {
  2880. /* Break was after Warichu */
  2881. *pcActualBreakRecord = 0;
  2882. return lserrNone;
  2883. };
  2884. /* This Assert actually means != wbreaktypeInvalid */
  2885. Assert (pdobj->wbreaktype [ind] == wbreaktypeInside);
  2886. if (cBreakRecord < 1) return lserrInsufficientBreakRecBuffer;
  2887. Assert (cBreakRecord >= 1); /* Broken warichu is not terminate ;-) */
  2888. /* REVIEW (antons): Find better way to check correctess of break data */
  2889. Assert (pdobj->wlayoutBreak [ind].wsubline1.plssubl != NULL);
  2890. lserr = DestroyWLayout (&pdobj->wlayout);
  2891. if (lserr != lserrNone) return lserr;
  2892. * pwlayout = pdobj->wlayoutBreak [ind]; /* Copy break wlayout to current */
  2893. ClearWLayout (&pdobj->wlayoutBreak [ind]);
  2894. /* REVIEW (antons): is there any other exceptions? */
  2895. Assert (brkkind == brkkindForce || pwlayout->fBroken);
  2896. Assert (pwlayout->wsubline2.plssubl != NULL);
  2897. /* Have to set break at the end of second line */
  2898. /* REVIEW (antons): ? Assert against incorrect dimensions? */
  2899. lserr = LsSetBreakSubline ( pwlayout->wsubline2.plssubl,
  2900. pwlayout->brkkind,
  2901. cBreakRecord - 1,
  2902. & rgBreakRecord [1],
  2903. pcActualBreakRecord );
  2904. if (lserr != lserrNone) return lserr;
  2905. lserr = SubmitWLayoutSublines (pdobj, pwlayout);
  2906. if (lserr != lserrNone) return lserr;
  2907. rgBreakRecord [0].idobj = pdobj->pilsobj->idobj;
  2908. rgBreakRecord [0].cpFirst = pdobj->cpStartObj; /* REVIEW (antons) */
  2909. (*pcActualBreakRecord) ++; /* Add 1 for Warichu break record */
  2910. return lserrNone;
  2911. };
  2912. }
  2913. /* W A R I C H U G E T S P E C I A L E F F E C T S I N S I D E */
  2914. /*----------------------------------------------------------------------------
  2915. %%Function: WarichuGetSpecialEffectsInside
  2916. %%Contact: antons
  2917. ----------------------------------------------------------------------------*/
  2918. LSERR WINAPI WarichuGetSpecialEffectsInside (PDOBJ pdobj, UINT *pEffectsFlags)
  2919. {
  2920. LSERR lserr;
  2921. WLAYOUT * pwlayout = & pdobj->wlayout;
  2922. UINT uiOpen = 0;
  2923. UINT uiClose = 0;
  2924. UINT uiFirst = 0;
  2925. UINT uiSecond = 0;
  2926. if (FOpenBraceInWLayout (pdobj, pwlayout))
  2927. {
  2928. lserr = LsGetSpecialEffectsSubline (pdobj->wbraceOpen.plssubl, &uiOpen);
  2929. if (lserr != lserrNone) return lserr;
  2930. };
  2931. lserr = LsGetSpecialEffectsSubline (pwlayout->wsubline1.plssubl, &uiFirst);
  2932. if (lserr != lserrNone) return lserr;
  2933. if (pwlayout->wsubline2.plssubl != NULL)
  2934. {
  2935. lserr = LsGetSpecialEffectsSubline (pwlayout->wsubline2.plssubl, &uiSecond);
  2936. if (lserr != lserrNone) return lserr;
  2937. };
  2938. if (FCloseBraceInWLayout (pdobj, pwlayout))
  2939. {
  2940. lserr = LsGetSpecialEffectsSubline (pdobj->wbraceClose.plssubl, &uiClose);
  2941. if (lserr != lserrNone) return lserr;
  2942. };
  2943. *pEffectsFlags = uiOpen | uiClose | uiFirst | uiSecond;
  2944. return lserrNone;
  2945. }
  2946. /* W A R I C H U C A L C P R E S E N T A T I O N */
  2947. /*----------------------------------------------------------------------------
  2948. %%Function: WarichuCalcPresentation
  2949. %%Contact: antons
  2950. ----------------------------------------------------------------------------*/
  2951. LSERR WINAPI WarichuCalcPresentation (PDOBJ pdobj, long dup, LSKJUST lskjust, BOOL fLastVisibleOnLine)
  2952. {
  2953. LSERR lserr;
  2954. WLAYOUT * pwlayout = & pdobj->wlayout;
  2955. WDISPLAY * pwdisplay = & pdobj->wdisplay;
  2956. long dupInside; /* Dup of the longest Warichu subline */
  2957. Unreferenced (fLastVisibleOnLine);
  2958. Unreferenced (lskjust);
  2959. Unreferenced (dup);
  2960. /* REVIEW (antons): The following Assert is agains the rule that object which
  2961. exceeded RM must be broken inside (see formatting code for details) */
  2962. Assert (FWLayoutValid (&pdobj->wlayout));
  2963. /* 1. Prepare both warichu lines for display & store dups in our structures */
  2964. if (pwlayout->wsubline1.objdim.dur >= pwlayout->wsubline2.objdim.dur)
  2965. {
  2966. /* First subline is bigger */
  2967. /* NOTE: THIS PIECE OF CODE (-then-) HAS A TWIN IN (-else-) */
  2968. lserr = WaMatchPresSubline (pwlayout->wsubline1.plssubl, & pwdisplay->wdispsubl1.dup);
  2969. if (lserr != lserrNone) return lserr;
  2970. dupInside = pwdisplay->wdispsubl1.dup; /* Dup of the first subline */
  2971. if (pwlayout->wsubline2.plssubl != NULL)
  2972. {
  2973. /* Second subline is not empty */
  2974. lserr = WaExpandSubline (pwlayout->wsubline2.plssubl,
  2975. lskjFullScaled,
  2976. pwdisplay->wdispsubl1.dup,
  2977. & pwdisplay->wdispsubl2.dup);
  2978. if (lserr != lserrNone) return lserr;
  2979. }
  2980. else
  2981. pwdisplay->wdispsubl2.dup = 0; /* Used in calculation further in this proc */
  2982. }
  2983. else
  2984. {
  2985. /* Second subline is bigger */
  2986. /* NOTE: THIS PIECE OF CODE (-else-) HAS A TWIN IN (-then-) */
  2987. lserr = WaMatchPresSubline (pwlayout->wsubline2.plssubl, & pwdisplay->wdispsubl2.dup);
  2988. if (lserr != lserrNone) return lserr;
  2989. dupInside = pwdisplay->wdispsubl2.dup; /* Dup of the second subline */
  2990. lserr = WaExpandSubline (pwlayout->wsubline1.plssubl,
  2991. lskjFullScaled,
  2992. pwdisplay->wdispsubl2.dup,
  2993. & pwdisplay->wdispsubl1.dup);
  2994. if (lserr != lserrNone) return lserr;
  2995. };
  2996. /* 2. Prepare brackets for display & store dups in our structures */
  2997. /* REVIEW (antons): Rick expanded closing brace if it was not DonePres before... */
  2998. if (FOpenBraceInWLayout(pdobj, pwlayout)) /* Open brace present */
  2999. {
  3000. lserr = WaMatchPresSubline (pdobj->wbraceOpen.plssubl, &pwdisplay->wdispbraceOpen.dup);
  3001. if (lserr != lserrNone) return lserr;
  3002. }
  3003. else
  3004. pwdisplay->wdispbraceOpen.dup = 0; /* Used in calculation further in this proc */
  3005. if (FCloseBraceInWLayout(pdobj, pwlayout)) /* Close brace present */
  3006. {
  3007. lserr = WaMatchPresSubline (pdobj->wbraceClose.plssubl, &pwdisplay->wdispbraceClose.dup);
  3008. if (lserr != lserrNone) return lserr;
  3009. }
  3010. else
  3011. pwdisplay->wdispbraceClose.dup = 0; /* Used in calculation further in this proc */
  3012. /* 3. Magic dvpBetween */
  3013. /* REVIEW (antons): Clear this issue */
  3014. pwdisplay->dvpBetween =
  3015. pwlayout->wdim.objdimAll.heightsPres.dvMultiLineHeight
  3016. - pwlayout->wsubline1.objdim.heightsPres.dvAscent
  3017. - pwlayout->wsubline1.objdim.heightsPres.dvDescent
  3018. - pwlayout->wsubline2.objdim.heightsPres.dvAscent
  3019. - pwlayout->wsubline2.objdim.heightsPres.dvDescent
  3020. - pwlayout->wdim.dvpDescentReserved ;
  3021. /* 3. Calculate relative positions of Warichu sublines & braces */
  3022. pwdisplay->wdispbraceOpen.duvStart.u = 0;
  3023. pwdisplay->wdispbraceOpen.duvStart.v = 0;
  3024. pwdisplay->wdispsubl1.duvStart.u = pwdisplay->wdispbraceOpen.dup;
  3025. pwdisplay->wdispsubl1.duvStart.v =
  3026. pwlayout->wsubline2.objdim.heightsPres.dvAscent
  3027. + pwlayout->wsubline2.objdim.heightsPres.dvDescent
  3028. + pwdisplay->dvpBetween
  3029. + pwlayout->wsubline1.objdim.heightsPres.dvDescent
  3030. - pwlayout->wdim.objdimAll.heightsPres.dvDescent
  3031. - pwlayout->wdim.dvpDescentReserved ;
  3032. if (pwlayout->wsubline2.plssubl != NULL)
  3033. {
  3034. pwdisplay->wdispsubl2.duvStart.u = pwdisplay->wdispbraceOpen.dup;
  3035. pwdisplay->wdispsubl2.duvStart.v =
  3036. pwlayout->wsubline2.objdim.heightsPres.dvDescent
  3037. - pwlayout->wdim.objdimAll.heightsPres.dvDescent
  3038. - pwlayout->wdim.dvpDescentReserved ;
  3039. Assert (pwdisplay->wdispsubl1.duvStart.v >= pwdisplay->wdispsubl2.duvStart.v);
  3040. };
  3041. pwdisplay->wdispbraceClose.duvStart.u = pwdisplay->wdispbraceOpen.dup
  3042. + dupInside;
  3043. pwdisplay->wdispbraceClose.duvStart.v = 0;
  3044. /* REVIEW (antons): Clear the problem of possible difference
  3045. between dup-input and calculated dup in this procedure */
  3046. pwdisplay->dupAll = pwdisplay->wdispbraceOpen.dup + pwdisplay->wdispbraceClose.dup +
  3047. + dupInside;
  3048. /* REVIEW (antons): It is better if we try to make
  3049. dup == pwdisplay->dupAll, do something like David Bangs in text */
  3050. /* REVIEW (antons): The following assert has been commented out for build 314 */
  3051. /* Assert (dup == pwdisplay->dupAll); */
  3052. return lserrNone;
  3053. } /* WarichuCalcPresentation */
  3054. /* W A R I C H U Q U E R Y P O I N T P C P */
  3055. /*----------------------------------------------------------------------------
  3056. %%Function: WarichuQueryPointPcp
  3057. %%Contact: antons
  3058. ----------------------------------------------------------------------------*/
  3059. LSERR WINAPI WarichuQueryPointPcp (
  3060. PDOBJ pdobj, /* (IN): dobj to query */
  3061. PCPOINTUV ppointuvQuery, /* (IN): query point (uQuery,vQuery) */
  3062. PCLSQIN plsqin, /* (IN): query input */
  3063. PLSQOUT plsqout) /* (OUT): query output */
  3064. {
  3065. /* REVIEW (antons): I changed logic of snapping; must be checked */
  3066. /* The new version does not allow to come to open & close bracket */
  3067. WDISPLAY * pwdisplay = & pdobj->wdisplay;
  3068. WLAYOUT * pwlayout = & pdobj->wlayout;
  3069. if (pwlayout->wsubline2.plssubl == NULL)
  3070. {
  3071. /* Only first subline ;-) */
  3072. return CreateQueryResult (pwlayout->wsubline1.plssubl,
  3073. pwdisplay->wdispsubl1.duvStart.u,
  3074. pwdisplay->wdispsubl1.duvStart.v,
  3075. plsqin, plsqout );
  3076. }
  3077. else
  3078. {
  3079. /* Two sublines; snap according to v-point */
  3080. long dvMiddle =
  3081. ( pwdisplay->wdispsubl1.duvStart.v - pwlayout->wsubline1.objdim.heightsPres.dvDescent +
  3082. pwdisplay->wdispsubl2.duvStart.v + pwlayout->wsubline2.objdim.heightsPres.dvAscent ) / 2;
  3083. /* dvMiddle is v-level which devides between first and second lines of Warichu */
  3084. if (ppointuvQuery->v >= dvMiddle)
  3085. {
  3086. /* Snapping to the first subline */
  3087. return CreateQueryResult (pwlayout->wsubline1.plssubl,
  3088. pwdisplay->wdispsubl1.duvStart.u,
  3089. pwdisplay->wdispsubl1.duvStart.v,
  3090. plsqin, plsqout );
  3091. }
  3092. else
  3093. {
  3094. /* Snapping to the second subline */
  3095. return CreateQueryResult (pwlayout->wsubline2.plssubl,
  3096. pwdisplay->wdispsubl2.duvStart.u,
  3097. pwdisplay->wdispsubl2.duvStart.v,
  3098. plsqin, plsqout );
  3099. };
  3100. }; /* if (pwlayout->wsubline2.plssubl == NULL) */
  3101. } /* WarichuQueryPointPcp */
  3102. /* W A R I C H U Q U E R Y C P P P O I N T */
  3103. /*----------------------------------------------------------------------------
  3104. %%Function: WarichuQueryCpPpoint
  3105. %%Contact: antons
  3106. ----------------------------------------------------------------------------*/
  3107. LSERR WINAPI WarichuQueryCpPpoint(
  3108. PDOBJ pdobj, /* (IN): dobj to query, */
  3109. LSDCP dcp, /* (IN): dcp for the query */
  3110. PCLSQIN plsqin, /* (IN): query input */
  3111. PLSQOUT plsqout) /* (OUT): query output */
  3112. {
  3113. /* REVIEW (antons): I changed logic of snapping; must be checked */
  3114. WDISPLAY * pwdisplay = & pdobj->wdisplay;
  3115. WLAYOUT * pwlayout = & pdobj->wlayout;
  3116. LSCP cpQuery = pdobj->cpStart + dcp;
  3117. if (FOpenBraceInWLayout (pdobj, pwlayout) &&
  3118. cpQuery < pwlayout->wsubline1.cpFirst)
  3119. {
  3120. /* Snap to the openning brace */
  3121. return CreateQueryResult (pdobj->wbraceOpen.plssubl,
  3122. pwdisplay->wdispbraceOpen.duvStart.u,
  3123. pwdisplay->wdispbraceOpen.duvStart.v,
  3124. plsqin, plsqout );
  3125. }
  3126. else if (FCloseBraceInWLayout (pdobj, pwlayout) &&
  3127. cpQuery >= pdobj->wbraceClose.cpFirst )
  3128. {
  3129. /* Snap to the closing brace */
  3130. return CreateQueryResult (pdobj->wbraceClose.plssubl,
  3131. pwdisplay->wdispbraceClose.duvStart.u,
  3132. pwdisplay->wdispbraceClose.duvStart.v,
  3133. plsqin, plsqout );
  3134. }
  3135. else if (pwlayout->wsubline2.plssubl == NULL)
  3136. {
  3137. /* Only first subline, snap to the first */
  3138. return CreateQueryResult (pwlayout->wsubline1.plssubl,
  3139. pwdisplay->wdispsubl1.duvStart.u,
  3140. pwdisplay->wdispsubl1.duvStart.v,
  3141. plsqin, plsqout );
  3142. }
  3143. else if (cpQuery < pwlayout->wsubline2.cpFirst)
  3144. {
  3145. /* Snap to the first subline */
  3146. return CreateQueryResult (pwlayout->wsubline1.plssubl,
  3147. pwdisplay->wdispsubl1.duvStart.u,
  3148. pwdisplay->wdispsubl1.duvStart.v,
  3149. plsqin, plsqout );
  3150. }
  3151. else
  3152. {
  3153. /* Snap to the second subline */
  3154. return CreateQueryResult (pwlayout->wsubline2.plssubl,
  3155. pwdisplay->wdispsubl2.duvStart.u,
  3156. pwdisplay->wdispsubl2.duvStart.v,
  3157. plsqin, plsqout );
  3158. };
  3159. } /* WarichuQueryPointPcp */
  3160. /* G E T W A R I C H U X Y P O I N T S */
  3161. /*----------------------------------------------------------------------------
  3162. %%Function: GetWarichuXYPoints
  3163. %%Contact: antons
  3164. ----------------------------------------------------------------------------*/
  3165. static void GetWarichuXYPoints (
  3166. PDOBJ pdobj,
  3167. const POINT * ppt,
  3168. LSTFLOW lstflow,
  3169. POINT * pptOpen,
  3170. POINT * pptFirst,
  3171. POINT * pptSecond,
  3172. POINT * pptClose )
  3173. {
  3174. LSERR lserr;
  3175. WDISPLAY * pwdisplay = & pdobj->wdisplay;
  3176. WLAYOUT * pwlayout = & pdobj->wlayout;
  3177. /* REVIEW (antons): How they can not be equal */
  3178. Assert (lstflow == pdobj->lstflowParent);
  3179. /* OPEN BRACE */
  3180. if (FOpenBraceInWLayout(pdobj, pwlayout))
  3181. {
  3182. lserr = LsPointXYFromPointUV (ppt, lstflow,
  3183. & pwdisplay->wdispbraceOpen.duvStart, pptOpen);
  3184. /* REVIEW (antons): Is it OK to have such asserts? */
  3185. Assert (lserr == lserrNone);
  3186. };
  3187. /* FIRST SUBLINE */
  3188. lserr = LsPointXYFromPointUV (ppt, lstflow,
  3189. & pwdisplay->wdispsubl1.duvStart, pptFirst);
  3190. Assert (lserr == lserrNone);
  3191. /* SECIND SUBLINE */
  3192. if (pwlayout->wsubline2.plssubl != NULL)
  3193. {
  3194. lserr = LsPointXYFromPointUV (ppt, lstflow,
  3195. & pwdisplay->wdispsubl2.duvStart, pptSecond);
  3196. Assert (lserr == lserrNone);
  3197. };
  3198. /* CLOSE BRACE */
  3199. if (FCloseBraceInWLayout(pdobj, pwlayout))
  3200. {
  3201. lserr = LsPointXYFromPointUV (ppt, lstflow,
  3202. & pwdisplay->wdispbraceClose.duvStart, pptClose);
  3203. Assert (lserr == lserrNone);
  3204. };
  3205. } /* GetWarichuXYPoints */
  3206. /* W A R I C H U D I S P L A Y */
  3207. /*----------------------------------------------------------------------------
  3208. %%Function: WarichuDisplay
  3209. %%Contact: antons
  3210. ----------------------------------------------------------------------------*/
  3211. LSERR WINAPI WarichuDisplay (PDOBJ pdobj, PCDISPIN pcdispin)
  3212. {
  3213. /* Now it is very elegant ;-) */
  3214. WLAYOUT *pwlayout = & pdobj->wlayout;
  3215. LSERR lserr;
  3216. POINT ptOpen;
  3217. POINT ptFirst;
  3218. POINT ptSecond;
  3219. POINT ptClose;
  3220. GetWarichuXYPoints (pdobj, &pcdispin->ptPen, pcdispin->lstflow,
  3221. & ptOpen, & ptFirst, & ptSecond, & ptClose );
  3222. /* Printing open brace */
  3223. if (FOpenBraceInWLayout(pdobj, pwlayout))
  3224. {
  3225. lserr = LsDisplaySubline (pdobj->wbraceOpen.plssubl, &ptOpen,
  3226. pcdispin->kDispMode, pcdispin->prcClip);
  3227. if (lserr != lserrNone) return lserr;
  3228. };
  3229. /* Printing 1st subline of Warichu */
  3230. lserr = LsDisplaySubline (pwlayout->wsubline1.plssubl, &ptFirst,
  3231. pcdispin->kDispMode, pcdispin->prcClip);
  3232. if (lserr != lserrNone) return lserr;
  3233. /* Printing 2nd subline of Warichu */
  3234. if (pwlayout->wsubline2.plssubl != NULL)
  3235. {
  3236. lserr = LsDisplaySubline (pwlayout->wsubline2.plssubl, &ptSecond,
  3237. pcdispin->kDispMode, pcdispin->prcClip);
  3238. if (lserr != lserrNone) return lserr;
  3239. }
  3240. /* Printing close brace */
  3241. if (FCloseBraceInWLayout(pdobj, pwlayout))
  3242. {
  3243. lserr = LsDisplaySubline (pdobj->wbraceClose.plssubl, &ptClose,
  3244. pcdispin->kDispMode, pcdispin->prcClip);
  3245. if (lserr != lserrNone) return lserr;
  3246. };
  3247. return lserrNone;
  3248. }
  3249. /* W A R I C H U D E S T R O Y D O B J */
  3250. /*----------------------------------------------------------------------------
  3251. %%Function: WarichuDestroyDobj
  3252. %%Contact: antons
  3253. ----------------------------------------------------------------------------*/
  3254. LSERR WINAPI WarichuDestroyDobj (PDOBJ pdobj)
  3255. {
  3256. /* REVIEW (antons): Should we eliminate this extra call? */
  3257. return DestroyDobj (pdobj);
  3258. }
  3259. /* W A R I C H U E N U M */
  3260. /*----------------------------------------------------------------------------
  3261. %%Function: WarichuEnum
  3262. %%Contact: antons
  3263. ----------------------------------------------------------------------------*/
  3264. LSERR WINAPI WarichuEnum(
  3265. PDOBJ pdobj, /*(IN): dobj to enumerate */
  3266. PLSRUN plsrun, /*(IN): from DNODE */
  3267. PCLSCHP plschp, /*(IN): from DNODE */
  3268. LSCP cp, /*(IN): from DNODE */
  3269. LSDCP dcp, /*(IN): from DNODE */
  3270. LSTFLOW lstflow, /*(IN): text flow*/
  3271. BOOL fReverse, /*(IN): enumerate in reverse order */
  3272. BOOL fGeometryNeeded, /*(IN): do we provide geometry ? */
  3273. const POINT *pt, /*(IN): starting position (top left), iff fGeometryNeeded */
  3274. PCHEIGHTS pcheights, /*(IN): from DNODE, relevant iff fGeometryNeeded */
  3275. long dupRun) /*(IN): from DNODE, relevant iff fGeometryNeeded */
  3276. {
  3277. POINT ptOpen;
  3278. POINT ptClose;
  3279. POINT ptFirst;
  3280. POINT ptSecond;
  3281. WLAYOUT * pwlayout = & pdobj->wlayout;
  3282. WDISPLAY * pwdisplay = & pdobj->wdisplay;
  3283. if (fGeometryNeeded)
  3284. {
  3285. GetWarichuXYPoints (pdobj, pt, lstflow, &ptOpen, &ptFirst, &ptSecond, &ptClose);
  3286. }
  3287. /* REVIEW (antons): Should we provide something like fOpenBrace & fCloseBrace */
  3288. return pdobj->pilsobj->warichucbk.pfnWarichuEnum (
  3289. pdobj->pilsobj->pols,
  3290. plsrun, plschp, cp, dcp,
  3291. lstflow, fReverse, fGeometryNeeded,
  3292. pt, pcheights, dupRun,
  3293. & ptOpen, & pdobj->wbraceOpen. objdim.heightsPres, pwdisplay->wdispbraceOpen .dup,
  3294. & ptClose, & pdobj->wbraceClose.objdim.heightsPres, pwdisplay->wdispbraceClose.dup,
  3295. &ptFirst, & pwlayout->wsubline1.objdim.heightsPres, pwdisplay->wdispsubl1.dup,
  3296. &ptSecond,& pwlayout->wsubline2.objdim.heightsPres, pwdisplay->wdispsubl2.dup,
  3297. pdobj->wbraceOpen.plssubl,
  3298. pdobj->wbraceClose.plssubl,
  3299. pwlayout->wsubline1.plssubl,
  3300. pwlayout->wsubline2.plssubl );
  3301. }
  3302. /* G E T W A R I C H U L S I M E T H O D S */
  3303. /*----------------------------------------------------------------------------
  3304. %%Function: GetWarichuLsimethods
  3305. %%Contact: ricksa
  3306. Get LSIMETHODS so client application can use Warichu object handler.
  3307. ----------------------------------------------------------------------------*/
  3308. LSERR WINAPI LsGetWarichuLsimethods (LSIMETHODS *plsim)
  3309. {
  3310. plsim->pfnCreateILSObj = WarichuCreateILSObj;
  3311. plsim->pfnDestroyILSObj = WarichuDestroyILSObj;
  3312. plsim->pfnSetDoc = WarichuSetDoc;
  3313. plsim->pfnCreateLNObj = WarichuCreateLNObj;
  3314. plsim->pfnDestroyLNObj = WarichuDestroyLNObj;
  3315. plsim->pfnFmt = WarichuFmt;
  3316. plsim->pfnFmtResume = WarichuFmtResume;
  3317. plsim->pfnGetModWidthPrecedingChar = WarichuGetModWidthPrecedingChar;
  3318. plsim->pfnGetModWidthFollowingChar = WarichuGetModWidthFollowingChar;
  3319. plsim->pfnTruncateChunk = WarichuTruncateChunk;
  3320. plsim->pfnFindPrevBreakChunk = WarichuFindPrevBreakChunk;
  3321. plsim->pfnFindNextBreakChunk = WarichuFindNextBreakChunk;
  3322. plsim->pfnForceBreakChunk = WarichuForceBreakChunk;
  3323. plsim->pfnSetBreak = WarichuSetBreak;
  3324. plsim->pfnGetSpecialEffectsInside = WarichuGetSpecialEffectsInside;
  3325. plsim->pfnFExpandWithPrecedingChar = ObjHelpFExpandWithPrecedingChar;
  3326. plsim->pfnFExpandWithFollowingChar = ObjHelpFExpandWithFollowingChar;
  3327. plsim->pfnCalcPresentation = WarichuCalcPresentation;
  3328. plsim->pfnQueryPointPcp = WarichuQueryPointPcp;
  3329. plsim->pfnQueryCpPpoint = WarichuQueryCpPpoint;
  3330. plsim->pfnDisplay = WarichuDisplay;
  3331. plsim->pfnDestroyDObj = WarichuDestroyDobj;
  3332. plsim->pfnEnum = WarichuEnum;
  3333. return lserrNone;
  3334. }