source: trunk/src/gui/inputmethod/qwininputcontext_win.cpp@ 347

Last change on this file since 347 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 28.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qwininputcontext_p.h"
43#include "qinputcontext_p.h"
44
45#include "qfont.h"
46#include "qwidget.h"
47#include "qapplication.h"
48#include "qlibrary.h"
49#include "qevent.h"
50#include "qtextformat.h"
51
52//#define Q_IME_DEBUG
53
54/* Active Input method support on Win95/98/NT */
55#include <objbase.h>
56#include <initguid.h>
57
58#ifdef Q_IME_DEBUG
59#include "qdebug.h"
60#endif
61
62#if defined(Q_OS_WINCE)
63extern void qt_wince_show_SIP(bool show); // defined in qguifunctions_wince.cpp
64#endif
65
66QT_BEGIN_NAMESPACE
67
68extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
69
70
71DEFINE_GUID(IID_IActiveIMMApp,
720x08c0e040, 0x62d1, 0x11d1, 0x93, 0x26, 0x0, 0x60, 0xb0, 0x67, 0xb8, 0x6e);
73
74
75
76DEFINE_GUID(CLSID_CActiveIMM,
770x4955DD33, 0xB159, 0x11d0, 0x8F, 0xCF, 0x0, 0xAA, 0x00, 0x6B, 0xCC, 0x59);
78
79
80
81DEFINE_GUID(IID_IActiveIMMMessagePumpOwner,
820xb5cf2cfa, 0x8aeb, 0x11d1, 0x93, 0x64, 0x0, 0x60, 0xb0, 0x67, 0xb8, 0x6e);
83
84
85
86interface IEnumRegisterWordW;
87interface IEnumInputContext;
88
89
90bool qt_sendSpontaneousEvent(QObject*, QEvent*);
91
92
93#define IFMETHOD HRESULT STDMETHODCALLTYPE
94
95interface IActiveIMMApp : public IUnknown
96{
97public:
98 virtual IFMETHOD AssociateContext(HWND hWnd, HIMC hIME, HIMC __RPC_FAR *phPrev) = 0;
99 virtual IFMETHOD dummy_ConfigureIMEA() = 0;
100 virtual IFMETHOD ConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, REGISTERWORDW __RPC_FAR *pData) = 0;
101 virtual IFMETHOD CreateContext(HIMC __RPC_FAR *phIMC) = 0;
102 virtual IFMETHOD DestroyContext(HIMC hIME) = 0;
103 virtual IFMETHOD dummy_EnumRegisterWordA() = 0;
104 virtual IFMETHOD EnumRegisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szRegister, LPVOID pData,
105 IEnumRegisterWordW __RPC_FAR *__RPC_FAR *pEnum) = 0;
106 virtual IFMETHOD dummy_EscapeA() = 0;
107 virtual IFMETHOD EscapeW(HKL hKL, HIMC hIMC, UINT uEscape, LPVOID pData, LRESULT __RPC_FAR *plResult) = 0;
108 virtual IFMETHOD dummy_GetCandidateListA() = 0;
109 virtual IFMETHOD GetCandidateListW(HIMC hIMC, DWORD dwIndex, UINT uBufLen, CANDIDATELIST __RPC_FAR *pCandList,
110 UINT __RPC_FAR *puCopied) = 0;
111 virtual IFMETHOD dummy_GetCandidateListCountA() = 0;
112 virtual IFMETHOD GetCandidateListCountW(HIMC hIMC, DWORD __RPC_FAR *pdwListSize, DWORD __RPC_FAR *pdwBufLen) = 0;
113 virtual IFMETHOD GetCandidateWindow(HIMC hIMC, DWORD dwIndex, CANDIDATEFORM __RPC_FAR *pCandidate) = 0;
114 virtual IFMETHOD dummy_GetCompositionFontA() = 0;
115 virtual IFMETHOD GetCompositionFontW(HIMC hIMC, LOGFONTW __RPC_FAR *plf) = 0;
116 virtual IFMETHOD dummy_GetCompositionStringA() = 0;
117 virtual IFMETHOD GetCompositionStringW(HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LONG __RPC_FAR *plCopied, LPVOID pBuf) = 0;
118 virtual IFMETHOD GetCompositionWindow(HIMC hIMC, COMPOSITIONFORM __RPC_FAR *pCompForm) = 0;
119 virtual IFMETHOD GetContext(HWND hWnd, HIMC __RPC_FAR *phIMC) = 0;
120 virtual IFMETHOD dummy_GetConversionListA() = 0;
121 virtual IFMETHOD GetConversionListW(HKL hKL, HIMC hIMC, LPWSTR pSrc, UINT uBufLen, UINT uFlag,
122 CANDIDATELIST __RPC_FAR *pDst, UINT __RPC_FAR *puCopied) = 0;
123 virtual IFMETHOD GetConversionStatus(HIMC hIMC, DWORD __RPC_FAR *pfdwConversion, DWORD __RPC_FAR *pfdwSentence) = 0;
124 virtual IFMETHOD GetDefaultIMEWnd(HWND hWnd, HWND __RPC_FAR *phDefWnd) = 0;
125 virtual IFMETHOD dummy_GetDescriptionA() = 0;
126 virtual IFMETHOD GetDescriptionW(HKL hKL, UINT uBufLen, LPWSTR szDescription, UINT __RPC_FAR *puCopied) = 0;
127 virtual IFMETHOD dummy_GetGuideLineA() = 0;
128 virtual IFMETHOD GetGuideLineW(HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LPWSTR pBuf, DWORD __RPC_FAR *pdwResult) = 0;
129 virtual IFMETHOD dummy_GetIMEFileNameA() = 0;
130 virtual IFMETHOD GetIMEFileNameW(HKL hKL, UINT uBufLen, LPWSTR szFileName, UINT __RPC_FAR *puCopied) = 0;
131 virtual IFMETHOD GetOpenStatus(HIMC hIMC) = 0;
132 virtual IFMETHOD GetProperty(HKL hKL, DWORD fdwIndex, DWORD __RPC_FAR *pdwProperty) = 0;
133 virtual IFMETHOD dummy_GetRegisterWordStyleA() = 0;
134 virtual IFMETHOD GetRegisterWordStyleW(HKL hKL, UINT nItem, STYLEBUFW __RPC_FAR *pStyleBuf, UINT __RPC_FAR *puCopied) = 0;
135 virtual IFMETHOD GetStatusWindowPos(HIMC hIMC, POINT __RPC_FAR *pptPos) = 0;
136 virtual IFMETHOD GetVirtualKey(HWND hWnd, UINT __RPC_FAR *puVirtualKey) = 0;
137 virtual IFMETHOD dummy_InstallIMEA() = 0;
138 virtual IFMETHOD InstallIMEW(LPWSTR szIMEFileName, LPWSTR szLayoutText, HKL __RPC_FAR *phKL) = 0;
139 virtual IFMETHOD IsIME(HKL hKL) = 0;
140 virtual IFMETHOD dummy_IsUIMessageA() = 0;
141 virtual IFMETHOD IsUIMessageW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) = 0;
142 virtual IFMETHOD NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) = 0;
143 virtual IFMETHOD dummy_RegisterWordA() = 0;
144 virtual IFMETHOD RegisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szRegister) = 0;
145 virtual IFMETHOD ReleaseContext(HWND hWnd, HIMC hIMC) = 0;
146 virtual IFMETHOD SetCandidateWindow(HIMC hIMC, CANDIDATEFORM __RPC_FAR *pCandidate) = 0;
147 virtual IFMETHOD SetCompositionFontA(HIMC hIMC, LOGFONTA __RPC_FAR *plf) = 0;
148 virtual IFMETHOD SetCompositionFontW(HIMC hIMC, LOGFONTW __RPC_FAR *plf) = 0;
149 virtual IFMETHOD dummy_SetCompositionStringA() = 0;
150 virtual IFMETHOD SetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen,
151 LPVOID pRead, DWORD dwReadLen) = 0;
152 virtual IFMETHOD SetCompositionWindow(HIMC hIMC, COMPOSITIONFORM __RPC_FAR *pCompForm) = 0;
153 virtual IFMETHOD SetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) = 0;
154 virtual IFMETHOD SetOpenStatus(HIMC hIMC, BOOL fOpen) = 0;
155 virtual IFMETHOD SetStatusWindowPos(HIMC hIMC, POINT __RPC_FAR *pptPos) = 0;
156 virtual IFMETHOD SimulateHotKey(HWND hWnd, DWORD dwHotKeyID) = 0;
157 virtual IFMETHOD dummy_UnregisterWordA() = 0;
158 virtual IFMETHOD UnregisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szUnregister) = 0;
159 virtual IFMETHOD Activate(BOOL fRestoreLayout) = 0;
160 virtual IFMETHOD Deactivate(void) = 0;
161 virtual IFMETHOD OnDefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT __RPC_FAR *plResult) = 0;
162 virtual IFMETHOD FilterClientWindows(ATOM __RPC_FAR *aaClassList, UINT uSize) = 0;
163 virtual IFMETHOD dummy_GetCodePageA() = 0;
164 virtual IFMETHOD GetLangId(HKL hKL, LANGID __RPC_FAR *plid) = 0;
165 virtual IFMETHOD AssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) = 0;
166 virtual IFMETHOD DisableIME(DWORD idThread) = 0;
167 virtual IFMETHOD dummy_GetImeMenuItemsA() = 0;
168 virtual IFMETHOD GetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, /*IMEMENUITEMINFOW*/ void __RPC_FAR *pImeParentMenu,
169 /*IMEMENUITEMINFOW*/ void __RPC_FAR *pImeMenu, DWORD dwSize, DWORD __RPC_FAR *pdwResult) = 0;
170 virtual IFMETHOD EnumInputContext(DWORD idThread, IEnumInputContext __RPC_FAR *__RPC_FAR *ppEnum) = 0;
171};
172
173interface IActiveIMMMessagePumpOwner : public IUnknown
174{
175public:
176 virtual IFMETHOD Start(void) = 0;
177 virtual IFMETHOD End(void) = 0;
178 virtual IFMETHOD OnTranslateMessage(const MSG __RPC_FAR *pMsg) = 0;
179 virtual IFMETHOD Pause(DWORD __RPC_FAR *pdwCookie) = 0;
180 virtual IFMETHOD Resume(DWORD dwCookie) = 0;
181};
182
183
184static IActiveIMMApp *aimm = 0;
185static IActiveIMMMessagePumpOwner *aimmpump = 0;
186static QString *imeComposition = 0;
187static int imePosition = -1;
188bool qt_use_rtl_extensions = false;
189static bool haveCaret = false;
190
191#ifndef LGRPID_INSTALLED
192#define LGRPID_INSTALLED 0x00000001 // installed language group ids
193#define LGRPID_SUPPORTED 0x00000002 // supported language group ids
194#endif
195
196#ifndef LGRPID_ARABIC
197#define LGRPID_WESTERN_EUROPE 0x0001 // Western Europe & U.S.
198#define LGRPID_CENTRAL_EUROPE 0x0002 // Central Europe
199#define LGRPID_BALTIC 0x0003 // Baltic
200#define LGRPID_GREEK 0x0004 // Greek
201#define LGRPID_CYRILLIC 0x0005 // Cyrillic
202#define LGRPID_TURKISH 0x0006 // Turkish
203#define LGRPID_JAPANESE 0x0007 // Japanese
204#define LGRPID_KOREAN 0x0008 // Korean
205#define LGRPID_TRADITIONAL_CHINESE 0x0009 // Traditional Chinese
206#define LGRPID_SIMPLIFIED_CHINESE 0x000a // Simplified Chinese
207#define LGRPID_THAI 0x000b // Thai
208#define LGRPID_HEBREW 0x000c // Hebrew
209#define LGRPID_ARABIC 0x000d // Arabic
210#define LGRPID_VIETNAMESE 0x000e // Vietnamese
211#define LGRPID_INDIC 0x000f // Indic
212#define LGRPID_GEORGIAN 0x0010 // Georgian
213#define LGRPID_ARMENIAN 0x0011 // Armenian
214#endif
215
216static DWORD WM_MSIME_MOUSE = 0;
217
218QWinInputContext::QWinInputContext(QObject *parent)
219 : QInputContext(parent), recursionGuard(false)
220{
221 if (QSysInfo::WindowsVersion < QSysInfo::WV_2000) {
222 // try to get the Active IMM COM object on Win95/98/NT, where english versions don't
223 // support the regular Windows input methods.
224 if (CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_INPROC_SERVER,
225 IID_IActiveIMMApp, (LPVOID *)&aimm) != S_OK) {
226 aimm = 0;
227 }
228 if (aimm && (aimm->QueryInterface(IID_IActiveIMMMessagePumpOwner, (LPVOID *)&aimmpump) != S_OK ||
229 aimm->Activate(true) != S_OK)) {
230 aimm->Release();
231 aimm = 0;
232 if (aimmpump)
233 aimmpump->Release();
234 aimmpump = 0;
235 }
236 if (aimmpump)
237 aimmpump->Start();
238 }
239
240#ifndef Q_OS_WINCE
241 QSysInfo::WinVersion ver = QSysInfo::windowsVersion();
242 if (ver & QSysInfo::WV_NT_based && ver >= QSysInfo::WV_VISTA) {
243 // Since the IsValidLanguageGroup/IsValidLocale functions always return true on
244 // Vista, check the Keyboard Layouts for enabling RTL.
245 UINT nLayouts = GetKeyboardLayoutList(0, 0);
246 if (nLayouts) {
247 HKL *lpList = new HKL[nLayouts];
248 GetKeyboardLayoutList(nLayouts, lpList);
249 for (int i = 0; i<(int)nLayouts; i++) {
250 WORD plangid = PRIMARYLANGID((quintptr)lpList[i]);
251 if (plangid == LANG_ARABIC
252 || plangid == LANG_HEBREW
253 || plangid == LANG_FARSI
254#ifdef LANG_SYRIAC
255 || plangid == LANG_SYRIAC
256#endif
257 ) {
258 qt_use_rtl_extensions = true;
259 break;
260 }
261 }
262 delete []lpList;
263 }
264 } else {
265 // figure out whether a RTL language is installed
266 typedef BOOL(WINAPI *PtrIsValidLanguageGroup)(DWORD,DWORD);
267 PtrIsValidLanguageGroup isValidLanguageGroup = (PtrIsValidLanguageGroup)QLibrary::resolve(QLatin1String("kernel32"), "IsValidLanguageGroup");
268 if (isValidLanguageGroup) {
269 qt_use_rtl_extensions = isValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED)
270 || isValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED);
271 }
272 qt_use_rtl_extensions |= IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
273 || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
274#ifdef LANG_SYRIAC
275 || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
276#endif
277 || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED);
278 }
279#else
280 qt_use_rtl_extensions = false;
281#endif
282
283 WM_MSIME_MOUSE = QT_WA_INLINE(RegisterWindowMessage(L"MSIMEMouseOperation"), RegisterWindowMessageA("MSIMEMouseOperation"));
284}
285
286QWinInputContext::~QWinInputContext()
287{
288 // release active input method if we have one
289 if (aimm) {
290 aimmpump->End();
291 aimmpump->Release();