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.

622 lines
22 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. editcomp.cpp
  5. Abstract:
  6. This file implements the EditCompositionString Class.
  7. Author:
  8. Revision History:
  9. Notes:
  10. --*/
  11. #include "private.h"
  12. #include "immif.h"
  13. #include "editcomp.h"
  14. #include "template.h"
  15. #include "compstr.h"
  16. static BOOL fHanjaRequested = FALSE; // consider: this is not thread safe
  17. /////////////////////////////////////////////////////////////////////////////
  18. // EditCompositionString
  19. //
  20. // Set (almost) all in composition string
  21. //
  22. HRESULT
  23. EditCompositionString::SetString(
  24. IMCLock& imc,
  25. CWCompString* CompStr,
  26. CWCompAttribute* CompAttr,
  27. CWCompClause* CompClause,
  28. CWCompCursorPos* CompCursorPos,
  29. CWCompDeltaStart* CompDeltaStart,
  30. CWCompTfGuidAtom* CompGuid,
  31. OUT BOOL* lpbBufferOverflow,
  32. CWCompString* CompReadStr,
  33. CWCompAttribute* CompReadAttr,
  34. CWCompClause* CompReadClause,
  35. CWCompString* ResultStr,
  36. CWCompClause* ResultClause,
  37. CWCompString* ResultReadStr,
  38. CWCompClause* ResultReadClause,
  39. CWInterimString* InterimStr,
  40. // n.b. ResultRead is not supported for now...
  41. BOOL fGenerateMessage
  42. )
  43. {
  44. HRESULT hr;
  45. CAImeContext* _pAImeContext = imc->m_pAImeContext;
  46. if (_pAImeContext == NULL)
  47. return E_FAIL;
  48. #ifdef UNSELECTCHECK
  49. if (!_pAImeContext->m_fSelected)
  50. return S_OK;
  51. #endif UNSELECTCHECK
  52. if (_pAImeContext->m_fHanjaReConversion ||
  53. _pAImeContext->IsInClearDocFeedEditSession())
  54. {
  55. if (g_fTrident55 && _pAImeContext->m_fHanjaReConversion)
  56. fHanjaRequested = TRUE;
  57. return S_OK;
  58. }
  59. //
  60. // Clear the contents of candidate list
  61. //
  62. imc.ClearCand();
  63. TRANSMSG msg;
  64. if (InterimStr) {
  65. hr = _MakeInterimData(imc,
  66. InterimStr,
  67. &msg.lParam);
  68. }
  69. else {
  70. hr = _MakeCompositionData(imc,
  71. CompStr, CompAttr, CompClause,
  72. CompCursorPos, CompDeltaStart,
  73. CompGuid,
  74. CompReadStr, CompReadAttr, CompReadClause,
  75. ResultStr, ResultClause,
  76. ResultReadStr, ResultReadClause,
  77. &msg.lParam,
  78. lpbBufferOverflow);
  79. }
  80. if ( hr == S_OK || // In case of valid dwCompSize in the CCompStrFactory::CreateCompositionString
  81. (hr == S_FALSE && _pAImeContext->m_fStartComposition)
  82. // In case of empty dwCompSize but still m_fStartComposition
  83. ) {
  84. //
  85. // Is available compstr/attr/clause, compread, result or resultread ?
  86. //
  87. bool fNoCompResultData = false;
  88. if (! (msg.lParam & (GCS_COMP | GCS_COMPREAD | GCS_RESULT | GCS_RESULTREAD))) {
  89. DebugMsg(TF_GENERAL, "EditCompositionString::SetString: No data in compstr, compread, result or resultread.");
  90. fNoCompResultData = true;
  91. if ( _pAImeContext &&
  92. ! _pAImeContext->m_fStartComposition) {
  93. DebugMsg(TF_ERROR, "EditCompositionString::SetString: No send WM_IME_STARTCOMPOSITION yet.");
  94. return S_FALSE;
  95. }
  96. }
  97. //
  98. // New Trident(5.5 & 6.0) had a bug to convert Hanja.
  99. // So _GenerateHanja() funtion try to generate message like as Korean
  100. // legacy IME behavior.
  101. //
  102. // Send WM_IME_ENDCOMPOSITION and then WM_IME_COMPOSITION GCS_RESULT msg.
  103. //
  104. if (g_fTrident55 && fHanjaRequested &&
  105. !fNoCompResultData && (msg.lParam & GCS_RESULT))
  106. {
  107. LANGID langid;
  108. IMTLS *ptls = IMTLS_GetOrAlloc();
  109. fHanjaRequested = FALSE;
  110. if (ptls != NULL)
  111. ptls->pAImeProfile->GetLangId(&langid);
  112. if (PRIMARYLANGID(langid) == LANG_KOREAN)
  113. {
  114. return _GenerateHanja(imc, ResultStr, fGenerateMessage);
  115. }
  116. }
  117. fHanjaRequested = FALSE;
  118. //
  119. // set private input context
  120. //
  121. bool fSetStartComp = false;
  122. if ( _pAImeContext &&
  123. ! _pAImeContext->m_fStartComposition) {
  124. _pAImeContext->m_fStartComposition = TRUE;
  125. TRANSMSG start_msg;
  126. start_msg.message = WM_IME_STARTCOMPOSITION;
  127. start_msg.wParam = (WPARAM) 0;
  128. start_msg.lParam = (LPARAM) 0;
  129. if (_pAImeContext->m_pMessageBuffer) {
  130. _pAImeContext->m_pMessageBuffer->SetData(start_msg);
  131. fSetStartComp = true;
  132. }
  133. }
  134. if (! fNoCompResultData) {
  135. msg.message = WM_IME_COMPOSITION;
  136. IMCCLock<COMPOSITIONSTRING> pCompStr((HIMCC)imc->hCompStr);
  137. if (msg.lParam & GCS_RESULT)
  138. msg.wParam = (WPARAM)(*(WCHAR*)pCompStr.GetOffsetPointer(pCompStr->dwResultStrOffset));
  139. else
  140. msg.wParam = (WPARAM)(*(WCHAR*)pCompStr.GetOffsetPointer(pCompStr->dwCompStrOffset));
  141. if (_pAImeContext &&
  142. _pAImeContext->m_pMessageBuffer) {
  143. _pAImeContext->m_pMessageBuffer->SetData(msg);
  144. //
  145. // Internal notification to UI window
  146. // When receive this msg in UI wnd, then calls QueryCharPos().
  147. //
  148. if (fSetStartComp) {
  149. TRANSMSG notify_msg;
  150. notify_msg.message = WM_IME_NOTIFY;
  151. notify_msg.wParam = (WPARAM)WM_IME_STARTCOMPOSITION;
  152. notify_msg.lParam = 0;
  153. _pAImeContext->m_pMessageBuffer->SetData(notify_msg);
  154. }
  155. }
  156. }
  157. else {
  158. msg.message = WM_IME_COMPOSITION;
  159. msg.wParam = (WPARAM)VK_ESCAPE;
  160. msg.lParam = (LPARAM)(GCS_COMPREAD | GCS_COMP | GCS_CURSORPOS | GCS_DELTASTART);
  161. if (_pAImeContext &&
  162. _pAImeContext->m_pMessageBuffer)
  163. _pAImeContext->m_pMessageBuffer->SetData(msg);
  164. }
  165. if ((ResultStr && ResultStr->GetSize() && !(msg.lParam & GCS_COMP))
  166. || fNoCompResultData) {
  167. //
  168. // We're ending the composition
  169. //
  170. if (_pAImeContext)
  171. _pAImeContext->m_fStartComposition = FALSE;
  172. TRANSMSG end_msg;
  173. end_msg.message = WM_IME_ENDCOMPOSITION;
  174. end_msg.wParam = (WPARAM) 0;
  175. end_msg.lParam = (LPARAM) 0;
  176. if (_pAImeContext &&
  177. _pAImeContext->m_pMessageBuffer) {
  178. _pAImeContext->m_pMessageBuffer->SetData(end_msg);
  179. //
  180. // Internal notification to UI window
  181. // When receive this msg in UI wnd, then clear QueryCharPos's flag.
  182. //
  183. TRANSMSG notify_msg;
  184. notify_msg.message = WM_IME_NOTIFY;
  185. notify_msg.wParam = (WPARAM)WM_IME_ENDCOMPOSITION;
  186. notify_msg.lParam = 0;
  187. _pAImeContext->m_pMessageBuffer->SetData(notify_msg);
  188. }
  189. }
  190. #ifdef DEBUG
  191. IMCCLock<COMPOSITIONSTRING> comp(imc->hCompStr);
  192. #endif
  193. if (fGenerateMessage) {
  194. imc.GenerateMessage();
  195. }
  196. }
  197. return hr;
  198. }
  199. //
  200. // Make composition string data in the IMCCLock<_COMPOSITIONSTRING> comp.
  201. //
  202. HRESULT
  203. EditCompositionString::_MakeCompositionData(
  204. IMCLock& imc,
  205. CWCompString* CompStr,
  206. CWCompAttribute* CompAttr,
  207. CWCompClause* CompClause,
  208. CWCompCursorPos* CompCursorPos,
  209. CWCompDeltaStart* CompDeltaStart,
  210. CWCompTfGuidAtom* CompGuid,
  211. CWCompString* CompReadStr,
  212. CWCompAttribute* CompReadAttr,
  213. CWCompClause* CompReadClause,
  214. CWCompString* ResultStr,
  215. CWCompClause* ResultClause,
  216. CWCompString* ResultReadStr,
  217. CWCompClause* ResultReadClause,
  218. OUT LPARAM* lpdwFlag,
  219. OUT BOOL* lpbBufferOverflow
  220. )
  221. {
  222. DebugMsg(TF_FUNC, "EditCompositionString::MakeCompositionData");
  223. *lpdwFlag = (LPARAM) 0;
  224. HRESULT hr;
  225. CCompStrFactory compstrfactory(imc->hCompStr);
  226. if (FAILED(hr=compstrfactory.GetResult()))
  227. return hr;
  228. hr = compstrfactory.CreateCompositionString(CompStr,
  229. CompAttr,
  230. CompClause,
  231. CompGuid,
  232. CompReadStr,
  233. CompReadAttr,
  234. CompReadClause,
  235. ResultStr,
  236. ResultClause,
  237. ResultReadStr,
  238. ResultReadClause
  239. );
  240. if (FAILED(hr))
  241. return hr;
  242. //
  243. // Composition string
  244. //
  245. if (lpbBufferOverflow != NULL)
  246. *lpbBufferOverflow = FALSE;
  247. if (CompStr && CompStr->GetSize()) {
  248. #if 0
  249. /*
  250. * If composition string length over the buffer of COMPOSITIONSTRING.compstr[NMAXKEY],
  251. * then we want to finalize this composition string.
  252. */
  253. if ((*comp)->dwCompStrLen >= NMAXKEY) {
  254. if (lpbBufferOverflow != NULL)
  255. *lpbBufferOverflow = TRUE;
  256. //
  257. // Clear compsition string length.
  258. //
  259. (*comp)->dwCompStrLen = 0;
  260. //
  261. // Make result string.
  262. //
  263. (*comp)->dwResultStrLen = NMAXKEY;
  264. CompStr->ReadCompData((*comp)->W.resultstr, ARRAYSIZE((*comp)->W.resultstr));
  265. *lpdwFlag |= (LPARAM) GCS_RESULTSTR;
  266. }
  267. else
  268. #endif
  269. {
  270. hr = compstrfactory.WriteData<CWCompString, WCHAR>(*CompStr,
  271. &compstrfactory->CompStr.dwCompStrLen,
  272. &compstrfactory->CompStr.dwCompStrOffset
  273. );
  274. *lpdwFlag |= (LPARAM) GCS_COMPSTR;
  275. }
  276. }
  277. if ((lpbBufferOverflow == NULL) ||
  278. (lpbBufferOverflow != NULL && (! *lpbBufferOverflow))) {
  279. //
  280. // Compoition attribute
  281. //
  282. if (CompAttr && CompAttr->GetSize()) {
  283. hr = compstrfactory.WriteData<CWCompAttribute, BYTE>(*CompAttr,
  284. &compstrfactory->CompStr.dwCompAttrLen,
  285. &compstrfactory->CompStr.dwCompAttrOffset
  286. );
  287. *lpdwFlag |= (LPARAM) GCS_COMPATTR;
  288. }
  289. //
  290. // Compoition clause
  291. //
  292. if (CompClause && CompClause->GetSize()) {
  293. hr = compstrfactory.WriteData<CWCompClause, DWORD>(*CompClause,
  294. &compstrfactory->CompStr.dwCompClauseLen,
  295. &compstrfactory->CompStr.dwCompClauseOffset
  296. );
  297. compstrfactory->CompStr.dwCompClauseLen *= sizeof(DWORD);
  298. *lpdwFlag |= (LPARAM) GCS_COMPCLAUSE;
  299. }
  300. //
  301. // Composition Reading string
  302. //
  303. if (CompReadStr && CompReadStr->GetSize()) {
  304. hr = compstrfactory.WriteData<CWCompString, WCHAR>(*CompReadStr,
  305. &compstrfactory->CompStr.dwCompReadStrLen,
  306. &compstrfactory->CompStr.dwCompReadStrOffset
  307. );
  308. *lpdwFlag |= (LPARAM) GCS_COMPREADSTR;
  309. }
  310. //
  311. // Compoition Reading attribute
  312. //
  313. if (CompReadAttr && CompReadAttr->GetSize()) {
  314. hr = compstrfactory.WriteData<CWCompAttribute, BYTE>(*CompReadAttr,
  315. &compstrfactory->CompStr.dwCompReadAttrLen,
  316. &compstrfactory->CompStr.dwCompReadAttrOffset
  317. );
  318. *lpdwFlag |= (LPARAM) GCS_COMPREADATTR;
  319. }
  320. //
  321. // Composition Reading clause
  322. //
  323. if (CompReadClause && CompReadClause->GetSize()) {
  324. hr = compstrfactory.WriteData<CWCompClause, DWORD>(*CompReadClause,
  325. &compstrfactory->CompStr.dwCompReadClauseLen,
  326. &compstrfactory->CompStr.dwCompReadClauseOffset
  327. );
  328. compstrfactory->CompStr.dwCompReadClauseLen *= sizeof(DWORD);
  329. *lpdwFlag |= (LPARAM) GCS_COMPREADCLAUSE;
  330. }
  331. //
  332. // Result String
  333. //
  334. if (ResultStr && ResultStr->GetSize()) {
  335. hr = compstrfactory.WriteData<CWCompString, WCHAR>(*ResultStr,
  336. &compstrfactory->CompStr.dwResultStrLen,
  337. &compstrfactory->CompStr.dwResultStrOffset
  338. );
  339. *lpdwFlag |= (LPARAM) GCS_RESULTSTR;
  340. }
  341. //
  342. // Result clause
  343. //
  344. if (ResultClause && ResultClause->GetSize()) {
  345. hr = compstrfactory.WriteData<CWCompClause, DWORD>(*ResultClause,
  346. &compstrfactory->CompStr.dwResultClauseLen,
  347. &compstrfactory->CompStr.dwResultClauseOffset
  348. );
  349. compstrfactory->CompStr.dwResultClauseLen *= sizeof(DWORD);
  350. *lpdwFlag |= (LPARAM) GCS_RESULTCLAUSE;
  351. }
  352. //
  353. // Result Reading string
  354. //
  355. if (ResultReadStr && ResultReadStr->GetSize()) {
  356. hr = compstrfactory.WriteData<CWCompString, WCHAR>(*ResultReadStr,
  357. &compstrfactory->CompStr.dwResultReadStrLen,
  358. &compstrfactory->CompStr.dwResultReadStrOffset
  359. );
  360. *lpdwFlag |= (LPARAM) GCS_RESULTREADSTR;
  361. }
  362. //
  363. // Result Reading clause
  364. //
  365. if (ResultReadClause && ResultReadClause->GetSize()) {
  366. hr = compstrfactory.WriteData<CWCompClause, DWORD>(*ResultReadClause,
  367. &compstrfactory->CompStr.dwResultReadClauseLen,
  368. &compstrfactory->CompStr.dwResultReadClauseOffset
  369. );
  370. compstrfactory->CompStr.dwResultReadClauseLen *= sizeof(DWORD);
  371. *lpdwFlag |= (LPARAM) GCS_RESULTREADCLAUSE;
  372. }
  373. //
  374. // TfGuidAtom
  375. //
  376. if (CompGuid && CompGuid->GetSize()) {
  377. // set INIT_GUID_ATOM flag in the fdwInit.
  378. imc->fdwInit |= INIT_GUID_ATOM;
  379. hr = compstrfactory.WriteData<CWCompTfGuidAtom, TfGuidAtom>(*CompGuid,
  380. &compstrfactory->dwTfGuidAtomLen,
  381. &compstrfactory->dwTfGuidAtomOffset
  382. );
  383. // temporary make a buffer of dwGuidMapAttr
  384. if (CompAttr && CompAttr->GetSize()) {
  385. hr = compstrfactory.WriteData<CWCompAttribute, BYTE>(*CompAttr,
  386. &compstrfactory->dwGuidMapAttrLen,
  387. &compstrfactory->dwGuidMapAttrOffset
  388. );
  389. }
  390. }
  391. }
  392. //
  393. // Composition Cursor Position
  394. //
  395. if (CompCursorPos && CompCursorPos->GetSize()) {
  396. CompCursorPos->ReadCompData(&compstrfactory->CompStr.dwCursorPos, 1);
  397. *lpdwFlag |= (LPARAM) GCS_CURSORPOS;
  398. }
  399. //
  400. // Delta Start
  401. //
  402. if (CompDeltaStart && CompDeltaStart->GetSize()) {
  403. CompDeltaStart->ReadCompData(&compstrfactory->CompStr.dwDeltaStart, 1);
  404. *lpdwFlag |= (LPARAM) GCS_DELTASTART;
  405. }
  406. //
  407. // Copy back hCompStr to the Input Context
  408. //
  409. imc->hCompStr = compstrfactory.GetHandle();
  410. return hr;
  411. }
  412. //
  413. // Make interim string data in the IMCCLock<_COMPOSITIONSTRING> comp.
  414. //
  415. HRESULT
  416. EditCompositionString::_MakeInterimData(
  417. IMCLock& imc,
  418. CWInterimString* InterimStr,
  419. LPARAM* lpdwFlag
  420. )
  421. {
  422. DebugMsg(TF_FUNC, "EditCompositionString::MakeInterimData");
  423. *lpdwFlag = (LPARAM) 0;
  424. //
  425. // Interim character and result string
  426. //
  427. HRESULT hr;
  428. CCompStrFactory compstrfactory(imc->hCompStr);
  429. if (FAILED(hr=compstrfactory.GetResult()))
  430. return hr;
  431. hr = compstrfactory.CreateCompositionString(InterimStr);
  432. if (FAILED(hr))
  433. return hr;
  434. //
  435. // Result string
  436. //
  437. if (InterimStr && InterimStr->GetSize()) {
  438. hr = compstrfactory.WriteData<CWInterimString, WCHAR>(*InterimStr,
  439. &compstrfactory->CompStr.dwResultStrLen,
  440. &compstrfactory->CompStr.dwResultStrOffset
  441. );
  442. *lpdwFlag |= (LPARAM) GCS_RESULTSTR;
  443. }
  444. //
  445. // Composition string (Interim character)
  446. // Compoition attribute
  447. //
  448. CWCompString ch;
  449. CWCompAttribute attr;
  450. InterimStr->ReadInterimChar(&ch, &attr);
  451. if (ch.GetSize() && ch.GetAt(0)) {
  452. hr = compstrfactory.WriteData<CWCompString, WCHAR>(ch,
  453. &compstrfactory->CompStr.dwCompStrLen,
  454. &compstrfactory->CompStr.dwCompStrOffset
  455. );
  456. *lpdwFlag |= (LPARAM) GCS_COMPSTR;
  457. hr = compstrfactory.WriteData<CWCompAttribute, BYTE>(attr,
  458. &compstrfactory->CompStr.dwCompAttrLen,
  459. &compstrfactory->CompStr.dwCompAttrOffset
  460. );
  461. *lpdwFlag |= (LPARAM) GCS_COMPATTR;
  462. *lpdwFlag |= (LPARAM) CS_INSERTCHAR | CS_NOMOVECARET;
  463. }
  464. //
  465. // Copy back hCompStr to the Input Context
  466. //
  467. imc->hCompStr = compstrfactory.GetHandle();
  468. return hr;
  469. }
  470. //
  471. // Generate WM_IME_ENDCOMPOSITION and WM_IME_COMPOSITION message for
  472. // Trident 5.5 version. Since Trident 5.5 always expect WM_IME_ENDCOMPOSITION
  473. // first in case of Hanja conversion.
  474. //
  475. HRESULT
  476. EditCompositionString::_GenerateHanja(IMCLock& imc,
  477. CWCompString* ResultStr,
  478. BOOL fGenerateMessage)
  479. {
  480. HRESULT hr = S_OK;
  481. CAImeContext* _pAImeContext = imc->m_pAImeContext;
  482. if (_pAImeContext == NULL)
  483. return E_FAIL;
  484. if (ResultStr && ResultStr->GetSize())
  485. {
  486. //
  487. // We're ending the composition
  488. //
  489. if (_pAImeContext)
  490. _pAImeContext->m_fStartComposition = FALSE;
  491. TRANSMSG end_msg;
  492. end_msg.message = WM_IME_ENDCOMPOSITION;
  493. end_msg.wParam = (WPARAM) 0;
  494. end_msg.lParam = (LPARAM) 0;
  495. if (_pAImeContext &&
  496. _pAImeContext->m_pMessageBuffer)
  497. {
  498. _pAImeContext->m_pMessageBuffer->SetData(end_msg);
  499. //
  500. // Internal notification to UI window
  501. // When receive this msg in UI wnd, then clear QueryCharPos's flag.
  502. //
  503. TRANSMSG notify_msg;
  504. notify_msg.message = WM_IME_NOTIFY;
  505. notify_msg.wParam = (WPARAM)WM_IME_ENDCOMPOSITION;
  506. notify_msg.lParam = 0;
  507. _pAImeContext->m_pMessageBuffer->SetData(notify_msg);
  508. }
  509. TRANSMSG result_msg;
  510. result_msg.message = WM_IME_COMPOSITION;
  511. result_msg.lParam = GCS_RESULT;
  512. IMCCLock<COMPOSITIONSTRING> pCompStr((HIMCC)imc->hCompStr);
  513. result_msg.wParam = (WPARAM)(*(WCHAR*)pCompStr.GetOffsetPointer(pCompStr->dwResultStrOffset));
  514. if (_pAImeContext &&
  515. _pAImeContext->m_pMessageBuffer)
  516. {
  517. _pAImeContext->m_pMessageBuffer->SetData(result_msg);
  518. }
  519. }
  520. #ifdef DEBUG
  521. IMCCLock<COMPOSITIONSTRING> comp(imc->hCompStr);
  522. #endif
  523. if (fGenerateMessage)
  524. {
  525. imc.GenerateMessage();
  526. }
  527. return hr;
  528. }