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.

1106 lines
34 KiB

  1. #include "lsmem.h"
  2. #include "lstxtini.h"
  3. #include "zqfromza.h"
  4. #include "lscbk.h"
  5. #include "lsdocinf.h"
  6. #include "tlpr.h"
  7. #include "txtils.h"
  8. #include "txtln.h"
  9. #include "txtobj.h"
  10. #include "txtconst.h"
  11. #define min(a,b) ((a) > (b) ? (b) : (a))
  12. #define TxtVisiMask (fTxtVisiCondHyphens | fTxtVisiParaMarks | fTxtVisiSpaces | fTxtVisiTabs | fTxtVisiBreaks)
  13. /* Internal Functions Prototypes */
  14. static void DestroyLNObjTextCore(PLNOBJ plnobj);
  15. static LSERR ErrorLNObjText(PLNOBJ* plnobj, LSERR lserr);
  16. static LSERR TxtAddSpec(PILSOBJ pilsobj, WCHAR wchSymbol, CLABEL clab, WCHAR wchUndef);
  17. static LSERR TxtSortSpec(WCHAR* rgwchSpec, CLABEL* rgbKind, DWORD cwchSpec);
  18. static void CkeckModWidthClasses(PILSOBJ pilsobj, DWORD cModWidthClasses);
  19. /* Export Functions Implementation*/
  20. /* D E S T R O Y I L S O B J T E X T */
  21. /*----------------------------------------------------------------------------
  22. %%Function: DestroyILSObjText
  23. %%Contact: sergeyge
  24. Deallocates list of arrays of txtobj's
  25. Deallocates arrays anchored to ILSOBJ
  26. Deallocates text ilsobj
  27. ----------------------------------------------------------------------------*/
  28. LSERR WINAPI DestroyILSObjText(PILSOBJ pilsobj)
  29. {
  30. if (pilsobj != NULL)
  31. {
  32. if ( pilsobj->pwchOrig != NULL )
  33. {
  34. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pwchOrig);
  35. pilsobj->pwchOrig = NULL;
  36. }
  37. if ( pilsobj->pdur != NULL )
  38. {
  39. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pdur);
  40. pilsobj->pdur = NULL;
  41. }
  42. if ( pilsobj->pdurLeft != NULL )
  43. {
  44. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pdurLeft);
  45. pilsobj->pdurLeft = NULL;
  46. }
  47. if ( pilsobj->pdurRight != NULL )
  48. {
  49. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pdurRight);
  50. pilsobj->pdurRight = NULL;
  51. }
  52. if ( pilsobj->pduAdjust != NULL )
  53. {
  54. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pduAdjust);
  55. pilsobj->pduAdjust = NULL;
  56. }
  57. if ( pilsobj->ptxtinf != NULL )
  58. {
  59. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->ptxtinf);
  60. pilsobj->ptxtinf = NULL;
  61. }
  62. if ( pilsobj->pdurGind != NULL )
  63. {
  64. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pdurGind);
  65. pilsobj->pdurGind = NULL;
  66. }
  67. if ( pilsobj->pginf != NULL )
  68. {
  69. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pginf);
  70. pilsobj->pginf = NULL;
  71. }
  72. if ( pilsobj->pduGright != NULL )
  73. {
  74. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pduGright);
  75. pilsobj->pduGright = NULL;
  76. }
  77. if ( pilsobj->plsexpinf != NULL )
  78. {
  79. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plsexpinf);
  80. pilsobj->plsexpinf = NULL;
  81. }
  82. if ( pilsobj->pwSpaces != NULL )
  83. {
  84. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pwSpaces);
  85. pilsobj->pwSpaces = NULL;
  86. }
  87. if ( pilsobj->plspairact != NULL )
  88. {
  89. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plspairact);
  90. pilsobj->plspairact = NULL;
  91. }
  92. if ( pilsobj->pilspairact != NULL )
  93. {
  94. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pilspairact);
  95. pilsobj->pilspairact = NULL;
  96. }
  97. if ( pilsobj->plspract != NULL )
  98. {
  99. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plspract);
  100. pilsobj->plspract = NULL;
  101. }
  102. if ( pilsobj->pilspract != NULL )
  103. {
  104. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pilspract);
  105. pilsobj->pilspract = NULL;
  106. }
  107. if ( pilsobj->plsexpan != NULL )
  108. {
  109. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plsexpan);
  110. pilsobj->plsexpan = NULL;
  111. }
  112. if ( pilsobj->pilsexpan != NULL )
  113. {
  114. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pilsexpan);
  115. pilsobj->pilsexpan = NULL;
  116. }
  117. if ( pilsobj->plsbrk != NULL )
  118. {
  119. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plsbrk);
  120. pilsobj->plsbrk = NULL;
  121. }
  122. if ( pilsobj->pilsbrk != NULL )
  123. {
  124. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pilsbrk);
  125. pilsobj->pilsbrk = NULL;
  126. }
  127. if ( pilsobj->plnobj != NULL )
  128. {
  129. DestroyLNObjTextCore(pilsobj->plnobj);
  130. pilsobj->plnobj = NULL;
  131. }
  132. if (pilsobj->pbreakinf != NULL);
  133. {
  134. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pbreakinf);
  135. pilsobj->pbreakinf = NULL;
  136. }
  137. (*pilsobj->plscbk->pfnDisposePtr) (pilsobj->pols, pilsobj);
  138. }
  139. return lserrNone;
  140. }
  141. /* C R E A T E I L S O B J T E X T */
  142. /*----------------------------------------------------------------------------
  143. %%Function: CreateILSObjText
  144. %%Contact: sergeyge
  145. Allocates text ilsobj and sets pols, plsc and call-backs in it
  146. Allocates first array of the list of arrays of txtobj's
  147. Allocates wchOrig/dur arrays. Other arrays will be allocated when needed.
  148. ----------------------------------------------------------------------------*/
  149. LSERR WINAPI CreateILSObjText(POLS pols, PCLSC plsc, PCLSCBK plscbk, DWORD idobj, PILSOBJ* ppilsobj)
  150. {
  151. PILSOBJ ptxtils;
  152. Unreferenced(idobj);
  153. *ppilsobj = NULL;
  154. ptxtils = (*plscbk->pfnNewPtr)(pols, sizeof(struct ilsobj));
  155. if (ptxtils == NULL)
  156. return lserrOutOfMemory;
  157. *ppilsobj = ptxtils;
  158. memset(ptxtils, 0, sizeof(struct ilsobj) );
  159. ptxtils->pols = pols;
  160. ptxtils->plsc = (PLSC)plsc;
  161. ptxtils->plscbk = plscbk;
  162. return lserrNone;
  163. }
  164. /* D E S T R O Y L N O B J T E X T */
  165. /*----------------------------------------------------------------------------
  166. %%Function: DestroyLNObjText
  167. %%Contact: sergeyge
  168. Deallocates arrays anchored to LNOBJ
  169. Deallocates text lnobj
  170. ----------------------------------------------------------------------------*/
  171. LSERR WINAPI DestroyLNObjText(PLNOBJ plnobj)
  172. {
  173. if (plnobj->pilsobj->plnobj == NULL)
  174. {
  175. plnobj->pilsobj->plnobj = plnobj;
  176. }
  177. else if (plnobj != NULL)
  178. {
  179. DestroyLNObjTextCore(plnobj);
  180. }
  181. return lserrNone;
  182. }
  183. /* C R E A T E L N O B J T E X T */
  184. /*----------------------------------------------------------------------------
  185. %%Function: CreateLNObjText
  186. %%Contact: sergeyge
  187. Allocates text lnobj
  188. Allocates wch/dup arrays. dupPenAllocArray will be allocated when needed.
  189. ----------------------------------------------------------------------------*/
  190. LSERR WINAPI CreateLNObjText(PCILSOBJ pilsobj, PLNOBJ* pplnobj)
  191. {
  192. PLNOBJ ptxtln;
  193. if (pilsobj->plnobj != NULL)
  194. {
  195. *pplnobj = pilsobj->plnobj;
  196. if (pilsobj->plnobj->wchMax != pilsobj->wchMax)
  197. {
  198. Assert(pilsobj->plnobj->pwch != NULL);
  199. Assert(pilsobj->plnobj->pdup != NULL);
  200. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pwch);
  201. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pdup);
  202. if (pilsobj->plnobj->pgmap != NULL)
  203. {
  204. /* it will be allocated in CheckReallocGlyphs in lstxtnti.c */
  205. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pgmap);
  206. pilsobj->plnobj->pgmap = NULL;
  207. }
  208. if (pilsobj->plnobj->pdupPenAlloc != NULL)
  209. {
  210. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pdupPenAlloc);
  211. }
  212. pilsobj->plnobj->pdupPenAlloc = NULL;
  213. pilsobj->plnobj->wchMax = pilsobj->wchMax;
  214. pilsobj->plnobj->pwch = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(WCHAR) * pilsobj->wchMax);
  215. pilsobj->plnobj->pdup = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax);
  216. if (pilsobj->plnobj->pwch == NULL || pilsobj->plnobj->pdup == NULL)
  217. {
  218. pilsobj->plnobj = NULL;
  219. return ErrorLNObjText(pplnobj, lserrOutOfMemory);
  220. }
  221. }
  222. if (pilsobj->plnobj->gindMax != pilsobj->gindMax)
  223. {
  224. if (pilsobj->plnobj->pgind != NULL )
  225. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pgind);
  226. if (pilsobj->plnobj->pdupGind != NULL )
  227. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pdupGind);
  228. if (pilsobj->plnobj->pgoffs != NULL )
  229. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pgoffs);
  230. if (pilsobj->plnobj->pexpt != NULL )
  231. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pexpt);
  232. if (pilsobj->plnobj->pdupBeforeJust != NULL )
  233. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pdupBeforeJust);
  234. if (pilsobj->plnobj->pgprop != NULL )
  235. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plnobj->pgprop);
  236. pilsobj->plnobj->gindMax = pilsobj->gindMax;
  237. pilsobj->plnobj->pgind = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(GINDEX) * pilsobj->gindMax);
  238. pilsobj->plnobj->pdupGind = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->gindMax);
  239. pilsobj->plnobj->pgoffs = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(GOFFSET) * pilsobj->gindMax);
  240. pilsobj->plnobj->pexpt = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(EXPTYPE) * pilsobj->gindMax);
  241. pilsobj->plnobj->pdupBeforeJust = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->gindMax);
  242. pilsobj->plnobj->pgprop = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(GPROP) * pilsobj->gindMax);
  243. if (pilsobj->plnobj->pgind == NULL || pilsobj->plnobj->pdupGind == NULL ||
  244. pilsobj->plnobj->pgoffs == NULL || pilsobj->plnobj->pexpt == NULL ||
  245. pilsobj->plnobj->pdupBeforeJust == NULL ||
  246. pilsobj->plnobj->pgprop == NULL)
  247. {
  248. pilsobj->plnobj = NULL;
  249. return ErrorLNObjText(pplnobj, lserrOutOfMemory);
  250. }
  251. memset(pilsobj->plnobj->pexpt, 0, sizeof(EXPTYPE) * pilsobj->gindMax);
  252. }
  253. pilsobj->plnobj = NULL;
  254. }
  255. else
  256. {
  257. *pplnobj = NULL;
  258. ptxtln = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(struct lnobj));
  259. if (ptxtln == NULL)
  260. {
  261. return lserrOutOfMemory;
  262. }
  263. *pplnobj = ptxtln;
  264. memset(ptxtln, 0, sizeof(struct lnobj) );
  265. ptxtln->pilsobj = pilsobj;
  266. ptxtln->ptxtobj = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(TXTOBJ) * txtobjMaxM + sizeof(TXTOBJ**));
  267. if ( ptxtln->ptxtobj == NULL)
  268. {
  269. return ErrorLNObjText(pplnobj, lserrOutOfMemory);
  270. }
  271. ptxtln->ptxtobjFirst = ptxtln->ptxtobj;
  272. *(TXTOBJ**)( ptxtln->ptxtobj + txtobjMaxM) = NULL;
  273. ptxtln->wchMax = pilsobj->wchMax;
  274. ptxtln->pwch = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(WCHAR) * pilsobj->wchMax);
  275. ptxtln->pdup = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax);
  276. if (ptxtln->pwch == NULL || ptxtln->pdup == NULL)
  277. {
  278. return ErrorLNObjText(pplnobj, lserrOutOfMemory);
  279. }
  280. if (pilsobj->gindMax > 0)
  281. {
  282. ptxtln->pgind = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(GINDEX) * pilsobj->gindMax);
  283. ptxtln->pdupGind = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->gindMax);
  284. ptxtln->pgoffs = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(GOFFSET) * pilsobj->gindMax);
  285. ptxtln->pexpt = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(EXPTYPE) * pilsobj->gindMax);
  286. ptxtln->pdupBeforeJust = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->gindMax);
  287. ptxtln->pgprop = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(GPROP) * pilsobj->gindMax);
  288. if (ptxtln->pgind == NULL || ptxtln->pdupGind == NULL ||
  289. ptxtln->pgoffs == NULL || ptxtln->pexpt == NULL ||
  290. ptxtln->pdupBeforeJust == NULL || ptxtln->pgprop == NULL)
  291. {
  292. return ErrorLNObjText(pplnobj, lserrOutOfMemory);
  293. }
  294. ptxtln->gindMax = pilsobj->gindMax;
  295. }
  296. }
  297. if (pilsobj->fNotSimpleText)
  298. {
  299. if (pilsobj->pdurRight != NULL)
  300. {
  301. memset(pilsobj->pdurRight, 0, sizeof(long) * pilsobj->wchMac );
  302. Assert (pilsobj->pdurLeft != NULL);
  303. memset(pilsobj->pdurLeft, 0, sizeof(long) * pilsobj->wchMac );
  304. Assert (pilsobj->ptxtinf != NULL);
  305. memset(pilsobj->ptxtinf, 0, sizeof(TXTINF) * pilsobj->wchMac );
  306. }
  307. if ((*pplnobj)->pdupPen == (*pplnobj)->pdupPenAlloc && (*pplnobj)->pdupPen != NULL)
  308. memset((*pplnobj)->pdupPenAlloc, 0, sizeof(long) * pilsobj->wchMax);
  309. if (pilsobj->gindMac != 0)
  310. {
  311. Assert (pilsobj->pduGright != NULL);
  312. memset(pilsobj->pduGright, 0, sizeof(long) * pilsobj->gindMac );
  313. Assert (pilsobj->plsexpinf != NULL);
  314. memset(pilsobj->plsexpinf, 0, sizeof(LSEXPINFO) * pilsobj->gindMac );
  315. Assert ((*pplnobj)->pexpt != NULL);
  316. memset((*pplnobj)->pexpt, 0, sizeof(EXPTYPE) * pilsobj->gindMac );
  317. }
  318. }
  319. pilsobj->txtobjMac = 0;
  320. pilsobj->wchMac = 0;
  321. pilsobj->gindMac = 0;
  322. pilsobj->wSpacesMac = 0;
  323. pilsobj->fNotSimpleText = fFalse;
  324. pilsobj->fDifficultForAdjust = fFalse;
  325. pilsobj->fTruncatedBefore = fFalse;
  326. pilsobj->iwchCompressFetchedFirst = 0;
  327. pilsobj->itxtobjCompressFetchedLim = 0;
  328. pilsobj->iwchCompressFetchedLim = 0;
  329. pilsobj->dcpFetchedWidth = 0;
  330. pilsobj->breakinfMac = 3;
  331. pilsobj->pbreakinf[0].pdobj = NULL;
  332. pilsobj->pbreakinf[1].pdobj = NULL;
  333. pilsobj->pbreakinf[2].pdobj = NULL;
  334. (*pplnobj)->ptxtobj = (*pplnobj)->ptxtobjFirst;
  335. (*pplnobj)->pdupPen = (*pplnobj)->pdup;
  336. (*pplnobj)->pdobjHyphen = NULL;
  337. (*pplnobj)->dwchYsr = 0;
  338. return lserrNone;
  339. }
  340. /* S E T D O C T E X T */
  341. /*----------------------------------------------------------------------------
  342. %%Function: SetDocText
  343. %%Contact: sergeyge
  344. Initialization at the doc level
  345. Called when resolutions are changed
  346. ----------------------------------------------------------------------------*/
  347. LSERR WINAPI SetDocText(PILSOBJ pilsobj, PCLSDOCINF plsdocinf)
  348. {
  349. pilsobj->fDisplay = plsdocinf->fDisplay;
  350. pilsobj->fPresEqualRef = plsdocinf->fPresEqualRef;
  351. pilsobj->lsdevres = plsdocinf->lsdevres;
  352. /* Be careful---In Visi case fPresEqualRef can be True, but sizes of characters---different
  353. */
  354. if (pilsobj->fDisplay && !pilsobj->fPresEqualRef)
  355. {
  356. pilsobj->MagicConstantX = LsLwMultDivR(pilsobj->lsdevres.dxpInch, 1 << 21, pilsobj->lsdevres.dxrInch);
  357. pilsobj->durRightMaxX = min(1 << 21, (0x7FFFFFFF - (1 << 20)) / pilsobj->MagicConstantX);
  358. pilsobj->MagicConstantY = pilsobj->MagicConstantX;
  359. pilsobj->durRightMaxY = pilsobj->durRightMaxY;
  360. if (pilsobj->lsdevres.dxrInch != pilsobj->lsdevres.dyrInch ||
  361. pilsobj->lsdevres.dxpInch != pilsobj->lsdevres.dypInch)
  362. pilsobj->MagicConstantY = LsLwMultDivR(pilsobj->lsdevres.dypInch, 1 << 21, pilsobj->lsdevres.dyrInch);
  363. pilsobj->durRightMaxY = min(1 << 21, (0x7FFFFFFF - (1 << 20)) / pilsobj->MagicConstantY);
  364. }
  365. return lserrNone;
  366. }
  367. /* S E T T E X T B R E A K I N G */
  368. /*----------------------------------------------------------------------------
  369. %%Function: SetTextBreaking
  370. %%Contact: sergeyge
  371. Initialization on the doc level
  372. Called when the breaking table should be installed or changed
  373. ----------------------------------------------------------------------------*/
  374. LSERR SetTextBreaking(PILSOBJ pilsobj, DWORD clsbrk, const LSBRK* rglsbrk,
  375. DWORD cBreakingClasses, const BYTE* rgibrk)
  376. {
  377. DWORD i;
  378. if (pilsobj->cBreakingClasses < cBreakingClasses)
  379. {
  380. if (pilsobj->cBreakingClasses > 0)
  381. {
  382. Assert(pilsobj->pilsbrk != NULL);
  383. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pilsbrk);
  384. pilsobj->pilsbrk = NULL;
  385. pilsobj->cBreakingClasses = 0;
  386. }
  387. pilsobj->pilsbrk = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols,
  388. sizeof(BYTE) * cBreakingClasses * cBreakingClasses);
  389. if ( pilsobj->pilsbrk == NULL)
  390. {
  391. return lserrOutOfMemory;
  392. }
  393. pilsobj->cBreakingClasses = cBreakingClasses;
  394. }
  395. if (pilsobj->clsbrk < clsbrk)
  396. {
  397. if (pilsobj->clsbrk > 0)
  398. {
  399. Assert(pilsobj->plsbrk != NULL);
  400. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plsbrk);
  401. pilsobj->plsbrk = NULL;
  402. pilsobj->clsbrk = 0;
  403. }
  404. pilsobj->plsbrk = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(LSBRK) * clsbrk);
  405. if ( pilsobj->plsbrk == NULL)
  406. {
  407. return lserrOutOfMemory;
  408. }
  409. pilsobj->clsbrk = clsbrk;
  410. }
  411. memcpy(pilsobj->plsbrk, rglsbrk, sizeof(LSBRK) * clsbrk);
  412. memcpy(pilsobj->pilsbrk, rgibrk, sizeof(BYTE) * cBreakingClasses * cBreakingClasses);
  413. for (i = 0; i < cBreakingClasses * cBreakingClasses; i++)
  414. {
  415. if (rgibrk[i] >= clsbrk)
  416. {
  417. Assert(fFalse);
  418. return lserrInvalidParameter; /* REVIEW sergeyge: another error code? */
  419. }
  420. }
  421. return lserrNone;
  422. }
  423. /* S E T T E X T M O D W I D T H P A I R S */
  424. /*----------------------------------------------------------------------------
  425. %%Function: SetTextModWidthPairs
  426. %%Contact: sergeyge
  427. Initialization on the doc level
  428. Called when the ModWidthPairs table should be installed or changed
  429. ----------------------------------------------------------------------------*/
  430. LSERR SetTextModWidthPairs(PILSOBJ pilsobj, DWORD clspairact, const LSPAIRACT* rglspairact,
  431. DWORD cModWidthClasses, const BYTE* rgipairact)
  432. {
  433. DWORD i;
  434. CkeckModWidthClasses(pilsobj, cModWidthClasses);
  435. if (pilsobj->pilspairact == NULL)
  436. {
  437. pilsobj->pilspairact = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols,
  438. sizeof(BYTE) * cModWidthClasses * cModWidthClasses);
  439. if ( pilsobj->pilspairact == NULL)
  440. {
  441. return lserrOutOfMemory;
  442. }
  443. }
  444. if (pilsobj->clspairact < clspairact)
  445. {
  446. if (pilsobj->clspairact > 0)
  447. {
  448. Assert(pilsobj->plspairact != NULL);
  449. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plspairact);
  450. pilsobj->plspairact = NULL;
  451. pilsobj->clspairact = 0;
  452. }
  453. pilsobj->plspairact = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(LSPAIRACT) * clspairact);
  454. if ( pilsobj->plspairact == NULL)
  455. {
  456. return lserrOutOfMemory;
  457. }
  458. pilsobj->clspairact = clspairact;
  459. }
  460. memcpy(pilsobj->plspairact, rglspairact, sizeof(LSPAIRACT) * clspairact);
  461. memcpy(pilsobj->pilspairact, rgipairact, sizeof(BYTE) * cModWidthClasses * cModWidthClasses);
  462. for (i = 0; i < cModWidthClasses * cModWidthClasses; i++)
  463. {
  464. if (rgipairact[i] >= clspairact)
  465. {
  466. Assert(fFalse);
  467. return lserrInvalidParameter; /* REVIEW sergeyge: another error code? */
  468. }
  469. }
  470. return lserrNone;
  471. }
  472. /* S E T T E X T C O M P R E S S I O N */
  473. /*----------------------------------------------------------------------------
  474. %%Function: SetTextCompression
  475. %%Contact: sergeyge
  476. Initialization on the doc level
  477. Called when the Compression table should be installed or changed
  478. ----------------------------------------------------------------------------*/
  479. LSERR SetTextCompression(PILSOBJ pilsobj, DWORD cCompPrior, DWORD clspract, const LSPRACT* rglspract,
  480. DWORD cModWidthClasses, const BYTE* rgipract)
  481. {
  482. DWORD i;
  483. CkeckModWidthClasses(pilsobj, cModWidthClasses);
  484. if (pilsobj->pilspract == NULL)
  485. {
  486. pilsobj->pilspract = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols,
  487. sizeof(BYTE) * cModWidthClasses);
  488. if ( pilsobj->pilspract == NULL)
  489. {
  490. return lserrOutOfMemory;
  491. }
  492. }
  493. if (pilsobj->clspract < clspract)
  494. {
  495. if (pilsobj->clspract > 0)
  496. {
  497. Assert(pilsobj->plspract != NULL);
  498. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plspract);
  499. pilsobj->plspract = NULL;
  500. pilsobj->clspract = 0;
  501. }
  502. pilsobj->plspract = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(LSPRACT) * clspract);
  503. if ( pilsobj->plspract == NULL)
  504. {
  505. return lserrOutOfMemory;
  506. }
  507. pilsobj->clspract = clspract;
  508. }
  509. pilsobj->cCompPrior = cCompPrior;
  510. memcpy(pilsobj->plspract, rglspract, sizeof(LSPRACT) * clspract);
  511. memcpy(pilsobj->pilspract, rgipract, sizeof(BYTE) * cModWidthClasses);
  512. for (i = 0; i < cModWidthClasses; i++)
  513. {
  514. if (rgipract[i] >= clspract)
  515. {
  516. Assert(fFalse);
  517. return lserrInvalidParameter; /* REVIEW sergeyge: another error code? */
  518. }
  519. }
  520. return lserrNone;
  521. }
  522. /* S E T T E X T E X P A N S I O N */
  523. /*----------------------------------------------------------------------------
  524. %%Function: SetTextExpansion
  525. %%Contact: sergeyge
  526. Initialization on the doc level
  527. Called when the Expansion table should be installed or changed
  528. ----------------------------------------------------------------------------*/
  529. LSERR SetTextExpansion(PILSOBJ pilsobj, DWORD clsexpan, const LSEXPAN* rglsexpan,
  530. DWORD cModWidthClasses, const BYTE* rgiexpan)
  531. {
  532. DWORD i;
  533. CkeckModWidthClasses(pilsobj, cModWidthClasses);
  534. if (pilsobj->pilsexpan == NULL)
  535. {
  536. pilsobj->pilsexpan = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols,
  537. sizeof(BYTE) * cModWidthClasses * cModWidthClasses);
  538. if ( pilsobj->pilsexpan == NULL)
  539. {
  540. return lserrOutOfMemory;
  541. }
  542. }
  543. if (pilsobj->clsexpan < clsexpan)
  544. {
  545. if (pilsobj->clsexpan > 0)
  546. {
  547. Assert(pilsobj->plsexpan != NULL);
  548. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->plsexpan);
  549. pilsobj->plsexpan = NULL;
  550. pilsobj->clsexpan = 0;
  551. }
  552. pilsobj->plsexpan = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(LSEXPAN) * clsexpan);
  553. if ( pilsobj->plsexpan == NULL)
  554. {
  555. return lserrOutOfMemory;
  556. }
  557. pilsobj->clsexpan = clsexpan;
  558. }
  559. memcpy(pilsobj->plsexpan, rglsexpan, sizeof(LSEXPAN) * clsexpan);
  560. memcpy(pilsobj->pilsexpan, rgiexpan, sizeof(BYTE) * cModWidthClasses * cModWidthClasses);
  561. for (i = 0; i < cModWidthClasses * cModWidthClasses; i++)
  562. {
  563. if (rgiexpan[i] >= clsexpan)
  564. {
  565. Assert(fFalse);
  566. return lserrInvalidParameter; /* REVIEW sergeyge: another error code? */
  567. }
  568. }
  569. return lserrNone;
  570. }
  571. /* S E T T E X T L I N E P A R A M S */
  572. /*----------------------------------------------------------------------------
  573. %%Function: SetTextLineParams
  574. %%Contact: sergeyge
  575. Initialization at the beginning of the line
  576. with the text specific parameters.
  577. ----------------------------------------------------------------------------*/
  578. LSERR SetTextLineParams(PLNOBJ plnobj, const TLPR* ptlpr)
  579. {
  580. PILSOBJ pilsobj;
  581. pilsobj = plnobj->pilsobj;
  582. pilsobj->grpf = ptlpr->grpfText;
  583. pilsobj->fSnapGrid = ptlpr->fSnapGrid;
  584. pilsobj->duaHyphenationZone = ptlpr->duaHyphenationZone;
  585. pilsobj->lskeop = ptlpr->lskeop;
  586. plnobj->fDrawInCharCodes = pilsobj->grpf & fTxtDrawInCharCodes;
  587. if ( (pilsobj->grpf & fTxtApplyBreakingRules) && pilsobj->pilsbrk == NULL)
  588. return lserrBreakingTableNotSet;
  589. return lserrNone;
  590. }
  591. /* M O D I F Y T E X T L I N E E N D I N G */
  592. /*----------------------------------------------------------------------------
  593. %%Function: ModifyTextLineEnding
  594. %%Contact: sergeyge
  595. Modifies line ending information when text vanishes across paragraph boundary
  596. ----------------------------------------------------------------------------*/
  597. LSERR ModifyTextLineEnding(PLNOBJ plnobj, LSKEOP lskeop)
  598. {
  599. plnobj->pilsobj->lskeop = lskeop;
  600. return lserrNone;
  601. }
  602. /* S E T T E X T C O N F I G */
  603. /*----------------------------------------------------------------------------
  604. %%Function: SetTextConfig
  605. %%Contact: sergeyge
  606. Sets special characters in the ilsobj
  607. ----------------------------------------------------------------------------*/
  608. LSERR SetTextConfig(PILSOBJ pilsobj, const LSTXTCFG* plstxtcfg)
  609. {
  610. LSERR lserr;
  611. WCHAR wchUndef;
  612. wchUndef = plstxtcfg->wchUndef;
  613. pilsobj->wchVisiNull = plstxtcfg->wchVisiNull;
  614. pilsobj->wchVisiEndPara = plstxtcfg->wchVisiEndPara;
  615. pilsobj->wchVisiAltEndPara = plstxtcfg->wchVisiAltEndPara;
  616. pilsobj->wchVisiEndLineInPara = plstxtcfg->wchVisiEndLineInPara;
  617. pilsobj->wchVisiSpace = plstxtcfg->wchVisiSpace;
  618. pilsobj->wchVisiNonBreakSpace = plstxtcfg->wchVisiNonBreakSpace;
  619. pilsobj->wchVisiNonBreakHyphen = plstxtcfg->wchVisiNonBreakHyphen;
  620. pilsobj->wchVisiNonReqHyphen = plstxtcfg->wchVisiNonReqHyphen;
  621. pilsobj->wchVisiTab = plstxtcfg->wchVisiTab;
  622. pilsobj->wchVisiEmSpace = plstxtcfg->wchVisiEmSpace;
  623. pilsobj->wchVisiEnSpace = plstxtcfg->wchVisiEnSpace;
  624. pilsobj->wchVisiNarrowSpace = plstxtcfg->wchVisiNarrowSpace;
  625. pilsobj->wchVisiOptBreak = plstxtcfg->wchVisiOptBreak;
  626. pilsobj->wchVisiNoBreak = plstxtcfg->wchVisiNoBreak;
  627. pilsobj->wchVisiFESpace = plstxtcfg->wchVisiFESpace;
  628. Assert(0 == clabRegular);
  629. Assert(pilsobj->wchVisiEndPara != wchUndef);
  630. Assert(pilsobj->wchVisiAltEndPara != wchUndef);
  631. Assert(pilsobj->wchVisiEndLineInPara != wchUndef);
  632. pilsobj->wchSpace = plstxtcfg->wchSpace;
  633. pilsobj->wchHyphen = plstxtcfg->wchHyphen;
  634. pilsobj->wchReplace = plstxtcfg->wchReplace;
  635. pilsobj->wchNonBreakSpace = plstxtcfg->wchNonBreakSpace;
  636. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchNull, clabNull, wchUndef);
  637. if (lserr != lserrNone) return lserr;
  638. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchSpace, clabSpace, wchUndef);
  639. if (lserr != lserrNone) return lserr;
  640. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchHyphen, clabHardHyphen, wchUndef);
  641. if (lserr != lserrNone) return lserr;
  642. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchTab, clabTab, wchUndef);
  643. if (lserr != lserrNone) return lserr;
  644. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchEndPara1, clabEOP1, wchUndef);
  645. if (lserr != lserrNone) return lserr;
  646. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchEndPara2, clabEOP2, wchUndef);
  647. if (lserr != lserrNone) return lserr;
  648. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchAltEndPara, clabAltEOP, wchUndef);
  649. if (lserr != lserrNone) return lserr;
  650. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchEndLineInPara, clabEndLineInPara, wchUndef);
  651. if (lserr != lserrNone) return lserr;
  652. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchColumnBreak, clabColumnBreak, wchUndef);
  653. if (lserr != lserrNone) return lserr;
  654. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchSectionBreak, clabSectionBreak, wchUndef);
  655. if (lserr != lserrNone) return lserr;
  656. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchPageBreak, clabPageBreak, wchUndef);
  657. if (lserr != lserrNone) return lserr;
  658. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchNonBreakSpace, clabNonBreakSpace, wchUndef);
  659. if (lserr != lserrNone) return lserr;
  660. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchNonBreakHyphen, clabNonBreakHyphen, wchUndef);
  661. if (lserr != lserrNone) return lserr;
  662. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchNonReqHyphen, clabNonReqHyphen, wchUndef);
  663. if (lserr != lserrNone) return lserr;
  664. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchEmDash, clabHardHyphen, wchUndef);
  665. if (lserr != lserrNone) return lserr;
  666. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchEnDash, clabHardHyphen, wchUndef);
  667. if (lserr != lserrNone) return lserr;
  668. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchEnSpace, clabEnSpace, wchUndef);
  669. if (lserr != lserrNone) return lserr;
  670. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchEmSpace, clabEmSpace, wchUndef);
  671. if (lserr != lserrNone) return lserr;
  672. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchNarrowSpace, clabNarrowSpace, wchUndef);
  673. if (lserr != lserrNone) return lserr;
  674. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchOptBreak, clabOptBreak, wchUndef);
  675. if (lserr != lserrNone) return lserr;
  676. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchNoBreak, clabNonBreak, wchUndef);
  677. if (lserr != lserrNone) return lserr;
  678. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchFESpace, clabFESpace, wchUndef);
  679. if (lserr != lserrNone) return lserr;
  680. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchJoiner, clabJoiner, wchUndef);
  681. if (lserr != lserrNone) return lserr;
  682. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchNonJoiner, clabNonJoiner, wchUndef);
  683. if (lserr != lserrNone) return lserr;
  684. lserr = TxtAddSpec(pilsobj, plstxtcfg->wchToReplace, clabToReplace, wchUndef);
  685. if (lserr != lserrNone) return lserr;
  686. lserr = TxtSortSpec( pilsobj->rgwchSpec, pilsobj->rgbKind, pilsobj->cwchSpec);
  687. if (lserr != lserrNone) return lserr;
  688. Assert(pilsobj->pwchOrig == NULL && pilsobj->pdur == NULL && pilsobj->pwSpaces == NULL);
  689. pilsobj->wchMax = plstxtcfg->cEstimatedCharsPerLine;
  690. pilsobj->pwchOrig = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(WCHAR) * pilsobj->wchMax );
  691. pilsobj->pdur = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * pilsobj->wchMax );
  692. pilsobj->pwSpaces = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(long) * wSpacesMaxM);
  693. pilsobj->pbreakinf = (*pilsobj->plscbk->pfnNewPtr)(pilsobj->pols, sizeof(BREAKINFO) * 3);
  694. /* One for Prev/Next/Force Break for main subline */
  695. if (pilsobj->pwchOrig == NULL || pilsobj->pdur == NULL || pilsobj->pwSpaces == NULL ||
  696. pilsobj->pbreakinf == NULL)
  697. {
  698. return lserrOutOfMemory;
  699. }
  700. pilsobj->wSpacesMax = wSpacesMaxM;
  701. pilsobj->breakinfMax = 3;
  702. pilsobj->breakinfMac = 3;
  703. /* be careful---CreateLNObjText makes pilsobj->plnobj = NULL,
  704. if pilsobj->plnobj is not NULL
  705. */
  706. Assert(pilsobj->plnobj == NULL);
  707. lserr = CreateLNObjText(pilsobj, &pilsobj->plnobj);
  708. return lserr;
  709. }
  710. /* Internal Functions Implementation */
  711. /*----------------------------------------------------------------------------
  712. %%Function: ErrorLNObjText
  713. %%Contact: sergeyge
  714. ----------------------------------------------------------------------------*/
  715. static LSERR ErrorLNObjText(PLNOBJ* pplnobj, LSERR lserr)
  716. {
  717. DestroyLNObjTextCore(*pplnobj);
  718. *pplnobj = NULL;
  719. return lserr;
  720. }
  721. /*----------------------------------------------------------------------------
  722. %%Function: DestroyLNObjTextCore
  723. %%Contact: sergeyge
  724. ----------------------------------------------------------------------------*/
  725. static void DestroyLNObjTextCore(PLNOBJ plnobj)
  726. {
  727. PILSOBJ pilsobj;
  728. PTXTOBJ ptxtobj;
  729. PTXTOBJ ptxtobjNext;
  730. pilsobj = plnobj->pilsobj;
  731. ptxtobj = plnobj->ptxtobjFirst;
  732. while ( ptxtobj != NULL )
  733. {
  734. ptxtobjNext = *(TXTOBJ**)(ptxtobj + txtobjMaxM);
  735. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, ptxtobj);
  736. ptxtobj = ptxtobjNext;
  737. }
  738. plnobj->ptxtobjFirst = NULL;
  739. if ( plnobj->pwch != NULL )
  740. {
  741. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pwch);
  742. plnobj->pwch = NULL;
  743. }
  744. if ( plnobj->pdup != NULL )
  745. {
  746. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pdup);
  747. plnobj->pdup = NULL;
  748. }
  749. if ( plnobj->pdupPenAlloc != NULL )
  750. {
  751. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pdupPenAlloc);
  752. plnobj->pdupPenAlloc = NULL;
  753. }
  754. if ( plnobj->pgind != NULL )
  755. {
  756. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pgind);
  757. plnobj->pgind = NULL;
  758. }
  759. if ( plnobj->pdupGind != NULL )
  760. {
  761. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pdupGind);
  762. plnobj->pdupGind = NULL;
  763. }
  764. if ( plnobj->pgoffs != NULL )
  765. {
  766. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pgoffs);
  767. plnobj->pgoffs = NULL;
  768. }
  769. if ( plnobj->pexpt != NULL )
  770. {
  771. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pexpt);
  772. plnobj->pexpt = NULL;
  773. }
  774. if ( plnobj->pdupBeforeJust != NULL )
  775. {
  776. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pdupBeforeJust);
  777. plnobj->pdupBeforeJust = NULL;
  778. }
  779. if ( plnobj->pgprop != NULL )
  780. {
  781. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pgprop);
  782. plnobj->pgprop = NULL;
  783. }
  784. if ( plnobj->pgmap != NULL )
  785. {
  786. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, plnobj->pgmap);
  787. plnobj->pgmap = NULL;
  788. }
  789. (*pilsobj->plscbk->pfnDisposePtr) (pilsobj->pols, plnobj);
  790. return;
  791. }
  792. /* C H E C K C M O D W I D T H C L A S S E S */
  793. /*----------------------------------------------------------------------------
  794. %%Function: CheckCModWidthClasses
  795. %%Contact: sergeyge
  796. Checks that new cModWidthClasses does not contradict old one.
  797. If it does, disposes all relevant arrays
  798. ----------------------------------------------------------------------------*/
  799. static void CkeckModWidthClasses(PILSOBJ pilsobj, DWORD cModWidthClasses)
  800. {
  801. if (pilsobj->cModWidthClasses != cModWidthClasses)
  802. {
  803. if (pilsobj->pilspairact != NULL)
  804. {
  805. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pilspairact);
  806. pilsobj->pilspairact = NULL;
  807. }
  808. if (pilsobj->pilspract != NULL)
  809. {
  810. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pilspract);
  811. pilsobj->pilspract = NULL;
  812. }
  813. if (pilsobj->pilsexpan != NULL)
  814. {
  815. (*pilsobj->plscbk->pfnDisposePtr)(pilsobj->pols, pilsobj->pilsexpan);
  816. pilsobj->pilsexpan = NULL;
  817. }
  818. pilsobj->cModWidthClasses = cModWidthClasses;
  819. }
  820. }
  821. /* T X T A D D S P E C */
  822. /*----------------------------------------------------------------------------
  823. %%Function: TxtAddSpec
  824. %%Contact: sergeyge
  825. Sets special character in the ilsobj structure
  826. Strategy:
  827. if special character (wchSymbol) less than 256,
  828. set its type in the rgbSwitch[wchSymbol] (there cannot be more then 15 different types)
  829. if special character is greater than 256,
  830. set first bit of rgbSwitch[wchSymbol & 0x00FF]
  831. (it is independent of types of characters < 256 , since these types <= 15);
  832. also remember character and it's type in
  833. rgwchSpec, rgbKind respectively.
  834. ----------------------------------------------------------------------------*/
  835. static LSERR TxtAddSpec(PILSOBJ pilsobj, WCHAR wchSymbol, CLABEL clab, WCHAR wchUndef)
  836. {
  837. CLABEL* rgbSwitch;
  838. rgbSwitch = pilsobj->rgbSwitch;
  839. if (wchSymbol == wchUndef)
  840. {
  841. return lserrNone;
  842. }
  843. if (wchSymbol < 256)
  844. {
  845. if ( (rgbSwitch[wchSymbol] & fSpecMask) == 0)
  846. {
  847. rgbSwitch[wchSymbol] |= clab;
  848. }
  849. else
  850. {
  851. Assert(fFalse);
  852. return lserrDuplicateSpecialCharacter;
  853. }
  854. }
  855. else
  856. {
  857. rgbSwitch[wchSymbol & 0x00FF] |= clabSuspicious;
  858. pilsobj->rgwchSpec[pilsobj->cwchSpec] = wchSymbol;
  859. pilsobj->rgbKind[pilsobj->cwchSpec] = clab;
  860. pilsobj->cwchSpec++;
  861. }
  862. return lserrNone;
  863. }
  864. /* T X T S O R T S P E C */
  865. /*----------------------------------------------------------------------------
  866. %%Function: TxtSortSpec
  867. %%Contact: sergeyge
  868. Sorts rgwchSpec array (and moves elements of rgbKind appropriately)
  869. to make search for special chars >= 256 faster.
  870. ----------------------------------------------------------------------------*/
  871. static LSERR TxtSortSpec(WCHAR* rgwchSpec, CLABEL* rgbKind, DWORD cwchSpec)
  872. {
  873. int i, j, iMin;
  874. WCHAR wchChange;
  875. CLABEL clabChange;
  876. BOOL fChanged;
  877. for (i=0; i < (int)cwchSpec-1; i++)
  878. {
  879. iMin = i;
  880. fChanged = fFalse;
  881. for (j = i+1; j < (int)cwchSpec; j++)
  882. {
  883. if (rgwchSpec[j] < rgwchSpec[iMin])
  884. {
  885. fChanged = fTrue;
  886. iMin = j;
  887. }
  888. }
  889. if (fChanged)
  890. {
  891. clabChange = rgbKind[i];
  892. wchChange = rgwchSpec[i];
  893. rgbKind[i] = rgbKind[iMin];
  894. rgwchSpec[i] = rgwchSpec[iMin];
  895. rgbKind[iMin] = clabChange;
  896. rgwchSpec[iMin] = wchChange;
  897. }
  898. }
  899. for (i=0; i < (int)cwchSpec-1; i++)
  900. {
  901. if (rgwchSpec[i] == rgwchSpec[i+1])
  902. {
  903. Assert(fFalse);
  904. return lserrDuplicateSpecialCharacter;
  905. }
  906. }
  907. return lserrNone;
  908. }