本來這個blog是記錄開發輸入法的點滴的,後來越來越雜,現在什麼都記錄了。

2008年12月30日 星期二

Subprime, CDS, CDO 是什麼?

美國樓價在01-05年節節上升,金融基構為了增加收入,不惜降低貸款要求,令到
大量收入較低,信用記錄較差的人,都輕易借錢買樓。這一批按揭,就叫次按。

而金融基構為了轉嫁風險,和盡快套現,將次按包裝成為金融產品,再混合其他
不同信貸風險的債卷資產,組成債卷抵押證卷,即是 CDO.

買了CDO的投資者,又為了分散風險,就向債卷保險商定期支付費用,就好像買保險一樣。
萬一債卷出現違約,投資者就獲得賠償。這就是信用違約掉期 CDS

2008年12月17日 星期三

Problem with Microsoft's Text Service Framework (TSF) Examples.

Problem with Microsoft's Text Service Framework (TSF) Examples.

In the previous version of YLam Input method, one of the bugs is when you are typing towards the windows of an application, and then you switch to another application, the YLam Input method windows does not hide itself.

The reason is YLam Input method is based on Microsoft's "Sample Code for Text Services Framework" and there is no examples shows how to auto hide the input method window when the application loses its focus.

After the email discussion with a net friend "zhangruisen", it is known that to support auto show/hide, the "IID_ITfThreadFocusSink" event sink is needed, and in the appropriate functions (i.e. STDAPI CTextService::OnSetThreadFocus() and STDAPI CTextService::OnKillThreadFocus() ), call the show / hide input method window. In Windows SDK, Windows SDK 的 Samples\WinUI\TSFcase, there is an example.

So, I added the following code to my YLam Input Method:

  BOOL
  CTextService::_InitThreadFocusSink() {
      HRESULT hr;
      ITfSource *pSource = NULL;
      if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) != S_OK)
          return FALSE;
      hr = pSource->AdviseSink(IID_ITfThreadFocusSink, (ITfThreadFocusSink *)this,
&_dwThreadFocusSinkCookie);
      pSource->Release();
      return (hr == S_OK);
  }

  // _UninitThreadFocusSink
  // Unadvise a Focus sink.  Assumes a sink has been advised already.
  void
  CTextService::_UninitThreadFocusSink() {
      ITfSource *pSource;
      if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) != S_OK)
          return;
      pSource->UnadviseSink(_dwThreadFocusSinkCookie);
      pSource->Release();
  }

  STDAPI
  CTextService::OnSetThreadFocus() {
      if (_pCandidateWin)
          _pCandidateWin->Show(TRUE);
      return S_OK;
  }

  STDAPI
  CTextService::OnKillThreadFocus()
  {
      if (_pCandidateWin)
          _pCandidateWin->Show(FALSE);
      return S_OK;
  }

Then in CTextService::Activate(), I called CTextService::_InitThreadFocusSink() and expect that is all! However, no matter how hard I tried to tweak the code, calling _InitThreadFocusSink() always returns S_FAILED. This puzzled me for more that 1/2 years.

Until last evening after back home from work, though very tired, I still tried to compare the Windows SDK's TSF Case example and my YLam Input Method carefully and I finally know what's wroong! It turns out:

STDAPI
CTextService::QueryInterface(REFIID riid, void **ppvObj) {
    if (ppvObj == NULL)
        return E_INVALIDARG;

    *ppvObj = NULL;

    if (IsEqualIID(riid, IID_IUnknown) ||
        IsEqualIID(riid, IID_ITfTextInputProcessor))
    {
        *ppvObj = (ITfTextInputProcessor *)this;
    } else if (IsEqualIID(riid, IID_ITfThreadMgrEventSink)) {
        *ppvObj = (ITfThreadMgrEventSink *)this;
    }
     else if (IsEqualIID(riid, IID_ITfThreadFocusSink)) {
        *ppvObj = (ITfThreadFocusSink *)this;
    }

else if (IsEqualIID(riid, IID_ITfTextEditSink)) {
        *ppvObj = (ITfTextEditSink *)this;
    } else if (IsEqualIID(riid, IID_ITfKeyEventSink)) {
        *ppvObj = (ITfKeyEventSink *)this;
    } else if (IsEqualIID(riid, IID_ITfCompositionSink)) {
        *ppvObj = (ITfKeyEventSink *)this;
    } else if (IsEqualIID(riid, IID_ITfDisplayAttributeProvider)) {
        *ppvObj = (ITfDisplayAttributeProvider *)this;
    }

    if (*ppvObj) {
        AddRef();
        return S_OK;
    }

    return E_NOINTERFACE;
}
 

In Windows SDK's TSF Case, the part in box above exits and it does not exist in YLam Input Method and other TSF Sample code!!!!!!!! After adding the few lines above, now my YLam input method can do auto show /hide!!!

Oh my god, such a few lines spent me 1/2 years!