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.

730 lines
19 KiB

  1. #include "private.h"
  2. #include "proputil.h"
  3. #include "immxutil.h"
  4. #include "helpers.h"
  5. //+---------------------------------------------------------------------------
  6. //
  7. // HrVariantToBlob
  8. //
  9. // cbvalue: on sizeof VARTYPE
  10. //
  11. //----------------------------------------------------------------------------
  12. HRESULT HrVariantToBlob(VARIANT *pv, void *pvalue, ULONG *pcbvalue, VARTYPE vt)
  13. {
  14. HRESULT hr = S_OK;
  15. SAFEARRAY *psa = NULL;
  16. void *pdata = NULL;
  17. int lb, ub;
  18. int iElemSize;
  19. ULONG cbvalue;
  20. while (V_VT(pv) == (VT_BYREF | VT_VARIANT))
  21. pv = V_VARIANTREF(pv);
  22. if (V_VT(pv) != (VT_ARRAY | vt))
  23. return E_FAIL;
  24. psa = V_ARRAY(pv);
  25. hr = SafeArrayLock(psa);
  26. if (FAILED(hr))
  27. goto Ret;
  28. hr = SafeArrayGetLBound(psa, 1, (LONG *)&lb);
  29. if (FAILED(hr))
  30. goto Ret;
  31. hr = SafeArrayGetUBound(psa, 1, (LONG *)&ub);
  32. if (FAILED(hr))
  33. goto Ret;
  34. iElemSize = SafeArrayGetElemsize(psa);
  35. cbvalue = ub - lb + 1;
  36. if (cbvalue * iElemSize > *pcbvalue)
  37. {
  38. hr = E_FAIL;
  39. goto Ret;
  40. }
  41. hr = SafeArrayAccessData(psa, (void **)&pdata);
  42. if (FAILED(hr))
  43. goto Ret;
  44. memcpy(pvalue, pdata, cbvalue * iElemSize);
  45. hr = SafeArrayUnaccessData(psa);
  46. if (FAILED(hr))
  47. goto Ret;
  48. *pcbvalue = cbvalue;
  49. Ret:
  50. if (psa) SafeArrayUnlock(psa);
  51. return hr;
  52. }
  53. //+---------------------------------------------------------------------------
  54. //
  55. // HrBlobToVariant
  56. //
  57. // cbvalue: on sizeof VARTYPE
  58. //
  59. //----------------------------------------------------------------------------
  60. HRESULT HrBlobToVariant(const void *value, ULONG cbvalue, VARIANT *pv, VARTYPE vt)
  61. {
  62. HRESULT hr = S_OK;
  63. SAFEARRAY *psa = NULL;
  64. SAFEARRAYBOUND rsabound[1];
  65. void *pdata = NULL;
  66. int iElemSize;
  67. rsabound[0].lLbound = 0;
  68. rsabound[0].cElements = cbvalue;
  69. if (!(psa = SafeArrayCreate(vt, 1, rsabound)))
  70. {
  71. hr = E_OUTOFMEMORY;
  72. goto Ret;
  73. }
  74. iElemSize = SafeArrayGetElemsize(psa);
  75. hr = SafeArrayAccessData(psa, (void **)&pdata);
  76. if (FAILED(hr))
  77. goto Ret;
  78. memcpy(pdata, value, cbvalue * iElemSize);
  79. hr = SafeArrayUnaccessData(psa);
  80. if (FAILED(hr))
  81. goto Ret;
  82. V_VT(pv) = VT_ARRAY | vt;
  83. V_ARRAY(pv) = psa;
  84. psa = NULL;
  85. Ret:
  86. if (psa) SafeArrayDestroy(psa);
  87. return hr;
  88. }
  89. //+---------------------------------------------------------------------------
  90. //
  91. // GetGUIDPropertyData
  92. //
  93. //----------------------------------------------------------------------------
  94. HRESULT GetGUIDPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, TfGuidAtom *pguid)
  95. {
  96. VARIANT var;
  97. HRESULT hr = E_FAIL;
  98. *pguid = TF_INVALID_GUIDATOM;
  99. if (SUCCEEDED(pProp->GetValue(ec, pRange, &var)))
  100. {
  101. if (var.vt == VT_I4)
  102. *pguid = (TfGuidAtom)var.lVal;
  103. // no need to VariantClear because VT_I4
  104. hr = S_OK;
  105. }
  106. return hr;
  107. }
  108. //+---------------------------------------------------------------------------
  109. //
  110. // SetGUIDPropertyData
  111. //
  112. //----------------------------------------------------------------------------
  113. HRESULT SetGUIDPropertyData(LIBTHREAD *plt, TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, REFGUID rguid)
  114. {
  115. VARIANT var;
  116. GUID guid = rguid;
  117. var.vt = VT_I4;
  118. GetGUIDATOMFromGUID(plt, guid, (TfGuidAtom *)&var.lVal);
  119. return pProp->SetValue(ec, pRange, &var);
  120. }
  121. //+---------------------------------------------------------------------------
  122. //
  123. // VarToLangId
  124. //
  125. //----------------------------------------------------------------------------
  126. WORD VarToWORD(VARIANT *pv)
  127. {
  128. if (V_VT(pv) == VT_I2)
  129. return (WORD)V_I2(pv);
  130. return 0;
  131. }
  132. //+---------------------------------------------------------------------------
  133. //
  134. // SetLangToVar
  135. //
  136. //----------------------------------------------------------------------------
  137. void SetWORDToVar(VARIANT *pv, WORD w)
  138. {
  139. V_VT(pv) = VT_I2;
  140. V_I2(pv) = w;
  141. }
  142. //+---------------------------------------------------------------------------
  143. //
  144. // GetDWORDPropertyData
  145. //
  146. //----------------------------------------------------------------------------
  147. HRESULT GetDWORDPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, DWORD *pdw)
  148. {
  149. VARIANT var;
  150. HRESULT hr = E_FAIL;
  151. if (pProp->GetValue(ec, pRange, &var) == S_OK)
  152. {
  153. Assert(var.vt == VT_I4); // expecting DWORD
  154. *pdw = var.lVal;
  155. // no need to VariantClear because VT_I4
  156. hr = S_OK;
  157. }
  158. return hr;
  159. }
  160. //+---------------------------------------------------------------------------
  161. //
  162. // SetDWORDPropertyData
  163. //
  164. //----------------------------------------------------------------------------
  165. HRESULT SetDWORDPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, DWORD dw)
  166. {
  167. VARIANT var;
  168. if (!dw)
  169. {
  170. return pProp->Clear(ec, pRange);
  171. }
  172. var.vt = VT_I4;
  173. var.lVal = dw;
  174. return pProp->SetValue(ec, pRange, &var);
  175. }
  176. //+---------------------------------------------------------------------------
  177. //
  178. // GetBSTRPropertyData
  179. //
  180. //----------------------------------------------------------------------------
  181. HRESULT GetBSTRPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, BSTR *pbstr)
  182. {
  183. VARIANT var = { 0 };
  184. HRESULT hr = E_FAIL;
  185. *pbstr = NULL;
  186. if (pProp->GetValue(ec, pRange, &var) != S_OK)
  187. return E_FAIL;
  188. if (var.vt != VT_BSTR)
  189. goto Exit;
  190. *pbstr = SysAllocString(var.bstrVal);
  191. if (*pbstr)
  192. hr = S_OK;
  193. else
  194. hr = E_OUTOFMEMORY;
  195. Exit:
  196. VariantClear(&var);
  197. return hr;
  198. }
  199. //+---------------------------------------------------------------------------
  200. //
  201. // SetBSTRPropertyData
  202. //
  203. //----------------------------------------------------------------------------
  204. HRESULT SetBSTRPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, BSTR bstr)
  205. {
  206. VARIANT var;
  207. HRESULT hr;
  208. if (!bstr)
  209. return pProp->Clear(ec, pRange);
  210. var.vt = VT_BSTR;
  211. var.bstrVal = SysAllocString(bstr);
  212. if (!var.bstrVal)
  213. return E_OUTOFMEMORY;
  214. hr = pProp->SetValue(ec, pRange, &var);
  215. VariantClear(&var);
  216. return hr;
  217. }
  218. //+---------------------------------------------------------------------------
  219. //
  220. // GetUnknownPropertyData
  221. //
  222. //----------------------------------------------------------------------------
  223. HRESULT GetUnknownPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, IUnknown **ppunk)
  224. {
  225. VARIANT var = { 0 };
  226. *ppunk = NULL;
  227. if (pProp->GetValue(ec, pRange, &var) != S_OK)
  228. return E_FAIL;
  229. if (var.vt != VT_UNKNOWN)
  230. goto Exit;
  231. *ppunk = var.punkVal;
  232. (*ppunk)->AddRef();
  233. Exit:
  234. VariantClear(&var);
  235. return (*ppunk == NULL) ? E_FAIL : S_OK;
  236. }
  237. //+---------------------------------------------------------------------------
  238. //
  239. // SetUnknownPropertyData
  240. //
  241. //----------------------------------------------------------------------------
  242. HRESULT SetUnknownPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, IUnknown *punk)
  243. {
  244. VARIANT var;
  245. if (!punk)
  246. return pProp->Clear(ec, pRange);
  247. var.vt = VT_UNKNOWN;
  248. var.punkVal = punk;
  249. return pProp->SetValue(ec, pRange, &var);
  250. }
  251. //+---------------------------------------------------------------------------
  252. //
  253. // GetReadingStrPropertyData
  254. //
  255. //----------------------------------------------------------------------------
  256. HRESULT GetReadingStrPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, BSTR *pbstr)
  257. {
  258. return GetBSTRPropertyData(ec, pProp, pRange, pbstr);
  259. }
  260. //+---------------------------------------------------------------------------
  261. //
  262. // SetIntAttribute
  263. //
  264. //----------------------------------------------------------------------------
  265. void SetIntAttribute(IXMLDOMElement *pElem, WCHAR *pszTag, int nData)
  266. {
  267. WCHAR wch[32];
  268. NumToW((DWORD)nData, wch);
  269. SetCharAttribute(pElem, pszTag, wch);
  270. }
  271. //+---------------------------------------------------------------------------
  272. //
  273. // SetCharAttribute
  274. //
  275. //----------------------------------------------------------------------------
  276. void SetCharAttribute(IXMLDOMElement *pElem, WCHAR *pszTag, WCHAR *pszData)
  277. {
  278. VARIANT var;
  279. BSTR bstrTmp = SysAllocString(pszTag);
  280. BSTR bstrTmp2;
  281. if (!bstrTmp)
  282. return;
  283. bstrTmp2 = SysAllocString(pszData);
  284. if (bstrTmp2)
  285. {
  286. V_VT(&var) = VT_BSTR;
  287. V_BSTR(&var) = bstrTmp2;
  288. pElem->setAttribute(bstrTmp, var);
  289. }
  290. VariantClear(&var);
  291. SysFreeString(bstrTmp);
  292. }
  293. //+---------------------------------------------------------------------------
  294. //
  295. // GetIntAttribute
  296. //
  297. //----------------------------------------------------------------------------
  298. HRESULT GetIntAttribute(IXMLDOMElement *pElem, WCHAR *pszTag, int *pnRet)
  299. {
  300. WCHAR wch[32];
  301. if (FAILED(GetCharAttribute(pElem, pszTag, wch, ARRAYSIZE(wch))))
  302. return E_FAIL;
  303. *pnRet = (int)WToNum(wch);
  304. return S_OK;
  305. }
  306. //+---------------------------------------------------------------------------
  307. //
  308. // GetCharAttribute
  309. //
  310. //----------------------------------------------------------------------------
  311. HRESULT GetCharAttribute(IXMLDOMElement *pElem, WCHAR *pszTag, WCHAR *pszData, int nSize)
  312. {
  313. BSTR bstrTmp;
  314. VARIANT var;
  315. int nData = 0;
  316. HRESULT hr = E_FAIL;
  317. *pszData = L'\0';
  318. QuickVariantInit(&var);
  319. bstrTmp = SysAllocString(pszTag);
  320. if (!bstrTmp)
  321. return E_OUTOFMEMORY;
  322. if (SUCCEEDED(pElem->getAttribute(bstrTmp, &var)))
  323. {
  324. if (V_VT(&var) == VT_BSTR)
  325. {
  326. if (wcsncpy(pszData, V_BSTR(&var), nSize))
  327. hr = S_OK;
  328. }
  329. }
  330. SysFreeString(bstrTmp);
  331. VariantClear(&var);
  332. return hr;
  333. }
  334. //+---------------------------------------------------------------------------
  335. //
  336. // SetTextAndProperty
  337. //
  338. //----------------------------------------------------------------------------
  339. HRESULT SetTextAndProperty(LIBTHREAD *plt, TfEditCookie ec, ITfContext *pic, ITfRange *pRange, const WCHAR *pchText, LONG cchText, LANGID langid, const GUID *pattr)
  340. {
  341. HRESULT hr;
  342. // Issue: sometimes we want to set TFST_CORRECTION
  343. hr = pRange->SetText(ec, 0, pchText, cchText);
  344. if (SUCCEEDED(hr) && cchText)
  345. {
  346. ITfProperty *pProp = NULL;
  347. // set langid
  348. if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_LANGID, &pProp)))
  349. {
  350. SetLangIdPropertyData(ec, pProp, pRange, langid);
  351. pProp->Release();
  352. }
  353. if (pattr)
  354. {
  355. // set attr
  356. if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_ATTRIBUTE, &pProp)))
  357. {
  358. hr = SetAttrPropertyData(plt, ec, pProp, pRange, *pattr);
  359. pProp->Release();
  360. }
  361. }
  362. }
  363. return hr;
  364. }
  365. //+---------------------------------------------------------------------------
  366. //
  367. // SetTextAndReading
  368. //
  369. //----------------------------------------------------------------------------
  370. HRESULT SetTextAndReading(LIBTHREAD *plt, TfEditCookie ec, ITfContext *pic, ITfRange *pRange, const WCHAR *pchText, LONG cchText, LANGID langid, const WCHAR *pszRead)
  371. {
  372. ITfProperty *pProp;
  373. HRESULT hr;
  374. hr = SetTextAndProperty(plt, ec, pic, pRange, pchText, cchText, langid, NULL);
  375. if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_READING, &pProp)))
  376. {
  377. BSTR bstr = SysAllocString(pszRead);
  378. if (bstr)
  379. {
  380. SetBSTRPropertyData(ec, pProp, pRange, bstr);
  381. SysFreeString(bstr);
  382. }
  383. else
  384. {
  385. hr = E_OUTOFMEMORY;
  386. }
  387. pProp->Release();
  388. }
  389. return hr;
  390. }
  391. //+---------------------------------------------------------------------------
  392. //
  393. // IsOwnerAndFocus
  394. //
  395. // This is service function for EnumTrackTextAndFocus.
  396. //
  397. //----------------------------------------------------------------------------
  398. BOOL IsOwnerAndFocus(LIBTHREAD *plt, TfEditCookie ec, REFCLSID rclsid, ITfReadOnlyProperty *pProp, ITfRange *pRange)
  399. {
  400. IEnumTfPropertyValue *pEnumPropVal;
  401. BOOL bRet = FALSE;
  402. VARIANT var;
  403. ULONG iTextOwner;
  404. ULONG iFocus;
  405. TF_PROPERTYVAL rgValue[2];
  406. if (SUCCEEDED(pProp->GetValue(ec, pRange, &var)))
  407. {
  408. Assert(var.vt == VT_UNKNOWN);
  409. if (SUCCEEDED(var.punkVal->QueryInterface(IID_IEnumTfPropertyValue,
  410. (void **)&pEnumPropVal)))
  411. {
  412. if (pEnumPropVal->Next(2, rgValue, NULL) == S_OK)
  413. {
  414. Assert(rgValue[0].varValue.vt == VT_I4);
  415. Assert(rgValue[1].varValue.vt == VT_I4);
  416. // Issue: should we change the spec so the order is guaranteed maintained?
  417. if (IsEqualGUID(rgValue[0].guidId, GUID_PROP_TEXTOWNER))
  418. {
  419. Assert(IsEqualGUID(rgValue[1].guidId, GUID_PROP_COMPOSING));
  420. iTextOwner = 0;
  421. iFocus = 1;
  422. }
  423. else
  424. {
  425. iTextOwner = 1;
  426. iFocus = 0;
  427. }
  428. // does the owner match rclisd?
  429. if (IsEqualTFGUIDATOM(plt, (TfGuidAtom)rgValue[iTextOwner].varValue.lVal, rclsid))
  430. {
  431. // is the focus property set (not VT_EMPTY) and is it set TRUE?
  432. bRet = (rgValue[iFocus].varValue.vt == VT_I4 && rgValue[iFocus].varValue.lVal != 0);
  433. }
  434. }
  435. pEnumPropVal->Release();
  436. }
  437. VariantClear(&var);
  438. }
  439. return bRet;
  440. }
  441. //+---------------------------------------------------------------------------
  442. //
  443. // EnumTrackTextAndFocus
  444. //
  445. //----------------------------------------------------------------------------
  446. HRESULT EnumTrackTextAndFocus(TfEditCookie ec, ITfContext *pic, ITfRange *pRange, ITfReadOnlyProperty **ppProp, IEnumTfRanges **ppEnumTrack)
  447. {
  448. static const GUID *rgguidProp[2] = { &GUID_PROP_TEXTOWNER, &GUID_PROP_COMPOSING };
  449. ITfReadOnlyProperty *pPropTrack = NULL;
  450. HRESULT hr;
  451. *ppEnumTrack = NULL;
  452. *ppProp = NULL;
  453. if (SUCCEEDED(hr = pic->TrackProperties(rgguidProp, ARRAYSIZE(rgguidProp),
  454. 0, NULL,
  455. &pPropTrack)))
  456. {
  457. hr = pPropTrack->EnumRanges(ec, ppEnumTrack, pRange);
  458. *ppProp = pPropTrack;
  459. }
  460. return hr;
  461. }
  462. //+---------------------------------------------------------------------------
  463. //
  464. // IsGUIDProp
  465. //
  466. //----------------------------------------------------------------------------
  467. BOOL IsGUIDProp(LIBTHREAD *plt, TfEditCookie ec, REFGUID rclsid, ITfProperty *pProp, ITfRange *pRange)
  468. {
  469. TfGuidAtom guidatom;
  470. if (SUCCEEDED(GetGUIDPropertyData(ec, pProp, pRange, &guidatom)))
  471. {
  472. if (IsEqualTFGUIDATOM(plt, guidatom, rclsid))
  473. {
  474. return TRUE;
  475. }
  476. }
  477. return FALSE;
  478. }
  479. //+---------------------------------------------------------------------------
  480. //
  481. // AdjustRangeByProperty
  482. //
  483. //----------------------------------------------------------------------------
  484. HRESULT AdjustRangeByTextOwner(TfEditCookie ec, ITfContext *pic, ITfRange *pRange, ITfRange **ppRange, REFCLSID rclsid)
  485. {
  486. ITfProperty *pProp;
  487. ITfRange *pRangeStart = NULL;
  488. ITfRange *pRangeEnd = NULL;
  489. HRESULT hr = E_FAIL;
  490. if (SUCCEEDED(pic->GetProperty(GUID_PROP_TEXTOWNER, &pProp)))
  491. {
  492. BOOL fEmpty = FALSE;
  493. pRange->IsEmpty(ec, &fEmpty);
  494. if (fEmpty)
  495. {
  496. pProp->FindRange(ec, pRange, &pRangeStart, TF_ANCHOR_START);
  497. }
  498. else
  499. {
  500. pProp->FindRange(ec, pRange, &pRangeStart, TF_ANCHOR_START);
  501. pProp->FindRange(ec, pRange, &pRangeEnd, TF_ANCHOR_END);
  502. }
  503. pProp->Release();
  504. }
  505. if (!pRangeStart)
  506. goto Exit;
  507. if (pRangeEnd)
  508. {
  509. pRangeStart->ShiftEndToRange(ec, pRangeEnd, TF_ANCHOR_END);
  510. }
  511. pRangeStart->Clone(ppRange);
  512. hr = S_OK;
  513. Exit:
  514. SafeRelease(pRangeStart);
  515. SafeRelease(pRangeEnd);
  516. return hr;
  517. }
  518. //+---------------------------------------------------------------------------
  519. //
  520. // AdjustRangeByAttribute
  521. //
  522. //----------------------------------------------------------------------------
  523. HRESULT AdjustRangeByAttribute(LIBTHREAD *plt, TfEditCookie ec, ITfContext *pic, ITfRange *pRange, ITfRange **ppRange, const GUID *rgRGuid, int cGuid)
  524. {
  525. ITfProperty *pProp;
  526. ITfRange *pRangeStart = NULL;
  527. ITfRange *pRangeEnd = NULL;
  528. HRESULT hr = E_FAIL;
  529. if (SUCCEEDED(pic->GetProperty(GUID_PROP_ATTRIBUTE, &pProp)))
  530. {
  531. IEnumTfRanges *pEnumProp;
  532. if (SUCCEEDED(pProp->EnumRanges(ec, &pEnumProp, pRange)))
  533. {
  534. ITfRange *pRangeProp;
  535. //
  536. // first range.
  537. //
  538. while (!pRangeStart &&
  539. pEnumProp->Next(1, &pRangeProp, NULL) == S_OK)
  540. {
  541. for ( int i = 0; i < cGuid; i++ )
  542. {
  543. if (IsGUIDProp(plt, ec, rgRGuid[i], pProp, pRangeProp))
  544. {
  545. pRangeProp->Clone(&pRangeStart);
  546. }
  547. }
  548. pRangeProp->Release();
  549. }
  550. if (pRangeStart)
  551. {
  552. //
  553. // last range.
  554. //
  555. while (pEnumProp->Next(1, &pRangeProp, NULL) == S_OK)
  556. {
  557. for ( int i = 0; i < cGuid; i++ )
  558. {
  559. if (IsGUIDProp(plt, ec, rgRGuid[i], pProp, pRangeProp))
  560. {
  561. SafeRelease(pRangeEnd);
  562. pRangeProp->Clone(&pRangeEnd);
  563. }
  564. }
  565. pRangeProp->Release();
  566. }
  567. }
  568. pEnumProp->Release();
  569. }
  570. pProp->Release();
  571. }
  572. if (!pRangeStart)
  573. goto Exit;
  574. if (pRangeEnd)
  575. {
  576. pRangeStart->ShiftEndToRange(ec, pRangeEnd, TF_ANCHOR_END);
  577. }
  578. pRangeStart->Clone(ppRange);
  579. hr = S_OK;
  580. Exit:
  581. SafeRelease(pRangeStart);
  582. SafeRelease(pRangeEnd);
  583. return hr;
  584. }