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.

518 lines
16 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. candpos.cpp
  5. Abstract:
  6. This file implements the CCandidatePosition Class.
  7. Author:
  8. Revision History:
  9. Notes:
  10. --*/
  11. #include "private.h"
  12. #include "candpos.h"
  13. #include "a_context.h"
  14. #include "ctxtcomp.h"
  15. HRESULT
  16. CCandidatePosition::GetCandidatePosition(
  17. OUT RECT* out_rcArea
  18. )
  19. {
  20. IMTLS *ptls;
  21. ptls = IMTLS_GetOrAlloc();
  22. if (ptls == NULL)
  23. return E_FAIL;
  24. HRESULT hr;
  25. IMCLock imc(ptls->hIMC);
  26. if (FAILED(hr = imc.GetResult()))
  27. return hr;
  28. ::SetRect(out_rcArea, 0, 0, 0, 0);
  29. LANGID langid;
  30. ptls->pAImeProfile->GetLangId(&langid);
  31. #if 0
  32. //
  33. // Simplified Chinese TIP's Candidate window create ic and Push it.
  34. // AIMM can know candidate window status.
  35. // If it opened, we returns position of imc->cfCandForm.
  36. // Not use QueryCharPos() because it returns position of Reading window.
  37. //
  38. if (langid == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)) {
  39. CAImeContext* _pAImeContext = imc->m_pAImeContext;
  40. if (_pAImeContext == NULL)
  41. return E_FAIL;
  42. if (_pAImeContext->m_fOpenCandidateWindow) {
  43. if (imc->cfCandForm[0].dwStyle != CFS_DEFAULT && imc->cfCandForm[0].dwStyle != CFS_EXCLUDE) {
  44. #if 0
  45. //
  46. // Chinese TIP needs rectangle
  47. //
  48. IMECHARPOSITION ip = {0};
  49. ip.dwSize = sizeof(IMECHARPOSITION);
  50. if (QueryCharPos(ptls, imc, &ip)) {
  51. //
  52. // Sure. Support "query positioning".
  53. //
  54. RECT rect;
  55. hr = GetRectFromApp(ptls,
  56. imc,
  57. &rect); // rect = screen coordinate.
  58. if (SUCCEEDED(hr)) {
  59. MapWindowPoints(HWND_DESKTOP, imc->hWnd, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
  60. hr = GetRectFromHIMC(imc,
  61. CFS_EXCLUDE,
  62. &imc->cfCandForm[0].ptCurrentPos,
  63. &rect,
  64. out_rcArea);
  65. if (SUCCEEDED(hr))
  66. return hr;
  67. }
  68. }
  69. #endif
  70. //
  71. // Chinese TIP needs rectangle
  72. //
  73. hr = GetRectFromCompFont(ptls,
  74. imc,
  75. &imc->cfCandForm[0].ptCurrentPos,
  76. out_rcArea);
  77. if (SUCCEEDED(hr))
  78. return hr;
  79. }
  80. hr = GetRectFromHIMC(imc,
  81. imc->cfCandForm[0].dwStyle,
  82. &imc->cfCandForm[0].ptCurrentPos,
  83. &imc->cfCandForm[0].rcArea,
  84. out_rcArea);
  85. return hr;
  86. }
  87. }
  88. #endif
  89. CAImeContext* _pAImeContext = imc->m_pAImeContext;
  90. if (_pAImeContext == NULL)
  91. return E_FAIL;
  92. //
  93. // Is apps support "query positioning" ?
  94. //
  95. CAImeContext::IME_QUERY_POS qpos;
  96. if (SUCCEEDED(_pAImeContext->InquireIMECharPosition(imc, &qpos)) &&
  97. qpos == CAImeContext::IME_QUERY_POS_YES) {
  98. //
  99. // Sure. Support "query positioning".
  100. //
  101. hr = GetRectFromApp(ptls,
  102. imc,
  103. langid,
  104. out_rcArea);
  105. if (SUCCEEDED(hr))
  106. return hr;
  107. else
  108. _pAImeContext->ResetIMECharPosition(imc);
  109. }
  110. if ( (PRIMARYLANGID(langid) == LANG_CHINESE) &&
  111. (imc->cfCandForm[0].dwIndex == -1))
  112. {
  113. //
  114. // Assume CHT/CHS's Reading Window Position.
  115. //
  116. hr = GetRectFromHIMC(imc,
  117. imc->cfCompForm.dwStyle,
  118. &imc->cfCompForm.ptCurrentPos,
  119. &imc->cfCompForm.rcArea,
  120. out_rcArea);
  121. return hr;
  122. }
  123. hr = GetRectFromHIMC(imc,
  124. imc->cfCandForm[0].dwStyle,
  125. &imc->cfCandForm[0].ptCurrentPos,
  126. &imc->cfCandForm[0].rcArea,
  127. out_rcArea);
  128. return hr;
  129. }
  130. HRESULT
  131. CCandidatePosition::GetRectFromApp(
  132. IN IMTLS* ptls,
  133. IN IMCLock& imc,
  134. IN LANGID langid,
  135. OUT RECT* out_rcArea
  136. )
  137. {
  138. CAImeContext* _pAImeContext = imc->m_pAImeContext;
  139. if (_pAImeContext == NULL)
  140. return E_FAIL;
  141. IMECHARPOSITION ip = {0};
  142. ip.dwSize = sizeof(IMECHARPOSITION);
  143. CWCompCursorPos wCursorPosition;
  144. HRESULT hr;
  145. if (PRIMARYLANGID(langid) == LANG_JAPANESE &&
  146. (hr = FindAttributeInCompositionString(imc,
  147. ATTR_TARGET_CONVERTED,
  148. wCursorPosition)) == S_OK) {
  149. ip.dwCharPos = wCursorPosition.GetAt(0);
  150. }
  151. else {
  152. if (SUCCEEDED(hr = GetCursorPosition(imc,
  153. wCursorPosition))) {
  154. CWCompCursorPos wStartSelection;
  155. CWCompCursorPos wEndSelection;
  156. if (SUCCEEDED(hr = GetSelection(imc,
  157. wStartSelection, wEndSelection))) {
  158. ip.dwCharPos = min(wCursorPosition.GetAt(0),
  159. wStartSelection.GetAt(0));
  160. }
  161. else {
  162. ip.dwCharPos = wCursorPosition.GetAt(0);
  163. }
  164. }
  165. else {
  166. ip.dwCharPos = 0;
  167. }
  168. }
  169. if (SUCCEEDED(hr = _pAImeContext->RetrieveIMECharPosition(imc, &ip))) {
  170. switch (DocumentDirection(imc)) {
  171. case DIR_TOP_BOTTOM:
  172. ::SetRect(out_rcArea,
  173. ip.pt.x - ip.cLineHeight, // left
  174. ip.pt.y, // top
  175. ip.pt.x, // right
  176. max(ip.pt.y, ip.rcDocument.bottom)); // bottom
  177. break;
  178. case DIR_BOTTOM_TOP:
  179. ::SetRect(out_rcArea,
  180. ip.pt.x - ip.cLineHeight, // left
  181. min(ip.pt.y, ip.rcDocument.top), // top
  182. ip.pt.x, // right
  183. ip.pt.y); // bottom
  184. break;
  185. case DIR_RIGHT_LEFT:
  186. ::SetRect(out_rcArea,
  187. min(ip.pt.x, ip.rcDocument.left), // left
  188. ip.pt.y, // top
  189. ip.pt.x, // right
  190. ip.pt.y + ip.cLineHeight); // bottom
  191. break;
  192. case DIR_LEFT_RIGHT:
  193. ::SetRect(out_rcArea,
  194. ip.pt.x, // left
  195. ip.pt.y, // top
  196. max(ip.pt.x, ip.rcDocument.right), // right
  197. ip.pt.y + ip.cLineHeight); // bottom
  198. break;
  199. }
  200. }
  201. return hr;
  202. }
  203. HRESULT
  204. CCandidatePosition::GetRectFromHIMC(
  205. IN IMCLock& imc,
  206. IN DWORD dwStyle,
  207. IN POINT* ptCurrentPos,
  208. IN RECT* rcArea,
  209. OUT RECT* out_rcArea
  210. )
  211. {
  212. HWND hWnd = imc->hWnd;
  213. POINT pt;
  214. if (dwStyle == CFS_DEFAULT)
  215. {
  216. ::SystemParametersInfo(SPI_GETWORKAREA,
  217. 0,
  218. out_rcArea,
  219. 0);
  220. out_rcArea->left = out_rcArea->right;
  221. out_rcArea->top = out_rcArea->bottom;
  222. }
  223. else if (dwStyle == CFS_RECT)
  224. {
  225. out_rcArea->left = ptCurrentPos->x;
  226. out_rcArea->right = ptCurrentPos->x;
  227. out_rcArea->top = ptCurrentPos->y;
  228. out_rcArea->bottom = ptCurrentPos->y;
  229. }
  230. else if (dwStyle == CFS_CANDIDATEPOS)
  231. {
  232. IMTLS *ptls;
  233. ptls = IMTLS_GetOrAlloc();
  234. if (ptls == NULL)
  235. return E_FAIL;
  236. //
  237. // We needs rectangle
  238. //
  239. return GetRectFromCompFont(ptls,
  240. imc,
  241. ptCurrentPos,
  242. out_rcArea);
  243. }
  244. else if (dwStyle == CFS_EXCLUDE)
  245. {
  246. GetCandidateArea(imc, dwStyle, ptCurrentPos, rcArea, out_rcArea);
  247. }
  248. pt.x = pt.y = 0;
  249. ClientToScreen(hWnd, &pt);
  250. out_rcArea->left += pt.x;
  251. out_rcArea->right += pt.x;
  252. out_rcArea->top += pt.y;
  253. out_rcArea->bottom += pt.y;
  254. return S_OK;
  255. }
  256. HRESULT
  257. CCandidatePosition::GetRectFromCompFont(
  258. IN IMTLS* ptls,
  259. IN IMCLock& imc,
  260. IN POINT* ptCurrentPos,
  261. OUT RECT* out_rcArea
  262. )
  263. {
  264. HRESULT hr = E_FAIL;
  265. HDC dc = ::GetDC(imc->hWnd);
  266. if (dc != NULL) {
  267. LOGFONTA logfont;
  268. if (SUCCEEDED(ptls->pAImm->GetCompositionFontA((HIMC)imc, &logfont))) {
  269. HFONT font = ::CreateFontIndirectA( &logfont );
  270. if (font != NULL) {
  271. HFONT prev_font;
  272. prev_font = (HFONT)::SelectObject(dc, font);
  273. TEXTMETRIC metric;
  274. if (::GetTextMetrics(dc, &metric)) {
  275. int font_cx = metric.tmMaxCharWidth;
  276. int font_cy = metric.tmHeight;
  277. switch (DocumentDirection(imc)) {
  278. case DIR_TOP_BOTTOM:
  279. ::SetRect(out_rcArea,
  280. ptCurrentPos->x - font_cx, // left
  281. ptCurrentPos->y, // top
  282. ptCurrentPos->x, // right
  283. ptCurrentPos->y + font_cy); // bottom
  284. break;
  285. case DIR_BOTTOM_TOP:
  286. ::SetRect(out_rcArea,
  287. ptCurrentPos->x, // left
  288. ptCurrentPos->y - font_cy, // top
  289. ptCurrentPos->x + font_cx, // right
  290. ptCurrentPos->y); // bottom
  291. break;
  292. case DIR_RIGHT_LEFT:
  293. ::SetRect(out_rcArea,
  294. ptCurrentPos->x - font_cx, // left
  295. ptCurrentPos->y - font_cy, // top
  296. ptCurrentPos->x, // right
  297. ptCurrentPos->y); // bottom
  298. break;
  299. case DIR_LEFT_RIGHT:
  300. ::SetRect(out_rcArea,
  301. ptCurrentPos->x, // left
  302. ptCurrentPos->y, // top
  303. ptCurrentPos->x + font_cx, // right
  304. ptCurrentPos->y + font_cy); // bottom
  305. break;
  306. }
  307. POINT pt;
  308. pt.x = pt.y = 0;
  309. ClientToScreen(imc->hWnd, &pt);
  310. out_rcArea->left += pt.x;
  311. out_rcArea->right += pt.x;
  312. out_rcArea->top += pt.y;
  313. out_rcArea->bottom += pt.y;
  314. hr = S_OK;
  315. }
  316. ::SelectObject(dc, prev_font);
  317. ::DeleteObject(font);
  318. }
  319. }
  320. ::ReleaseDC(imc->hWnd, dc);
  321. }
  322. return hr;
  323. }
  324. /*
  325. *
  326. * dwStyle == CFS_EXCLUDE
  327. *
  328. */
  329. HRESULT
  330. CCandidatePosition::GetCandidateArea(
  331. IN IMCLock& imc,
  332. IN DWORD dwStyle,
  333. IN POINT* ptCurrentPos,
  334. IN RECT* rcArea,
  335. OUT RECT* out_rcArea
  336. )
  337. {
  338. POINT pt = *ptCurrentPos;
  339. RECT rc = *rcArea;
  340. switch (DocumentDirection(imc)) {
  341. case DIR_TOP_BOTTOM:
  342. ::SetRect(out_rcArea,
  343. min(pt.x, rcArea->left), // left
  344. max(pt.y, rcArea->top), // top
  345. max(pt.x, rcArea->right), // right
  346. rcArea->bottom); // bottom
  347. break;
  348. case DIR_BOTTOM_TOP:
  349. ::SetRect(out_rcArea,
  350. min(pt.x, rcArea->left), // left
  351. rcArea->top, // top
  352. max(pt.x, rcArea->right), // right
  353. min(pt.y, rcArea->bottom)); // bottom
  354. break;
  355. case DIR_RIGHT_LEFT:
  356. ::SetRect(out_rcArea,
  357. rcArea->left, // left
  358. min(pt.y, rcArea->top), // top
  359. min(pt.x, rcArea->right), // right
  360. max(pt.y, rcArea->bottom)); // bottom
  361. break;
  362. case DIR_LEFT_RIGHT:
  363. ::SetRect(out_rcArea,
  364. max(pt.x, rcArea->left), // left
  365. min(pt.y, rcArea->top), // top
  366. rcArea->right, // right
  367. max(pt.y, rcArea->bottom)); // bottom
  368. break;
  369. }
  370. return S_OK;
  371. }
  372. HRESULT
  373. CCandidatePosition::FindAttributeInCompositionString(
  374. IN IMCLock& imc,
  375. IN BYTE target_attribute,
  376. OUT CWCompCursorPos& wCursorPosition
  377. )
  378. {
  379. HRESULT hr = E_FAIL;
  380. CAImeContext* _pAImeContext = imc->m_pAImeContext;
  381. if (_pAImeContext != NULL) {
  382. CWCompString wCompString;
  383. CWCompAttribute wCompAttribute;
  384. if (SUCCEEDED(hr = _pAImeContext->GetTextAndAttribute((HIMC)imc,
  385. &wCompString, &wCompAttribute))) {
  386. LONG num_of_written = (LONG)wCompAttribute.ReadCompData();
  387. if (num_of_written == 0)
  388. return E_FAIL;
  389. BYTE* attribute = new BYTE[ num_of_written ];
  390. if (attribute != NULL) {
  391. //
  392. // Get attribute data.
  393. //
  394. wCompAttribute.ReadCompData(attribute, num_of_written);
  395. LONG start_position = 0;
  396. LONG ich = 0;
  397. LONG attr_size = num_of_written;
  398. while (ich < attr_size && attribute[ich] != target_attribute)
  399. ich++;
  400. if (ich < attr_size) {
  401. start_position = ich;
  402. }
  403. else {
  404. //
  405. // If not hit with target_attribute, then returns S_FALSE.
  406. //
  407. hr = S_FALSE;
  408. }
  409. wCursorPosition.Set(start_position);
  410. delete [] attribute;
  411. }
  412. }
  413. }
  414. return hr;
  415. }
  416. HRESULT
  417. CCandidatePosition::GetCursorPosition(
  418. IN IMCLock& imc,
  419. OUT CWCompCursorPos& wCursorPosition
  420. )
  421. {
  422. HRESULT hr = E_FAIL;
  423. CAImeContext* _pAImeContext = imc->m_pAImeContext;
  424. if (_pAImeContext != NULL) {
  425. hr = _pAImeContext->GetCursorPosition((HIMC)imc, &wCursorPosition);
  426. }
  427. return hr;
  428. }
  429. HRESULT
  430. CCandidatePosition::GetSelection(
  431. IN IMCLock& imc,
  432. OUT CWCompCursorPos& wStartSelection,
  433. OUT CWCompCursorPos& wEndSelection
  434. )
  435. {
  436. HRESULT hr = E_FAIL;
  437. CAImeContext* _pAImeContext = imc->m_pAImeContext;
  438. if (_pAImeContext != NULL) {
  439. hr = _pAImeContext->GetSelection((HIMC)imc, wStartSelection, wEndSelection);
  440. }
  441. return hr;
  442. }