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