1 //#define OV_DEBUG
2 #include "ImmController.h"
3
4 ImmController* ImmController::m_self = NULL;
5
ImmController()6 ImmController::ImmController()
7 {
8 m_shiftPressedTime = 0;
9 m_isCompStarted = false;
10 }
11
~ImmController(void)12 ImmController::~ImmController(void)
13 {
14 m_self = NULL;
15 }
16
open()17 ImmController* ImmController::open()
18 {
19 if(m_self == NULL)
20 m_self = new ImmController();
21
22 return m_self;
23 }
24
close(void)25 void ImmController::close(void)
26 {
27 if(m_self) delete m_self;
28 }
29
onKeyShiftOnly(HIMC hIMC,LPARAM lKeyData)30 int ImmController::onKeyShiftOnly(HIMC hIMC, LPARAM lKeyData)
31 {
32 int shiftState;
33 if(!getKeyInfo(lKeyData).isKeyUp) // Shift pressed
34 {
35 murmur("shift-only: down");
36 m_shiftPressedTime = GetTickCount();
37 shiftState = 1;
38 }
39 else if(GetTickCount() - m_shiftPressedTime < 200) // Shift Up
40 {
41 murmur("shift-only: up");
42 //Toggle Chinese/English mode.
43 //lParam == 2
44 MyGenerateMessage(hIMC, WM_IME_NOTIFY, IMN_PRIVATE, 2);
45 shiftState = 2;
46 m_shiftPressedTime = 0;
47 }
48 else //Shift Up too late
49 {
50 murmur("shift-only: other");
51 shiftState = 0;
52 m_shiftPressedTime = 0;
53 }
54
55 return shiftState;
56 }
57
onKeyShift(HIMC hIMC,UINT uVKey,LPARAM lKeyData)58 int ImmController::onKeyShift(HIMC hIMC, UINT uVKey, LPARAM lKeyData)
59 {
60 int processState;
61 if(LOWORD(uVKey) == VK_SPACE) //shift + space
62 {
63 murmur("S: vkey=%u", LOWORD(uVKey));
64 murmur("S_Space: Full-Half char");
65 m_shiftPressedTime = 0;
66 processState = 1;
67 }
68 else if(LOWORD(uVKey) == VK_SHIFT) // only shift
69 {
70 switch(onKeyShiftOnly(hIMC, lKeyData)) {
71 case 1:
72 murmur("S: EN-ZH: waiting for key-up");
73 processState = 1;
74 break;
75 case 2:
76 murmur("S: EN-ZH: proceeded");
77 //processState = 1;
78 processState = 2;
79 break;
80 case 0:
81 default:
82 murmur("S: passed");
83 m_shiftPressedTime = 0;
84 processState = 0;
85 break;
86 }
87 }
88 else //shift + ?
89 {
90 murmur("S_%u: assume normal", LOWORD(uVKey));
91 m_shiftPressedTime = 0;
92 processState = 2;
93 }
94 return processState;
95 }
96
onKeyCtrl(HIMC hIMC,UINT uVKey)97 int ImmController::onKeyCtrl(HIMC hIMC, UINT uVKey)
98 {
99 int processState;
100 switch(LOWORD(uVKey)) {
101 case VK_CONTROL:
102 murmur("C: passed");
103 processState = 0;
104 break;
105 case VK_MENU:
106 murmur("C_A: passed");
107 processState = 0;
108 break;
109 case VK_OEM_5:
110 //Change the module by Ctrl+"\":
111 //lParam == 8
112 murmur("C_\\: change module");
113 MyGenerateMessage(hIMC, WM_IME_NOTIFY, IMN_PRIVATE, 8);
114 processState = 1;
115 break;
116 case VK_OEM_PLUS:
117 //Change the BoPoMoFo keyboard layout by Ctrl+"=":
118 //lParam == 5
119 murmur("C_=: change Hsu's layout");
120 MyGenerateMessage(hIMC, WM_IME_NOTIFY, IMN_PRIVATE, 5);
121 processState = 1;
122 break;
123 case VK_SPACE:
124 murmur("C_Space: switch IME");
125 processState = 1;
126 break;
127 case VK_SHIFT:
128 murmur("C_S: rotate IME");
129 processState = 1;
130 break;
131 default:
132 murmur("C_%u: assume normal", LOWORD(uVKey));
133 processState = 2;
134 }
135 return processState;
136 }
137
onKeyCtrlAlt(HIMC hIMC,UINT uVKey)138 int ImmController::onKeyCtrlAlt(HIMC hIMC, UINT uVKey)
139 {
140 int processState;
141 switch(LOWORD(uVKey)) {
142 case VK_MENU:
143 case VK_CONTROL:
144 murmur("C_A: passed");
145 processState = 0;
146 break;
147 case VK_G:
148 //Toggle Traditional / Simplified Chinese.
149 //lParam == 4
150 murmur("C_A_g: TW-CN");
151 MyGenerateMessage(hIMC, WM_IME_NOTIFY, IMN_PRIVATE, 4);
152 processState = 1;
153 break;
154 case VK_K:
155 //Toggle Large Candidate window.
156 //lParam == 6
157 murmur("C_A_k: Expand Cand");
158 MyGenerateMessage(hIMC, WM_IME_NOTIFY, IMN_PRIVATE, 6);
159 processState = 1;
160 break;
161 case VK_L:
162 // Test Notify window.
163 murmur("C_A_l: Notify");
164 MyGenerateMessage(hIMC, WM_IME_NOTIFY, IMN_PRIVATE, 7);
165 processState = 1;
166 break;
167 default:
168 murmur("C_A_%u: assume normal", LOWORD(uVKey));
169 processState = 2;
170 break;
171 }
172 return processState;
173 }
174
onControlEvent(HIMC hIMC,UINT uVKey,LPARAM lKeyData,CONST LPBYTE lpbKeyState)175 int ImmController::onControlEvent
176 (HIMC hIMC, UINT uVKey, LPARAM lKeyData, CONST LPBYTE lpbKeyState)
177 {
178 int processState;
179
180 if(getKeyInfo(lKeyData).isKeyUp)
181 {
182 if(LOWORD(uVKey) == VK_SHIFT) {
183 processState = onKeyShift(hIMC, uVKey, lKeyData);
184 } else {
185 murmur("other key up");
186 m_shiftPressedTime = 0;
187 processState = 0;
188 }
189 }
190 else if(isCtrlPressed(lpbKeyState))
191 {
192 if(isAltPressed(lpbKeyState)) {
193 murmur("ctrl-alt state");
194 processState = onKeyCtrlAlt(hIMC, uVKey);
195 }
196 else {
197 murmur("ctrl state");
198 processState = onKeyCtrl(hIMC, uVKey);
199 }
200 }
201 else if(isShiftPressed(lpbKeyState)) {
202 murmur("shift state");
203 processState = onKeyShift(hIMC, uVKey, lKeyData);
204 DWORD conv, sentence;
205 ImmGetConversionStatus(hIMC, &conv, &sentence);
206 //Alphanumeric mode
207 if(!(conv & IME_CMODE_NATIVE)) processState = 0;
208 //else processState = onKeyShift(hIMC, uVKey, lKeyData);
209 }
210 else {
211 murmur("other state: assume normal");
212 m_shiftPressedTime = 0;
213
214 DWORD conv, sentence;
215 ImmGetConversionStatus(hIMC, &conv, &sentence);
216 //Alphanumeric mode
217 if(!(conv & IME_CMODE_NATIVE)) processState = 0;
218 else processState = 2;
219 }
220 return processState;
221 }
222
onTypingEvent(HIMC hIMC,UINT uVKey,LPARAM lKeyData,CONST LPBYTE lpbKeyState)223 BOOL ImmController::onTypingEvent
224 (HIMC hIMC, UINT uVKey, LPARAM lKeyData, CONST LPBYTE lpbKeyState)
225 {
226 BOOL isProcessed = FALSE;
227
228 //if(getKeyInfo(lKeyData).isKeyUp) return isProcessed;
229 /*
230 DWORD conv, sentence;
231 ImmGetConversionStatus(hIMC, &conv, &sentence);
232 //Alphanumeric mode
233 if(!(conv & IME_CMODE_NATIVE)) return isProcessed;
234 */
235
236 ImmModel* model = ImmModel::open(hIMC);
237 if(!m_isCompStarted &&
238 wcslen(GETLPCOMPSTR(model->getCompStr())) == 0)
239 {
240 murmur("STARTCOMPOSITION");
241 m_isCompStarted = true;//�n����!
242 MyGenerateMessage(hIMC, WM_IME_STARTCOMPOSITION, 0, 0);
243 }
244 ImmModel::close();
245
246 int k = LOWORD(uVKey);
247 if( k >= 65 && k <= 90)
248 k = k + 32;
249
250 switch(LOWORD(uVKey)) {
251 case VK_PRIOR: // pageup
252 k = 11;
253 break;
254 case VK_NEXT: // pagedown
255 k = 12;
256 break;
257 case VK_END:
258 k = 4;
259 break;
260 case VK_HOME:
261 k = 1;
262 break;
263 case VK_LEFT:
264 k = 28;
265 break;
266 case VK_UP:
267 k = 30;
268 break;
269 case VK_RIGHT:
270 k = 29;
271 break;
272 case VK_DOWN:
273 k = 31;
274 break;
275 case VK_DELETE:
276 k = 127;
277 break;
278 default:
279 //DebugLog("uVKey: %x, %c\n", LOWORD(uVKey), LOWORD(uVKey));
280 break;
281 }
282
283 WORD out[2];
284 int spec =
285 ToAscii(uVKey, MapVirtualKey(uVKey, 0), lpbKeyState, (LPWORD)&out, 0);
286 if(spec == 1) k = (char)out[0];
287 murmur("KEY: %c", out[0]);
288
289 AVKeyCode keycode(k);
290 if(LOWORD(lpbKeyState[VK_CAPITAL]))
291 keycode.setCapslock(1);
292 if(isShiftPressed(lpbKeyState) || LOWORD(uVKey) == VK_SHIFT)
293 keycode.setShift(1);
294 if(isCtrlPressed(lpbKeyState))
295 keycode.setCtrl(1);
296 if(isAltPressed(lpbKeyState))
297 keycode.setAlt(1);
298 if((lpbKeyState[VK_NUMLOCK])
299 && (uVKey >= VK_NUMPAD0)
300 && (uVKey <= VK_DIVIDE))
301 keycode.setNum(1);
302
303 AVLoader* loader = AVLoader::open();
304 if(loader->keyEvent(UICurrentInputMethod(), keycode)) //�p�G�ثe�ҲճB�z��key
305 {
306 isProcessed = TRUE;
307 //<comment author='b6s'>
308 // Moves this block back to DisplayServer.
309 /*
310 if(LOWORD(uVKey) != VK_RETURN) {
311 murmur("COMPOSITION GCS_COMPSTR");
312 MyGenerateMessage(hIMC, WM_IME_COMPOSITION, 0, GCS_COMPSTR);
313 }
314 else {
315 murmur("COMPOSITION GCS_RESULTSTR");
316 MyGenerateMessage(hIMC, WM_IME_COMPOSITION, 0, GCS_RESULTSTR);
317
318 m_isCompStarted = false; //�n����!
319 murmur("ENDCOMPOSITION");
320 MyGenerateMessage(hIMC, WM_IME_ENDCOMPOSITION, 0, 0);
321 //InitCompStr(m_model->getCompStr());
322 }
323 */
324 //</comment>
325 } else {
326 model = ImmModel::open(hIMC);
327 //James comment: �ѨM���զ��r���e��r comp window �|���������D(?�ݰӺe)
328 if(m_isCompStarted &&
329 wcslen(GETLPCOMPSTR(model->getCompStr())) == 0)
330 {
331 murmur("ENDCOMPOSITION");
332 m_isCompStarted = false; //�n����!
333 MyGenerateMessage(hIMC, WM_IME_ENDCOMPOSITION, 0, 0);
334 }
335 ImmModel::close();
336 }
337
338 return isProcessed;
339 }
340