// // nuimgr.cpp // #include "private.h" #include "tim.h" #include "nuimgr.h" #include "nuictrl.h" #include "marshal.h" #include "timlist.h" #include "lbaddin.h" #include "hotkey.h" DBG_ID_INSTANCE(CLBarItemSink); DBG_ID_INSTANCE(CLBarItemSinkProxy); DBG_ID_INSTANCE(CLangBarItemMgr); DBG_ID_INSTANCE(CEnumLBItem); ////////////////////////////////////////////////////////////////////////////// // // marshalling misc func // ////////////////////////////////////////////////////////////////////////////// //+--------------------------------------------------------------------------- // // FreeStubForThis // // this function clean up all marshaling stubs for the LangBarItem. // //+--------------------------------------------------------------------------- void FreeMarshaledStubOfItem(SYSTHREAD *psfn, REFGUID rguid) { ITfLangBarItem *pItem; if (!psfn->prgStub) return; // // #489905 // // we can not call sink anymore after DLL_PROCESS_DETACH. // if (DllShutdownInProgress()) return; int nCnt = psfn->prgStub->Count(); int i = 0; for (i = 0; i < nCnt; i++) { TryThisIdAgain: CStub *pStub = psfn->prgStub->Get(i); HRESULT hr; TF_LANGBARITEMINFO info; // // Win98-J and Satori cause exception at the sutdown of notepad. // we need to make sure this exception handler is not hiding any // potential problems. // _try { if (FAILED(pStub->_punk->QueryInterface(IID_ITfLangBarItem, (void **)&pItem))) continue; } _except (1) { continue; } hr = pItem->GetInfo(&info); pItem->Release(); if (SUCCEEDED(hr) && IsEqualGUID(info.guidItem, rguid)) { pStub->_fNoRemoveInDtor = TRUE; psfn->prgStub->Remove(i, 1); delete pStub; nCnt--; if (i < nCnt) goto TryThisIdAgain; return; } } } ////////////////////////////////////////////////////////////////////////////// // // CLangBarItemMgr // ////////////////////////////////////////////////////////////////////////////// //+--------------------------------------------------------------------------- // // ctor // //---------------------------------------------------------------------------- CLangBarItemMgr::CLangBarItemMgr(SYSTHREAD *psfn) : CSysThreadRef(psfn) { Dbg_MemSetThisNameID(TEXT("CLangBarItemMgr")); Assert(_GetThis() == NULL); _SetThis(this); _dwCurCookie = 0; _ulInAssemblyChange = 0; _fHandleOnUpdate = TRUE; EnsureMarshalWnd(); } //+--------------------------------------------------------------------------- // // dtor // //---------------------------------------------------------------------------- CLangBarItemMgr::~CLangBarItemMgr() { g_timlist.ClearFlags(_psfn->dwThreadId, TLF_LBIMGR); _RemoveSystemItems(_psfn); CleanUp(); _SetThis(NULL); } //+--------------------------------------------------------------------------- // // IUnknown // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::QueryInterface(REFIID riid, void **ppvObj) { if (ppvObj == NULL) return E_INVALIDARG; *ppvObj = NULL; if (IsEqualIID(riid, IID_ITfLangBarItemMgr) || IsEqualIID(riid, IID_IUnknown)) { *ppvObj = SAFECAST(this, ITfLangBarItemMgr *); } if (*ppvObj) { AddRef(); return S_OK; } return E_NOINTERFACE; } STDAPI_(ULONG) CLangBarItemMgr::AddRef() { // // we don't have ref count. // Keep this class in psfn and delete at the end of thread. // return 2; } STDAPI_(ULONG) CLangBarItemMgr::Release() { // // we don't have ref count. // Keep this class in psfn and delete at the end of thread. // return 1; } //+--------------------------------------------------------------------------- // // _RemoveSystemItems // //---------------------------------------------------------------------------- void CLangBarItemMgr::_RemoveSystemItems(SYSTHREAD *psfn) { int i; CLBarItemDeviceType *plbiDT; DWORD dwThreadId = GetCurrentThreadId(); if (_plbiCtrl != NULL) { RemoveItem(*_plbiCtrl->GetGuidItem()); if (_plbiCtrl->Release() > 0) { if (psfn && (psfn->dwThreadId == dwThreadId)) { // Clean up a pointer that is marshalled to UTB. delete _plbiCtrl; } } _plbiCtrl = NULL; } if (_plbiReconv != NULL) { RemoveItem(*_plbiReconv->GetGuidItem()); if (_plbiReconv->Release() > 0) { if (psfn && (psfn->dwThreadId == dwThreadId)) { // Clean up a pointer that is marshalled to UTB. delete _plbiReconv; } } _plbiReconv = NULL; } if (_plbiWin32IME != NULL) { RemoveItem(*_plbiWin32IME->GetGuidItem()); if (_plbiWin32IME->Release() > 0) { if (psfn && (psfn->dwThreadId == dwThreadId)) { // Clean up a pointer that is marshalled to UTB. delete _plbiWin32IME; } } _plbiWin32IME = NULL; } if (_plbiHelp != NULL) { RemoveItem(*_plbiHelp->GetGuidItem()); if (_plbiHelp->Release() > 0) { if (psfn && (psfn->dwThreadId == dwThreadId)) { // Clean up a pointer that is marshalled to UTB. delete _plbiHelp; } } _plbiHelp = NULL; } for (i = 0; i < _rglbiDeviceType.Count(); i++) { plbiDT = _rglbiDeviceType.Get(i); if (plbiDT) { RemoveItem(*plbiDT->GetGuidItem()); if (plbiDT->Release() > 0) { if (psfn && (psfn->dwThreadId == dwThreadId)) { // Clean up a pointer that is marshalled to UTB. delete plbiDT; } } } } _rglbiDeviceType.Clear(); } //+--------------------------------------------------------------------------- // // CreateInstance // //---------------------------------------------------------------------------- /* static */ HRESULT CLangBarItemMgr::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj) { CLangBarItemMgr *plbim; HRESULT hr; if (ppvObj == NULL) return E_INVALIDARG; *ppvObj = NULL; if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION; if (plbim = _GetThis()) { return plbim->QueryInterface(riid, ppvObj); } SYSTHREAD *psfn = GetSYSTHREAD(); if (!psfn) return E_OUTOFMEMORY; if ((plbim = new CLangBarItemMgr(psfn)) == NULL) return E_OUTOFMEMORY; if (!plbim->_Init()) { plbim->Release(); return E_FAIL; } hr = plbim->QueryInterface(riid, ppvObj); plbim->Release(); #ifdef WINLOGON_LANGBAR ExecuteLoader(); #endif return hr; } //+--------------------------------------------------------------------------- // // FindDeviceTypeItem // //---------------------------------------------------------------------------- CLBarItemDeviceType *CLangBarItemMgr::FindDeviceTypeItem(REFGUID guid) { int i; CLBarItemDeviceType *plbiDT; for (i = 0; i < _rglbiDeviceType.Count(); i++) { plbiDT = _rglbiDeviceType.Get(i); if (plbiDT) { if (IsEqualGUID(*plbiDT->GetDeviceTypeGUID(), guid)) { return plbiDT; } } } return NULL; } //+--------------------------------------------------------------------------- // // _Init // //---------------------------------------------------------------------------- BOOL CLangBarItemMgr::_Init() { CLBarItemDeviceType **pplbiDT; GUID guid; // // set TLF_LBIMGR flag for this thread of timlist. // if (EnsureTIMList(_psfn)) { g_timlist.SetFlags(_psfn->dwThreadId, TLF_LBIMGR); InitLangChangeHotKey(); } // init the system default ctls if (!_plbiCtrl && (_plbiCtrl = new CLBarItemCtrl(_psfn)) == NULL) return FALSE; AddItem(_plbiCtrl); // // I want to hide a help button on Winlogon. // But IMJP8 causes av, if we don't have Help button... // // if (!IsInWinLogOnDesktop()) { if (!_plbiHelp && (_plbiHelp = new CLBarItemHelp(_psfn)) != NULL) { AddItem(_plbiHelp); } } if (CThreadInputMgr::_GetThis()) { if (!_plbiReconv && (_plbiReconv = new CLBarItemReconv(_psfn))) { AddItem(_plbiReconv); _plbiReconv->ShowOrHide(FALSE); } IEnumGUID *pEnum; if (SUCCEEDED(CCategoryMgr::s_EnumItemsInCategory( GUID_TFCAT_CATEGORY_OF_TIP, &pEnum))) { while (pEnum->Next(1, &guid, NULL) == S_OK) { if (FindDeviceTypeItem(guid)) continue; pplbiDT = _rglbiDeviceType.Append(1); if (pplbiDT) { *pplbiDT = new CLBarItemDeviceType(_psfn, guid); if (*pplbiDT) { (*pplbiDT)->Init(); AddItem(*pplbiDT); } else { int nCnt = _rglbiDeviceType.Count(); if (nCnt) _rglbiDeviceType.Remove(nCnt - 1, 1); } } } pEnum->Release(); } } else { if (!FindDeviceTypeItem(GUID_TFCAT_TIP_KEYBOARD)) { pplbiDT = _rglbiDeviceType.Append(1); if (pplbiDT) { *pplbiDT = new CLBarItemDeviceType(_psfn, GUID_TFCAT_TIP_KEYBOARD); if (*pplbiDT) { (*pplbiDT)->Init(); AddItem(*pplbiDT); } else { int nCnt = _rglbiDeviceType.Count(); if (nCnt) _rglbiDeviceType.Remove(nCnt - 1, 1); } } } } if (_plbiCtrl) { _plbiCtrl->_UpdateLangIcon(NULL, FALSE); } UpdateLangBarAddIns(); MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId()); return TRUE; } //+--------------------------------------------------------------------------- // // CleanUp // //---------------------------------------------------------------------------- void CLangBarItemMgr::CleanUp() { // // we can not call COM in PROCESS_DETACH. we just make sure // if someone forget to call UnRegister. // #if 1 // Assert(!_rglbiProxy.Count()); #else int i; int nCnt; nCnt = _rglbiProxy.Count(); for (i = 0; i < nCnt; i++) { CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i); pProxy->Clear(); pProxy->Release(); } #endif _rglbiProxy.Clear(); int i; int nCnt = _rgSink.Count(); for (i = 0; i < nCnt ; i++) { CLBarItemSink *pSink = _rgSink.Get(i); Assert(pSink); TraceMsg(TF_GENERAL, "NuiMgr clean up ItemSink - 0x%x08", (UINT_PTR)pSink); // // Issue: This is a pointer that is marshalled from UTB. // If this is called in DllMain(THREAD_DETACH). // calling Release() cause dead lock.... // pSink->_pItemSink->Release(); pSink->_pItemSink = NULL; delete pSink; } _rgSink.Clear(); } //+--------------------------------------------------------------------------- // // AddItem // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::AddItem(ITfLangBarItem *pItem) { ITfSource *pSource = NULL; HRESULT hr = E_FAIL; CLBarItemSinkProxy *pProxy; TF_LANGBARITEMINFO info; if (pItem == NULL) return E_INVALIDARG; if (FAILED(pItem->QueryInterface(IID_ITfSource, (void **)&pSource))) { goto Exit; } if (SUCCEEDED(pItem->GetInfo(&info))) { int i; int nCnt = _rglbiProxy.Count(); for (i = 0; i < nCnt; i++) { pProxy = _rglbiProxy.Get(i); if (IsEqualGUID(pProxy->_info.guidItem, info.guidItem)) { hr = E_INVALIDARG; goto Exit; } } } else { goto Exit; } pProxy = new CLBarItemSinkProxy(); if (!pProxy) { hr = E_OUTOFMEMORY; goto Exit; } if (!pProxy->Init(this, pItem, &info)) { goto Exit; } if (FAILED(pSource->AdviseSink(IID_ITfLangBarItemSink, pProxy, &pProxy->_dwCookie))) { pProxy->Clear(); pProxy->Release(); } else { int nCnt = _rglbiProxy.Count(); if (!_rglbiProxy.Insert(nCnt, 1)) { pSource->UnadviseSink(pProxy->_dwCookie); pProxy->Clear(); pProxy->Release(); hr = E_OUTOFMEMORY; goto Exit; } _rglbiProxy.Set(nCnt, pProxy); if (!_ulInAssemblyChange) MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId()); _fItemChanged = TRUE; hr = S_OK; } Exit: SafeRelease(pSource); return hr; } //+--------------------------------------------------------------------------- // // RemoveItem // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::RemoveItem(ITfLangBarItem *pItem) { TF_LANGBARITEMINFO info; if (!pItem) return E_INVALIDARG; if (FAILED(pItem->GetInfo(&info))) return E_FAIL; return RemoveItem(info.guidItem); } //+--------------------------------------------------------------------------- // // RemoveItem // //---------------------------------------------------------------------------- HRESULT CLangBarItemMgr::RemoveItem(REFGUID rguid) { int nCnt; int i; nCnt = _rglbiProxy.Count(); for (i = 0; i < nCnt; i++) { CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i); if (IsEqualGUID(pProxy->_info.guidItem, rguid)) { ITfSource *pSource; if (SUCCEEDED(pProxy->_plbi->QueryInterface(IID_ITfSource, (void **)&pSource))) { pSource->UnadviseSink(pProxy->_dwCookie); pSource->Release(); } _rglbiProxy.Remove(i, 1); pProxy->Clear(); pProxy->Release(); if (!_ulInAssemblyChange) { MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId()); } SYSTHREAD *psfn = FindSYSTHREAD(); if (psfn && (psfn->dwThreadId == _psfn->dwThreadId)) FreeMarshaledStubOfItem(psfn, rguid); _fItemChanged = TRUE; break; } } return S_OK; } //+--------------------------------------------------------------------------- // // RegisterItemSink // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::AdviseItemSink(ITfLangBarItemSink *punk, DWORD *pdwCookie, REFGUID rguidItem) { CLBarItemSinkProxy *pProxy; CLBarItemSink *pSink; int nCnt; HRESULT hr; if (pdwCookie == NULL) return E_POINTER; *pdwCookie = 0; if (punk == NULL) return E_POINTER; pProxy = GetItemSinkProxy(rguidItem); if (!pProxy) return E_INVALIDARG; pSink = new CLBarItemSink(); if (!pSink) { hr = E_OUTOFMEMORY; goto Exit; } *pdwCookie = _GetCookie(); if (!pSink->Init(punk, &pProxy->_info, *pdwCookie)) { hr = E_FAIL; goto Exit; } nCnt = _rgSink.Count(); if (!_rgSink.Insert(nCnt, 1)) { hr = E_OUTOFMEMORY; goto Exit; } _rgSink.Set(nCnt, pSink); hr = S_OK; Exit: return hr; } //+--------------------------------------------------------------------------- // // UnregisterItemSink // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::UnadviseItemSink(DWORD dwCookie) { int i; int nCnt = _rgSink.Count(); for (i = 0; i < nCnt ; i++) { CLBarItemSink *pSink = _rgSink.Get(i); if (pSink->_dwCookie == dwCookie) { #ifdef DEBUG pSink->_fUnadvised = TRUE; #endif _rgSink.Remove(i, 1); delete pSink; break; } } return S_OK; } //+--------------------------------------------------------------------------- // // GetItemFloatingRect // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::GetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc) { if (!prc) return E_INVALIDARG; if (!dwThreadId) dwThreadId = GetCurrentThreadId(); memset(prc, 0, sizeof(*prc)); return ThreadGetItemFloatingRect(dwThreadId, rguid, prc); } //+--------------------------------------------------------------------------- // // GetItemsStatus // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::GetItemsStatus(ULONG ulCount, const GUID *prgguid, DWORD *pdwStatus) { ULONG ul; for (ul = 0; ul < ulCount; ul++) { int i; BOOL fFound = FALSE; for (i = 0; i < _rglbiProxy.Count(); i++) { CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i); if (IsEqualGUID(pProxy->_info.guidItem, *prgguid)) { if (FAILED(pProxy->_plbi->GetStatus(pdwStatus))) return E_FAIL; pdwStatus++; prgguid++; fFound = TRUE; break; } } if (!fFound) return E_FAIL; } return S_OK; } //+--------------------------------------------------------------------------- // // GetItemNum // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::GetItemNum(ULONG *pulCount) { if (!pulCount) return E_INVALIDARG; *pulCount = _rglbiProxy.Count(); return S_OK; } //+--------------------------------------------------------------------------- // // GetItems // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::GetItems(ULONG ulCount, ITfLangBarItem **ppItem, TF_LANGBARITEMINFO *pInfo, DWORD *pdwStatus, ULONG *pcFetched) { int i; ULONG ulFetched = 0; CThreadInputMgr *ptim = CThreadInputMgr::_GetThis(); BOOL fHasFocusDIM; if (!ulCount) return S_FALSE; fHasFocusDIM = (ptim && ptim->_GetFocusDocInputMgr()) ? TRUE : FALSE; for (i = 0; i < _rglbiProxy.Count(); i++) { CLBarItemSinkProxy *pProxy = _rglbiProxy.Get(i); if (!fHasFocusDIM && pProxy->_fCicTip) continue; if (FAILED(pProxy->_plbi->GetInfo(pInfo))) return E_FAIL; pInfo++; if (FAILED(pProxy->_plbi->GetStatus(pdwStatus))) return E_FAIL; pdwStatus++; *ppItem = pProxy->_plbi; pProxy->_plbi->AddRef(); ppItem++; ulFetched++; if (ulFetched >= ulCount) break; } if (pcFetched) *pcFetched = ulFetched; return (ulFetched == ulCount) ? S_OK : S_FALSE; } //+--------------------------------------------------------------------------- // // AdviseItemsSink // //---------------------------------------------------------------------------- STDMETHODIMP CLangBarItemMgr::AdviseItemsSink(ULONG ulCount, ITfLangBarItemSink **ppunk, const GUID *pguidItem, DWORD *pdwCookie) { ULONG ul; for ( ul = 0; ul < ulCount; ul++) { if (FAILED(AdviseItemSink(ppunk[ul], &pdwCookie[ul], pguidItem[ul]))) return E_FAIL; } return S_OK; } //+--------------------------------------------------------------------------- // // UnadviseItemsSink // //---------------------------------------------------------------------------- STDMETHODIMP CLangBarItemMgr::UnadviseItemsSink(ULONG ulCount, DWORD *pdwCookie) { ULONG ul; for ( ul = 0; ul < ulCount; ul++) { if (FAILED(UnadviseItemSink(pdwCookie[ul]))) return E_FAIL; } return S_OK; } //+--------------------------------------------------------------------------- // // EnumLBItem // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::EnumItems(IEnumTfLangBarItems **ppEnum) { CEnumLBItem *pEnum = new CEnumLBItem(_psfn); *ppEnum = pEnum; return S_OK; } //+--------------------------------------------------------------------------- // // GetItem // //---------------------------------------------------------------------------- STDAPI CLangBarItemMgr::GetItem(REFGUID rguid, ITfLangBarItem **ppItem) { if (!ppItem) return E_INVALIDARG; *ppItem = NULL; CLBarItemSinkProxy *pProxy = GetItemSinkProxy(rguid); if (pProxy) { *ppItem = pProxy->_plbi; (*ppItem)->AddRef(); } return *ppItem ? S_OK : S_FALSE; } //+--------------------------------------------------------------------------- // // _AddWin32IMECtrl // //---------------------------------------------------------------------------- void CLangBarItemMgr::_AddWin32IMECtrl(BOOL fNotify) { if (_plbiWin32IME != NULL) return; if (_plbiWin32IME = new CLBarItemWin32IME) { AddItem(_plbiWin32IME); _plbiWin32IME->ShowInternal(TRUE, fNotify); } } //+--------------------------------------------------------------------------- // // _RemoveWin32IMECtrl // //---------------------------------------------------------------------------- void CLangBarItemMgr::_RemoveWin32IMECtrl() { if (_plbiWin32IME == NULL) return; RemoveItem(_plbiWin32IME); } //+--------------------------------------------------------------------------- // // GetItemSinkProxy // //---------------------------------------------------------------------------- CLBarItemSinkProxy *CLangBarItemMgr::GetItemSinkProxy(REFGUID rguid) { CLBarItemSinkProxy *pProxy = NULL; int nCnt = _rglbiProxy.Count(); int i; for (i = 0; i < nCnt; i++) { CLBarItemSinkProxy *pProxyTemp = _rglbiProxy.Get(i); if (IsEqualGUID(pProxyTemp->_info.guidItem, rguid)) { pProxy = pProxyTemp; break; } } return pProxy; } //+--------------------------------------------------------------------------- // // UpdateIcon // //---------------------------------------------------------------------------- HRESULT CLangBarItemMgr::OnUpdate(ITfLangBarItem *plbi, DWORD dwFlags) { int i; int nCnt; HRESULT hr; TF_LANGBARITEMINFO info; BOOL fFound; // // Toolbar will be being updated. So no need to handle OnUpdate. // Toolbar will ask icons, bitmaps no matter what. // if (!_fHandleOnUpdate) return S_OK; hr = plbi->GetInfo(&info); if (FAILED(hr)) return hr; fFound = FALSE; nCnt = _rgSink.Count(); for (i = 0; i < nCnt ; i++) { CLBarItemSink *pSink = _rgSink.Get(i); #ifdef DEBUG Assert(!pSink->_fUnadvised); #endif if (IsEqualGUID(pSink->_info.guidItem, info.guidItem)) { pSink->_dwDirtyUpdateFlags |= dwFlags; fFound = TRUE; } } if (_fDirtyUpdateHandling) { // // #509783 // // Some apps (Adobe PhotoShop) call PeekMessage() to eat the message // from queue but it does not call DispatchMessage() sometimes. // We need a way to restore _fDirtyUpdateHandling flag. // if (GetTickCount() - dwDirtyUpdateHandlingTime > 1000) { _fDirtyUpdateHandling = 0; } } if (fFound && !_fDirtyUpdateHandling) { HWND hwnd = EnsureMarshalWnd(); if (hwnd) { PostMessage(hwnd, g_msgNuiMgrDirtyUpdate, 0, 0); _fDirtyUpdateHandling = TRUE; dwDirtyUpdateHandlingTime = GetTickCount(); // // we need to check Kana-Caps status every time the langbar item // is updated. // SYSTHREAD *psfn = FindSYSTHREAD(); if (psfn) StartKanaCapsUpdateTimer(psfn); } } return S_OK; } //+--------------------------------------------------------------------------- // // OnUpdateHandler // //---------------------------------------------------------------------------- HRESULT CLangBarItemMgr::OnUpdateHandler() { int i; int nCnt; _fDirtyUpdateHandling = FALSE; _fInOnUpdateHandler = TRUE; nCnt = _rgSink.Count(); for (i = 0; i < nCnt ; i++) { CLBarItemSink *pSink = _rgSink.Get(i); DWORD dwFlags = pSink->_dwDirtyUpdateFlags; if (!dwFlags) continue; pSink->_dwDirtyUpdateFlags = 0; pSink->_pItemSink->OnUpdate(dwFlags); int nCntNew = _rgSink.Count(); if (nCnt > nCntNew) { nCnt = nCntNew; i--; } } _fInOnUpdateHandler = FALSE; return S_OK; } ////////////////////////////////////////////////////////////////////////////// // // CLBarItemSinkProxy // ////////////////////////////////////////////////////////////////////////////// BOOL CLBarItemSinkProxy::Init(CLangBarItemMgr *plbiMgr, ITfLangBarItem *plbi, TF_LANGBARITEMINFO *pinfo) { _plbiMgr = plbiMgr; // don't AddRef, because this obj is contained in the mgr's life // we'd create a circular ref if we did, and we don't need to _plbi = plbi; _plbi->AddRef(); _fCicTip = FALSE; _info = *pinfo; CTip *ptip; TfGuidAtom guidatom; CThreadInputMgr *ptim = CThreadInputMgr::_GetThis(); if (ptim && SUCCEEDED(MyRegisterGUID(_info.clsidService, &guidatom))) { _fCicTip = ptim->_GetCTipfromGUIDATOM(guidatom, &ptip); } return TRUE; } ////////////////////////////////////////////////////////////////////////////// // // CEnumLBItem // ////////////////////////////////////////////////////////////////////////////// //+--------------------------------------------------------------------------- // // ctor // //---------------------------------------------------------------------------- CEnumLBItem::CEnumLBItem(SYSTHREAD *psfn) : CSysThreadRef(psfn) { Dbg_MemSetThisNameID(TEXT("CEnumLBItem")); CThreadInputMgr *ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(_psfn); if (ptim) _fHasFocusDIM = ptim->_GetFocusDocInputMgr() ? TRUE : FALSE; _nCur = 0; } //+--------------------------------------------------------------------------- // // dtor // //---------------------------------------------------------------------------- CEnumLBItem::~CEnumLBItem() { } //+--------------------------------------------------------------------------- // // Clone // //---------------------------------------------------------------------------- HRESULT CEnumLBItem::Clone(IEnumTfLangBarItems **ppEnum) { return E_NOTIMPL; } //+--------------------------------------------------------------------------- // // Next // //---------------------------------------------------------------------------- HRESULT CEnumLBItem::Next(ULONG ulCount, ITfLangBarItem **ppLBItem, ULONG *pcFetched) { int nCnt; ULONG cFetched; CLangBarItemMgr *plbim = _psfn->plbim; if (!plbim) return E_FAIL; nCnt = plbim->_rglbiProxy.Count(); cFetched = 0; if (!ppLBItem) return E_INVALIDARG; *ppLBItem = NULL; while (cFetched < ulCount) { *ppLBItem = NULL; CLBarItemSinkProxy *pProxy; if (nCnt <= _nCur) break; pProxy = plbim->_rglbiProxy.Get(_nCur); if (!pProxy) break; if (_fHasFocusDIM || !pProxy->_fCicTip) { *ppLBItem = pProxy->_plbi; (*ppLBItem)->AddRef(); ppLBItem++; cFetched++; } _nCur++; } if (pcFetched) *pcFetched = cFetched; return (cFetched == ulCount) ? S_OK : S_FALSE; } //+--------------------------------------------------------------------------- // // Reset // //---------------------------------------------------------------------------- HRESULT CEnumLBItem::Reset() { _nCur = 0; return S_OK; } //+--------------------------------------------------------------------------- // // Skip // //---------------------------------------------------------------------------- HRESULT CEnumLBItem::Skip(ULONG ulCount) { int nCnt; CLangBarItemMgr *plbim = _psfn->plbim; if (!plbim) return E_FAIL; nCnt = plbim->_rglbiProxy.Count(); while (ulCount) { if (nCnt <= _nCur) break; _nCur++; ulCount--; } return ulCount ? S_FALSE : S_OK; }