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.

288 lines
8.0 KiB

  1. //
  2. // keys.cpp
  3. //
  4. // ITfKeyEventSink implementation.
  5. //
  6. #include "globals.h"
  7. #include "case.h"
  8. #include "editsess.h"
  9. class CKeystrokeEditSession : public CEditSessionBase
  10. {
  11. public:
  12. CKeystrokeEditSession(ITfContext *pContext, WPARAM wParam) : CEditSessionBase(pContext)
  13. {
  14. _wParam = wParam;
  15. }
  16. // ITfEditSession
  17. STDMETHODIMP DoEditSession(TfEditCookie ec);
  18. private:
  19. WPARAM _wParam;
  20. };
  21. /* 5d6d1b1e-64f2-47cd-9fe1-4e032c2dae77 */
  22. static const GUID GUID_PRESERVEDKEY_FLIPCASE = { 0x5d6d1b1e, 0x64f2, 0x47cd, {0x9f, 0xe1, 0x4e, 0x03, 0x2c, 0x2d, 0xae, 0x77} };
  23. // arbitrary hotkey: ctl-f
  24. static const TF_PRESERVEDKEY c_FlipCaseKey = { 'F', TF_MOD_CONTROL };
  25. //+---------------------------------------------------------------------------
  26. //
  27. // IsKeyEaten
  28. //
  29. //----------------------------------------------------------------------------
  30. inline BOOL IsKeyEaten(BOOL fFlipKeys, WPARAM wParam)
  31. {
  32. // we're only interested in VK_A - VK_Z, when the "Flip Keys" menu option
  33. // is on
  34. return fFlipKeys && (wParam >= 'A') && (wParam <= 'Z');
  35. }
  36. //+---------------------------------------------------------------------------
  37. //
  38. // _Menu_FlipKeys
  39. //
  40. // Advise or unadvise a keystroke sink.
  41. //----------------------------------------------------------------------------
  42. /* static */
  43. void CCaseTextService::_Menu_FlipKeys(CCaseTextService *_this)
  44. {
  45. _this->_fFlipKeys = !_this->_fFlipKeys;
  46. }
  47. //+---------------------------------------------------------------------------
  48. //
  49. // _InitKeystrokeSink
  50. //
  51. // Advise a keystroke sink.
  52. //----------------------------------------------------------------------------
  53. BOOL CCaseTextService::_InitKeystrokeSink()
  54. {
  55. ITfKeystrokeMgr *pKeystrokeMgr;
  56. HRESULT hr;
  57. if (_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr) != S_OK)
  58. return FALSE;
  59. hr = pKeystrokeMgr->AdviseKeyEventSink(_tfClientId, (ITfKeyEventSink *)this, TRUE);
  60. pKeystrokeMgr->Release();
  61. return (hr == S_OK);
  62. }
  63. //+---------------------------------------------------------------------------
  64. //
  65. // _UninitKeystrokeSink
  66. //
  67. // Unadvise a keystroke sink. Assumes we have advised one already.
  68. //----------------------------------------------------------------------------
  69. void CCaseTextService::_UninitKeystrokeSink()
  70. {
  71. ITfKeystrokeMgr *pKeystrokeMgr;
  72. if (_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr) != S_OK)
  73. return;
  74. pKeystrokeMgr->UnadviseKeyEventSink(_tfClientId);
  75. pKeystrokeMgr->Release();
  76. }
  77. //+---------------------------------------------------------------------------
  78. //
  79. // _InitPreservedKey
  80. //
  81. // Register a hot key.
  82. //----------------------------------------------------------------------------
  83. BOOL CCaseTextService::_InitPreservedKey()
  84. {
  85. ITfKeystrokeMgr *pKeystrokeMgr;
  86. HRESULT hr;
  87. if (_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr) != S_OK)
  88. return FALSE;
  89. hr = pKeystrokeMgr->PreserveKey(_tfClientId, GUID_PRESERVEDKEY_FLIPCASE,
  90. &c_FlipCaseKey, L"Toggle Case",
  91. wcslen(L"Toggle Case"));
  92. pKeystrokeMgr->Release();
  93. return (hr == S_OK);
  94. }
  95. //+---------------------------------------------------------------------------
  96. //
  97. // _UninitPreservedKey
  98. //
  99. // Uninit a hot key.
  100. //----------------------------------------------------------------------------
  101. void CCaseTextService::_UninitPreservedKey()
  102. {
  103. ITfKeystrokeMgr *pKeystrokeMgr;
  104. if (_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr) != S_OK)
  105. return;
  106. pKeystrokeMgr->UnpreserveKey(GUID_PRESERVEDKEY_FLIPCASE, &c_FlipCaseKey);
  107. pKeystrokeMgr->Release();
  108. }
  109. //+---------------------------------------------------------------------------
  110. //
  111. // OnSetFocus
  112. //
  113. // Called by the system whenever this service gets the keystroke device focus.
  114. //----------------------------------------------------------------------------
  115. STDAPI CCaseTextService::OnSetFocus(BOOL fForeground)
  116. {
  117. return S_OK;
  118. }
  119. //+---------------------------------------------------------------------------
  120. //
  121. // OnTestKeyDown
  122. //
  123. // Called by the system to query this service wants a potential keystroke.
  124. //----------------------------------------------------------------------------
  125. STDAPI CCaseTextService::OnTestKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  126. {
  127. *pfEaten = IsKeyEaten(_fFlipKeys, wParam);
  128. return S_OK;
  129. }
  130. //+---------------------------------------------------------------------------
  131. //
  132. // OnKeyDown
  133. //
  134. // Called by the system to offer this service a keystroke. If *pfEaten == TRUE
  135. // on exit, the application will not handle the keystroke.
  136. //----------------------------------------------------------------------------
  137. STDAPI CCaseTextService::OnKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  138. {
  139. CKeystrokeEditSession *pEditSession;
  140. HRESULT hr = S_OK;
  141. *pfEaten = IsKeyEaten(_fFlipKeys, wParam);
  142. if (*pfEaten)
  143. {
  144. // we'll insert a char ourselves in place of this keystroke
  145. if ((pEditSession = new CKeystrokeEditSession(pContext, wParam)) == NULL)
  146. {
  147. hr = E_OUTOFMEMORY;
  148. goto Exit;
  149. }
  150. // we need a lock to do our work
  151. // nb: this method is one of the few places where it is legal to use
  152. // the TF_ES_SYNC flag
  153. if (pContext->RequestEditSession(_tfClientId, pEditSession, TF_ES_SYNC | TF_ES_READWRITE, &hr) != S_OK)
  154. {
  155. hr = E_FAIL;
  156. }
  157. pEditSession->Release();
  158. }
  159. Exit:
  160. if (hr != S_OK)
  161. {
  162. *pfEaten = FALSE;
  163. }
  164. return S_OK;
  165. }
  166. //+---------------------------------------------------------------------------
  167. //
  168. // DoEditSession
  169. //
  170. //----------------------------------------------------------------------------
  171. STDAPI CKeystrokeEditSession::DoEditSession(TfEditCookie ec)
  172. {
  173. WCHAR wc;
  174. // we want to toggle the english case of the keystroke
  175. // nb: this is quick-and-dirty code, not intended to demonstrate the
  176. // correct way to flip capitalization!
  177. if (GetKeyState(VK_SHIFT) & 0x8000)
  178. {
  179. // shift-key, make it lowercase
  180. wc = (WCHAR)(_wParam | 32);
  181. }
  182. else
  183. {
  184. // else make it capital
  185. wc = (WCHAR)_wParam;
  186. }
  187. InsertTextAtSelection(ec, _pContext, &wc, 1);
  188. return S_OK;
  189. }
  190. //+---------------------------------------------------------------------------
  191. //
  192. // OnTestKeyUp
  193. //
  194. // Called by the system to query this service wants a potential keystroke.
  195. //----------------------------------------------------------------------------
  196. STDAPI CCaseTextService::OnTestKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  197. {
  198. *pfEaten = IsKeyEaten(_fFlipKeys, wParam);
  199. return S_OK;
  200. }
  201. //+---------------------------------------------------------------------------
  202. //
  203. // OnKeyUp
  204. //
  205. // Called by the system to offer this service a keystroke. If *pfEaten == TRUE
  206. // on exit, the application will not handle the keystroke.
  207. //----------------------------------------------------------------------------
  208. STDAPI CCaseTextService::OnKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
  209. {
  210. *pfEaten = IsKeyEaten(_fFlipKeys, wParam);
  211. return S_OK;
  212. }
  213. //+---------------------------------------------------------------------------
  214. //
  215. // OnPreservedKey
  216. //
  217. // Called when a hotkey (registered by us, or by the system) is typed.
  218. //----------------------------------------------------------------------------
  219. STDAPI CCaseTextService::OnPreservedKey(ITfContext *pContext, REFGUID rguid, BOOL *pfEaten)
  220. {
  221. if (IsEqualGUID(rguid, GUID_PRESERVEDKEY_FLIPCASE))
  222. {
  223. _Menu_FlipDoc(this);
  224. *pfEaten = TRUE;
  225. }
  226. else
  227. {
  228. *pfEaten = FALSE;
  229. }
  230. return S_OK;
  231. }