Advertisement
Guest User

Untitled

a guest
Dec 13th, 2018
663
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 63.86 KB | None | 0 0
  1. #include "StdAfx.h"
  2. #include "IME.h"
  3. #include "TextTag.h"
  4. #include "../eterBase/Utils.h"
  5. #include "msctf.h"
  6. #include <oleauto.h>
  7.  
  8. #define COUNTOF(a) ( sizeof( a ) / sizeof( ( a )[0] ) )
  9.  
  10. int CIME::ms_compLen;
  11. int CIME::ms_curpos;
  12. int CIME::ms_lastpos;
  13. wchar_t CIME::m_wText[IMESTR_MAXLEN];
  14.  
  15. #define MAKEIMEVERSION(major, minor) ((DWORD)(((BYTE)(major) << 24) | ((BYTE)(minor) << 16)))
  16. #define IMEID_VER(dwId) ((dwId) & 0xffff0000)
  17. #define IMEID_LANG(dwId) ((dwId) & 0x0000ffff)
  18.  
  19. #define GETLANG() LOWORD(CIME::ms_hklCurrent)
  20. #define GETPRIMLANG() ((WORD)PRIMARYLANGID(GETLANG()))
  21. #define GETSUBLANG() SUBLANGID(GETLANG())
  22.  
  23. #define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
  24. #define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
  25.  
  26. // Chinese Traditional
  27. #define _CHT_HKL_DAYI ((HKL)0xE0060404) // DaYi
  28. #define _CHT_HKL_NEW_PHONETIC ((HKL)0xE0080404) // New Phonetic
  29. #define _CHT_HKL_NEW_CHANG_JIE ((HKL)0xE0090404) // New Chang Jie
  30. #define _CHT_HKL_NEW_QUICK ((HKL)0xE00A0404) // New Quick
  31. #define _CHT_HKL_HK_CANTONESE ((HKL)0xE00B0404) // Hong Kong Cantonese
  32.  
  33. #define CHT_IMEFILENAME1 "TINTLGNT.IME" // New Phonetic
  34. #define CHT_IMEFILENAME2 "CINTLGNT.IME" // New Chang Jie
  35. #define CHT_IMEFILENAME3 "MSTCIPHA.IME" // Phonetic 5.1
  36.  
  37. #define IMEID_CHT_VER42 (LANG_CHT | MAKEIMEVERSION(4, 2)) // New(Phonetic/ChanJie)IME98 : 4.2.x.x // Win98
  38. #define IMEID_CHT_VER43 (LANG_CHT | MAKEIMEVERSION(4, 3)) // New(Phonetic/ChanJie)IME98a : 4.3.x.x // Win2k
  39. #define IMEID_CHT_VER44 (LANG_CHT | MAKEIMEVERSION(4, 4)) // New ChanJie IME98b : 4.4.x.x // WinXP
  40. #define IMEID_CHT_VER50 (LANG_CHT | MAKEIMEVERSION(5, 0)) // New(Phonetic/ChanJie)IME5.0 : 5.0.x.x // WinME
  41. #define IMEID_CHT_VER51 (LANG_CHT | MAKEIMEVERSION(5, 1)) // New(Phonetic/ChanJie)IME5.1 : 5.1.x.x // IME2002(w/OfficeXP)
  42. #define IMEID_CHT_VER52 (LANG_CHT | MAKEIMEVERSION(5, 2)) // New(Phonetic/ChanJie)IME5.2 : 5.2.x.x // IME2002a(w/Whistler)
  43. #define IMEID_CHT_VER60 (LANG_CHT | MAKEIMEVERSION(6, 0)) // New(Phonetic/ChanJie)IME6.0 : 6.0.x.x // IME XP(w/WinXP SP1)
  44. #define IMEID_CHT_VER_VISTA (LANG_CHT | MAKEIMEVERSION(7, 0)) // All TSF TIP under Cicero UI-less mode: a hack to make GetImeId() return non-zero value
  45.  
  46. // Chinese Simplized
  47. #define _CHS_HKL ((HKL)0xE00E0804) // MSPY
  48. #define _CHS_HKL_QQPINYIN ((HKL)0xE0210804) // QQ PinYin
  49. #define _CHS_HKL_SOGOU ((HKL)0xE0220804) // Sougou PinYin
  50. #define _CHS_HKL_GOOGLEPINYIN ((HKL)0xE0230804) // Google PinYin
  51.  
  52. #define CHS_IMEFILENAME1 "PINTLGNT.IME" // MSPY1.5/2/3
  53. #define CHS_IMEFILENAME2 "MSSCIPYA.IME" // MSPY3 for OfficeXP
  54. #define CHS_IMEFILENAME_QQPINYIN "QQPINYIN.IME" // QQ PinYin
  55. #define CHS_IMEFILENAME_SOGOUPY "SOGOUPY.IME" // Sougou PinYin
  56. #define CHS_IMEFILENAME_GOOGLEPINYIN2 "GOOGLEPINYIN2.IME" // Google PinYin 2
  57.  
  58. #define IMEID_CHS_VER41 (LANG_CHS | MAKEIMEVERSION(4, 1)) // MSPY1.5 // SCIME97 or MSPY1.5 (w/Win98, Office97)
  59. #define IMEID_CHS_VER42 (LANG_CHS | MAKEIMEVERSION(4, 2)) // MSPY2 // Win2k/WinME
  60. #define IMEID_CHS_VER53 (LANG_CHS | MAKEIMEVERSION(5, 3)) // MSPY3 // WinXP
  61.  
  62. enum { INDICATOR_NON_IME, INDICATOR_CHS, INDICATOR_CHT, INDICATOR_KOREAN, INDICATOR_JAPANESE };
  63. enum { IMEUI_STATE_OFF, IMEUI_STATE_ON, IMEUI_STATE_ENGLISH };
  64.  
  65. #define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
  66.  
  67. wchar_t s_aszIndicator[5][3] =
  68. {
  69. L"En",
  70. L"\x7B80",
  71. L"\x7E41",
  72. L"\xAC00",
  73. L"\x3042",
  74. };
  75.  
  76. INPUTCONTEXT* (WINAPI * CIME::_ImmLockIMC)( HIMC );
  77. BOOL (WINAPI * CIME::_ImmUnlockIMC)( HIMC );
  78. LPVOID (WINAPI * CIME::_ImmLockIMCC)( HIMCC );
  79. BOOL (WINAPI * CIME::_ImmUnlockIMCC)( HIMCC );
  80.  
  81. UINT (WINAPI * CIME::_GetReadingString)( HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT );
  82. BOOL (WINAPI * CIME::_ShowReadingWindow)( HIMC, BOOL );
  83.  
  84. bool CIME::ms_bInitialized = false;
  85. bool CIME::ms_bDisableIMECompletely = false;
  86. bool CIME::ms_bImeEnabled = false;
  87. bool CIME::ms_bUILessMode = false;
  88. bool CIME::ms_bCaptureInput = false;
  89. bool CIME::ms_bChineseIME = false;
  90. bool CIME::ms_bUseIMMCandidate = false;
  91.  
  92. HWND CIME::ms_hWnd;
  93. HKL CIME::ms_hklCurrent;
  94. char CIME::ms_szKeyboardLayout[KL_NAMELENGTH+1];
  95. OSVERSIONINFOA CIME::ms_stOSVI;
  96.  
  97. HINSTANCE CIME::ms_hImm32Dll;
  98. HINSTANCE CIME::ms_hCurrentImeDll;
  99. DWORD CIME::ms_dwImeState;
  100.  
  101. DWORD CIME::ms_adwId[2] = { 0, 0 };
  102.  
  103. // IME Level
  104. DWORD CIME::ms_dwIMELevel;
  105. DWORD CIME::ms_dwIMELevelSaved;
  106.  
  107. // Candidate List
  108. bool CIME::ms_bCandidateList;
  109. DWORD CIME::ms_dwCandidateCount;
  110. bool CIME::ms_bVerticalCandidate;
  111. int CIME::ms_iCandListIndexBase;
  112. WCHAR CIME::ms_wszCandidate[CIME::MAX_CANDLIST][MAX_CANDIDATE_LENGTH];
  113. DWORD CIME::ms_dwCandidateSelection;
  114. DWORD CIME::ms_dwCandidatePageSize;
  115.  
  116. // Reading Window
  117. bool CIME::ms_bReadingInformation;
  118. int CIME::ms_iReadingError = 0;
  119. bool CIME::ms_bHorizontalReading;
  120. std::vector<wchar_t> CIME::ms_wstrReading;
  121.  
  122. // Indicator
  123. wchar_t* CIME::ms_wszCurrentIndicator;
  124.  
  125. IIMEEventSink* CIME::ms_pEvent;
  126.  
  127. int CIME::ms_ulbegin;
  128. int CIME::ms_ulend;
  129.  
  130. UINT CIME::ms_uOutputCodePage = 0;
  131. UINT CIME::ms_uInputCodePage = 0;
  132.  
  133. extern DWORD gs_codePage=0;
  134. extern DWORD GetDefaultCodePage();
  135. extern int ReadToken(const char* token);
  136. extern const char* FindToken(const char* begin, const char* end);
  137.  
  138. ///////////////////////////////////////////////////////////////////////////////
  139. //
  140. // CTsfUiLessMode
  141. // Handles IME events using Text Service Framework (TSF). Before Vista,
  142. // IMM (Input Method Manager) API has been used to handle IME events and
  143. // inqueries. Some IMM functions lose backward compatibility due to design
  144. // of TSF, so we have to use new TSF interfaces.
  145. //
  146. ///////////////////////////////////////////////////////////////////////////////
  147. class CTsfUiLessMode
  148. {
  149. protected:
  150. // Sink receives event notifications
  151. class CUIElementSink : public ITfUIElementSink, public ITfInputProcessorProfileActivationSink, public ITfCompartmentEventSink
  152. {
  153. public:
  154. CUIElementSink();
  155. ~CUIElementSink();
  156.  
  157. // IUnknown
  158. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj);
  159. STDMETHODIMP_(ULONG) AddRef(void);
  160. STDMETHODIMP_(ULONG) Release(void);
  161.  
  162. // ITfUIElementSink
  163. // Notifications for Reading Window events. We could process candidate as well, but we'll use IMM for simplicity sake.
  164. STDMETHODIMP BeginUIElement(DWORD dwUIElementId, BOOL *pbShow);
  165. STDMETHODIMP UpdateUIElement(DWORD dwUIElementId);
  166. STDMETHODIMP EndUIElement(DWORD dwUIElementId);
  167.  
  168. // ITfInputProcessorProfileActivationSink
  169. // Notification for keyboard input locale change
  170. STDMETHODIMP OnActivated(DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid,
  171. REFGUID guidProfile, HKL hkl, DWORD dwFlags);
  172.  
  173. // ITfCompartmentEventSink
  174. // Notification for open mode (toggle state) change
  175. STDMETHODIMP OnChange(REFGUID rguid);
  176.  
  177. private:
  178. LONG _cRef;
  179. };
  180.  
  181. static void MakeReadingInformationString(ITfReadingInformationUIElement* preading);
  182. static void MakeCandidateStrings(ITfCandidateListUIElement* pcandidate);
  183. static ITfUIElement* GetUIElement(DWORD dwUIElementId);
  184. static BOOL GetCompartments( ITfCompartmentMgr** ppcm, ITfCompartment** ppTfOpenMode, ITfCompartment** ppTfConvMode );
  185. static BOOL SetupCompartmentSinks( BOOL bResetOnly = FALSE, ITfCompartment* pTfOpenMode = NULL, ITfCompartment* ppTfConvMode = NULL );
  186.  
  187. static ITfThreadMgrEx* m_tm;
  188. static DWORD m_dwUIElementSinkCookie;
  189. static DWORD m_dwAlpnSinkCookie;
  190. static DWORD m_dwOpenModeSinkCookie;
  191. static DWORD m_dwConvModeSinkCookie;
  192. static CUIElementSink *m_TsfSink;
  193. static int m_nCandidateRefCount; // Some IME shows multiple candidate lists but the Library doesn't support multiple candidate list.
  194. // So track open / close events to make sure the candidate list opened last is shown.
  195. CTsfUiLessMode() {} // this class can't be instanciated
  196.  
  197. public:
  198. static BOOL SetupSinks();
  199. static void ReleaseSinks();
  200. static BOOL CurrentInputLocaleIsIme();
  201. static void UpdateImeState(BOOL bResetCompartmentEventSink = FALSE);
  202. static void EnableUiUpdates(bool bEnable);
  203. };
  204.  
  205. ITfThreadMgrEx* CTsfUiLessMode::m_tm;
  206. DWORD CTsfUiLessMode::m_dwUIElementSinkCookie = TF_INVALID_COOKIE;
  207. DWORD CTsfUiLessMode::m_dwAlpnSinkCookie = TF_INVALID_COOKIE;
  208. DWORD CTsfUiLessMode::m_dwOpenModeSinkCookie = TF_INVALID_COOKIE;
  209. DWORD CTsfUiLessMode::m_dwConvModeSinkCookie = TF_INVALID_COOKIE;
  210. CTsfUiLessMode::CUIElementSink* CTsfUiLessMode::m_TsfSink = NULL;
  211. int CTsfUiLessMode::m_nCandidateRefCount = NULL;
  212.  
  213. // Class to disable Cicero in case ImmDisableTextFrameService() doesn't disable it completely
  214. class CDisableCicero
  215. {
  216. public:
  217. CDisableCicero() : m_ptim( NULL ), m_bComInit( false )
  218. {
  219. }
  220. ~CDisableCicero()
  221. {
  222. Uninitialize();
  223. }
  224. void Initialize()
  225. {
  226. if ( m_bComInit )
  227. {
  228. return;
  229. }
  230. HRESULT hr;
  231. hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
  232. if ( SUCCEEDED( hr ) )
  233. {
  234. m_bComInit = true;
  235. hr = CoCreateInstance( CLSID_TF_ThreadMgr,
  236. NULL,
  237. CLSCTX_INPROC_SERVER,
  238. __uuidof(ITfThreadMgr),
  239. (void**)&m_ptim );
  240. }
  241. }
  242. void Uninitialize()
  243. {
  244. if ( m_ptim )
  245. {
  246. m_ptim->Release();
  247. m_ptim = NULL;
  248. }
  249. if ( m_bComInit )
  250. CoUninitialize();
  251. m_bComInit = false;
  252. }
  253.  
  254. void DisableCiceroOnThisWnd( HWND hwnd )
  255. {
  256. if ( m_ptim == NULL )
  257. return;
  258. ITfDocumentMgr* pdimPrev; // the dim that is associated previously.
  259. // Associate NULL dim to the window.
  260. // When this window gets the focus, Cicero does not work and IMM32 IME
  261. // will be activated.
  262. if ( SUCCEEDED( m_ptim->AssociateFocus( hwnd, NULL, &pdimPrev ) ) )
  263. {
  264. if ( pdimPrev )
  265. pdimPrev->Release();
  266. }
  267. }
  268. private:
  269. ITfThreadMgr* m_ptim;
  270. bool m_bComInit;
  271. };
  272. static CDisableCicero g_disableCicero;
  273.  
  274. /*---------------------------------------------------------------------------*/ /* Public */
  275. CIME::CIME()
  276. {
  277. ms_hWnd = NULL;
  278.  
  279. ms_bCandidateList = false;
  280. ms_bReadingInformation = false;
  281.  
  282. Clear();
  283.  
  284. m_max = 0;
  285. m_userMax = 0;
  286.  
  287. m_bOnlyNumberMode = FALSE;
  288. m_hOrgIMC = NULL;
  289.  
  290. m_bEnablePaste = true;
  291. m_bUseDefaultIME = false;
  292. }
  293.  
  294. CIME::~CIME()
  295. {
  296. SAFE_FREE_LIBRARY(ms_hCurrentImeDll);
  297. SAFE_FREE_LIBRARY(ms_hImm32Dll);
  298. }
  299.  
  300. bool CIME::Initialize(HWND hWnd)
  301. {
  302. if(ms_bInitialized)
  303. return true;
  304. ms_hWnd = hWnd;
  305.  
  306. g_disableCicero.Initialize();
  307.  
  308. ms_stOSVI.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  309. GetVersionExA(&ms_stOSVI);
  310.  
  311. bool bUnicodeImm = false;
  312. // IMM in NT or Win98 supports Unicode
  313. if ( ms_stOSVI.dwPlatformId == VER_PLATFORM_WIN32_NT ||
  314. ( ms_stOSVI.dwMajorVersion > 4 ) ||
  315. ( ms_stOSVI.dwMajorVersion == 4 ) && ( ms_stOSVI.dwMinorVersion > 0 ) ) {
  316. bUnicodeImm = true;
  317. }
  318.  
  319. // Load ImmLock/ImmUnlock Function Proc
  320. CHAR szPath[MAX_PATH+1];
  321. ms_bDisableIMECompletely = false;
  322.  
  323. if(GetSystemDirectoryA(szPath, MAX_PATH+1)) {
  324. strcat(szPath, "\\imm32.dll");
  325. ms_hImm32Dll = LoadLibraryA(szPath);
  326. if(ms_hImm32Dll)
  327. {
  328. _ImmLockIMC = (INPUTCONTEXT*(WINAPI *)(HIMC)) GetProcAddress(ms_hImm32Dll, "ImmLockIMC");
  329. _ImmUnlockIMC = (BOOL(WINAPI *)(HIMC)) GetProcAddress(ms_hImm32Dll, "ImmUnlockIMC");
  330. _ImmLockIMCC = (LPVOID(WINAPI *)(HIMCC)) GetProcAddress(ms_hImm32Dll, "ImmLockIMCC");
  331. _ImmUnlockIMCC = (BOOL(WINAPI *)(HIMCC)) GetProcAddress(ms_hImm32Dll, "ImmUnlockIMCC");
  332. BOOL (WINAPI* _ImmDisableTextFrameService)(DWORD) = (BOOL (WINAPI*)(DWORD))GetProcAddress(ms_hImm32Dll, "ImmDisableTextFrameService");
  333. if ( _ImmDisableTextFrameService )
  334. _ImmDisableTextFrameService( (DWORD)-1 );
  335. } else {
  336. ms_bDisableIMECompletely = true;
  337. }
  338. }
  339.  
  340. ms_bInitialized = true;
  341.  
  342. m_hOrgIMC = ImmGetContext( ms_hWnd );
  343. ImmReleaseContext( ms_hWnd, m_hOrgIMC );
  344.  
  345. CheckInputLocale();
  346. ChangeInputLanguageWorker();
  347. SetSupportLevel(2);
  348.  
  349. ms_bUILessMode = CTsfUiLessMode::SetupSinks() != FALSE;
  350. CheckToggleState();
  351. if ( ms_bUILessMode )
  352. {
  353. ms_bChineseIME = ( GETPRIMLANG() == LANG_CHINESE ) && CTsfUiLessMode::CurrentInputLocaleIsIme();
  354. CTsfUiLessMode::UpdateImeState();
  355. }
  356.  
  357. return true;
  358. }
  359.  
  360. void CIME::Uninitialize()
  361. {
  362. if ( !ms_bInitialized )
  363. return;
  364. CTsfUiLessMode::ReleaseSinks();
  365. if ( ms_hWnd )
  366. ImmAssociateContext(ms_hWnd, m_hOrgIMC);
  367. ms_hWnd = NULL;
  368. m_hOrgIMC = NULL;
  369. SAFE_FREE_LIBRARY(ms_hCurrentImeDll);
  370. SAFE_FREE_LIBRARY(ms_hImm32Dll);
  371. g_disableCicero.Uninitialize();
  372. ms_bInitialized = false;
  373. }
  374.  
  375. void CIME::UseDefaultIME()
  376. {
  377. m_bUseDefaultIME = true;
  378. }
  379.  
  380. bool CIME::IsIMEEnabled()
  381. {
  382. return ms_bImeEnabled;
  383. }
  384.  
  385. void CIME::EnableIME(bool bEnable)
  386. {
  387. if (!ms_bInitialized || !ms_hWnd)
  388. return;
  389. if (ms_bDisableIMECompletely)
  390. bEnable = false;
  391. ImmAssociateContext(ms_hWnd, bEnable ? m_hOrgIMC : NULL);
  392. ms_bImeEnabled = bEnable;
  393. if (bEnable)
  394. CheckToggleState();
  395. CTsfUiLessMode::EnableUiUpdates(bEnable);
  396. }
  397.  
  398. void CIME::DisableIME()
  399. {
  400. EnableIME(false);
  401. }
  402.  
  403. void CIME::EnableCaptureInput()
  404. {
  405. ms_bCaptureInput = true;
  406. }
  407.  
  408. void CIME::DisableCaptureInput()
  409. {
  410. ms_bCaptureInput = false;
  411. }
  412.  
  413. bool CIME::IsCaptureEnabled()
  414. {
  415. return ms_bCaptureInput;
  416. }
  417.  
  418. void CIME::Clear()
  419. {
  420. ms_lastpos = 0;
  421. ms_curpos = 0;
  422.  
  423. ms_compLen = 0;
  424. ms_ulbegin = 0;
  425. ms_ulend = 0;
  426. }
  427.  
  428. int CIME::GetReading(std::string & rstrText)
  429. {
  430. char reading[IMEREADING_MAXLEN];
  431.  
  432. if(ms_wstrReading.size() == 0)
  433. return 0;
  434. int readingLen = WideCharToMultiByte(ms_uOutputCodePage, 0, &ms_wstrReading[0], ms_wstrReading.size(), reading, sizeof(reading), NULL, NULL);
  435.  
  436. rstrText.append(GetCodePageText());
  437. rstrText.append(reading, reading + readingLen);
  438.  
  439. return rstrText.size();
  440. }
  441.  
  442. int CIME::GetReadingError()
  443. {
  444. return ms_iReadingError;
  445. }
  446.  
  447. void CIME::SetMax(int iMax)
  448. {
  449. m_max = iMax;
  450. }
  451.  
  452. void CIME::SetUserMax(int iMax)
  453. {
  454. m_userMax = iMax;
  455. }
  456.  
  457. void CIME::SetText(const char* szText, int len)
  458. {
  459. ms_compLen = 0;
  460. ms_ulbegin = 0;
  461. ms_ulend = 0;
  462.  
  463. const char* begin = szText;
  464. const char* end = begin + len;
  465. const char* iter = FindToken(begin, end);
  466.  
  467. int m_wTextLen = sizeof(m_wText)/sizeof(wchar_t);
  468.  
  469. ms_lastpos = MultiByteToWideChar(ms_uInputCodePage, 0, begin, iter-begin, m_wText, m_wTextLen);
  470.  
  471. if (iter < end)
  472. ms_lastpos += MultiByteToWideChar(ReadToken(iter), 0, (iter+5), end-(iter+5), m_wText+ms_lastpos, m_wTextLen-ms_lastpos);
  473.  
  474. ms_curpos = min(ms_curpos, ms_lastpos);
  475. }
  476.  
  477. int CIME::GetText(std::string & rstrText, bool addCodePage)
  478. {
  479. int outCodePage = ms_uOutputCodePage;
  480. int dataCodePage;
  481. switch (outCodePage)
  482. {
  483. //case 1256: // ARABIC
  484. case 1268: // VIETNAM
  485. dataCodePage = CP_UTF8;
  486. break;
  487. default:
  488. dataCodePage = outCodePage;
  489. }
  490.  
  491. int len = 0;
  492. char text[IMESTR_MAXLEN];
  493.  
  494. len += WideCharToMultiByte(dataCodePage, 0, m_wText, ms_curpos, text, sizeof(text)-len, NULL, NULL);
  495. len += WideCharToMultiByte(dataCodePage, 0, m_wszComposition, ms_compLen, text+len, sizeof(text)-len, NULL, NULL);
  496. len += WideCharToMultiByte(dataCodePage, 0, m_wText+ms_curpos, ms_lastpos-ms_curpos, text+len, sizeof(text)-len, NULL, NULL);
  497.  
  498. int i;
  499. for(i=0; i<len; ++i)
  500. if((BYTE)text[i] > 0x7F) break;
  501.  
  502. if(i == len)
  503. {
  504. rstrText.append(text, text+len);
  505. }
  506. else
  507. {
  508. rstrText.append(text, text+i);
  509.  
  510. //if (addCodePage)
  511. // rstrText.append(GetCodePageText());
  512.  
  513. rstrText.append(text+i, text+len);
  514. }
  515.  
  516. return rstrText.size();
  517. }
  518.  
  519. const char* CIME::GetCodePageText()
  520. {
  521. static char szCodePage[16];
  522.  
  523. const int defCodePage = GetDefaultCodePage();
  524. const int outCodePage = ms_uOutputCodePage;
  525.  
  526. if (outCodePage != defCodePage)
  527. {
  528. sprintf(szCodePage, "@%04d", outCodePage);
  529. }
  530. else
  531. {
  532. szCodePage[0] = 0;
  533. }
  534.  
  535. return szCodePage;
  536. }
  537.  
  538. int CIME::GetCodePage()
  539. {
  540. return ms_uOutputCodePage;
  541. }
  542.  
  543. int CIME::GetCandidatePageCount()
  544. {
  545. return ms_dwCandidatePageSize;
  546. }
  547.  
  548. int CIME::GetCandidateCount()
  549. {
  550. return ms_dwCandidateCount;
  551. }
  552.  
  553. int CIME::GetCandidate(DWORD index, std::string & rstrText)
  554. {
  555. if(index >= MAX_CANDLIST)
  556. return 0;
  557.  
  558. LPCWSTR wszText = ms_wszCandidate[index];
  559. if(wszText == NULL)
  560. return 0;
  561.  
  562. int wTextLen = wcslen(wszText);
  563. if(wTextLen == 0)
  564. return 0;
  565.  
  566. char text[IMESTR_MAXLEN];
  567. int len = ::WideCharToMultiByte(CP_UTF8, 0, wszText, wTextLen, text, sizeof(text), 0, 0);
  568.  
  569. rstrText.append("@9999");
  570. rstrText.append(text, text+len);
  571.  
  572. return wTextLen;
  573. }
  574.  
  575. int CIME::GetCandidateSelection()
  576. {
  577. return ms_dwCandidateSelection;
  578. }
  579.  
  580. void CIME::SetInputMode(DWORD dwMode)
  581. {
  582. HIMC hImc = ImmGetContext(ms_hWnd);
  583.  
  584. ImmSetConversionStatus(hImc, dwMode, IME_SMODE_AUTOMATIC);
  585.  
  586. ImmReleaseContext(ms_hWnd, hImc);
  587. }
  588.  
  589. DWORD CIME::GetInputMode()
  590. {
  591. DWORD dwCMode, dwSMode;
  592.  
  593. HIMC hImc = ImmGetContext(ms_hWnd);
  594.  
  595. ImmGetConversionStatus(hImc, &dwCMode, &dwSMode);
  596.  
  597. ImmReleaseContext(ms_hWnd, hImc);
  598.  
  599. return dwCMode;
  600. }
  601.  
  602. void CIME::SetNumberMode()
  603. {
  604. m_bOnlyNumberMode = TRUE;
  605. }
  606.  
  607. void CIME::SetStringMode()
  608. {
  609. m_bOnlyNumberMode = FALSE;
  610. }
  611.  
  612. void CIME::AddExceptKey(wchar_t key)
  613. {
  614. m_exceptKey.push_back(key);
  615. }
  616.  
  617. void CIME::ClearExceptKey()
  618. {
  619. m_exceptKey.clear();
  620. }
  621.  
  622. bool CIME::__IsWritable(wchar_t key)
  623. {
  624. if ( m_exceptKey.end() == std::find(m_exceptKey.begin(),m_exceptKey.end(),key) )
  625. return true;
  626. else
  627. return false;
  628. }
  629.  
  630. void CIME::EnablePaste(bool bFlag)
  631. {
  632. m_bEnablePaste = bFlag;
  633. }
  634.  
  635. void CIME::PasteTextFromClipBoard()
  636. {
  637. if (!m_bEnablePaste)
  638. return;
  639.  
  640. if (!OpenClipboard(NULL))
  641. return;
  642.  
  643. HANDLE handle = GetClipboardData(CF_TEXT);
  644. if (!handle)
  645. return;
  646. char * buffer = (char*)GlobalLock(handle);
  647. if (!buffer)
  648. return;
  649. std::string strClipboard = buffer;
  650. GlobalUnlock(handle);
  651. CloseClipboard();
  652.  
  653. if (strClipboard.empty())
  654. return;
  655.  
  656. const char* begin = strClipboard.c_str();
  657. const char* end = begin + strClipboard.length();
  658. wchar_t m_wText[IMESTR_MAXLEN];
  659. int wstrLen = MultiByteToWideChar(ms_uInputCodePage, 0, begin, end-begin, m_wText, IMESTR_MAXLEN);
  660.  
  661. InsertString(m_wText, wstrLen);
  662. if(ms_pEvent)
  663. ms_pEvent->OnUpdate();
  664. }
  665.  
  666. void CIME::FinalizeString(bool bSend)
  667. {
  668. HIMC himc;
  669. static bool s_bProcessing = false; // to avoid infinite recursion
  670. if ( !ms_bInitialized || s_bProcessing || NULL == ( himc = ImmGetContext( ms_hWnd ) ) )
  671. return;
  672. s_bProcessing = true;
  673.  
  674. if (ms_dwIMELevel == 2 && bSend)
  675. {
  676. //// Send composition string to app.
  677. //LONG lRet = lstrlenW( m_wszComposition );
  678. ////assert( lRet >= 2);
  679. //// In case of CHT IME, don't send the trailing double byte space, if it exists.
  680. //if ( GETLANG() == LANG_CHT && (lRet >= 1)
  681. // && m_wszComposition[lRet - 1] == 0x3000 )
  682. //{
  683. // lRet--;
  684. //}
  685. //SendCompString();
  686. }
  687.  
  688. //InitCompStringData();
  689. // clear composition string in IME
  690. ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
  691. if (ms_bUILessMode)
  692. {
  693. // For some reason ImmNotifyIME doesn't work on DaYi and Array CHT IMEs. Cancel composition string by setting zero-length string.
  694. ImmSetCompositionStringW(himc, SCS_SETSTR, L"", sizeof(wchar_t), L"", sizeof(wchar_t));
  695. }
  696. // the following line is necessary as Korean IME doesn't close cand list when comp string is cancelled.
  697. ImmNotifyIME( himc, NI_CLOSECANDIDATE, 0, 0 );
  698. ImmReleaseContext(ms_hWnd, himc);
  699. // Zooty2 RAID #4759: Sometimes application doesn't receive IMN_CLOSECANDIDATE on Alt+Tab
  700. // So the same code for IMN_CLOSECANDIDATE is replicated here.
  701. CloseCandidateList();
  702. s_bProcessing = false;
  703. }
  704.  
  705. int CIME::GetCompLen()
  706. {
  707. return ms_compLen;
  708. }
  709.  
  710. int CIME::GetULBegin()
  711. {
  712. return ms_ulbegin;
  713. }
  714.  
  715. int CIME::GetULEnd()
  716. {
  717. return ms_ulend;
  718. }
  719.  
  720. void CIME::CloseCandidateList()
  721. {
  722. ms_bCandidateList = false;
  723. ms_dwCandidateCount = 0;
  724. memset(&ms_wszCandidate, 0, sizeof(ms_wszCandidate));
  725. if(ms_pEvent)
  726. ms_pEvent->OnCloseCandidateList();
  727. }
  728.  
  729. void CIME::CloseReadingInformation()
  730. {
  731. CIME::ms_bReadingInformation = false;
  732. if(CIME::ms_pEvent)
  733. CIME::ms_pEvent->OnCloseReadingWnd();
  734. }
  735.  
  736. void CIME::ChangeInputLanguage()
  737. {
  738. UINT uLanguage = (UINT) GETLANG();
  739. CheckToggleState();
  740. ChangeInputLanguageWorker();
  741. if (uLanguage != GETLANG())
  742. {
  743. // Korean IME always uses level 3 support.
  744. // Other languages use the level that is specified by ImeUi_SetSupportLevel()
  745. SetSupportLevel( ( GETPRIMLANG() == LANG_KOREAN ) ? 3 : ms_dwIMELevelSaved );
  746. }
  747.  
  748. if(ms_pEvent)
  749. ms_pEvent->OnChangeCodePage();
  750.  
  751. //HWND hwndImeDef = ImmGetDefaultIMEWnd(ms_hWnd);
  752. //if ( hwndImeDef )
  753. //{
  754. // // Fix for Zooty #3995: prevent CHT IME toobar from showing up
  755. // SendMessageA(hwndImeDef, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0);
  756. // SendMessageA(hwndImeDef, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0);
  757. //}
  758. }
  759.  
  760. void CIME::ChangeInputLanguageWorker()
  761. {
  762. if ( !ms_bUILessMode )
  763. ms_iCandListIndexBase = ( ms_hklCurrent == _CHT_HKL_DAYI ) ? 0 : 1;
  764. SetupImeApi();
  765. }
  766.  
  767. void CIME::SetSupportLevel( DWORD dwImeLevel )
  768. {
  769. if ( dwImeLevel < 2 || 3 < dwImeLevel )
  770. return;
  771. if ( GETPRIMLANG() == LANG_KOREAN )
  772. {
  773. dwImeLevel = 3;
  774. }
  775. ms_dwIMELevel = dwImeLevel;
  776. // cancel current composition string.
  777. FinalizeString();
  778. //SetCompStringColor();
  779. }
  780.  
  781. /*---------------------------------------------------------------------------*/ /* Protected */
  782. void CIME::IncCurPos()
  783. {
  784. if (ms_curpos < ms_lastpos)
  785. {
  786. int pos = FindColorTagEndPosition(m_wText + ms_curpos, ms_lastpos - ms_curpos);
  787.  
  788. if (pos > 0)
  789. ms_curpos = min(ms_lastpos, max(0, ms_curpos + (pos + 1)));
  790. else
  791. ++ms_curpos;
  792. //++ms_curpos;
  793. }
  794. }
  795.  
  796. void CIME::DecCurPos()
  797. {
  798. if (ms_curpos > 0)
  799. {
  800. int pos = FindColorTagStartPosition(m_wText + ms_curpos - 1, ms_curpos);
  801.  
  802. if (pos > 0)
  803. ms_curpos = min(ms_lastpos, max(0, ms_curpos - (pos + 1)));
  804. else
  805. --ms_curpos;
  806. //--ms_curpos;
  807. }
  808. }
  809.  
  810. int CIME::GetCurPos()
  811. {
  812. int pos = GetTextTagOutputLen(m_wText, ms_curpos);
  813. return pos;
  814. //return ms_curpos;
  815. }
  816.  
  817. void CIME::SetCurPos(int offset)
  818. {
  819. if (offset < 0 || offset > ms_lastpos)
  820. {
  821. ms_curpos = ms_lastpos;
  822. return;
  823. }
  824. else
  825. {
  826. // offset은 보여지는 텍스트의 위치로 온다. 따라서 새로 계산해야함.
  827. //ms_curpos = min(ms_lastpos, offset);
  828. ms_curpos = min(ms_lastpos, GetTextTagInternalPosFromRenderPos(m_wText, ms_lastpos, offset));
  829. }
  830. }
  831.  
  832. void CIME::DelCurPos()
  833. {
  834. if (ms_curpos < ms_lastpos)
  835. {
  836. int eraseCount = FindColorTagEndPosition(m_wText + ms_curpos, ms_lastpos - ms_curpos) + 1;
  837. wcscpy(m_wText + ms_curpos, m_wText + ms_curpos + eraseCount);
  838. ms_lastpos -= eraseCount;
  839. ms_curpos = min(ms_lastpos, ms_curpos);
  840. }
  841. }
  842.  
  843. void CIME::PasteString(const char * str)
  844. {
  845. const char * begin = str;
  846. const char * end = str + strlen(str);
  847. wchar_t m_wText[IMESTR_MAXLEN];
  848. int wstrLen = MultiByteToWideChar(ms_uInputCodePage, 0, begin, end - begin, m_wText, IMESTR_MAXLEN);
  849. InsertString(m_wText, wstrLen);
  850. if(ms_pEvent)
  851. ms_pEvent->OnUpdate();
  852. }
  853.  
  854. /*---------------------------------------------------------------------------*/ /* Private */
  855. void CIME::InsertString(wchar_t* wString, int iSize)
  856. {
  857. if (IsMax(wString, iSize))
  858. return;
  859.  
  860. if (ms_curpos < ms_lastpos)
  861. memmove(m_wText+ms_curpos+iSize, m_wText+ms_curpos, sizeof(wchar_t)*(ms_lastpos-ms_curpos));
  862.  
  863. memcpy(m_wText+ms_curpos, wString, sizeof(wchar_t)*iSize);
  864.  
  865. ms_curpos += iSize;
  866. ms_lastpos += iSize;
  867. }
  868.  
  869. void CIME::OnChar(wchar_t c)
  870. {
  871. if (m_bOnlyNumberMode)
  872. if (!iswdigit(c))
  873. return;
  874.  
  875. if (c == 0x16)
  876. return;
  877.  
  878. //if (!__IsWritable(c))
  879. //return;
  880.  
  881. InsertString(&c, 1);
  882. }
  883.  
  884. UINT CIME::GetCodePageFromLang(LANGID langid)
  885. {
  886. unsigned pri_langid = PRIMARYLANGID(langid);
  887. switch (pri_langid)
  888. {
  889. case LANG_JAPANESE:
  890. //setlocale(LC_ALL, ".932");
  891. return 932;
  892. case LANG_KOREAN:
  893. //setlocale(LC_ALL, ".949");
  894. return 949;
  895. case LANG_CHINESE:
  896. {
  897. switch (SUBLANGID(langid))
  898. {
  899. case SUBLANG_CHINESE_SIMPLIFIED:
  900. case SUBLANG_CHINESE_SINGAPORE:
  901. //setlocale(LC_ALL, ".936");
  902. return 936;
  903. case SUBLANG_CHINESE_TRADITIONAL:
  904. case SUBLANG_CHINESE_MACAU:
  905. case SUBLANG_CHINESE_HONGKONG:
  906. //setlocale(LC_ALL, ".950");
  907. return 950;
  908. }
  909. }
  910. //setlocale(LC_ALL, ".936");
  911. return 936;
  912. case LANG_ARABIC:
  913. return 1256;
  914. case LANG_GREEK:
  915. //setlocale(LC_ALL, ".1253");
  916. return 1253;
  917. case LANG_TURKISH:
  918. //setlocale(LC_ALL, ".1254");
  919. return 1254;
  920. case LANG_HEBREW:
  921. //setlocale(LC_ALL, ".1255");
  922. return 1255;
  923. case LANG_ESTONIAN:
  924. case LANG_LATVIAN:
  925. case LANG_LITHUANIAN:
  926. //setlocale(LC_ALL, ".1257");
  927. return 1257;
  928. case LANG_VIETNAMESE:
  929. return 1258;
  930. case LANG_THAI:
  931. //setlocale(LC_ALL, ".874");
  932. return 874;
  933. case LANG_CZECH:
  934. case LANG_HUNGARIAN:
  935. case LANG_POLISH:
  936. case LANG_CROATIAN:
  937. case LANG_MACEDONIAN:
  938. case LANG_ROMANIAN:
  939. case LANG_SLOVAK:
  940. case LANG_SLOVENIAN:
  941. //setlocale(LC_ALL, ".1250");
  942. return 1250;
  943. case LANG_RUSSIAN:
  944. case LANG_BELARUSIAN:
  945. case LANG_BULGARIAN:
  946. case LANG_UKRAINIAN:
  947. return 1251;
  948. case LANG_GERMAN:
  949. //_wsetlocale(LC_ALL, ".1252");
  950. return 1252;
  951. default:
  952. //TraceError("UNKNOWN IME[%d]\n", langid);
  953. //setlocale(LC_ALL, ".949");
  954. return 1252;
  955. }
  956. }
  957.  
  958. void CIME::CompositionProcess(HIMC hImc)
  959. {
  960. ms_compLen = ImmGetCompositionStringW(hImc, GCS_COMPSTR, m_wszComposition, sizeof(m_wszComposition))/sizeof(wchar_t);
  961.  
  962. //OutputDebugStringW( L"Composition: " );
  963. //OutputDebugStringW( m_wszComposition );
  964. //for( int i=0; i < (int) ms_compLen * 2; i++ ) {
  965. // LPBYTE pbyData = (LPBYTE) m_wszComposition;
  966. // pbyData += i;
  967. // WCHAR tszName[32];
  968.  
  969. // swprintf_s( tszName, L"%02X ", (unsigned int) *pbyData );
  970. // OutputDebugStringW( tszName );
  971. //}
  972. //OutputDebugStringW( L"\n" );
  973.  
  974. if (IsMax(m_wszComposition, ms_compLen))
  975. {
  976. ImmNotifyIME(hImc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
  977. ms_compLen = 0;
  978. }
  979. }
  980.  
  981. void CIME::CompositionProcessBuilding(HIMC hImc)
  982. {
  983. int textLen = WideCharToMultiByte(ms_uOutputCodePage, 0, m_wText, ms_lastpos, 0, 0, NULL, NULL);
  984.  
  985. if (textLen >= m_max)
  986. {
  987. ImmNotifyIME(hImc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
  988. ms_compLen = 0;
  989. return;
  990. }
  991.  
  992. ms_compLen = ImmGetCompositionStringW(hImc, GCS_COMPSTR, m_wszComposition, sizeof(m_wszComposition))/sizeof(wchar_t);
  993.  
  994. //OutputDebugStringW( L"Composition: " );
  995. //OutputDebugStringW( m_wszComposition );
  996. //for( int i=0; i < (int) ms_compLen * 2; i++ ) {
  997. // LPBYTE pbyData = (LPBYTE) m_wszComposition;
  998. // pbyData += i;
  999. // WCHAR tszName[32];
  1000.  
  1001. // swprintf_s( tszName, L"%02X ", (unsigned int) *pbyData );
  1002. // OutputDebugStringW( tszName );
  1003. //}
  1004. //OutputDebugStringW( L"\n" );
  1005. }
  1006.  
  1007. void CIME::ResultProcess(HIMC hImc)
  1008. {
  1009. wchar_t temp[IMESTR_MAXLEN];
  1010.  
  1011. int len = ImmGetCompositionStringW(hImc, GCS_RESULTSTR, temp, sizeof(temp))/sizeof(wchar_t);
  1012.  
  1013. if (len <= 0)
  1014. return;
  1015.  
  1016. InsertString(temp, len);
  1017. }
  1018.  
  1019. void CIME::AttributeProcess(HIMC hImc)
  1020. {
  1021. BYTE attribute[IMESTR_MAXLEN];
  1022. LONG attributeLen = ImmGetCompositionStringW(hImc, GCS_COMPATTR, &attribute, sizeof(attribute)) / sizeof(BYTE);
  1023.  
  1024. int start,end;
  1025. for(start=0; start<attributeLen; ++start) if(attribute[start]==ATTR_TARGET_CONVERTED || attribute[start]==ATTR_TARGET_NOTCONVERTED) break;
  1026. for(end=start; end<attributeLen; ++end) if(attribute[end]!=attribute[start]) break;
  1027.  
  1028. ms_ulbegin = start;
  1029. ms_ulend = end;
  1030. }
  1031.  
  1032. void CIME::CandidateProcess(HIMC hImc)
  1033. {
  1034. std::vector<BYTE> abyCandidate;
  1035. DWORD dwCandidateLen = ImmGetCandidateListW(hImc, 0, NULL, 0);
  1036. abyCandidate.resize(dwCandidateLen);
  1037. if(dwCandidateLen > 0) {
  1038. ms_bCandidateList = true;
  1039.  
  1040. CANDIDATELIST* lpCandidateList = (CANDIDATELIST*)(&abyCandidate[0]);
  1041. dwCandidateLen = ImmGetCandidateListW(hImc, 0, lpCandidateList, dwCandidateLen);
  1042.  
  1043. ms_dwCandidateSelection = lpCandidateList->dwSelection;
  1044. ms_dwCandidateCount = lpCandidateList->dwCount;
  1045.  
  1046. int iStartOfPage = 0;
  1047.  
  1048. if( GETLANG() == LANG_CHS ) {
  1049. // MSPY (CHS IME) has variable number of candidates in candidate window find where current page starts, and the size of current page
  1050. const int maxCandChar = 18 * (3 - sizeof(TCHAR));
  1051. UINT cChars = 0;
  1052. UINT i;
  1053. for (i = 0; i < ms_dwCandidateCount; i++)
  1054. {
  1055. UINT uLen = lstrlenW((LPWSTR)((DWORD)lpCandidateList + lpCandidateList->dwOffset[i])) + (3 - sizeof(WCHAR));
  1056. if (uLen + cChars > maxCandChar)
  1057. {
  1058. if (i > ms_dwCandidateSelection)
  1059. {
  1060. break;
  1061. }
  1062. iStartOfPage = i;
  1063. cChars = uLen;
  1064. }
  1065. else
  1066. {
  1067. cChars += uLen;
  1068. }
  1069. }
  1070. ms_dwCandidatePageSize = i - iStartOfPage;
  1071. } else {
  1072. ms_dwCandidatePageSize = MIN( lpCandidateList->dwPageSize, MAX_CANDLIST );
  1073. iStartOfPage = ms_bUILessMode ? lpCandidateList->dwPageStart : (ms_dwCandidateSelection / (MAX_CANDLIST - 1)) * (MAX_CANDLIST - 1);
  1074. }
  1075.  
  1076. ms_dwCandidateSelection = ( GETLANG() == LANG_CHS && !GetImeId() ) ? (DWORD)-1 : ms_dwCandidateSelection - iStartOfPage;
  1077.  
  1078. //printf( "SEL: %d, START: %d, PAGED: %d\n", ms_dwCandidateSelection, iStartOfPage, ms_dwCandidatePageSize );
  1079. memset(&ms_wszCandidate, 0, sizeof(ms_wszCandidate));
  1080. for(UINT i = iStartOfPage, j = 0; (DWORD)i < lpCandidateList->dwCount && j < ms_dwCandidatePageSize; i++, j++) {
  1081. wcscpy( ms_wszCandidate[j], (LPWSTR)( (DWORD)lpCandidateList + lpCandidateList->dwOffset[i] ) );
  1082. }
  1083.  
  1084. // don't display selection in candidate list in case of Korean and old Chinese IME.
  1085. if ( GETPRIMLANG() == LANG_KOREAN || GETLANG() == LANG_CHT && !GetImeId() )
  1086. ms_dwCandidateSelection = (DWORD) -1;
  1087. }
  1088. }
  1089.  
  1090. void CIME::ReadingProcess(HIMC hImc)
  1091. {
  1092. if (!ms_adwId[0])
  1093. {
  1094. return;
  1095. }
  1096.  
  1097. DWORD dwErr = 0;
  1098.  
  1099. if (_GetReadingString)
  1100. {
  1101. UINT uMaxUiLen;
  1102. BOOL bVertical;
  1103. // Obtain the reading string size
  1104. int wstrLen = _GetReadingString(hImc, 0, NULL, (PINT)&dwErr, &bVertical, &uMaxUiLen);
  1105.  
  1106. if(wstrLen == 0) {
  1107. ms_wstrReading.resize(0);
  1108. } else {
  1109. wchar_t *wstr = (wchar_t*)alloca(sizeof(wchar_t) * wstrLen);
  1110. _GetReadingString(hImc, wstrLen, wstr, (PINT)&dwErr, &bVertical, &uMaxUiLen);
  1111. ms_wstrReading.assign(wstr, wstr+wstrLen);
  1112. }
  1113.  
  1114. ms_bHorizontalReading = (bVertical == 0);
  1115.  
  1116. } else {
  1117.  
  1118. // IMEs that doesn't implement Reading String API
  1119. wchar_t* temp = NULL;
  1120. DWORD tempLen = 0;
  1121. bool bUnicodeIme = false;
  1122. INPUTCONTEXT *lpIC = _ImmLockIMC(hImc);
  1123.  
  1124. if (lpIC == NULL)
  1125. {
  1126. temp = NULL;
  1127. tempLen = 0;
  1128. }
  1129. else
  1130. {
  1131. LPBYTE p = 0;
  1132. switch(ms_adwId[0])
  1133. {
  1134. case IMEID_CHT_VER42: // New(Phonetic/ChanJie)IME98 : 4.2.x.x // Win98
  1135. case IMEID_CHT_VER43: // New(Phonetic/ChanJie)IME98a : 4.3.x.x // WinMe, Win2k
  1136. case IMEID_CHT_VER44: // New ChanJie IME98b : 4.4.x.x // WinXP
  1137. p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + 24);
  1138. if (!p) break;
  1139. tempLen = *(DWORD *)(p + 7 * 4 + 32 * 4);
  1140. dwErr = *(DWORD *)(p + 8 * 4 + 32 * 4);
  1141. temp = (wchar_t *)(p + 56);
  1142. bUnicodeIme = true;
  1143. break;
  1144.  
  1145. case IMEID_CHT_VER50: // 5.0.x.x // WinME
  1146. p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + 3 * 4);
  1147. if(!p) break;
  1148. p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4 + 4*2);
  1149. if(!p) break;
  1150. tempLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16);
  1151. dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 + 1*4);
  1152. temp = (wchar_t *)(p + 1*4 + (16*2+2*4) + 5*4);
  1153. bUnicodeIme = false;
  1154. break;
  1155.  
  1156. case IMEID_CHT_VER51: // 5.1.x.x // IME2002(w/OfficeXP)
  1157. case IMEID_CHT_VER52: // 5.2.x.x // (w/whistler)
  1158. case IMEID_CHS_VER53: // 5.3.x.x // SCIME2k or MSPY3 (w/OfficeXP and Whistler)
  1159. p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + 4);
  1160. if(!p) break;
  1161. p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4);
  1162. if(!p) break;
  1163. tempLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * 2);
  1164. dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * 2 + 1*4);
  1165. temp = (wchar_t *) (p + 1*4 + (16*2+2*4) + 5*4);
  1166. bUnicodeIme = true;
  1167. break;
  1168.  
  1169. // the code tested only with Win 98 SE (MSPY 1.5/ ver 4.1.0.21)
  1170. case IMEID_CHS_VER41:
  1171. {
  1172. int nOffset;
  1173. nOffset = (ms_adwId[1] >= 0x00000002) ? 8 : 7;
  1174.  
  1175. p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + nOffset * 4);
  1176. if(!p) break;
  1177. tempLen = *(DWORD *)(p + 7*4 + 16*2*4);
  1178. dwErr = *(DWORD *)(p + 8*4 + 16*2*4);
  1179. dwErr = min(dwErr, tempLen);
  1180. temp = (wchar_t *)(p + 6*4 + 16*2*1);
  1181. bUnicodeIme = true;
  1182. }
  1183. break;
  1184.  
  1185. case IMEID_CHS_VER42: // 4.2.x.x // SCIME98 or MSPY2 (w/Office2k, Win2k, WinME, etc)
  1186. {
  1187. OSVERSIONINFOA osi;
  1188. osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  1189. GetVersionExA(&osi);
  1190.  
  1191. int nTcharSize = (osi.dwPlatformId == VER_PLATFORM_WIN32_NT) ? sizeof(wchar_t) : sizeof(char);
  1192. p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIC->hPrivate) + 1*4 + 1*4 + 6*4);
  1193. if(!p) break;
  1194. tempLen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * nTcharSize);
  1195. dwErr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * nTcharSize + 1*4);
  1196. temp = (wchar_t *) (p + 1*4 + (16*2+2*4) + 5*4);
  1197. bUnicodeIme = (osi.dwPlatformId == VER_PLATFORM_WIN32_NT) ? true : false;
  1198. }
  1199. break;
  1200.  
  1201. default:
  1202. temp = NULL;
  1203. tempLen = 0;
  1204. break;
  1205. }
  1206. }
  1207.  
  1208. if(tempLen == 0) {
  1209. ms_wstrReading.resize(0);
  1210. } else {
  1211. if(bUnicodeIme) {
  1212. ms_wstrReading.assign(temp, temp+tempLen);
  1213. } else {
  1214. int wstrLen = MultiByteToWideChar(ms_uInputCodePage, 0, (char*)temp, tempLen, NULL, 0);
  1215. wchar_t* wstr = (wchar_t*)alloca(sizeof(wchar_t)*wstrLen);
  1216. MultiByteToWideChar(ms_uInputCodePage, 0, (char*)temp, tempLen, wstr, wstrLen);
  1217. ms_wstrReading.assign(wstr, wstr+wstrLen);
  1218. }
  1219. }
  1220.  
  1221. _ImmUnlockIMCC(lpIC->hPrivate);
  1222. _ImmUnlockIMC(hImc);
  1223.  
  1224. ms_bHorizontalReading = GetReadingWindowOrientation();
  1225. }
  1226. if (ms_wstrReading.size()) {
  1227. ms_bReadingInformation = true;
  1228. if(ms_pEvent)
  1229. ms_pEvent->OnOpenReadingWnd();
  1230. } else {
  1231. CloseReadingInformation();
  1232. }
  1233. }
  1234.  
  1235. bool CIME::IsMax(const wchar_t* wInput, int len)
  1236. {
  1237. if (ms_lastpos + len > IMESTR_MAXLEN)
  1238. return true;
  1239.  
  1240. int textLen = WideCharToMultiByte(ms_uOutputCodePage, 0, m_wText, ms_lastpos, 0, 0, NULL, NULL);
  1241. int inputLen = WideCharToMultiByte(ms_uOutputCodePage, 0, wInput, len, 0, 0, NULL, NULL);
  1242. //return textLen + inputLen > m_max;
  1243.  
  1244. if (textLen + inputLen > m_max)
  1245. return true;
  1246. else if (m_userMax != 0 && m_max != m_userMax)
  1247. {
  1248. std::wstring str = GetTextTagOutputString(m_wText, ms_lastpos);
  1249. std::wstring input = GetTextTagOutputString(wInput, len);
  1250. int textLen = WideCharToMultiByte(ms_uOutputCodePage, 0, str.c_str(), str.length(), 0, 0, NULL, NULL);
  1251. int inputLen = WideCharToMultiByte(ms_uOutputCodePage, 0, input.c_str(), input.length(), 0, 0, NULL, NULL);
  1252. return textLen + inputLen > m_userMax;
  1253. }
  1254. return false;
  1255. }
  1256.  
  1257. DWORD CIME::GetImeId( UINT uIndex )
  1258. {
  1259. static HKL hklPrev = 0;
  1260. char szTmp[1024];
  1261.  
  1262. if (uIndex >= COUNTOF(ms_adwId))
  1263. return 0;
  1264. HKL hkl = ms_hklCurrent;
  1265. if(hklPrev == hkl)
  1266. return ms_adwId[uIndex];
  1267. hklPrev = hkl;
  1268.  
  1269. DWORD dwLang = ((DWORD)hkl & 0xffff);
  1270.  
  1271. if ( ms_bUILessMode && GETLANG() == LANG_CHT ) {
  1272. // In case of Vista, artifitial value is returned so that it's not considered as older IME.
  1273. ms_adwId[0] = IMEID_CHT_VER_VISTA;
  1274. ms_adwId[1] = 0;
  1275. return ms_adwId[0];
  1276. }
  1277.  
  1278. if (!((ms_hklCurrent == _CHT_HKL_NEW_PHONETIC) || (ms_hklCurrent == _CHT_HKL_NEW_CHANG_JIE) || (ms_hklCurrent == _CHT_HKL_NEW_QUICK) || (ms_hklCurrent == _CHT_HKL_HK_CANTONESE) || (ms_hklCurrent == _CHS_HKL))) {
  1279. ms_adwId[0] = ms_adwId[1] = 0;
  1280. return 0;
  1281. }
  1282.  
  1283. if (!ImmGetIMEFileNameA(ms_hklCurrent, szTmp, (sizeof(szTmp) / sizeof(szTmp[0])) - 1)) {
  1284. ms_adwId[0] = ms_adwId[1] = 0;
  1285. return 0;
  1286. }
  1287.  
  1288. if (!_GetReadingString)
  1289. {
  1290. if ((CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHT_IMEFILENAME1, -1) != CSTR_EQUAL) &&
  1291. (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHT_IMEFILENAME2, -1) != CSTR_EQUAL) &&
  1292. (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHT_IMEFILENAME3, -1) != CSTR_EQUAL) &&
  1293. (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHS_IMEFILENAME1, -1) != CSTR_EQUAL) &&
  1294. (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTmp, -1, CHS_IMEFILENAME2, -1) != CSTR_EQUAL))
  1295. {
  1296. ms_adwId[0] = ms_adwId[1] = 0;
  1297. return 0;
  1298. }
  1299. }
  1300.  
  1301. DWORD dwVerHandle;
  1302. DWORD dwVerSize = GetFileVersionInfoSize(szTmp, &dwVerHandle);
  1303. LANGID langId = LOWORD(ms_hklCurrent);
  1304.  
  1305. if (dwVerSize)
  1306. {
  1307. LPVOID lpVerBuffer = alloca(dwVerSize);
  1308.  
  1309. if (GetFileVersionInfo(szTmp, dwVerHandle, dwVerSize, lpVerBuffer))
  1310. {
  1311. LPVOID lpVerData;
  1312. UINT cbVerData;
  1313.  
  1314. if(VerQueryValue(lpVerBuffer, "\\", &lpVerData, &cbVerData))
  1315. {
  1316. DWORD dwVer = ((VS_FIXEDFILEINFO*) lpVerData)->dwFileVersionMS;
  1317. dwVer = (dwVer & 0x00ff0000) << 8 | (dwVer & 0x000000ff) << 16;
  1318.  
  1319. if (_GetReadingString
  1320. ||
  1321. (langId == LANG_CHT &&
  1322. (dwVer == MAKEIMEVERSION(4, 2) ||
  1323. dwVer == MAKEIMEVERSION(4, 3) ||
  1324. dwVer == MAKEIMEVERSION(4, 4) ||
  1325. dwVer == MAKEIMEVERSION(5, 0) ||
  1326. dwVer == MAKEIMEVERSION(5, 1) ||
  1327. dwVer == MAKEIMEVERSION(5, 2) ||
  1328. dwVer == MAKEIMEVERSION(6, 0)))
  1329. ||
  1330. (langId == LANG_CHS &&
  1331. (dwVer == MAKEIMEVERSION(4, 1) ||
  1332. dwVer == MAKEIMEVERSION(4, 2) ||
  1333. dwVer == MAKEIMEVERSION(5, 3))))
  1334. {
  1335. ms_adwId[0] = dwVer | langId;
  1336. ms_adwId[1] = ((VS_FIXEDFILEINFO*)lpVerData)->dwFileVersionLS;
  1337. return ms_adwId[uIndex];
  1338. }
  1339. }
  1340. }
  1341. }
  1342. ms_adwId[0] = ms_adwId[1] = 0;
  1343. return ms_adwId[0];
  1344. }
  1345.  
  1346. bool CIME::GetReadingWindowOrientation()
  1347. {
  1348. bool bHorizontalReading = (ms_hklCurrent == _CHS_HKL) || (ms_hklCurrent == _CHT_HKL_NEW_CHANG_JIE) || (ms_adwId[0] == 0);
  1349. if(!bHorizontalReading && (GETLANG() == LANG_CHT))
  1350. {
  1351. char szRegPath[MAX_PATH];
  1352. HKEY hKey;
  1353. DWORD dwVer = ms_adwId[0] & 0xFFFF0000;
  1354. strcpy(szRegPath, "software\\microsoft\\windows\\currentversion\\");
  1355. strcat(szRegPath, (dwVer >= MAKEIMEVERSION(5, 1)) ? "MSTCIPH" : "TINTLGNT");
  1356. LONG lRc = RegOpenKeyExA(HKEY_CURRENT_USER, szRegPath, 0, KEY_READ, &hKey);
  1357. if (lRc == ERROR_SUCCESS)
  1358. {
  1359. DWORD dwSize = sizeof(DWORD), dwMapping, dwType;
  1360. lRc = RegQueryValueExA(hKey, "Keyboard Mapping", NULL, &dwType, (PBYTE)&dwMapping, &dwSize);
  1361. if (lRc == ERROR_SUCCESS)
  1362. {
  1363. if ((dwVer <= MAKEIMEVERSION(5, 0) &&
  1364. ((BYTE)dwMapping == 0x22 || (BYTE)dwMapping == 0x23))
  1365. ||
  1366. ((dwVer == MAKEIMEVERSION(5, 1) || dwVer == MAKEIMEVERSION(5, 2)) &&
  1367. (BYTE)dwMapping >= 0x22 && (BYTE)dwMapping <= 0x24)
  1368. )
  1369. {
  1370. bHorizontalReading = true;
  1371. }
  1372. }
  1373. RegCloseKey(hKey);
  1374. }
  1375. }
  1376.  
  1377. return bHorizontalReading;
  1378. }
  1379.  
  1380. void CIME::SetupImeApi()
  1381. {
  1382. char szImeFile[MAX_PATH + 1];
  1383.  
  1384. _GetReadingString = NULL;
  1385. _ShowReadingWindow = NULL;
  1386. ms_bUseIMMCandidate = false;
  1387.  
  1388. if(ImmGetIMEFileNameA(ms_hklCurrent, szImeFile, COUNTOF(szImeFile) - 1) == 0)
  1389. return;
  1390. if(stricmp(szImeFile, CHS_IMEFILENAME_QQPINYIN) == 0 || stricmp(szImeFile, CHS_IMEFILENAME_SOGOUPY) == 0 || stricmp(szImeFile, CHS_IMEFILENAME_GOOGLEPINYIN2) == 0)
  1391. ms_bUseIMMCandidate = true;
  1392. if (ms_bUILessMode)
  1393. return;
  1394. SAFE_FREE_LIBRARY(ms_hCurrentImeDll);
  1395. ms_hCurrentImeDll = LoadLibraryA(szImeFile);
  1396.  
  1397. if (ms_hCurrentImeDll) {
  1398. _GetReadingString = (UINT (WINAPI*)(HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT)) (GetProcAddress(ms_hCurrentImeDll, "GetReadingString"));
  1399. _ShowReadingWindow =(BOOL (WINAPI*)(HIMC, BOOL)) (GetProcAddress(ms_hCurrentImeDll, "ShowReadingWindow"));
  1400.  
  1401. if(_ShowReadingWindow) {
  1402. HIMC hImc = ImmGetContext(ms_hWnd);
  1403. if(hImc) {
  1404. _ShowReadingWindow(hImc, false);
  1405. ImmReleaseContext(ms_hWnd, hImc);
  1406. }
  1407. }
  1408. }
  1409. }
  1410.  
  1411. static unsigned long _strtoul( LPCSTR psz, LPTSTR*, int )
  1412. {
  1413. if ( !psz )
  1414. return 0;
  1415.  
  1416. ULONG ulRet = 0;
  1417. if ( psz[0] == '0' && ( psz[1] == 'x' || psz[1] == 'X' ) )
  1418. {
  1419. psz += 2;
  1420. ULONG ul = 0;
  1421. while ( *psz )
  1422. {
  1423. if ( '0' <= *psz && *psz <= '9' )
  1424. ul = *psz - '0';
  1425. else if ( 'A' <= *psz && *psz <= 'F' )
  1426. ul = *psz - 'A' + 10;
  1427. else if ( 'a' <= *psz && *psz <= 'f' )
  1428. ul = *psz - 'a' + 10;
  1429. else
  1430. break;
  1431. ulRet = ulRet * 16 + ul;
  1432. psz++;
  1433. }
  1434. }
  1435. else {
  1436. while ( *psz && ( '0' <= *psz && *psz <= '9' ) )
  1437. {
  1438. ulRet = ulRet * 10 + ( *psz - '0' );
  1439. psz++;
  1440. }
  1441. }
  1442. return ulRet;
  1443. }
  1444.  
  1445. void CIME::CheckInputLocale()
  1446. {
  1447. static UINT s_uPrevCodePage = 0xFFFF;
  1448. static HKL s_hklPrev = NULL;
  1449.  
  1450. ms_hklCurrent = GetKeyboardLayout( 0 );
  1451. if ( s_hklPrev == ms_hklCurrent )
  1452. return;
  1453. s_hklPrev = ms_hklCurrent;
  1454.  
  1455. char szCodePage[8];
  1456. int iRc = GetLocaleInfoA( MAKELCID( GETLANG(), SORT_DEFAULT ), LOCALE_IDEFAULTANSICODEPAGE, szCodePage, COUNTOF( szCodePage ) ); iRc;
  1457. ms_uInputCodePage = _strtoul( szCodePage, NULL, 0 );
  1458. if ( s_uPrevCodePage == ms_uInputCodePage )
  1459. return;
  1460. s_uPrevCodePage = ms_uInputCodePage;
  1461.  
  1462. GetKeyboardLayoutName(ms_szKeyboardLayout);
  1463.  
  1464. switch (GETPRIMLANG())
  1465. {
  1466. case LANG_KOREAN:
  1467. ms_bVerticalCandidate = false;
  1468. ms_wszCurrentIndicator = s_aszIndicator[INDICATOR_KOREAN];
  1469. break;
  1470.  
  1471. case LANG_JAPANESE:
  1472. ms_bVerticalCandidate = true;
  1473. ms_wszCurrentIndicator = s_aszIndicator[INDICATOR_JAPANESE];
  1474. break;
  1475.  
  1476. case LANG_CHINESE:
  1477. ms_bVerticalCandidate = true;
  1478.  
  1479. switch(GETSUBLANG())
  1480. {
  1481. case SUBLANG_CHINESE_SIMPLIFIED:
  1482. case SUBLANG_CHINESE_SINGAPORE:
  1483. //ms_bVerticalCandidate = (GetImeId() == 0);
  1484. ms_bVerticalCandidate = false;
  1485. ms_wszCurrentIndicator = s_aszIndicator[INDICATOR_CHS];
  1486. break;
  1487.  
  1488. case SUBLANG_CHINESE_TRADITIONAL:
  1489. case SUBLANG_CHINESE_HONGKONG:
  1490. case SUBLANG_CHINESE_MACAU:
  1491. ms_wszCurrentIndicator = s_aszIndicator[INDICATOR_CHT];
  1492. break;
  1493.  
  1494. default: // unsupported sub-language
  1495. ms_wszCurrentIndicator = s_aszIndicator[INDICATOR_NON_IME];
  1496. break;
  1497. }
  1498. break;
  1499.  
  1500. default:
  1501. ms_wszCurrentIndicator = s_aszIndicator[INDICATOR_NON_IME];
  1502. break;
  1503. }
  1504.  
  1505. if (ms_wszCurrentIndicator == s_aszIndicator[INDICATOR_NON_IME])
  1506. {
  1507. char szLang[10];
  1508. GetLocaleInfoA(MAKELCID(GETLANG(), SORT_DEFAULT), LOCALE_SABBREVLANGNAME, szLang, sizeof(szLang));
  1509. ms_wszCurrentIndicator[0] = szLang[0];
  1510. ms_wszCurrentIndicator[1] = towlower(szLang[1]);
  1511. }
  1512.  
  1513. // 아랍어에서 영어로 변경시 코드 페이지를 바꾸지 않는다
  1514. // 내용도 지우지 않는다.
  1515. if(ms_uOutputCodePage != 1256) {
  1516. ms_uOutputCodePage = ms_uInputCodePage;
  1517. Clear();
  1518. }
  1519.  
  1520. //for ( int i = 0; i < 256; i++ )
  1521. //{
  1522. // LeadByteTable[i] = (BYTE)IsDBCSLeadByteEx( g_uCodePage, (BYTE)i );
  1523. //}
  1524. }
  1525.  
  1526. void CIME::CheckToggleState()
  1527. {
  1528. CheckInputLocale();
  1529.  
  1530. // In Vista, we have to use TSF since few IMM functions don't work as expected.
  1531. // WARNING: Because of timing, g_dwState and g_bChineseIME may not be updated
  1532. // immediately after the change on IME states by user.
  1533. if ( ms_bUILessMode )
  1534. return;
  1535.  
  1536. /* Check Toggle State */
  1537. bool bIme = ImmIsIME( ms_hklCurrent ) != 0
  1538. && ( ( 0xF0000000 & (DWORD)ms_hklCurrent ) == 0xE0000000 ); // Hack to detect IME correctly. When IME is running as TIP, ImmIsIME() returns true for CHT US keyboard.
  1539. ms_bChineseIME = ( GETPRIMLANG() == LANG_CHINESE ) && bIme;
  1540.  
  1541. HIMC himc;
  1542. if (NULL != (himc = ImmGetContext(ms_hWnd))) {
  1543. if (ms_bChineseIME) {
  1544. DWORD dwConvMode, dwSentMode;
  1545. ImmGetConversionStatus(himc, &dwConvMode, &dwSentMode);
  1546. ms_dwImeState = ( dwConvMode & IME_CMODE_NATIVE ) ? IMEUI_STATE_ON : IMEUI_STATE_ENGLISH;
  1547. }
  1548. else
  1549. {
  1550. ms_dwImeState = ( bIme && ImmGetOpenStatus( himc ) != 0 ) ? IMEUI_STATE_ON : IMEUI_STATE_OFF;
  1551. }
  1552. ImmReleaseContext(ms_hWnd, himc);
  1553. }
  1554. else
  1555. ms_dwImeState = IMEUI_STATE_OFF;
  1556. }
  1557.  
  1558. ///////////////////////////////////////////////////////////////////////////////
  1559. //
  1560. // CTsfUiLessMode methods
  1561. //
  1562. ///////////////////////////////////////////////////////////////////////////////
  1563.  
  1564. //
  1565. // SetupSinks()
  1566. // Set up sinks. A sink is used to receive a Text Service Framework event.
  1567. // CUIElementSink implements multiple sink interfaces to receive few different TSF events.
  1568. //
  1569. BOOL CTsfUiLessMode::SetupSinks()
  1570. {
  1571. // ITfThreadMgrEx is available on Vista or later.
  1572. HRESULT hr;
  1573. hr = CoCreateInstance(CLSID_TF_ThreadMgr,
  1574. NULL,
  1575. CLSCTX_INPROC_SERVER,
  1576. __uuidof(ITfThreadMgrEx),
  1577. (void**)&m_tm);
  1578.  
  1579. if (hr != S_OK)
  1580. {
  1581. return FALSE;
  1582. }
  1583.  
  1584. // ready to start interacting
  1585. TfClientId cid; // not used
  1586. if (FAILED(m_tm->ActivateEx(&cid, TF_TMAE_UIELEMENTENABLEDONLY)))
  1587. {
  1588. return FALSE;
  1589. }
  1590.  
  1591. // Setup sinks
  1592. BOOL bRc = FALSE;
  1593. m_TsfSink = new CUIElementSink();
  1594. if (m_TsfSink)
  1595. {
  1596. ITfSource *srcTm;
  1597. if (SUCCEEDED(hr = m_tm->QueryInterface(__uuidof(ITfSource), (void **)&srcTm)))
  1598. {
  1599. // Sink for reading window change
  1600. if (SUCCEEDED(hr = srcTm->AdviseSink(__uuidof(ITfUIElementSink), (ITfUIElementSink*)m_TsfSink, &m_dwUIElementSinkCookie)))
  1601. {
  1602. // Sink for input locale change
  1603. if (SUCCEEDED(hr = srcTm->AdviseSink(__uuidof(ITfInputProcessorProfileActivationSink), (ITfInputProcessorProfileActivationSink*)m_TsfSink, &m_dwAlpnSinkCookie)))
  1604. {
  1605. if (SetupCompartmentSinks()) // Setup compartment sinks for the first time
  1606. {
  1607. bRc = TRUE;
  1608. }
  1609. }
  1610. }
  1611. srcTm->Release();
  1612. }
  1613. }
  1614. return bRc;
  1615. }
  1616.  
  1617. void CTsfUiLessMode::ReleaseSinks()
  1618. {
  1619. HRESULT hr;
  1620. ITfSource *source;
  1621.  
  1622. // Remove all sinks
  1623. if ( m_tm && SUCCEEDED(m_tm->QueryInterface(__uuidof(ITfSource), (void **)&source)))
  1624. {
  1625. hr = source->UnadviseSink(m_dwUIElementSinkCookie);
  1626. hr = source->UnadviseSink(m_dwAlpnSinkCookie);
  1627. source->Release();
  1628. SetupCompartmentSinks(TRUE); // Remove all compartment sinks
  1629. m_tm->Deactivate();
  1630. SAFE_RELEASE(m_tm);
  1631. SAFE_RELEASE(m_TsfSink);
  1632. }
  1633. }
  1634.  
  1635. CTsfUiLessMode::CUIElementSink::CUIElementSink()
  1636. {
  1637. _cRef = 1;
  1638. }
  1639.  
  1640.  
  1641. CTsfUiLessMode::CUIElementSink::~CUIElementSink()
  1642. {
  1643. }
  1644.  
  1645. STDAPI CTsfUiLessMode::CUIElementSink::QueryInterface(REFIID riid, void **ppvObj)
  1646. {
  1647. if (ppvObj == NULL)
  1648. return E_INVALIDARG;
  1649.  
  1650. *ppvObj = NULL;
  1651.  
  1652. if (IsEqualIID(riid, IID_IUnknown))
  1653. {
  1654. *ppvObj = reinterpret_cast<IUnknown *>(this);
  1655. }
  1656. else if (IsEqualIID(riid, __uuidof(ITfUIElementSink)))
  1657. {
  1658. *ppvObj = (ITfUIElementSink *)this;
  1659. }
  1660. else if (IsEqualIID(riid, __uuidof(ITfInputProcessorProfileActivationSink)))
  1661. {
  1662. *ppvObj = (ITfInputProcessorProfileActivationSink*)this;
  1663. }
  1664. else if (IsEqualIID(riid, __uuidof(ITfCompartmentEventSink)))
  1665. {
  1666. *ppvObj = (ITfCompartmentEventSink*)this;
  1667. }
  1668.  
  1669. if (*ppvObj)
  1670. {
  1671. AddRef();
  1672. return S_OK;
  1673. }
  1674.  
  1675. return E_NOINTERFACE;
  1676. }
  1677.  
  1678. STDAPI_(ULONG) CTsfUiLessMode::CUIElementSink::AddRef()
  1679. {
  1680. return ++_cRef;
  1681. }
  1682.  
  1683. STDAPI_(ULONG) CTsfUiLessMode::CUIElementSink::Release()
  1684. {
  1685. LONG cr = --_cRef;
  1686.  
  1687. if (_cRef == 0)
  1688. {
  1689. delete this;
  1690. }
  1691.  
  1692. return cr;
  1693. }
  1694.  
  1695. STDAPI CTsfUiLessMode::CUIElementSink::BeginUIElement(DWORD dwUIElementId, BOOL *pbShow)
  1696. {
  1697. ITfUIElement *pElement = GetUIElement(dwUIElementId);
  1698. if (!pElement)
  1699. return E_INVALIDARG;
  1700.  
  1701. ITfReadingInformationUIElement *preading = NULL;
  1702. ITfCandidateListUIElement *pcandidate = NULL;
  1703. *pbShow = FALSE;
  1704.  
  1705. //BSTR bstrDesc;
  1706. //OutputDebugStringW(L"BEGINUI: ");
  1707. //pElement->GetDescription(&bstrDesc);
  1708. //OutputDebugStringW(bstrDesc);
  1709. //OutputDebugStringW(L"\n");
  1710.  
  1711. if (SUCCEEDED(pElement->QueryInterface(__uuidof(ITfReadingInformationUIElement), (void **)&preading)))
  1712. {
  1713. MakeReadingInformationString(preading);
  1714. if(CIME::ms_pEvent)
  1715. CIME::ms_pEvent->OnOpenReadingWnd();
  1716. preading->Release();
  1717. }
  1718. else if (SUCCEEDED(pElement->QueryInterface(__uuidof(ITfCandidateListUIElement), (void **)&pcandidate)))
  1719. {
  1720. m_nCandidateRefCount++;
  1721. MakeCandidateStrings(pcandidate);
  1722. if(CIME::ms_pEvent)
  1723. CIME::ms_pEvent->OnOpenCandidateList();
  1724. pcandidate->Release();
  1725. }
  1726.  
  1727. pElement->Release();
  1728. return S_OK;
  1729. }
  1730.  
  1731. STDAPI CTsfUiLessMode::CUIElementSink::UpdateUIElement(DWORD dwUIElementId)
  1732. {
  1733. ITfUIElement *pElement = GetUIElement(dwUIElementId);
  1734. if (!pElement)
  1735. return E_INVALIDARG;
  1736.  
  1737. ITfReadingInformationUIElement *preading = NULL;
  1738. ITfCandidateListUIElement *pcandidate = NULL;
  1739.  
  1740. //BSTR bstrDesc;
  1741. //pElement->GetDescription(&bstrDesc);
  1742. //OutputDebugStringW(L"UPDATEUI: ");
  1743. //OutputDebugStringW(bstrDesc);
  1744. //OutputDebugStringW(L"\n");
  1745.  
  1746. if (SUCCEEDED(pElement->QueryInterface(__uuidof(ITfReadingInformationUIElement), (void **)&preading)))
  1747. {
  1748. MakeReadingInformationString(preading);
  1749. if(CIME::ms_pEvent)
  1750. CIME::ms_pEvent->OnOpenReadingWnd();
  1751. preading->Release();
  1752. }
  1753. else if (SUCCEEDED(pElement->QueryInterface(__uuidof(ITfCandidateListUIElement), (void **)&pcandidate)))
  1754. {
  1755. MakeCandidateStrings(pcandidate);
  1756. if(CIME::ms_pEvent)
  1757. CIME::ms_pEvent->OnOpenCandidateList();
  1758. pcandidate->Release();
  1759. }
  1760.  
  1761. pElement->Release();
  1762. return S_OK;
  1763. }
  1764.  
  1765. STDAPI CTsfUiLessMode::CUIElementSink::EndUIElement(DWORD dwUIElementId)
  1766. {
  1767. ITfUIElement *pElement = GetUIElement(dwUIElementId);
  1768. if (!pElement)
  1769. return E_INVALIDARG;
  1770.  
  1771. //BSTR bstrDesc;
  1772. //OutputDebugStringW(L"ENDUI: ");
  1773. //pElement->GetDescription(&bstrDesc);
  1774. //OutputDebugStringW(bstrDesc);
  1775. //OutputDebugStringW(L"\n");
  1776.  
  1777. ITfReadingInformationUIElement *preading = NULL;
  1778. if (SUCCEEDED(pElement->QueryInterface(__uuidof(ITfReadingInformationUIElement), (void **)&preading)))
  1779. {
  1780. CIME::CloseReadingInformation();
  1781. preading->Release();
  1782. }
  1783.  
  1784. ITfCandidateListUIElement *pcandidate = NULL;
  1785. if (SUCCEEDED(pElement->QueryInterface(__uuidof(ITfCandidateListUIElement), (void **)&pcandidate)))
  1786. {
  1787. m_nCandidateRefCount--;
  1788. if (m_nCandidateRefCount == 0)
  1789. CIME::CloseCandidateList();
  1790. pcandidate->Release();
  1791. }
  1792.  
  1793. pElement->Release();
  1794. return S_OK;
  1795. }
  1796.  
  1797. void CTsfUiLessMode::UpdateImeState(BOOL bResetCompartmentEventSink)
  1798. {
  1799. ITfCompartmentMgr* pcm;
  1800. ITfCompartment* pTfOpenMode = NULL;
  1801. ITfCompartment* pTfConvMode = NULL;
  1802. if ( GetCompartments( &pcm, &pTfOpenMode, &pTfConvMode ) )
  1803. {
  1804. VARIANT valOpenMode;
  1805. VARIANT valConvMode;
  1806. pTfOpenMode->GetValue( &valOpenMode );
  1807. pTfConvMode->GetValue( &valConvMode );
  1808. if ( valOpenMode.vt == VT_I4 )
  1809. {
  1810. if ( CIME::ms_bChineseIME )
  1811. {
  1812. CIME::ms_dwImeState = valOpenMode.lVal != 0 && valConvMode.lVal != 0 ? IMEUI_STATE_ON : IMEUI_STATE_ENGLISH;
  1813. }
  1814. else
  1815. {
  1816. CIME::ms_dwImeState = valOpenMode.lVal != 0 ? IMEUI_STATE_ON : IMEUI_STATE_OFF;
  1817. }
  1818. }
  1819. VariantClear( &valOpenMode );
  1820. VariantClear( &valConvMode );
  1821.  
  1822. if ( bResetCompartmentEventSink )
  1823. {
  1824. SetupCompartmentSinks( FALSE, pTfOpenMode, pTfConvMode ); // Reset compartment sinks
  1825. }
  1826. pTfOpenMode->Release();
  1827. pTfConvMode->Release();
  1828. pcm->Release();
  1829. }
  1830. }
  1831.  
  1832. STDAPI CTsfUiLessMode::CUIElementSink::OnActivated(DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid,
  1833. REFGUID guidProfile, HKL hkl, DWORD dwFlags)
  1834. {
  1835. static GUID TF_PROFILE_DAYI = { 0x037B2C25, 0x480C, 0x4D7F, 0xB0, 0x27, 0xD6, 0xCA, 0x6B, 0x69, 0x78, 0x8A };
  1836. CIME::ms_iCandListIndexBase = IsEqualGUID( TF_PROFILE_DAYI, guidProfile ) ? 0 : 1;
  1837. if ( IsEqualIID( catid, GUID_TFCAT_TIP_KEYBOARD ) && ( dwFlags & TF_IPSINK_FLAG_ACTIVE ) )
  1838. {
  1839. CIME::ms_bChineseIME = ( dwProfileType & TF_PROFILETYPE_INPUTPROCESSOR ) && langid == LANG_CHT;
  1840. if ( dwProfileType & TF_PROFILETYPE_INPUTPROCESSOR )
  1841. {
  1842. UpdateImeState(TRUE);
  1843. }
  1844. else
  1845. CIME::ms_dwImeState = IMEUI_STATE_OFF;
  1846. CIME::ChangeInputLanguage();
  1847. }
  1848. return S_OK;
  1849. }
  1850.  
  1851. STDAPI CTsfUiLessMode::CUIElementSink::OnChange(REFGUID rguid)
  1852. {
  1853. UpdateImeState();
  1854. return S_OK;
  1855. }
  1856.  
  1857. void CTsfUiLessMode::MakeReadingInformationString(ITfReadingInformationUIElement* preading)
  1858. {
  1859. UINT cchMax;
  1860. UINT uErrorIndex = 0;
  1861. BOOL fVertical;
  1862. DWORD dwFlags;
  1863.  
  1864. CIME::ms_wstrReading.resize(0);
  1865. preading->GetUpdatedFlags(&dwFlags);
  1866. preading->GetMaxReadingStringLength(&cchMax);
  1867. preading->GetErrorIndex(&uErrorIndex); // errorIndex is zero-based
  1868. preading->IsVerticalOrderPreferred(&fVertical);
  1869. CIME::ms_iReadingError = (int)uErrorIndex;
  1870. CIME::ms_bHorizontalReading = !fVertical;
  1871. CIME::ms_bReadingInformation = true;
  1872. BSTR bstr;
  1873. if (SUCCEEDED(preading->GetString(&bstr)))
  1874. {
  1875. if (bstr)
  1876. {
  1877. CIME::ms_wstrReading.assign( (wchar_t *) bstr, (wchar_t *) bstr+lstrlenW(bstr) );
  1878. LPCWSTR pszSource = &(CIME::ms_wstrReading[0]);
  1879. if ( fVertical )
  1880. {
  1881. CIME::ms_dwCandidatePageSize = CIME::MAX_CANDLIST;
  1882. // ms_iReadingError is used only in horizontal window, and has to be -1 if there's no error.
  1883. CIME::ms_dwCandidateSelection = CIME::ms_iReadingError ? CIME::ms_iReadingError - 1 : (DWORD)-1;
  1884. CIME::ms_dwCandidateCount = cchMax;
  1885. // for vertical reading window, copy each character to g_szCandidate array.
  1886. for ( UINT i = 0; i < cchMax; i++ )
  1887. {
  1888. LPWSTR pszDest = CIME::ms_wszCandidate[i];
  1889. if ( *pszSource )
  1890. {
  1891. LPWSTR pszNextSrc = CharNextW(pszSource);
  1892. SIZE_T size = (LPSTR)pszNextSrc - (LPSTR)pszSource;
  1893. CopyMemory( pszDest, pszSource, size );
  1894. pszSource = pszNextSrc;
  1895. pszDest += size;
  1896. }
  1897. *pszDest = 0;
  1898. }
  1899. }
  1900. //else
  1901. //{
  1902. // CIME::ms_wszCandidate[0][0] = L' '; // hack to make rendering happen
  1903. //}
  1904. SysFreeString(bstr);
  1905. }
  1906. }
  1907. }
  1908.  
  1909. void CTsfUiLessMode::MakeCandidateStrings(ITfCandidateListUIElement* pcandidate)
  1910. {
  1911. UINT uIndex = 0;
  1912. UINT uCount = 0;
  1913. UINT uCurrentPage = 0;
  1914. UINT *IndexList = NULL;
  1915. UINT uPageCnt = 0;
  1916. DWORD dwPageStart = 0;
  1917. DWORD dwPageSize = 0;
  1918. BSTR bstr;
  1919.  
  1920. pcandidate->GetSelection(&uIndex);
  1921. pcandidate->GetCount(&uCount);
  1922. pcandidate->GetCurrentPage(&uCurrentPage);
  1923. CIME::ms_dwCandidateSelection = (DWORD)uIndex;
  1924. CIME::ms_dwCandidateCount = (DWORD)uCount;
  1925. CIME::ms_bCandidateList = true;
  1926.  
  1927. pcandidate->GetPageIndex(NULL, 0, &uPageCnt);
  1928. if(uPageCnt > 0)
  1929. {
  1930. IndexList = (UINT *) malloc(sizeof(UINT)*uPageCnt);
  1931. if(IndexList)
  1932. {
  1933. pcandidate->GetPageIndex(IndexList, uPageCnt, &uPageCnt);
  1934. dwPageStart = IndexList[uCurrentPage];
  1935. dwPageSize = (uCurrentPage < uPageCnt-1) ?
  1936. min(uCount, IndexList[uCurrentPage+1]) - dwPageStart:
  1937. uCount - dwPageStart;
  1938. }
  1939. }
  1940.  
  1941. CIME::ms_dwCandidatePageSize = min(dwPageSize, CIME::MAX_CANDLIST);
  1942. CIME::ms_dwCandidateSelection = CIME::ms_dwCandidateSelection - dwPageStart;
  1943.  
  1944. memset(&CIME::ms_wszCandidate, 0, sizeof(CIME::ms_wszCandidate));
  1945. for (UINT i = dwPageStart, j = 0; (DWORD)i < CIME::ms_dwCandidateCount && j < CIME::ms_dwCandidatePageSize; i++, j++)
  1946. {
  1947. if (SUCCEEDED(pcandidate->GetString( i, &bstr )))
  1948. {
  1949. if(bstr)
  1950. {
  1951. wcscpy( CIME::ms_wszCandidate[j], bstr );
  1952. SysFreeString(bstr);
  1953. }
  1954. }
  1955. }
  1956. //OutputDebugStringW( L"\n" );
  1957.  
  1958. if (GETPRIMLANG() == LANG_KOREAN)
  1959. {
  1960. CIME::ms_dwCandidateSelection = (DWORD)-1;
  1961. }
  1962.  
  1963. if(IndexList)
  1964. {
  1965. free(IndexList);
  1966. }
  1967. }
  1968.  
  1969. ITfUIElement* CTsfUiLessMode::GetUIElement(DWORD dwUIElementId)
  1970. {
  1971. ITfUIElementMgr *puiem;
  1972. ITfUIElement *pElement = NULL;
  1973.  
  1974. if (SUCCEEDED(m_tm->QueryInterface(__uuidof(ITfUIElementMgr), (void **)&puiem)))
  1975. {
  1976. puiem->GetUIElement(dwUIElementId, &pElement);
  1977. puiem->Release();
  1978. }
  1979.  
  1980. return pElement;
  1981. }
  1982.  
  1983. BOOL CTsfUiLessMode::CurrentInputLocaleIsIme()
  1984. {
  1985. BOOL ret = FALSE;
  1986. HRESULT hr;
  1987.  
  1988. ITfInputProcessorProfiles *pProfiles;
  1989. hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, __uuidof(ITfInputProcessorProfiles), (LPVOID*)&pProfiles);
  1990. if (SUCCEEDED(hr))
  1991. {
  1992. ITfInputProcessorProfileMgr *pProfileMgr;
  1993. hr = pProfiles->QueryInterface(__uuidof(ITfInputProcessorProfileMgr), (LPVOID*)&pProfileMgr);
  1994. if (SUCCEEDED(hr))
  1995. {
  1996. TF_INPUTPROCESSORPROFILE tip;
  1997. hr = pProfileMgr->GetActiveProfile( GUID_TFCAT_TIP_KEYBOARD, &tip );
  1998. if (SUCCEEDED(hr))
  1999. {
  2000. ret = ( tip.dwProfileType & TF_PROFILETYPE_INPUTPROCESSOR ) != 0;
  2001. }
  2002. pProfileMgr->Release();
  2003. }
  2004. pProfiles->Release();
  2005. }
  2006. return ret;
  2007. }
  2008.  
  2009. // Sets up or removes sink for UI element.
  2010. // UI element sink should be removed when IME is disabled,
  2011. // otherwise the sink can be triggered when a game has multiple instances of IME UI library.
  2012. void CTsfUiLessMode::EnableUiUpdates(bool bEnable)
  2013. {
  2014. if ( m_tm == NULL ||
  2015. ( bEnable && m_dwUIElementSinkCookie != TF_INVALID_COOKIE ) ||
  2016. ( !bEnable && m_dwUIElementSinkCookie == TF_INVALID_COOKIE ) )
  2017. {
  2018. return;
  2019. }
  2020. ITfSource *srcTm = NULL;
  2021. HRESULT hr = E_FAIL;
  2022. if (SUCCEEDED(hr = m_tm->QueryInterface(__uuidof(ITfSource), (void **)&srcTm)))
  2023. {
  2024. if ( bEnable )
  2025. {
  2026. hr = srcTm->AdviseSink(__uuidof(ITfUIElementSink), (ITfUIElementSink*)m_TsfSink, &m_dwUIElementSinkCookie);
  2027. }
  2028. else
  2029. {
  2030. hr = srcTm->UnadviseSink(m_dwUIElementSinkCookie);
  2031. m_dwUIElementSinkCookie = TF_INVALID_COOKIE;
  2032. }
  2033. srcTm->Release();
  2034. }
  2035. }
  2036.  
  2037. // Returns open mode compartments and compartment manager.
  2038. // Function fails if it fails to acquire any of the objects to be returned.
  2039. BOOL CTsfUiLessMode::GetCompartments( ITfCompartmentMgr** ppcm, ITfCompartment** ppTfOpenMode, ITfCompartment** ppTfConvMode )
  2040. {
  2041. ITfCompartmentMgr* pcm = NULL;
  2042. ITfCompartment* pTfOpenMode = NULL;
  2043. ITfCompartment* pTfConvMode = NULL;
  2044.  
  2045. static GUID _GUID_COMPARTMENT_KEYBOARD_INPUTMODE_CONVERSION = { 0xCCF05DD8, 0x4A87, 0x11D7, 0xA6, 0xE2, 0x00, 0x06, 0x5B, 0x84, 0x43, 0x5C };
  2046.  
  2047. HRESULT hr;
  2048. if (SUCCEEDED(hr = m_tm->QueryInterface( IID_ITfCompartmentMgr, (void**)&pcm )))
  2049. {
  2050. if (SUCCEEDED(hr = pcm->GetCompartment( GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, &pTfOpenMode )))
  2051. {
  2052. if (SUCCEEDED(hr = pcm->GetCompartment( _GUID_COMPARTMENT_KEYBOARD_INPUTMODE_CONVERSION, &pTfConvMode )))
  2053. {
  2054. *ppcm = pcm;
  2055. *ppTfOpenMode = pTfOpenMode;
  2056. *ppTfConvMode = pTfConvMode;
  2057. return TRUE;
  2058. }
  2059. pTfOpenMode->Release();
  2060. }
  2061. pcm->Release();
  2062. }
  2063. return FALSE;
  2064. }
  2065.  
  2066. // There are three ways to call this function:
  2067. // SetupCompartmentSinks() : initialization
  2068. // SetupCompartmentSinks(FALSE, openmode, convmode) : Resetting sinks. This is necessary as DaYi and Array IME resets compartment on switching input locale
  2069. // SetupCompartmentSinks(TRUE) : clean up sinks
  2070. BOOL CTsfUiLessMode::SetupCompartmentSinks( BOOL bRemoveOnly, ITfCompartment* pTfOpenMode, ITfCompartment* pTfConvMode )
  2071. {
  2072. bool bLocalCompartments = false;
  2073. ITfCompartmentMgr* pcm = NULL;
  2074. BOOL bRc = FALSE;
  2075. HRESULT hr = E_FAIL;
  2076.  
  2077. if ( !pTfOpenMode && !pTfConvMode )
  2078. {
  2079. bLocalCompartments = true;
  2080. GetCompartments( &pcm, &pTfOpenMode, &pTfConvMode );
  2081. }
  2082. if ( !( pTfOpenMode && pTfConvMode ) )
  2083. {
  2084. // Invalid parameters or GetCompartments() has failed.
  2085. return FALSE;
  2086. }
  2087. ITfSource *srcOpenMode = NULL;
  2088. if (SUCCEEDED(hr = pTfOpenMode->QueryInterface( IID_ITfSource, (void**)&srcOpenMode )))
  2089. {
  2090. // Remove existing sink for open mode
  2091. if ( m_dwOpenModeSinkCookie != TF_INVALID_COOKIE )
  2092. {
  2093. srcOpenMode->UnadviseSink( m_dwOpenModeSinkCookie );
  2094. m_dwOpenModeSinkCookie = TF_INVALID_COOKIE;
  2095. }
  2096. // Setup sink for open mode (toggle state) change
  2097. if ( bRemoveOnly || SUCCEEDED(hr = srcOpenMode->AdviseSink( IID_ITfCompartmentEventSink, (ITfCompartmentEventSink*)m_TsfSink, &m_dwOpenModeSinkCookie )))
  2098. {
  2099. ITfSource *srcConvMode = NULL;
  2100. if (SUCCEEDED(hr = pTfConvMode->QueryInterface( IID_ITfSource, (void**)&srcConvMode )))
  2101. {
  2102. // Remove existing sink for open mode
  2103. if ( m_dwConvModeSinkCookie != TF_INVALID_COOKIE )
  2104. {
  2105. srcConvMode->UnadviseSink( m_dwConvModeSinkCookie );
  2106. m_dwConvModeSinkCookie = TF_INVALID_COOKIE;
  2107. }
  2108. // Setup sink for open mode (toggle state) change
  2109. if ( bRemoveOnly || SUCCEEDED(hr = srcConvMode->AdviseSink( IID_ITfCompartmentEventSink, (ITfCompartmentEventSink*)m_TsfSink, &m_dwConvModeSinkCookie )))
  2110. {
  2111. bRc = TRUE;
  2112. }
  2113. srcConvMode->Release();
  2114. }
  2115. }
  2116. srcOpenMode->Release();
  2117. }
  2118. if ( bLocalCompartments )
  2119. {
  2120. pTfOpenMode->Release();
  2121. pTfConvMode->Release();
  2122. pcm->Release();
  2123. }
  2124. return bRc;
  2125. }
  2126.  
  2127. /* IME Message Handler */
  2128. LRESULT CIME::WMInputLanguage(HWND hWnd, UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM lParam)
  2129. {
  2130. ChangeInputLanguage();
  2131. return 0;
  2132. }
  2133.  
  2134. LRESULT CIME::WMStartComposition(HWND /*hWnd*/, UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
  2135. {
  2136. return 1L;
  2137. }
  2138.  
  2139. LRESULT CIME::WMComposition(HWND hWnd, UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM lParam)
  2140. {
  2141. LRESULT result = 0;
  2142.  
  2143. if(ms_bCaptureInput == false)
  2144. return 0;
  2145.  
  2146. HIMC hImc = ImmGetContext(hWnd);
  2147.  
  2148. if(hImc == NULL)
  2149. return 0;
  2150.  
  2151. if(lParam&GCS_RESULTSTR)
  2152. ResultProcess(hImc);
  2153. if(lParam&GCS_COMPATTR)
  2154. AttributeProcess(hImc);
  2155. if(lParam&GCS_COMPSTR)
  2156. {
  2157. if (ms_uOutputCodePage == 950) // 대만 주음 입력 처리
  2158. {
  2159. if (lParam&GCS_COMPATTR)
  2160. CompositionProcessBuilding(hImc);
  2161. else
  2162. CompositionProcess(hImc);
  2163. }
  2164. else
  2165. {
  2166. CompositionProcess(hImc);
  2167. }
  2168. }
  2169.  
  2170. ImmReleaseContext(hWnd, hImc);
  2171.  
  2172. if(ms_pEvent)
  2173. ms_pEvent->OnUpdate();
  2174.  
  2175. return (result);
  2176. }
  2177.  
  2178. LRESULT CIME::WMEndComposition(HWND /*hWnd*/, UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
  2179. {
  2180. ms_compLen = 0;
  2181. ms_ulbegin = 0;
  2182. ms_ulend = 0;
  2183.  
  2184. if(ms_pEvent)
  2185. ms_pEvent->OnUpdate();
  2186.  
  2187. return 0L;
  2188. }
  2189.  
  2190. LRESULT CIME::WMNotify(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  2191. {
  2192. LRESULT result = 0;
  2193.  
  2194. if(ms_bCaptureInput == false)
  2195. return 0;
  2196. switch (wParam) {
  2197.  
  2198. case IMN_OPENCANDIDATE:
  2199. case IMN_CHANGECANDIDATE: {
  2200. if (ms_bUILessMode && !ms_bUseIMMCandidate)
  2201. break;
  2202. HIMC hImc = ImmGetContext(hWnd);
  2203. if (hImc == NULL)
  2204. break;
  2205. CandidateProcess(hImc);
  2206. if (!m_bUseDefaultIME) {
  2207. if(ms_pEvent)
  2208. ms_pEvent->OnOpenCandidateList();
  2209. } else
  2210. result = ::DefWindowProc(hWnd, uiMsg, wParam, lParam);
  2211. ImmReleaseContext(hWnd, hImc);
  2212. break;
  2213. }
  2214. case IMN_CLOSECANDIDATE:
  2215. if (ms_bUILessMode && !ms_bUseIMMCandidate)
  2216. break;
  2217. if (!m_bUseDefaultIME)
  2218. CloseCandidateList();
  2219. else
  2220. result = DefWindowProc(hWnd, uiMsg, wParam, lParam);
  2221. break;
  2222.  
  2223. case IMN_SETCONVERSIONMODE:
  2224. case IMN_SETOPENSTATUS:
  2225. if (ms_bUILessMode)
  2226. break;
  2227. CheckToggleState();
  2228. break;
  2229.  
  2230. case IMN_PRIVATE: {
  2231. if (ms_bUILessMode)
  2232. break;
  2233. HIMC hImc = ImmGetContext(hWnd);
  2234. if (hImc == NULL)
  2235. break;
  2236. ReadingProcess(hImc);
  2237.  
  2238. // Trap some messages to hide reading window
  2239. switch(ms_adwId[0])
  2240. {
  2241. case IMEID_CHT_VER42:
  2242. case IMEID_CHT_VER43:
  2243. case IMEID_CHT_VER44:
  2244. case IMEID_CHS_VER41:
  2245. case IMEID_CHS_VER42:
  2246. if ((lParam == 1)||(lParam == 2))
  2247. return true;
  2248. break;
  2249.  
  2250. case IMEID_CHT_VER50:
  2251. case IMEID_CHT_VER51:
  2252. case IMEID_CHT_VER52:
  2253. case IMEID_CHT_VER60:
  2254. case IMEID_CHS_VER53:
  2255. if ((lParam == 16)||(lParam == 17)||(lParam == 26)||(lParam == 27)||(lParam == 28))
  2256. return true;
  2257. break;
  2258. }
  2259. ImmReleaseContext(hWnd, hImc);
  2260. break;
  2261. }
  2262. }
  2263.  
  2264. if(ms_pEvent)
  2265. ms_pEvent->OnUpdate();
  2266.  
  2267. return result;
  2268. }
  2269.  
  2270. LRESULT CIME::WMChar(HWND /*hWnd*/, UINT /*uiMsg*/, WPARAM wParam, LPARAM lParam)
  2271. {
  2272. unsigned char c = unsigned char(wParam & 0xff);
  2273.  
  2274. switch (c)
  2275. {
  2276. case 8:
  2277. if(ms_bCaptureInput == false)
  2278. return 0;
  2279. if (ms_curpos > 0)
  2280. {
  2281. DecCurPos();
  2282. DelCurPos();
  2283. }
  2284. if(ms_pEvent)
  2285. ms_pEvent->OnUpdate();
  2286. return 0;
  2287. break;
  2288.  
  2289. default:
  2290. if(ms_pEvent) {
  2291. if (ms_pEvent->OnWM_CHAR(wParam, lParam))
  2292. break;
  2293. }
  2294. if(ms_bCaptureInput == false)
  2295. return 0;
  2296. wchar_t w[10];
  2297. MultiByteToWideChar(ms_uInputCodePage, 0, (char*)&c, 1, w, 1);
  2298.  
  2299. OnChar(w[0]);
  2300. if (w[0] == L'|')
  2301. OnChar(w[0]);
  2302. if(ms_pEvent)
  2303. ms_pEvent->OnUpdate();
  2304. break;
  2305. }
  2306.  
  2307. return 0;
  2308. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement