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.

483 lines
12 KiB

  1. #include "lsmem.h"
  2. #include "lstxtqry.h"
  3. #include "txtils.h"
  4. #include "txtln.h"
  5. #include "txtobj.h"
  6. #include "lsqin.h"
  7. #include "lsqout.h"
  8. typedef struct celldimensions
  9. {
  10. long iwchFirst, iwchLim;
  11. long igindFirst, igindLim;
  12. long dup;
  13. long dcp; // number of cps in cell - different from iwchLim - iwchFirst
  14. // if hyphenation added a character
  15. // filled just before calling AddHyphenationToCell
  16. } CELL;
  17. typedef CELL* PCELL;
  18. static const POINTUV ptZero = {0,0};
  19. // %%Function: GetCellDimensions
  20. // %%Contact: victork
  21. //
  22. // Input: iwchFirst and igindFirst in CELL structure
  23. // Output: the rest of the structure
  24. static void GetCellDimensions(PTXTOBJ ptxtobj, PCELL pcell)
  25. {
  26. PLNOBJ plnobj = ptxtobj->plnobj;
  27. long* rgdup = plnobj->pdupGind; // widths of glyphs
  28. GMAP* pgmap = plnobj->pgmap; // first glyph in a cell with given character
  29. // 0 <= i <= wchMax (wchMax in lnobj)
  30. // 0 <= pgmap[i] <= "glyphs in a shape" (not igindMax)
  31. long i, dupCell;
  32. GMAP iShapeGindFirstInCell; // iShape means index from gmap, not index to rgdup
  33. // Assert that pcell->iwchFirst is really the cell boundary
  34. // Notice that ptxtinf (and everything in ilsobj) is not valid in query time)
  35. Assert(pcell->iwchFirst == ptxtobj->iwchFirst || pgmap[pcell->iwchFirst] != pgmap[pcell->iwchFirst-1]);
  36. // Assert that pcell->igindFirst corresponds to pcell->iwchFirst
  37. Assert(ptxtobj->igindFirst + pgmap[pcell->iwchFirst] - pgmap [ptxtobj->iwchFirst] == pcell->igindFirst);
  38. // find out dimentions of the cell - all characters have the same gmap value
  39. iShapeGindFirstInCell = pgmap[pcell->iwchFirst];
  40. // "infinite" loop will stop when pcell->iwchLim is found
  41. Assert(pcell->iwchFirst < ptxtobj->iwchLim); // ensure loop ends
  42. for (i = pcell->iwchFirst + 1; ; i++)
  43. {
  44. if (i == ptxtobj->iwchLim)
  45. {
  46. pcell->iwchLim = ptxtobj->iwchLim;
  47. pcell->igindLim = ptxtobj->igindLim;
  48. break;
  49. }
  50. else if (pgmap[i] != iShapeGindFirstInCell)
  51. {
  52. pcell->iwchLim = i;
  53. pcell->igindLim = pcell->igindFirst + pgmap[i] - iShapeGindFirstInCell;
  54. break;
  55. }
  56. }
  57. for (i = pcell->igindFirst, dupCell = 0; i < pcell->igindLim; i++)
  58. {
  59. dupCell += rgdup[i];
  60. }
  61. pcell->dup = dupCell;
  62. }
  63. // %%Function: AddHyphenationToCell
  64. // %%Contact: victork
  65. //
  66. static void AddHyphenationToCell(PTXTOBJ ptxtobj, PCELL pcell)
  67. {
  68. long* rgdup;
  69. long i;
  70. long dwch = ptxtobj->plnobj->dwchYsr - 1; /* number of chars to add */
  71. if (ptxtobj->txtf&txtfGlyphBased)
  72. {
  73. rgdup = ptxtobj->plnobj->pdupGind;
  74. i = pcell->igindLim;
  75. while (dwch > 0)
  76. {
  77. pcell->dup += rgdup[i];
  78. pcell->iwchLim ++;
  79. pcell->igindLim ++; // there are no ligatures amongst added characters
  80. dwch--;
  81. i++;
  82. }
  83. }
  84. else
  85. {
  86. rgdup = ptxtobj->plnobj->pdup;
  87. i = pcell->iwchLim;
  88. while (dwch > 0)
  89. {
  90. pcell->dup += rgdup[i];
  91. pcell->iwchLim ++;
  92. dwch--;
  93. i++;
  94. }
  95. }
  96. Assert(pcell->iwchLim == (long) ptxtobj->iwchLim);
  97. }
  98. // %%Function: QueryDcpPcell
  99. // %%Contact: victork
  100. //
  101. static void QueryDcpPcell(PTXTOBJ ptxtobj, LSDCP dcp, PCELL pcell, long* pupStartCell)
  102. {
  103. PLNOBJ plnobj = ptxtobj->plnobj;
  104. long iwchLim = (long) ptxtobj->iwchLim;
  105. long* rgdup;
  106. long i;
  107. CELL cell = {0,0,0,0,0,0};
  108. long iwchQuery;
  109. long upStartCell;
  110. BOOL fHyphenationPresent = fFalse;
  111. if (ptxtobj == plnobj->pdobjHyphen)
  112. {
  113. fHyphenationPresent = fTrue;
  114. iwchLim -= (plnobj->dwchYsr - 1); /* exclude additional Ysr characters */
  115. }
  116. iwchQuery = ptxtobj->iwchFirst + dcp;
  117. Assert(iwchQuery < iwchLim);
  118. if (ptxtobj->txtf&txtfGlyphBased)
  119. {
  120. // initialize loop variables to describe non-existent previous cell
  121. upStartCell = 0;
  122. cell.iwchLim = ptxtobj->iwchFirst;
  123. cell.igindLim = ptxtobj->igindFirst;
  124. cell.dup = 0;
  125. // loop does cell after cell until the cell containing iwchQuery is found
  126. while (cell.iwchLim <= iwchQuery)
  127. {
  128. // start filling info about current cell
  129. upStartCell += cell.dup;
  130. cell.iwchFirst = cell.iwchLim;
  131. cell.igindFirst = cell.igindLim;
  132. // get the rest
  133. GetCellDimensions(ptxtobj, &cell);
  134. }
  135. }
  136. else
  137. {
  138. rgdup = plnobj->pdup;
  139. i = ptxtobj->iwchFirst;
  140. upStartCell = 0;
  141. while (dcp > 0)
  142. {
  143. upStartCell += rgdup[i];
  144. dcp--;
  145. i++;
  146. }
  147. Assert(i < iwchLim); /* I'm given dcp inside */
  148. // put the info into cell structure
  149. cell.dup = rgdup[i];
  150. cell.iwchFirst = i;
  151. cell.iwchLim = i+1;
  152. // these two are irrelevant, but for the sake of convenience...
  153. cell.igindFirst = i;
  154. cell.igindLim = i;
  155. }
  156. cell.dcp = cell.iwchLim - cell.iwchFirst; // hyphenation can change that
  157. // YSR can extend the last cell
  158. if (fHyphenationPresent && cell.iwchLim == iwchLim)
  159. {
  160. // the cell is up to the YSR sequence - let's include it
  161. AddHyphenationToCell(ptxtobj, &cell);
  162. }
  163. *pcell = cell;
  164. *pupStartCell = upStartCell;
  165. }
  166. // %%Function: QueryCpPpointText
  167. // %%Contact: victork
  168. //
  169. /* Input is dcp and dnode dimensions
  170. * Output is point where character begins (on baseline of dnode, so v is always zero),
  171. * dimensions of the character - only width is calculated
  172. */
  173. LSERR WINAPI QueryCpPpointText(PDOBJ pdobj, LSDCP dcp, PCLSQIN plsqin, PLSQOUT plsqout)
  174. {
  175. PTXTOBJ ptxtobj = (PTXTOBJ)pdobj;
  176. CELL cell;
  177. long upStartCell;
  178. plsqout->pointUvStartObj = ptZero;
  179. plsqout->heightsPresObj = plsqin->heightsPresRun;
  180. plsqout->dupObj = plsqin->dupRun;
  181. plsqout->plssubl = NULL;
  182. plsqout->pointUvStartSubline = ptZero;
  183. plsqout->lstextcell.pointUvStartCell = ptZero; // u can be changed later
  184. if (ptxtobj->txtkind == txtkindTab)
  185. {
  186. // A tab is always in a separate dnode and is treated differently
  187. Assert(dcp == 0);
  188. plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun;
  189. plsqout->lstextcell.cpEndCell = plsqin->cpFirstRun;
  190. plsqout->lstextcell.dupCell = plsqin->dupRun;
  191. plsqout->lstextcell.cCharsInCell = 1;
  192. plsqout->lstextcell.cGlyphsInCell = 0;
  193. return lserrNone;
  194. }
  195. if (ptxtobj->iwchFirst == ptxtobj->iwchLim)
  196. {
  197. // empty dobj (for NonReqHyphen, OptBreak, or NonBreak characters)
  198. Assert(dcp == 0);
  199. Assert(plsqin->dupRun == 0);
  200. Assert(ptxtobj->txtkind == txtkindNonReqHyphen || ptxtobj->txtkind == txtkindOptBreak ||
  201. ptxtobj->txtkind == txtkindOptNonBreak);
  202. plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun;
  203. plsqout->lstextcell.cpEndCell = plsqin->cpFirstRun;
  204. plsqout->lstextcell.dupCell = 0;
  205. plsqout->lstextcell.cCharsInCell = 0;
  206. plsqout->lstextcell.cGlyphsInCell = 0;
  207. return lserrNone;
  208. }
  209. // Find the cell - common with QueryTextCellDetails
  210. QueryDcpPcell(ptxtobj, dcp, &cell, &upStartCell);
  211. plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun + cell.iwchFirst - ptxtobj->iwchFirst;
  212. plsqout->lstextcell.cpEndCell = plsqout->lstextcell.cpStartCell + cell.dcp - 1;
  213. plsqout->lstextcell.pointUvStartCell.u = upStartCell;
  214. plsqout->lstextcell.dupCell = cell.dup;
  215. plsqout->lstextcell.cCharsInCell = cell.iwchLim - cell.iwchFirst;
  216. plsqout->lstextcell.cGlyphsInCell = cell.igindLim - cell.igindFirst;
  217. return lserrNone;
  218. }
  219. // %%Function: QueryPointPcpText
  220. // %%Contact: victork
  221. //
  222. LSERR WINAPI QueryPointPcpText(PDOBJ pdobj, PCPOINTUV pptIn, PCLSQIN plsqin, PLSQOUT plsqout)
  223. {
  224. PTXTOBJ ptxtobj = (PTXTOBJ)pdobj;
  225. PLNOBJ plnobj = ptxtobj->plnobj;
  226. long iwchLim = (long) ptxtobj->iwchLim;
  227. BOOL fHyphenationPresent = fFalse;
  228. long* rgdup;
  229. long i;
  230. long upQuery, upStartCell, upLimCell;
  231. CELL cell = {0,0,0,0,0,0}; // init'ed to get rid of assert
  232. plsqout->pointUvStartObj = ptZero;
  233. plsqout->heightsPresObj = plsqin->heightsPresRun;
  234. plsqout->dupObj = plsqin->dupRun;
  235. plsqout->plssubl = NULL;
  236. plsqout->pointUvStartSubline = ptZero;
  237. plsqout->lstextcell.pointUvStartCell = ptZero; // u can change later
  238. if (ptxtobj->txtkind == txtkindTab)
  239. {
  240. // A tab is always in a separate dnode and is treated differently
  241. plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun;
  242. plsqout->lstextcell.cpEndCell = plsqin->cpFirstRun;
  243. plsqout->lstextcell.dupCell = plsqin->dupRun;
  244. plsqout->lstextcell.cCharsInCell = 1;
  245. plsqout->lstextcell.cGlyphsInCell = 0;
  246. return lserrNone;
  247. }
  248. if (ptxtobj == plnobj->pdobjHyphen)
  249. {
  250. fHyphenationPresent = fTrue;
  251. iwchLim -= (plnobj->dwchYsr - 1); /* exclude additional Ysr characters */
  252. }
  253. upQuery = pptIn->u;
  254. if (upQuery < 0)
  255. {
  256. upQuery = 0; // return leftmost when clicked outside left
  257. }
  258. upStartCell = 0;
  259. if (ptxtobj->txtf&txtfGlyphBased)
  260. {
  261. // initialize loop variables to describe non-existent previous cell
  262. upLimCell = 0;
  263. cell.iwchLim = ptxtobj->iwchFirst;
  264. cell.igindLim = ptxtobj->igindFirst;
  265. cell.dup = 0;
  266. // loop does cell after cell until the last cell or the cell containing upQuery
  267. while (cell.iwchLim < iwchLim && upLimCell <= upQuery)
  268. {
  269. // start filling info about current cell
  270. upStartCell = upLimCell;
  271. cell.iwchFirst = cell.iwchLim;
  272. cell.igindFirst = cell.igindLim;
  273. // get the rest
  274. GetCellDimensions(ptxtobj, &cell);
  275. upLimCell = upStartCell + cell.dup;
  276. }
  277. }
  278. else
  279. {
  280. rgdup = plnobj->pdup;
  281. i = ptxtobj->iwchFirst;
  282. upLimCell = 0;
  283. while (upLimCell <= upQuery && i < iwchLim)
  284. {
  285. upStartCell = upLimCell;
  286. upLimCell += rgdup[i];
  287. i++;
  288. }
  289. // put the info into cell structure
  290. cell.dup = rgdup[i - 1];
  291. cell.iwchFirst = i - 1;
  292. cell.iwchLim = i;
  293. // these two are irrelevant, but for the sake of convenience...
  294. cell.igindFirst = i - 1;
  295. cell.igindLim = i - 1;
  296. }
  297. cell.dcp = cell.iwchLim - cell.iwchFirst; // hyphenation can change that
  298. // YSR can extend the last cell
  299. if (fHyphenationPresent && cell.iwchLim == iwchLim)
  300. {
  301. // the cell is up to the YSR sequence - let's include it
  302. AddHyphenationToCell(ptxtobj, &cell);
  303. }
  304. plsqout->lstextcell.cpStartCell = plsqin->cpFirstRun + cell.iwchFirst - ptxtobj->iwchFirst;
  305. plsqout->lstextcell.cpEndCell = plsqout->lstextcell.cpStartCell + cell.dcp - 1;
  306. plsqout->lstextcell.pointUvStartCell.u = upStartCell;
  307. plsqout->lstextcell.dupCell = cell.dup;
  308. plsqout->lstextcell.cCharsInCell = cell.iwchLim - cell.iwchFirst;
  309. plsqout->lstextcell.cGlyphsInCell = cell.igindLim - cell.igindFirst;
  310. return lserrNone;
  311. }
  312. // %%Function: QueryTextCellDetails
  313. // %%Contact: victork
  314. //
  315. LSERR WINAPI QueryTextCellDetails(
  316. PDOBJ pdobj,
  317. LSDCP dcp, /* IN: dcpStartCell */
  318. DWORD cChars, /* IN: cCharsInCell */
  319. DWORD cGlyphs, /* IN: cGlyphsInCell */
  320. LPWSTR pwchOut, /* OUT: pointer array[cChars] of char codes */
  321. PGINDEX pgindex, /* OUT: pointer array[cGlyphs] of glyph indices */
  322. long* pdup, /* OUT: pointer array[cGlyphs] of glyph widths */
  323. PGOFFSET pgoffset, /* OUT: pointer array[cGlyphs] of glyph offsets */
  324. PGPROP pgprop) /* OUT: pointer array[cGlyphs] of glyph handles */
  325. {
  326. PTXTOBJ ptxtobj = (PTXTOBJ)pdobj;
  327. PLNOBJ plnobj = ptxtobj->plnobj;
  328. CELL cell;
  329. long upDummy;
  330. Unreferenced(cGlyphs);
  331. Unreferenced(cChars); // used only in an assert
  332. if (ptxtobj->txtkind == txtkindTab)
  333. {
  334. // Tab is in a separate dnode always and is treated differently
  335. Assert(dcp == 0);
  336. Assert(cChars == 1);
  337. *pwchOut = ptxtobj->u.tab.wch;
  338. *pdup = (ptxtobj->plnobj->pdup)[ptxtobj->iwchFirst];
  339. return lserrNone;
  340. }
  341. if (ptxtobj->iwchFirst == ptxtobj->iwchLim)
  342. {
  343. // empty dobj (for NonReqHyphen, OptBreak, or NonBreak characters)
  344. Assert(dcp == 0);
  345. Assert(cChars == 0);
  346. Assert(cGlyphs == 0);
  347. return lserrNone;
  348. }
  349. // Find the cell - common with QueryCpPpointText
  350. QueryDcpPcell(ptxtobj, dcp, &cell, &upDummy);
  351. Assert(cell.iwchLim - cell.iwchFirst == (long) cChars);
  352. memcpy(pwchOut, &plnobj->pwch[cell.iwchFirst], sizeof(long) * cChars);
  353. if (ptxtobj->txtf&txtfGlyphBased)
  354. {
  355. Assert(cell.igindLim - cell.igindFirst == (long) cGlyphs);
  356. memcpy(pdup, &plnobj->pdupGind[cell.igindFirst], sizeof(long) * cGlyphs);
  357. memcpy(pgindex, &plnobj->pgind[cell.igindFirst], sizeof(long) * cGlyphs);
  358. memcpy(pgoffset, &plnobj->pgoffs[cell.igindFirst], sizeof(long) * cGlyphs);
  359. memcpy(pgprop, &plnobj->pgprop[cell.igindFirst], sizeof(long) * cGlyphs);
  360. }
  361. else
  362. {
  363. memcpy(pdup, &plnobj->pdup[cell.iwchFirst], sizeof(long) * cChars);
  364. }
  365. return lserrNone;
  366. }