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.

639 lines
17 KiB

  1. //
  2. // reconv.cpp
  3. //
  4. #include "private.h"
  5. #include "globals.h"
  6. #include "tim.h"
  7. #include "ic.h"
  8. #include "helpers.h"
  9. #include "fnrecon.h"
  10. #include "funcprv.h"
  11. #include "ptrary.h"
  12. #include "immxutil.h"
  13. #include "proputil.h"
  14. #include "rprop.h"
  15. #include "range.h"
  16. //+---------------------------------------------------------------------------
  17. //
  18. // ::GrowEmptyRangeByOne
  19. //
  20. // Helper to enlarge empty ranges by shifting the end anchor + 1.
  21. //
  22. //----------------------------------------------------------------------------
  23. HRESULT GrowEmptyRangeByOne(CInputContext *pic, ITfRange *range)
  24. {
  25. HRESULT hr = S_OK;
  26. if (pic->_DoPseudoSyncEditSession(TF_ES_READ, PSEUDO_ESCB_GROWRANGE, range, &hr) != S_OK || hr != S_OK)
  27. {
  28. Assert(0);
  29. }
  30. return hr;
  31. }
  32. HRESULT GrowEmptyRangeByOneCallback(TfEditCookie ec, ITfRange *range)
  33. {
  34. BOOL fEmpty;
  35. LONG l;
  36. HRESULT hr = S_OK;
  37. //
  38. // Check the length of the given range.
  39. // If the given range is 0 length, we try to find the owner of
  40. // the next char.
  41. //
  42. range->IsEmpty(ec, &fEmpty);
  43. if (fEmpty)
  44. {
  45. hr = range->ShiftEnd(ec, +1, &l, NULL);
  46. }
  47. return hr;
  48. }
  49. //////////////////////////////////////////////////////////////////////////////
  50. //
  51. // CFunction
  52. //
  53. //////////////////////////////////////////////////////////////////////////////
  54. //+---------------------------------------------------------------------------
  55. //
  56. // ctor
  57. //
  58. //----------------------------------------------------------------------------
  59. CFunction::CFunction(CFunctionProvider *pFuncPrv)
  60. {
  61. _pFuncPrv = pFuncPrv;
  62. _pFuncPrv->AddRef();
  63. }
  64. //+---------------------------------------------------------------------------
  65. //
  66. // dtor
  67. //
  68. //----------------------------------------------------------------------------
  69. CFunction::~CFunction()
  70. {
  71. SafeRelease(_pFuncPrv);
  72. CleanUpOwnerRange();
  73. }
  74. //+---------------------------------------------------------------------------
  75. //
  76. // CleanUpOwnerRange
  77. //
  78. //----------------------------------------------------------------------------
  79. void CFunction::CleanUpOwnerRange()
  80. {
  81. CRangeOwnerList *pRangeOwner;
  82. while (pRangeOwner = _listRangeOwner.GetFirst())
  83. {
  84. _listRangeOwner.Remove(pRangeOwner);
  85. delete pRangeOwner;
  86. }
  87. }
  88. //+---------------------------------------------------------------------------
  89. //
  90. // BuildOwnerRangeList
  91. //
  92. //----------------------------------------------------------------------------
  93. BOOL CFunction::BuildOwnerRangeList(CInputContext *pic, ITfRange *pRange)
  94. {
  95. HRESULT hr = S_OK;
  96. BUILDOWNERRANGELISTQUEUEINFO qInfo;
  97. BOOL bRet = TRUE;
  98. qInfo.pFunc = this;
  99. qInfo.pRange = pRange;
  100. if (pic->_DoPseudoSyncEditSession(TF_ES_READ, PSEUDO_ESCB_BUILDOWNERRANGELIST, &qInfo, &hr) != S_OK || hr != S_OK)
  101. {
  102. Assert(0);
  103. bRet = FALSE;
  104. }
  105. return bRet;
  106. }
  107. //+---------------------------------------------------------------------------
  108. //
  109. // BuildOwnerRangeListCallback
  110. //
  111. //----------------------------------------------------------------------------
  112. HRESULT CFunction::BuildOwnerRangeListCallback(TfEditCookie ec, CInputContext *pic, ITfRange *pRange)
  113. {
  114. CProperty *pProp;
  115. IEnumTfRanges *pEnumPropRange;
  116. CRange *pRangeP = NULL;
  117. HRESULT hr = E_FAIL;
  118. if (pic->_pPropTextOwner == NULL)
  119. goto ExitOk;
  120. pProp = pic->_pPropTextOwner;
  121. CleanUpOwnerRange();
  122. //
  123. // if pRange is NULL, we build owner list for entire dcoument.
  124. // we will enumerate all property ranges.
  125. //
  126. if (pRange)
  127. {
  128. if ((pRangeP = GetCRange_NA(pRange)) == NULL)
  129. goto Exit;
  130. }
  131. if (SUCCEEDED(pProp->EnumRanges(ec, &pEnumPropRange, pRange)))
  132. {
  133. ITfRange *pPropRange;
  134. while (pEnumPropRange->Next(1, &pPropRange, NULL) == S_OK)
  135. {
  136. TfGuidAtom guidOwner;
  137. CRangeOwnerList *pRangeOwner;
  138. ITfRange *pRangeTmp;
  139. CRange *pRangeTmpP;
  140. BOOL bKnownOwner = FALSE;
  141. pPropRange->Clone(&pRangeTmp);
  142. GetGUIDPropertyData(ec, pProp, pPropRange, &guidOwner);
  143. //
  144. // check if this guidOwner already appeared in the range.
  145. //
  146. pRangeOwner = _listRangeOwner.GetFirst();
  147. while(pRangeOwner)
  148. {
  149. if (guidOwner == pRangeOwner->_guidOwner)
  150. {
  151. bKnownOwner = TRUE;
  152. }
  153. pRangeOwner = pRangeOwner->GetNext();
  154. }
  155. //
  156. // get CRange.
  157. //
  158. if ((pRangeTmpP = GetCRange_NA(pRangeTmp)) == NULL)
  159. goto NoCRange;
  160. //
  161. // if pRangeP is NULL, we build owner list for entire document.
  162. // So we don't have to adjust pRangeTmp.
  163. //
  164. if (pRangeP)
  165. {
  166. if (CompareAnchors(pRangeTmpP->_GetStart(), pRangeP->_GetStart()) < 0)
  167. {
  168. // move pRangeTmp's start to match pRange
  169. pRangeTmpP->_GetStart()->ShiftTo(pRangeP->_GetStart());
  170. // insure pRangeTmp's end is no greater than pRange's end
  171. if (CompareAnchors(pRangeTmpP->_GetEnd(), pRangeP->_GetEnd()) > 0)
  172. {
  173. pRangeTmpP->_GetEnd()->ShiftTo(pRangeP->_GetEnd());
  174. }
  175. }
  176. else if (CompareAnchors(pRangeTmpP->_GetEnd(), pRangeP->_GetEnd()) > 0)
  177. {
  178. pRangeTmpP->_GetEnd()->ShiftTo(pRangeP->_GetEnd());
  179. }
  180. }
  181. pRangeOwner = new CRangeOwnerList(guidOwner, pRangeTmp, bKnownOwner);
  182. _listRangeOwner.Add(pRangeOwner);
  183. NoCRange:
  184. pPropRange->Release();
  185. pRangeTmp->Release();
  186. }
  187. pEnumPropRange->Release();
  188. }
  189. ExitOk:
  190. hr = S_OK;
  191. Exit:
  192. return hr;
  193. }
  194. //////////////////////////////////////////////////////////////////////////////
  195. //
  196. // CFnReconversion
  197. //
  198. //////////////////////////////////////////////////////////////////////////////
  199. //+---------------------------------------------------------------------------
  200. //
  201. // ctor
  202. //
  203. //----------------------------------------------------------------------------
  204. CFnReconversion::CFnReconversion(CFunctionProvider *pFuncPrv) :CFunction(pFuncPrv)
  205. {
  206. _pReconvCache = NULL;
  207. }
  208. //+---------------------------------------------------------------------------
  209. //
  210. // dtor
  211. //
  212. //----------------------------------------------------------------------------
  213. CFnReconversion::~CFnReconversion()
  214. {
  215. SafeRelease(_pReconvCache);
  216. }
  217. //+---------------------------------------------------------------------------
  218. //
  219. // GetDisplayName
  220. //
  221. //----------------------------------------------------------------------------
  222. STDAPI CFnReconversion::GetDisplayName(BSTR *pbstrName)
  223. {
  224. *pbstrName = SysAllocString(L"Reconversion");
  225. return *pbstrName != NULL ? S_OK : E_OUTOFMEMORY;
  226. }
  227. //+---------------------------------------------------------------------------
  228. //
  229. // CFnReconversion::GetReconversion
  230. //
  231. //----------------------------------------------------------------------------
  232. STDAPI CFnReconversion::GetReconversion(ITfRange *pRange, ITfCandidateList **ppCandList)
  233. {
  234. if (ppCandList == NULL)
  235. return E_INVALIDARG;
  236. *ppCandList = NULL;
  237. if (pRange == NULL)
  238. return E_INVALIDARG;
  239. return Internal_GetReconversion(pRange, ppCandList, NULL, RF_GETRECONVERSION, NULL);
  240. }
  241. //+---------------------------------------------------------------------------
  242. //
  243. // CFnReconversion::QueryRange
  244. //
  245. //----------------------------------------------------------------------------
  246. STDAPI CFnReconversion::QueryRange(ITfRange *pRange, ITfRange **ppNewRange, BOOL *pfConvertable)
  247. {
  248. if (ppNewRange != NULL)
  249. {
  250. *ppNewRange = NULL;
  251. }
  252. if (pfConvertable != NULL)
  253. {
  254. *pfConvertable = FALSE;
  255. }
  256. if (pRange == NULL ||
  257. ppNewRange == NULL ||
  258. pfConvertable == NULL)
  259. {
  260. return E_INVALIDARG;
  261. }
  262. return Internal_GetReconversion(pRange, NULL, ppNewRange, RF_QUERYRECONVERT, pfConvertable);
  263. }
  264. //+---------------------------------------------------------------------------
  265. //
  266. // CFnReconversion::Reconvert
  267. //
  268. //----------------------------------------------------------------------------
  269. STDAPI CFnReconversion::Reconvert(ITfRange *pRange)
  270. {
  271. if (pRange == NULL)
  272. return E_INVALIDARG;
  273. return Internal_GetReconversion(pRange, NULL, NULL, RF_RECONVERT, NULL);
  274. }
  275. //+---------------------------------------------------------------------------
  276. //
  277. // CFnReconversion::Internal_GetReconversion
  278. //
  279. //----------------------------------------------------------------------------
  280. HRESULT CFnReconversion::Internal_GetReconversion(ITfRange *pRange, ITfCandidateList **ppCandList, ITfRange **ppNewRange, RECONVFUNC rf, BOOL *pfConvertable)
  281. {
  282. BOOL bReleaseCache = FALSE;
  283. HRESULT hr = E_FAIL;
  284. ITfRange *pRangeTmp = NULL;
  285. ITfRange *pNewRange = NULL;
  286. ITfContext *pic = NULL;
  287. if (FAILED(pRange->Clone(&pRangeTmp)))
  288. goto Exit;
  289. if (FAILED(pRangeTmp->GetContext(&pic)))
  290. goto Exit;
  291. //
  292. // when RF_QUERYRECONVERT, we alwasy create new Reconv cache.
  293. // we will keep using this chace unless another RF_QUERYRECONVERT comes.
  294. //
  295. if (rf == RF_QUERYRECONVERT)
  296. SafeReleaseClear(_pReconvCache);
  297. if (!_pReconvCache)
  298. {
  299. CInputContext *pcic = GetCInputContext(pic);
  300. if (pcic)
  301. {
  302. QueryAndGetFunction(pcic, pRangeTmp, &_pReconvCache, &pNewRange);
  303. pcic->Release();
  304. }
  305. //
  306. // when it's not RF_QUERYRECONVERT and there was no cache,
  307. // we don't hold the reconv cache.
  308. //
  309. if (rf != RF_QUERYRECONVERT)
  310. bReleaseCache = TRUE;
  311. }
  312. if (!_pReconvCache)
  313. {
  314. hr = S_OK;
  315. goto Exit;
  316. }
  317. switch (rf)
  318. {
  319. case RF_GETRECONVERSION:
  320. if ((hr = _pReconvCache->GetReconversion(pRangeTmp, ppCandList)) != S_OK)
  321. {
  322. *ppCandList = NULL;
  323. }
  324. break;
  325. case RF_RECONVERT:
  326. hr = _pReconvCache->Reconvert(pRangeTmp);
  327. break;
  328. case RF_QUERYRECONVERT:
  329. if (!pNewRange)
  330. {
  331. if ((hr = _pReconvCache->QueryRange(pRangeTmp, ppNewRange, pfConvertable)) != S_OK)
  332. {
  333. *ppNewRange = NULL;
  334. *pfConvertable = FALSE;
  335. }
  336. }
  337. else
  338. {
  339. *ppNewRange = pNewRange;
  340. (*ppNewRange)->AddRef();
  341. *pfConvertable = TRUE;
  342. hr = S_OK;
  343. }
  344. break;
  345. }
  346. Assert(hr == S_OK);
  347. Exit:
  348. if (bReleaseCache || FAILED(hr))
  349. SafeReleaseClear(_pReconvCache);
  350. SafeRelease(pRangeTmp);
  351. SafeRelease(pNewRange);
  352. SafeRelease(pic);
  353. return hr;
  354. }
  355. //+---------------------------------------------------------------------------
  356. //
  357. // ctor
  358. //
  359. //----------------------------------------------------------------------------
  360. HRESULT CFnReconversion::QueryAndGetFunction(CInputContext *pic, ITfRange *pRange, ITfFnReconversion **ppFunc, ITfRange **ppRange)
  361. {
  362. IEnumTfFunctionProviders *pEnumFuncPrv;
  363. ITfFunctionProvider *pFuncPrv;
  364. CRangeOwnerList *pRangeOwner;
  365. HRESULT hr = E_FAIL;
  366. ITfRange *pRangeTmp = NULL;
  367. CThreadInputMgr *ptim;
  368. *ppFunc = NULL;
  369. if ((ptim = CThreadInputMgr::_GetThis()) == NULL)
  370. goto Exit;
  371. if (pRange)
  372. {
  373. //
  374. // To find the properr function provider, we use pRangeTmp.
  375. //
  376. if (FAILED(pRange->Clone(&pRangeTmp)))
  377. goto Exit;
  378. //
  379. // Check the length of the given range.
  380. // If the given range is 0 length, we try to find the owner of
  381. // the next char.
  382. //
  383. if (GrowEmptyRangeByOne(pic, pRangeTmp) != S_OK)
  384. goto Exit;
  385. }
  386. if (!BuildOwnerRangeList(pic, pRangeTmp))
  387. goto Exit;
  388. pRangeOwner = _listRangeOwner.GetFirst();
  389. if (pRangeOwner)
  390. {
  391. GUID guid;
  392. if (SUCCEEDED(MyGetGUID(pRangeOwner->_guidOwner, &guid)))
  393. {
  394. CTip *ptip;
  395. //
  396. // A way to get the TextOwner's reconversion function.
  397. //
  398. // - find a function provider of the ower.
  399. // - Do QI the text owner TIP.
  400. // - CoCreate the text onwer CLSID.
  401. //
  402. if (SUCCEEDED(ptim->GetFunctionProvider(guid, &pFuncPrv)))
  403. {
  404. hr = pFuncPrv->GetFunction(GUID_NULL,
  405. IID_ITfFnReconversion,
  406. (IUnknown **)ppFunc);
  407. SafeReleaseClear(pFuncPrv);
  408. }
  409. else if (ptim->_GetCTipfromGUIDATOM(pRangeOwner->_guidOwner, &ptip) && ptip->_pTip)
  410. {
  411. hr = ptip->_pTip->QueryInterface(IID_ITfFnReconversion,
  412. (void **)ppFunc);
  413. }
  414. else
  415. {
  416. hr = CoCreateInstance(guid,
  417. NULL,
  418. CLSCTX_INPROC_SERVER,
  419. IID_ITfFnReconversion,
  420. (void**)ppFunc);
  421. }
  422. if (FAILED(hr))
  423. *ppFunc = NULL;
  424. }
  425. }
  426. //
  427. // if there is no owner or the owner of the first range does not
  428. // have ITfFunction, we may find someone who has
  429. // ITfFunction.
  430. //
  431. if (!(*ppFunc) &&
  432. SUCCEEDED(ptim->EnumFunctionProviders(&pEnumFuncPrv)))
  433. {
  434. while (!(*ppFunc) && pEnumFuncPrv->Next(1, &pFuncPrv, NULL) == S_OK)
  435. {
  436. GUID guid;
  437. BOOL fSkip = TRUE;
  438. if (SUCCEEDED(pFuncPrv->GetType(&guid)))
  439. {
  440. if (!IsEqualGUID(guid, GUID_SYSTEM_FUNCTIONPROVIDER))
  441. fSkip = FALSE;
  442. }
  443. if(!fSkip)
  444. {
  445. hr = pFuncPrv->GetFunction(GUID_NULL, IID_ITfFnReconversion, (IUnknown **)ppFunc);
  446. if ((SUCCEEDED(hr) && *ppFunc))
  447. {
  448. BOOL fConvertable = FALSE;
  449. hr = (*ppFunc)->QueryRange(pRange, ppRange, &fConvertable);
  450. if (FAILED(hr) || !fConvertable)
  451. {
  452. (*ppFunc)->Release();
  453. *ppFunc = NULL;
  454. }
  455. }
  456. }
  457. SafeReleaseClear(pFuncPrv);
  458. }
  459. pEnumFuncPrv->Release();
  460. }
  461. Exit:
  462. SafeRelease(pRangeTmp);
  463. return (*ppFunc) ? S_OK : E_FAIL;
  464. }
  465. //////////////////////////////////////////////////////////////////////////////
  466. //
  467. // CFnAbort
  468. //
  469. //////////////////////////////////////////////////////////////////////////////
  470. //+---------------------------------------------------------------------------
  471. //
  472. // ctor
  473. //
  474. //----------------------------------------------------------------------------
  475. CFnAbort::CFnAbort(CFunctionProvider *pFuncPrv) : CFunction(pFuncPrv)
  476. {
  477. }
  478. //+---------------------------------------------------------------------------
  479. //
  480. // dtor
  481. //
  482. //----------------------------------------------------------------------------
  483. CFnAbort::~CFnAbort()
  484. {
  485. }
  486. //+---------------------------------------------------------------------------
  487. //
  488. // GetDisplayName
  489. //
  490. //----------------------------------------------------------------------------
  491. STDAPI CFnAbort::GetDisplayName(BSTR *pbstrName)
  492. {
  493. *pbstrName = SysAllocString(L"Abort");
  494. return *pbstrName != NULL ? S_OK : E_OUTOFMEMORY;
  495. }
  496. //+---------------------------------------------------------------------------
  497. //
  498. // CFnAbort::Abort
  499. //
  500. //----------------------------------------------------------------------------
  501. STDAPI CFnAbort::Abort(ITfContext *pic)
  502. {
  503. CThreadInputMgr *ptim;
  504. HRESULT hr = E_FAIL;
  505. int i;
  506. int nCnt;
  507. if (!pic)
  508. return E_INVALIDARG;
  509. if ((ptim = CThreadInputMgr::_GetThis()) == NULL)
  510. goto Exit;
  511. //
  512. // notify all tips with ITfFnAbort to abort any pending conversion.
  513. //
  514. nCnt = ptim->_GetTIPCount();
  515. for (i = 0; i < nCnt; i++)
  516. {
  517. ITfFnAbort *pAbort;
  518. const CTip *ptip = ptim->_GetCTip(i);
  519. if (!ptip->_pFuncProvider)
  520. continue;
  521. if (SUCCEEDED(ptip->_pFuncProvider->GetFunction(GUID_NULL,
  522. IID_ITfFnAbort,
  523. (IUnknown **)&pAbort)))
  524. {
  525. pAbort->Abort(pic);
  526. pAbort->Release();
  527. }
  528. }
  529. hr = S_OK;
  530. Exit:
  531. return hr;
  532. }