source: trunk/src/user32/oslibmsgtranslate.cpp@ 21308

Last change on this file since 21308 was 21308, checked in by ydario, 16 years ago

Minor updates, backout imm changes.

File size: 53.0 KB
Line 
1/* $Id: oslibmsgtranslate.cpp,v 1.125 2004-05-24 09:01:59 sandervl Exp $ */
2/*
3 * Window message translation functions for OS/2
4 *
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1999 Daniela Engert (dani@ngrt.de)
8 * Copyright 1999 Rene Pronk (R.Pronk@twi.tudelft.nl)
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 * TODO: Extra msgs: which messages must be put into the queue and which can be sent directly?
13 * (According to the docs TranslateMessage really inserts a msg in the queue)
14 * TODO: Filter translation isn't correct for posted messages
15 *
16 */
17#define INCL_NLS
18#define INCL_GPI
19#define INCL_WIN
20#define INCL_PM
21#define INCL_DOSPROCESS
22#include <os2wrap.h>
23#include <string.h>
24#include <misc.h>
25#include <winconst.h>
26#include <win32api.h>
27#include "oslibmsg.h"
28#include <winuser32.h>
29#include "win32wdesktop.h"
30#include "oslibutil.h"
31#include "timer.h"
32#include <thread.h>
33#include <wprocess.h>
34#include "pmwindow.h"
35#include "oslibwin.h"
36#include "winmouse.h"
37#include <pmkbdhk.h>
38#include <pmscan.h>
39#include <winscan.h>
40#include <winkeyboard.h>
41#include <winnls.h>
42#include <heapstring.h>
43#include "hook.h"
44#include "user32api.h"
45
46#include <os2im.h>
47#include <im32.h>
48
49#define DBG_LOCALLOG DBG_oslibmsgtranslate
50#include "dbglocal.h"
51
52static BOOL fGenerateDoubleClick = FALSE;
53static MSG doubleClickMsg = {0};
54
55extern UINT WINAPI GetACP(void); // from winnls.h
56
57//For wheel mouse translation
58#define WHEEL_DELTA 120
59#define OS2_WHEEL_CORRECTION 1
60//PF Correction is different for different mouse drivers. For now no correction
61//is ok because lots of Odin controls rely on minimum delta. However in future
62//we will possibly detect mouse driver and use correction if speed will be
63//too high or too low.
64
65//******************************************************************************
66//
67// setThreadQueueExtraCharMessage: queues WM_CHAR message so it is retrieved
68// by GetMessage & PeekMessage
69//
70// NOTE: WM_CHAR message always in ascii format
71//
72//******************************************************************************
73BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
74{
75 if ( teb->o.odin.tidAttachedInputThread
76 && OSLibForwardMessageToAttachedThread(teb, pExtraMsg, NULL))
77 return TRUE;
78
79 // check if the single slot is occupied already
80 if (teb->o.odin.fTranslated == TRUE) {
81 // there's still an already translated message to be processed
82 dprintf(("WARNING: translated message already pending!"));
83 return FALSE;
84 }
85
86 teb->o.odin.fTranslated = TRUE;
87 memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
88 return TRUE;
89}
90
91//******************************************************************************
92//******************************************************************************
93ULONG ConvertNumPadKey(ULONG pmScan)
94{
95 ULONG ret;
96 BYTE winKey;
97
98 switch (pmScan)
99 {
100 case PMSCAN_PAD7: ret = PMSCAN_HOME; break;
101 case PMSCAN_PAD8: ret = PMSCAN_UP; break;
102 case PMSCAN_PAD9: ret = PMSCAN_PAGEUP; break;
103 case PMSCAN_PAD4: ret = PMSCAN_LEFT; break;
104 case PMSCAN_PAD6: ret = PMSCAN_RIGHT; break;
105 case PMSCAN_PAD1: ret = PMSCAN_END; break;
106 case PMSCAN_PAD2: ret = PMSCAN_DOWN; break;
107 case PMSCAN_PAD3: ret = PMSCAN_PAGEDOWN; break;
108 case PMSCAN_PAD0: ret = PMSCAN_INSERT; break;
109 case PMSCAN_PADPERIOD: ret = PMSCAN_DELETE; break;
110 default:
111 ret = pmScan;
112 }
113
114 KeyTranslatePMScanToWinVKey(ret, FALSE, (PBYTE)&winKey, NULL, NULL);
115 return winKey;
116
117}
118//******************************************************************************
119//******************************************************************************
120LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
121{
122 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
123}
124//******************************************************************************
125//******************************************************************************
126void OSLibSetMenuDoubleClick(BOOL fSet)
127{
128 fGenerateDoubleClick = fSet;
129}
130//******************************************************************************
131
132
133/**
134 * Inter process/thread packet cleanup.
135 * See OSLibPackMessage() for details on the packing.
136 *
137 * @param pTeb Pointer to the thread environment block for the current thread.
138 * @param pPacket Pointer to the packet in question.
139 * @param pWinMsg Pointer to the window message corresponding to the packet.
140 */
141inline void OSLibCleanupPacket(TEB *pTeb, POSTMSG_PACKET *pPacket, MSG *pWinMsg)
142{
143 switch (pWinMsg->message)
144 {
145 /*
146 * Place this in the TEB freeing any previous WM_COPYDATA packet.
147 * Note! Nested WM_COPYDATA isn't working.
148 */
149 case WINWM_COPYDATA:
150 {
151 dprintf(("OSLibCleanupPacket: WM_COPYDATA: old %#p new %#p", pTeb->o.odin.pWM_COPYDATA, pPacket));
152 if (pTeb->o.odin.pWM_COPYDATA)
153 _sfree(pTeb->o.odin.pWM_COPYDATA);
154 pTeb->o.odin.pWM_COPYDATA = pPacket;
155 break;
156 }
157
158 /*
159 * Default packing - free the shared memory here.
160 */
161 default:
162 _sfree(pPacket);
163 break;
164 }
165}
166
167//******************************************************************************
168BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
169{
170 Win32BaseWindow *win32wnd = 0;
171 OSLIBPOINT point, ClientPoint;
172 POSTMSG_PACKET *packet;
173 TEB *teb = (TEB *)pTeb;
174 BOOL fWasDisabled = FALSE;
175 BOOL fIsFrame = FALSE;
176 int i;
177
178 /*
179 * Forwarded input (AttachThreadInput()).
180 */
181 if ( os2Msg->hwnd == NULLHANDLE
182 && os2Msg->msg == WIN32APP_FORWARDEDPOSTMSG
183 && os2Msg->mp2 == (MPARAM)WIN32APP_FORWARDEDPOSTMSG_MAGIC
184 && os2Msg->mp1 != NULL)
185 {
186 *winMsg = *(MSG*)os2Msg->mp1;
187 if (fMsgRemoved)
188 _sfree(os2Msg->mp1);
189 dprintf(("OS2ToWinMsgTranslate: Received forwarded messaged %x\n", os2Msg->msg));
190 return TRUE;
191 }
192
193 memset(winMsg, 0, sizeof(MSG));
194 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
195 if(!win32wnd) {
196 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
197 if(win32wnd) {
198 fIsFrame = TRUE;
199 }
200 }
201
202 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
203 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
204 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
205 {
206 goto dummymessage; //not a win32 client window
207 }
208 winMsg->time = os2Msg->time;
209 //CB: PM bug or undocumented feature? ptl.x highword is set!
210 winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
211 winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
212
213 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
214 winMsg->hwnd = win32wnd->getWindowHandle();
215
216 if(os2Msg->msg >= WIN32APP_POSTMSG) {
217 packet = (POSTMSG_PACKET *)os2Msg->mp2;
218 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
219 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
220 winMsg->wParam = packet->wParam;
221 winMsg->lParam = packet->lParam;
222 if (fMsgRemoved == MSG_REMOVE)
223 OSLibCleanupPacket(teb, packet, winMsg);
224 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
225 return TRUE;
226 }
227 else {//broadcasted message (no packet present)
228 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
229 winMsg->wParam = (UINT)os2Msg->mp1;
230 winMsg->lParam = (DWORD)os2Msg->mp2;
231 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
232 return TRUE;
233 }
234 goto dummymessage;
235 }
236
237 switch(os2Msg->msg)
238 {
239 //OS/2 msgs
240 case WM_CREATE:
241 {
242 if(teb->o.odin.newWindow == 0) {
243 DebugInt3();
244 goto dummymessage;
245 }
246
247 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
248 win32wnd->addRef();
249
250 winMsg->message = WINWM_CREATE;
251 winMsg->hwnd = win32wnd->getWindowHandle();
252 winMsg->wParam = 0;
253 winMsg->lParam = (LPARAM)win32wnd->tmpcs;
254 break;
255 }
256
257 case WM_QUIT:
258 winMsg->message = WINWM_QUIT;
259 if (fMsgRemoved && win32wnd && (ULONG)os2Msg->mp2 != 0) {
260 // mp2 != 0 -> sent by window list; be nice and close
261 // the window first
262 win32wnd->MsgClose();
263 }
264 break;
265
266 case WM_CLOSE:
267 winMsg->message = WINWM_CLOSE;
268 break;
269
270 case WM_DESTROY:
271 winMsg->message = WINWM_DESTROY;
272 break;
273
274 case WM_ENABLE:
275 winMsg->message = WINWM_ENABLE;
276 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
277 break;
278
279 case WM_SHOW:
280 winMsg->message = WINWM_SHOWWINDOW;
281 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
282 break;
283
284 case WM_REALIZEPALETTE:
285 winMsg->message = WINWM_PALETTECHANGED;
286 break;
287
288 case WM_WINDOWPOSCHANGED:
289 {
290 PSWP pswp = (PSWP)os2Msg->mp1;
291 SWP swpOld = *(pswp + 1);
292 HWND hParent = NULLHANDLE;
293 LONG yDelta = pswp->cy - swpOld.cy;
294 LONG xDelta = pswp->cx - swpOld.cx;
295
296 if(!fIsFrame) goto dummymessage;
297
298 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
299
300 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
301 if (win32wnd->isChild()) {
302 if(win32wnd->getParent()) {
303 hParent = win32wnd->getParent()->getOS2WindowHandle();
304 }
305 else goto dummymessage; //parent has just been destroyed
306 }
307 }
308 if(win32wnd->getParent()) {
309 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
310 win32wnd->getOS2WindowHandle());
311 }
312 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
313
314 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
315
316 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
317 {
318 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
319 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
320 {
321 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
322 if(wndAfter) {
323 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
324 RELEASE_WNDOBJ(wndAfter);
325 }
326 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
327 }
328 }
329 winMsg->message = WINWM_WINDOWPOSCHANGED;
330 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
331 break;
332 }
333
334 case WM_ACTIVATE:
335 {
336 HWND hwndActivate = (HWND)os2Msg->mp2;
337 BOOL fMinimized = FALSE;
338
339 hwndActivate = OS2ToWin32Handle(hwndActivate);
340 if(hwndActivate == 0) {
341 //another (non-win32) application's window
342 //set to desktop window handle
343 hwndActivate = windowDesktop->getWindowHandle();
344 }
345
346 if(win32wnd->getStyle() & WS_MINIMIZE_W)
347 {
348 fMinimized = TRUE;
349 }
350
351 winMsg->message = WINWM_ACTIVATE;
352 winMsg->wParam = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
353 winMsg->lParam = (LPARAM)hwndActivate;
354 break;
355 }
356
357 case WM_SETFOCUS:
358 {
359 HWND hwndFocus = (HWND)os2Msg->mp1;
360
361 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
362 //another (non-win32) application's window
363 //set to NULL (allowed according to win32 SDK) to avoid problems
364 hwndFocus = NULL;
365 }
366 else hwndFocus = OS2ToWin32Handle(hwndFocus);
367
368 if((ULONG)os2Msg->mp2 == TRUE) {
369 winMsg->message = WINWM_SETFOCUS;
370 winMsg->wParam = (WPARAM)hwndFocus;
371 }
372 else {
373 //If SetFocus(0) was called, then the window has already received
374 //a WM_KILLFOCUS; don't send another one
375 if(!fIgnoreKeystrokes) {
376 winMsg->message = WINWM_KILLFOCUS;
377 winMsg->wParam = (WPARAM)hwndFocus;
378 }
379 else {
380 dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
381 goto dummymessage;
382 }
383 }
384 break;
385 }
386
387 //**************************************************************************
388 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
389 //**************************************************************************
390 case WM_BUTTON1DOWN:
391 case WM_BUTTON1UP:
392 case WM_BUTTON1DBLCLK:
393 case WM_BUTTON2DOWN:
394 case WM_BUTTON2UP:
395 case WM_BUTTON2DBLCLK:
396 case WM_BUTTON3DOWN:
397 case WM_BUTTON3UP:
398 case WM_BUTTON3DBLCLK:
399 {
400 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
401
402 dprintf(("MsgButton %x (%x) %d at (%d,%d) time %x", winMsg->hwnd, os2Msg->hwnd, WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN), winMsg->pt.x, winMsg->pt.y, winMsg->time));
403
404 HWND hwnd;
405
406 DisableLogging();
407 if(GetCapture() != winMsg->hwnd)
408 {
409 hwnd = WindowFromPoint(winMsg->pt);
410 if(win32wnd->getWindowHandle() != hwnd) {
411 RELEASE_WNDOBJ(win32wnd);
412 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
413 if(win32wnd == NULL) {
414 DebugInt3();
415 EnableLogging();
416 goto dummymessage;
417 }
418 winMsg->hwnd = hwnd;
419 }
420 }
421
422 //if a window is disabled, its parent receives the mouse messages
423 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
424 if(win32wnd->getParent()) {
425 Win32BaseWindow *parent = win32wnd->getParent();;
426 if(parent) parent->addRef();
427 RELEASE_WNDOBJ(win32wnd);
428 win32wnd = parent;
429 }
430 fWasDisabled = TRUE;
431 }
432
433 if(IsNCMouseMsg(win32wnd)) {
434 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
435 winMsg->wParam = win32wnd->getLastHitTestVal();
436 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
437 }
438 else {
439 ClientPoint.x = winMsg->pt.x;
440 ClientPoint.y = winMsg->pt.y;
441 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
442 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
443 winMsg->wParam = GetMouseKeyState();
444 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
445 }
446 EnableLogging();
447
448 if(fWasDisabled) {
449 if(win32wnd) {
450 winMsg->hwnd = win32wnd->getWindowHandle();
451 }
452 else goto dummymessage; //don't send mouse messages to disabled windows
453 }
454
455 DisableLogging();
456 if ((winMsg->message == WINWM_LBUTTONDOWN) ||
457 (winMsg->message == WINWM_RBUTTONDOWN) ||
458 (winMsg->message == WINWM_MBUTTONDOWN) ||
459 (winMsg->message == WINWM_NCLBUTTONDOWN) ||
460 (winMsg->message == WINWM_NCRBUTTONDOWN) ||
461 (winMsg->message == WINWM_NCMBUTTONDOWN))
462 {
463 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
464 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
465 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
466 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
467 {
468 dprintf(("single -> double click"));
469 if(winMsg->message >= WINWM_LBUTTONDOWN) {
470 winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
471 }
472 else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
473 if(fMsgRemoved) doubleClickMsg.message = 0;
474 }
475 else {
476 dprintf(("save for double click"));
477 if(fMsgRemoved) {
478 doubleClickMsg = *winMsg;
479 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
480 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
481 }
482 }
483 }
484 }
485 EnableLogging();
486
487 if(fMsgRemoved == MSG_REMOVE)
488 {
489 MSLLHOOKSTRUCT hook;
490 ULONG msg;
491
492 if(winMsg->message >= WINWM_NCLBUTTONDOWN && winMsg->message <= WINWM_NCMBUTTONDBLCLK) {
493 msg = winMsg->message - WINWM_NCLBUTTONDOWN + WINWM_LBUTTONDOWN;
494 }
495 else msg = winMsg->message;
496
497 if(msg == WINWM_LBUTTONDBLCLK) {
498 msg = WINWM_LBUTTONDOWN;
499 }
500 else
501 if(msg == WINWM_RBUTTONDBLCLK) {
502 msg = WINWM_RBUTTONDOWN;
503 }
504 else
505 if(msg == WINWM_MBUTTONDBLCLK) {
506 msg = WINWM_MBUTTONDOWN;
507 }
508
509 // First the low-level mouse hook
510 hook.pt = winMsg->pt;
511 hook.mouseData = 0; //todo: XBUTTON1/2 (XP feature) or wheel data
512 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
513 hook.time = winMsg->time;
514 hook.dwExtraInfo = 0;
515
516 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, msg, (LPARAM)&hook)) {
517 goto dummymessage; //hook swallowed message
518 }
519 }
520 MOUSEHOOKSTRUCT mousehk;
521
522 // Now inform the WH_MOUSE hook
523 mousehk.pt = winMsg->pt;
524 mousehk.hwnd = winMsg->hwnd;
525 mousehk.wHitTestCode = win32wnd->getLastHitTestVal();
526 mousehk.dwExtraInfo = 0;
527
528 if(HOOK_CallHooksW( WH_MOUSE_W, (fMsgRemoved == MSG_REMOVE) ? HC_ACTION : HC_NOREMOVE, winMsg->message, (LPARAM)&mousehk)) {
529 //TODO: WH_CBT HCBT_CLICKSKIPPED
530 goto dummymessage; //hook swallowed message
531 }
532 break;
533 }
534
535 case WM_BUTTON2CLICK:
536 case WM_BUTTON1CLICK:
537 case WM_BUTTON3CLICK:
538 goto dummymessage;
539
540 case WM_BUTTON2MOTIONSTART:
541 case WM_BUTTON2MOTIONEND:
542 case WM_BUTTON1MOTIONSTART:
543 case WM_BUTTON1MOTIONEND:
544 case WM_BUTTON3MOTIONSTART:
545 case WM_BUTTON3MOTIONEND:
546 //no break; translate to WM_MOUSEMOVE
547 //Some applications (e.g. Unreal) retrieve all mouse messages
548 //when a mouse button is pressed and don't expect WM_NULL
549
550 case WM_MOUSEMOVE:
551 {
552 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
553
554 HWND hwnd;
555
556 dprintf2(("WM_MOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
557 DisableLogging();
558 if(GetCapture() != winMsg->hwnd)
559 {
560 hwnd = WindowFromPoint(winMsg->pt);
561 if(win32wnd->getWindowHandle() != hwnd) {
562 RELEASE_WNDOBJ(win32wnd);
563 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
564 if(win32wnd == NULL) {
565 DebugInt3();
566 EnableLogging();
567 goto dummymessage;
568 }
569 winMsg->hwnd = hwnd;
570 }
571 }
572
573 //if a window is disabled, its parent receives the mouse messages
574 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
575 if(win32wnd->getParent()) {
576 Win32BaseWindow *parent = win32wnd->getParent();;
577 if(parent) parent->addRef();
578 RELEASE_WNDOBJ(win32wnd);
579 win32wnd = parent;
580 }
581 fWasDisabled = TRUE;
582 }
583 if(IsNCMouseMsg(win32wnd))
584 {
585 winMsg->message = WINWM_NCMOUSEMOVE;
586 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
587 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
588 }
589 else
590 {
591 ClientPoint.x = winMsg->pt.x;
592 ClientPoint.y = winMsg->pt.y;
593 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
594
595 winMsg->message = WINWM_MOUSEMOVE;
596 winMsg->wParam = GetMouseKeyState();
597 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
598 }
599 EnableLogging();
600 if(fWasDisabled) {
601 if(win32wnd) {
602 winMsg->hwnd = win32wnd->getWindowHandle();
603 }
604 else {
605 goto dummymessage; //don't send mouse messages to disabled windows
606 }
607 }
608 MSLLHOOKSTRUCT hook;
609 if(fMsgRemoved == MSG_REMOVE)
610 {
611 hook.pt = winMsg->pt;
612 hook.mouseData = 0;
613 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
614 hook.time = winMsg->time;
615 hook.dwExtraInfo = 0;
616
617 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, winMsg->message, (LPARAM)&hook)) {
618 goto dummymessage; //hook swallowed message
619 }
620 }
621 MOUSEHOOKSTRUCT mousehk;
622
623 // Now inform the WH_MOUSE hook
624 mousehk.pt = winMsg->pt;
625 mousehk.hwnd = winMsg->hwnd;
626 mousehk.wHitTestCode = win32wnd->getLastHitTestVal();
627 mousehk.dwExtraInfo = 0;
628
629 if(HOOK_CallHooksW( WH_MOUSE_W, (fMsgRemoved == MSG_REMOVE) ? HC_ACTION : HC_NOREMOVE, winMsg->message, (LPARAM)&mousehk))
630 {
631 goto dummymessage; //hook swallowed message
632 }
633 break;
634 }
635
636 case WM_CONTROL:
637 goto dummymessage;
638
639 case WM_COMMAND:
640 if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
641 winMsg->message = WINWM_COMMAND;
642 winMsg->wParam = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
643 break;
644 }
645 //todo controls
646 goto dummymessage;
647
648 case WM_SYSCOMMAND:
649 {
650 ULONG x = 0, y = 0;
651 ULONG win32sc;
652
653 if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
654 POINTL pointl;
655 WinQueryPointerPos(HWND_DESKTOP, &pointl);
656 x = pointl.x;
657 y = mapScreenY(y);
658 }
659 switch(SHORT1FROMMP(os2Msg->mp1)) {
660 case SC_MOVE:
661 win32sc = SC_MOVE_W;
662 break;
663 case SC_CLOSE:
664 {
665 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
666 //TRUE -> user clicked on close button -> close window
667 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
668 {
669 HWND hwnd = win32wnd->GetTopParent();
670 if(win32wnd->getWindowHandle() != hwnd) {
671 RELEASE_WNDOBJ(win32wnd);
672 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
673 if(win32wnd == NULL) {
674 DebugInt3();
675 goto dummymessage;
676 }
677 winMsg->hwnd = hwnd;
678 }
679 }
680 win32sc = SC_CLOSE_W;
681 break;
682 }
683 case SC_MAXIMIZE:
684 win32sc = SC_MAXIMIZE_W;
685 break;
686 case SC_MINIMIZE:
687 win32sc = SC_MINIMIZE_W;
688 break;
689 case SC_NEXTFRAME:
690 case SC_NEXTWINDOW:
691 win32sc = SC_NEXTWINDOW_W;
692 break;
693 case SC_RESTORE:
694 win32sc = SC_RESTORE_W;
695 break;
696 case SC_TASKMANAGER:
697 win32sc = SC_TASKLIST_W;
698 break;
699 case SC_SYSMENU:
700 win32sc = SC_KEYMENU_W; //??
701 break;
702 default:
703 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
704 goto dummymessage;
705 }
706 winMsg->message= WINWM_SYSCOMMAND;
707 winMsg->wParam = (WPARAM)win32sc;
708 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
709 break;
710 }
711
712 case WM_CHAR_SPECIAL_ALTGRCONTROL:
713 {
714 // special char message from the keyboard hook
715 dprintf(("PM: WM_CHAR_SPECIAL_ALTGRCONTROL"));
716 // NO BREAK! FALLTHRU CASE!
717 }
718
719 case WM_CHAR_SPECIAL:
720 {
721 // @@@PH
722 // special char message from the keyboard hook
723 if(os2Msg->msg == WM_CHAR_SPECIAL) {
724 dprintf(("PM: WM_CHAR_SPECIAL"));
725 }
726 // NO BREAK! FALLTHRU CASE!
727 }
728
729 case WM_CHAR:
730 {
731 ULONG repeatCount=0;
732 ULONG virtualKey=0;
733 ULONG keyFlags=0;
734 USHORT scanCode=0;
735 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
736 BOOL keyWasPressed;
737 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
738 char c;
739 USHORT usPMScanCode = CHAR4FROMMP(os2Msg->mp1);
740
741 teb->o.odin.fTranslated = FALSE;
742 repeatCount = CHAR3FROMMP(os2Msg->mp1);
743 scanCode = CHAR4FROMMP(os2Msg->mp1);
744 keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
745
746 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x num=%d", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode, numPressed));
747 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
748
749 BOOL fWinExtended;
750 BYTE bWinVKey;
751 WORD wWinScan;
752
753 if ( (!IsDBCSEnv() && scanCode == 0) ||
754 (scanCode==0 ) && !( flags & KC_CHAR ) )
755 {
756 goto dummymessage;
757 }
758
759 if( scanCode != 0 )
760 {
761 switch( SHORT2FROMMP( os2Msg->mp2 ))
762 {
763 // for Korean
764 case VK_DBE_HANJA :
765 bWinVKey = 0x19;
766 break;
767
768 case VK_DBE_HANGEUL :
769 bWinVKey = 0x15;
770 break;
771
772 case VK_DBE_JAMO :
773 bWinVKey = 0;
774 break;
775
776 // for Japan
777 case VK_DBE_KATAKANA :
778 bWinVKey = 0;
779 break;
780
781 case VK_DBE_HIRAGANA :
782 bWinVKey = 0;
783 break;
784
785 case VK_DBE_SBCSCHAR :
786 bWinVKey = 0;
787 break;
788
789 case VK_DBE_DBCSCHAR :
790 bWinVKey = 0;
791 break;
792
793 case VK_DBE_SBCSDBCSCHAR :
794 bWinVKey = 0;
795 break;
796
797 case VK_DBE_ROMAN :
798 bWinVKey = 0;
799 break;
800
801 // for PRC-Chinese
802 case VK_DBE_HANZI :
803 bWinVKey = 0;
804 break;
805
806 // for Taiwan
807 case VK_DBE_TSANGJYE :
808 bWinVKey = 0;
809 break;
810
811 case VK_DBE_PHONETIC :
812 bWinVKey = 0;
813 break;
814
815 case VK_DBE_CONV :
816 bWinVKey = 0;
817 break;
818
819 case VK_DBE_NOCONV :
820 bWinVKey = 0;
821 break;
822
823 case VK_DBE_ALPHANUMERIC :
824 switch( GetACP())
825 {
826 case 949 : // Korea
827 case 1361 :
828 bWinVKey = 0x15;
829 break;
830
831 case 932 : // Japan
832 case 942 :
833 case 943 :
834
835 case 936 : // PRC
836 case 1381 :
837
838 case 950 : // Taiwan
839 default :
840 bWinVKey = 0;
841 }
842 break;
843
844 default :
845 KeyTranslatePMScanToWinVKey(usPMScanCode,
846 FALSE,
847 &bWinVKey,
848 &wWinScan,
849 &fWinExtended);
850 }
851
852 winMsg->wParam = bWinVKey;
853 }
854 else
855 {
856 dprintf(("PM: WM_CHAR: DBCS processing "));
857
858 winMsg->wParam = CHAR1FROMMP( os2Msg->mp2 );
859
860 wWinScan = 0;
861 fWinExtended = 0;
862
863 if( CHAR2FROMMP( os2Msg->mp2 )) // DBCS character
864 {
865 CHAR dbcsCh[ 2 ] = { CHAR1FROMMP( os2Msg->mp2 ), CHAR2FROMMP( os2Msg->mp2 )};
866
867 if( isUnicode )
868 {
869 WCHAR uniChar;
870
871 MultiByteToWideChar( CP_ACP, 0, dbcsCh, 2, &uniChar, 1 );
872 winMsg->wParam = ( WPARAM )uniChar;
873 }
874 else
875 winMsg->wParam = ( dbcsCh[ 0 ] << 8 ) | dbcsCh[ 1 ];
876 }
877 }
878 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
879 winMsg->lParam |= (wWinScan & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
880
881 // Set the extended bit when appropriate
882 if (fWinExtended)
883 winMsg->lParam = winMsg->lParam | WIN_KEY_EXTENDED;
884
885 //PF When we press shift we enable non-numeric functions of Numpad
886 if ((!numPressed || (flags & KC_SHIFT)) && (scanCode >= PMSCAN_PAD7) && (scanCode <= PMSCAN_PADPERIOD))
887 winMsg->wParam = ConvertNumPadKey(scanCode);
888
889 //@PF This looks ugly but this is just what we have in win32 both in win98/win2k
890 //what happens is that lParam is tweaked in win32 to contain some illegal codes
891 //I simply reproduce here all situation. Absolute values can be kept because
892 //Break scancode can be acheived only by pressing Ctrl-Break combination
893 if ((usPMScanCode == PMSCAN_BREAK) && !(flags & KC_KEYUP) && (flags & KC_CTRL)
894 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
895 {
896 MSG extramsg;
897 memcpy(&extramsg, winMsg, sizeof(MSG));
898 // adjust our WM_CHAR code
899 extramsg.lParam = 0x01460001;
900
901 //After SetFocus(0), all keystrokes are converted in WM_SYS*
902 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
903
904 setThreadQueueExtraCharMessage(teb, &extramsg);
905 // and finally adjust our WM_KEYDOWN code
906 winMsg->lParam = 0x01460001;
907 }
908
909 if (!(flags & KC_ALT))
910 {
911 //
912 // the Alt key is not pressed
913 // or no more pressed
914 //
915 if (flags & KC_KEYUP)
916 {
917 // check for a lonesome ALT key ...
918 // SvL: Only Left Alt; AltGr generates a WM_KEYUP when released
919 if ( (flags & KC_LONEKEY) &&
920 (winMsg->wParam == VK_LMENU_W) )
921 {
922 winMsg->message = WINWM_SYSKEYUP;
923 // held ALT-key when current key is released
924 // generates additional flag 0x2000000
925 // Note: PM seems to do this differently,
926 // KC_ALT is already reset
927 }
928 else
929 {
930 // send WM_KEYUP message
931 winMsg->message = WINWM_KEYUP;
932 }
933 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, always 1 for a WM_KEYUP message
934 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
935 }
936 else if( scanCode == 0 )
937 {
938 if( CHAR2FROMMP( os2Msg->mp2 ))
939 winMsg->message = WINWM_IME_CHAR;
940 else
941 {
942 //After SetFocus(0), all keystrokes are converted in WM_SYS*
943 winMsg->message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
944 }
945 }
946 else
947 { // send WM_KEYDOWN message
948 winMsg->message = WINWM_KEYDOWN;
949
950 if (keyWasPressed)
951 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
952
953 //Shift-Enter and possibly others need to have special handling
954 if (flags & KC_SHIFT)
955 {
956 if(fMsgRemoved && !(teb->o.odin.fTranslated))
957 {
958 dprintf(("PM: KC_SHIFT: %x",winMsg->wParam));
959 if (winMsg->wParam == VK_RETURN_W)
960 {
961 MSG extramsg;
962 memcpy(&extramsg, winMsg, sizeof(MSG));
963
964 //After SetFocus(0), all keystrokes are converted in WM_SYS*
965 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
966
967 // insert message into the queue
968 setThreadQueueExtraCharMessage(teb, &extramsg);
969 winMsg->lParam &= 0x3FFFFFFF;
970 }
971 } // else ???
972 } // KC_SHIFT
973 else
974 {
975 // in case we handle Enter directly through PMKBDHOOK
976 if ((os2Msg->msg == WM_CHAR_SPECIAL) && (winMsg->wParam == VK_RETURN_W)
977 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
978 {
979 MSG extramsg;
980 memcpy(&extramsg, winMsg, sizeof(MSG));
981
982 //After SetFocus(0), all keystrokes are converted in WM_SYS*
983 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
984
985 // insert message into the queue
986 setThreadQueueExtraCharMessage(teb, &extramsg);
987 }
988 }
989 }
990 // if right alt is down, then we need to set the alt down bit too
991 // except for the fake Ctrl WM_CHAR sent for AltGr emulation
992 if (os2Msg->msg != WM_CHAR_SPECIAL_ALTGRCONTROL &&
993 (WinGetKeyState(HWND_DESKTOP, VK_ALTGRAF) & 0x8000))
994 {
995 winMsg->lParam |= WIN_KEY_ALTHELD;
996 }
997 }
998 else
999 {
1000 //
1001 // the Alt key is pressed
1002 //
1003 if (flags & KC_KEYUP)
1004 {
1005 //@@PF Note that without pmkbdhook there will not be correct message for Alt-Enter
1006 winMsg->message = WINWM_SYSKEYUP;
1007 winMsg->lParam |= WIN_KEY_PREVSTATE;
1008 // No ALTHELD for Alt itself ;)
1009 winMsg->lParam |= WIN_KEY_ALTHELD;
1010 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
1011 }
1012 else
1013 {
1014 // send WM_SYSKEYDOWN message
1015 winMsg->message = WINWM_SYSKEYDOWN;
1016 if (keyWasPressed)
1017 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
1018
1019 // pressed ALT-key generates additional flag 0x2000000
1020 // if the current window has keyboard focus
1021 winMsg->lParam |= WIN_KEY_ALTHELD;
1022 }
1023 }
1024
1025 //After SetFocus(0), all keystrokes are converted in WM_SYS*
1026 if(fIgnoreKeystrokes) {
1027 if(winMsg->message == WINWM_KEYDOWN) {
1028 winMsg->message = WINWM_SYSKEYDOWN;
1029 }
1030 else
1031 if(winMsg->message == WINWM_KEYUP) {
1032 winMsg->message = WINWM_SYSKEYUP;
1033 }
1034 }
1035 break;
1036 }
1037
1038 case WM_TIMER:
1039//Why was this check here????
1040// if (os2Msg->mp2)
1041// {
1042 BOOL sys;
1043 ULONG id, proc;
1044
1045 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id, &proc))
1046 {
1047 winMsg->wParam = (WPARAM)id;
1048 winMsg->lParam = (LPARAM)proc;
1049 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
1050 break;
1051 }
1052// }
1053 goto dummymessage; //for caret blinking
1054
1055 case WM_SETWINDOWPARAMS:
1056 {
1057 WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
1058
1059 if(wndParams->fsStatus & WPM_TEXT) {
1060 winMsg->message = WINWM_SETTEXT;
1061 winMsg->lParam = (LPARAM)wndParams->pszText;
1062 break;
1063 }
1064 goto dummymessage;
1065 }
1066
1067#if 0
1068 case WM_QUERYWINDOWPARAMS:
1069 {
1070 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
1071 ULONG textlen;
1072 PSZ wintext;
1073
1074 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
1075 {
1076 if(wndpars->fsStatus & WPM_CCHTEXT)
1077 wndpars->cchText = win32wnd->MsgGetTextLength();
1078 if(wndpars->fsStatus & WPM_TEXT)
1079 wndpars->pszText = win32wnd->MsgGetText();
1080
1081 wndpars->fsStatus = 0;
1082 wndpars->cbCtlData = 0;
1083 wndpars->cbPresParams = 0;
1084 goto dummymessage;
1085 }
1086 }
1087#endif
1088
1089 case WM_PAINT:
1090 {
1091 if(win32wnd->IsWindowIconic()) {
1092 winMsg->message = WINWM_PAINTICON;
1093 }
1094 else winMsg->message = WINWM_PAINT;
1095 break;
1096 }
1097
1098 case WM_CONTEXTMENU:
1099 winMsg->message = WINWM_CONTEXTMENU;
1100 winMsg->wParam = win32wnd->getWindowHandle();
1101 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
1102 break;
1103
1104 case WM_RENDERFMT:
1105 winMsg->message = WINWM_RENDERFORMAT;
1106 extern UINT WIN32API clipboardPMToOdinFormat(ULONG ulPMFormat);
1107 winMsg->wParam = (UINT)clipboardPMToOdinFormat((ULONG)os2Msg->mp1);
1108 if (!winMsg->wParam)
1109 {
1110 dprintf(("WM_RENDERFMT: failed to convert clipboard format (%d)!!!\n", os2Msg->mp1));
1111 DebugInt3();
1112 }
1113 break;
1114
1115 case WM_RENDERALLFMTS:
1116 winMsg->message = WINWM_RENDERALLFORMATS;
1117 break;
1118
1119 case WM_DESTROYCLIPBOARD:
1120 winMsg->message = WINWM_DESTROYCLIPBOARD;
1121 break;
1122
1123 case WM_DRAWCLIPBOARD:
1124 winMsg->message = WINWM_DRAWCLIPBOARD;
1125 break;
1126
1127 case WM_HSCROLL:
1128 case WM_VSCROLL:
1129 //PF For win32 we support only vertical scrolling for WM_MOUSEWHEEL
1130 if (os2Msg->msg == WM_VSCROLL)
1131 {
1132 POINT CursorPoint;
1133 winMsg->message = WINWM_MOUSEWHEEL;
1134 if (OSLibWinQueryPointerPos(&CursorPoint))
1135 mapScreenPoint((OSLIBPOINT*)&CursorPoint);
1136
1137 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
1138 winMsg->wParam = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1139 else
1140 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
1141 winMsg->wParam = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1142 else
1143 winMsg->wParam = MAKELONG(GetMouseKeyState(), 0);
1144
1145 winMsg->lParam = MAKELONG(CursorPoint.x, CursorPoint.y);
1146
1147 dprintf(("WM_MOUSEWHEEL message delta %d at (%d,%d)",HIWORD(winMsg->wParam),CursorPoint.x, CursorPoint.y));
1148 if (fMsgRemoved == MSG_REMOVE)
1149 {
1150 MSLLHOOKSTRUCT hook;
1151 MOUSEHOOKSTRUCT mousehk;
1152
1153 hook.pt.x = os2Msg->ptl.x & 0xFFFF;
1154 hook.pt.y = mapScreenY(os2Msg->ptl.y);
1155 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
1156 hook.mouseData = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1157 else
1158 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
1159 hook.mouseData = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1160 else goto dummymessage; // IBM driver produces other messages as well sometimes
1161
1162 hook.flags = LLMHF_INJECTED;
1163 hook.time = winMsg->time;
1164 hook.dwExtraInfo = 0;
1165 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WINWM_MOUSEWHEEL, (LPARAM)&hook))
1166 goto dummymessage; //hook swallowed message
1167 }
1168 break;
1169 }
1170 goto dummymessage; //eat this message
1171 break;
1172
1173 case WM_IMENOTIFY:
1174 dprintf(("WM_IMENOTIFY"));
1175
1176 winMsg->wParam = 0;
1177 winMsg->lParam = 0;
1178
1179 switch(( ULONG )os2Msg->mp1 )
1180 {
1181 case IMN_STARTCONVERSION :
1182 winMsg->message = WM_IME_STARTCOMPOSITION_W;
1183 break;
1184
1185 case IMN_ENDCONVERSION :
1186 winMsg->message = WM_IME_ENDCOMPOSITION_W;
1187 break;
1188
1189 case IMN_CONVERSIONFULL :
1190 winMsg->message = WM_IME_COMPOSITIONFULL_W;
1191 break;
1192
1193 case IMN_IMECHANGED :
1194 winMsg->message = WM_IME_SELECT_W;
1195 // todo
1196 // fall through
1197
1198 default :
1199 goto dummymessage;
1200
1201 }
1202 break;
1203
1204 case WM_IMEREQUEST:
1205 winMsg->wParam = 0;
1206 winMsg->lParam = 0;
1207
1208 switch(( ULONG )os2Msg->mp1 )
1209 {
1210 case IMR_INSTANCEACTIVATE :
1211 {
1212 USHORT usIMR_IA = LOUSHORT( os2Msg->mp2 );
1213
1214 winMsg->message = WM_IME_SETCONTEXT_W;
1215 winMsg->wParam = HIUSHORT( os2Msg->mp2 );
1216
1217 if( usIMR_IA & IMR_IA_STATUS )
1218 winMsg->lParam |= ISC_SHOWUIGUIDELINE_W;
1219
1220 if( usIMR_IA & IMR_IA_CONVERSION )
1221 winMsg->lParam |= ISC_SHOWUICOMPOSITIONWINDOW_W;
1222
1223 if( usIMR_IA & IMR_IA_CANDIDATE )
1224 winMsg->lParam |= ISC_SHOWUIALLCANDIDATEWINDOW_W;
1225
1226 if( usIMR_IA & IMR_IA_INFOMSG )
1227 winMsg->lParam |= 0; // todo
1228
1229 if( usIMR_IA & IMR_IA_REGWORD )
1230 winMsg->lParam |= 0; // todo
1231 break;
1232 }
1233
1234 case IMR_STATUS :
1235 winMsg->message = WM_IME_NOTIFY_W;
1236
1237 switch(( ULONG )os2Msg->mp2 )
1238 {
1239 case IMR_STATUS_SHOW :
1240 winMsg->wParam = IMN_OPENSTATUSWINDOW_W;
1241 break;
1242
1243 case IMR_STATUS_HIDE :
1244 winMsg->wParam = IMN_CLOSESTATUSWINDOW_W;
1245 break;
1246
1247 case IMR_STATUS_INPUTMODE : // IMN_SETOPENSTATUS followed by IMN_SETCONVERSIONMODE
1248 winMsg->wParam = IMN_SETOPENSTATUS_W;
1249 break;
1250
1251 case IMR_STATUS_CONVERSIONMODE :
1252 winMsg->wParam = IMN_SETSENTENCEMODE_W;
1253 break;
1254
1255 case IMR_STATUS_STATUSPOS :
1256 winMsg->wParam = IMN_SETSTATUSWINDOWPOS_W;
1257 break;
1258
1259 case IMR_STATUS_STRING :
1260 case IMR_STATUS_STRINGATTR :
1261 case IMR_STATUS_CURSORPOS :
1262 case IMR_STATUS_CURSORATTR :
1263
1264 default :
1265 // todo
1266 goto dummymessage;
1267
1268 }
1269 break;
1270
1271 case IMR_CONVRESULT :
1272 {
1273 ULONG ulIMR = ( ULONG )os2Msg->mp2;
1274
1275 winMsg->message = WM_IME_COMPOSITION_W;
1276 winMsg->wParam = 0; // todo : current DBCS char
1277
1278 if( ulIMR & IMR_CONV_CONVERSIONSTRING )
1279 winMsg->lParam |= GCS_COMPSTR_W;
1280
1281 if( ulIMR & IMR_CONV_CONVERSIONATTR )
1282 winMsg->lParam |= GCS_COMPATTR_W;
1283
1284 if( ulIMR & IMR_CONV_CONVERSIONCLAUSE )
1285 winMsg->lParam |= GCS_COMPCLAUSE_W;
1286
1287 if( ulIMR & IMR_CONV_READINGSTRING )
1288 winMsg->lParam |= GCS_COMPREADSTR_W;
1289
1290 if( ulIMR & IMR_CONV_READINGATTR )
1291 winMsg->lParam |= GCS_COMPREADATTR_W;
1292
1293 if( ulIMR & IMR_CONV_READINGCLAUSE )
1294 winMsg->lParam |= GCS_COMPREADCLAUSE_W;
1295
1296 if( ulIMR & IMR_CONV_CURSORPOS )
1297 winMsg->lParam |= GCS_CURSORPOS_W;
1298
1299 if( ulIMR & IMR_CONV_CURSORATTR )
1300 winMsg->lParam |= 0; // todo
1301
1302 if( ulIMR & IMR_CONV_CHANGESTART )
1303 winMsg->lParam |= GCS_DELTASTART_W;
1304
1305 if( ulIMR & IMR_CONV_INSERTCHAR )
1306 winMsg->lParam |= CS_INSERTCHAR_W;
1307
1308 if( ulIMR & IMR_CONV_NOMOVECARET )
1309 winMsg->lParam |= CS_NOMOVECARET_W;
1310
1311 if( ulIMR & IMR_CONV_CONVERSIONFONT )
1312 winMsg->lParam |= 0; // todo
1313
1314 if( ulIMR & IMR_CONV_CONVERSIONPOS )
1315 winMsg->lParam |= 0; // todo
1316
1317 if( ulIMR & IMR_RESULT_RESULTSTRING )
1318 winMsg->lParam = GCS_RESULTSTR_W; // clear all composition info
1319
1320 if( ulIMR & IMR_RESULT_RESULTATTR )
1321 winMsg->lParam |= 0; // todo
1322
1323 if( ulIMR & IMR_RESULT_RESULTCLAUSE )
1324 winMsg->lParam |= GCS_RESULTCLAUSE_W;
1325
1326 if( ulIMR & IMR_RESULT_READINGSTRING )
1327 winMsg->lParam |= GCS_RESULTREADSTR_W;
1328
1329 if( ulIMR & IMR_RESULT_READINGATTR )
1330 winMsg->lParam |= 0; // todo
1331
1332 if( ulIMR & IMR_RESULT_READINGCLAUSE )
1333 winMsg->lParam |= GCS_RESULTREADCLAUSE_W;
1334
1335 if( ulIMR && ( winMsg->lParam == 0 ))
1336 goto dummymessage;
1337 break;
1338 }
1339
1340 case IMR_CANDIDATE :
1341 winMsg->message = WM_IME_NOTIFY_W;
1342 switch(( ULONG )os2Msg->mp2 )
1343 {
1344 case IMR_CANDIDATE_SHOW :
1345 case IMR_CANDIDATE_HIDE :
1346 case IMR_CANDIDATE_SELECT :
1347 case IMR_CANDIDATE_CHANGE :
1348 case IMR_CANDIDATE_CANDIDATEPOS :
1349 default :
1350 // todo
1351 goto dummymessage;
1352 }
1353 break;
1354
1355 case IMR_INFOMSG :
1356 winMsg->message = WM_IME_NOTIFY_W;
1357 winMsg->wParam = IMN_GUIDELINE_W;
1358 break;
1359
1360 case IMR_REGWORD :
1361 goto dummymessage;
1362
1363 case IMR_IMECHANGE :
1364 winMsg->message = WM_IME_SELECT_W;
1365 // todo
1366 goto dummymessage;
1367
1368 case IMR_CONFIG :
1369 // todo
1370 goto dummymessage;
1371
1372 case IMR_DICTIONARY :
1373 // todo
1374 goto dummymessage;
1375
1376 case IMR_OTHERINFO :
1377 // todo
1378 goto dummymessage;
1379 }
1380 break;
1381
1382#if 0 // application cannot receive this message
1383 case WM_IMECONTROL:
1384#endif
1385 case WM_INITMENU:
1386 case WM_MENUSELECT:
1387 case WM_MENUEND:
1388 case WM_NEXTMENU:
1389 case WM_SYSCOLORCHANGE:
1390 case WM_SYSVALUECHANGED:
1391 case WM_SETSELECTION:
1392 case WM_PPAINT:
1393 case WM_PSETFOCUS:
1394 case WM_PSYSCOLORCHANGE:
1395 case WM_PSIZE:
1396 case WM_PACTIVATE:
1397 case WM_PCONTROL:
1398 case WM_HELP:
1399 case WM_APPTERMINATENOTIFY:
1400 case WM_PRESPARAMCHANGED:
1401 case WM_DRAWITEM:
1402 case WM_MEASUREITEM:
1403 case WM_CONTROLPOINTER:
1404 case WM_QUERYDLGCODE:
1405 case WM_SUBSTITUTESTRING:
1406 case WM_MATCHMNEMONIC:
1407 case WM_SAVEAPPLICATION:
1408 case WM_SEMANTICEVENT:
1409 default:
1410dummymessage:
1411 dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
1412 winMsg->message = 0;
1413 winMsg->wParam = 0;
1414 winMsg->lParam = 0;
1415 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1416 return FALSE;
1417 }
1418msgdone:
1419 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1420 return TRUE;
1421}
1422//******************************************************************************
1423//******************************************************************************
1424BOOL OSLibWinTranslateMessage(MSG *msg)
1425{
1426 TEB *teb;
1427 MSG extramsg;
1428 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
1429 teb = GetThreadTEB();
1430 if(!teb)
1431 return FALSE;
1432
1433 UCHAR ucPMScanCode = CHAR4FROMMP(teb->o.odin.os2msg.mp1);
1434 ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
1435
1436
1437 //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
1438 // the newly generated WM_CHAR message.
1439 if(!teb->o.odin.fTranslated &&
1440 teb->o.odin.os2msg.msg == WM_CHAR &&
1441 !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
1442 {
1443 //TranslatedMessage was called before DispatchMessage, so queue WM_CHAR message
1444 memcpy(&extramsg, msg, sizeof(MSG));
1445 extramsg.wParam = SHORT1FROMMP(teb->o.odin.os2msg.mp2);
1446 extramsg.lParam = 0;
1447
1448 // ESCAPE generates a WM_CHAR under windows, so take
1449 // special care for this here.
1450 switch (ucPMScanCode)
1451 {
1452 case PMSCAN_ESC:
1453 extramsg.wParam = VK_ESCAPE_W;
1454 fl |= KC_CHAR;
1455 break;
1456 }
1457
1458 // PF With NumLock off do not generate any WM_CHAR messages at all
1459 // PADMINUS,PADPLUS fall in range of PAD7..PADPERIOD but they should generate WM_CHAR
1460 // other PAD(X) buttons miss that range at all and thus generate WM_CHAR
1461 if (!numPressed && (ucPMScanCode != PMSCAN_PADMINUS) && (ucPMScanCode != PMSCAN_PADPLUS) &&
1462 (ucPMScanCode >= PMSCAN_PAD7) && (ucPMScanCode <= PMSCAN_PADPERIOD))
1463 return FALSE;
1464
1465 if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN)
1466 {
1467 return FALSE;
1468 }
1469
1470 //the KC_COMPOSITE flag might be set; in that case this key will
1471 //be combined with the previous dead key, so we must use the scancode
1472 //(e.g. ^ on german keyboards)
1473 if((fl & (KC_VIRTUALKEY|KC_COMPOSITE)) == KC_VIRTUALKEY)
1474 {
1475 if(!msg->wParam)
1476 {//TODO: Why is this here????
1477 DebugInt3();
1478 extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
1479 }
1480 }
1481
1482 //After SetFocus(0), all keystrokes are converted in WM_SYS*
1483 if(msg->message >= WINWM_SYSKEYDOWN || fIgnoreKeystrokes)
1484 extramsg.message = WINWM_SYSCHAR;
1485 else
1486 extramsg.message = WINWM_CHAR;
1487
1488 if(fl & KC_DEADKEY)
1489 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
1490
1491
1492 extramsg.lParam = msg->lParam & 0x00FFFFFF;
1493 if ((fl & KC_ALT) || (msg->lParam & WIN_KEY_ALTHELD))
1494 extramsg.lParam |= WIN_KEY_ALTHELD;
1495 if(fl & KC_PREVDOWN)
1496 extramsg.lParam |= WIN_KEY_PREVSTATE;
1497 if(fl & KC_KEYUP)
1498 extramsg.lParam |= (1<<31);
1499
1500 // insert message into the queue
1501 setThreadQueueExtraCharMessage(teb, &extramsg);
1502
1503 return TRUE;
1504 }
1505 return FALSE;
1506}
1507//******************************************************************************
1508//******************************************************************************
1509
1510/**
1511 * Checks if the message is one that should be forwarded.
1512 *
1513 * @returns True if the message should be forwarded.
1514 * @returns False if the message doesn't fall in to that group.
1515 * @param pMsg Message to examin.
1516 * @remark Are there more messages???
1517 */
1518BOOL OSLibForwardableMessage(const MSG *pMsg)
1519{
1520 return ( (pMsg->message >= WINWM_KEYFIRST && pMsg->message <= WINWM_KEYLAST)
1521 || (pMsg->message >= WINWM_MOUSEFIRST && pMsg->message <= WINWM_MOUSELAST) );
1522}
1523
1524/**
1525 * Forwards this message to the attached thread if it's in the group of messages
1526 * which is supposed to be forwarded.
1527 *
1528 * @returns True if forwarded.
1529 * @returns False if not forwarded.
1530 * @param pTeb Pointer to the TEB of the current thread.
1531 * @param pMsg Message to forward.
1532 * @author knut st. osmundsen <bird-srcspam@anduin.net>
1533 */
1534BOOL OSLibForwardMessageToAttachedThread(void *pvTeb, MSG *pMsg, void *hmm)
1535{
1536 TEB *pTeb = (TEB *)pvTeb;
1537 dprintf(("OSLibForwardMessageToAttachedThread: %p %p (msg=%x)\n", pvTeb, pMsg, pMsg->message));
1538 if (!OSLibForwardableMessage(pMsg))
1539 return FALSE;
1540
1541 /*
1542 * Find the actual receiver thread.
1543 */
1544 int c = 100;
1545 TEB *pTebTo = pTeb;
1546 do
1547 {
1548 pTebTo = GetTEBFromThreadId(pTebTo->o.odin.tidAttachedInputThread);
1549 } while (c-- > 0 && !pTebTo && pTebTo->o.odin.tidAttachedInputThread);
1550 if (!c || !pTebTo)
1551 {
1552 if (c) dprintf(("OSLibForwardMessageToAttachedThread: The receiver thread is dead or non existing.\n"));
1553 else dprintf(("OSLibForwardMessageToAttachedThread: threads are attached in looooop.\n"));
1554 return FALSE; /* hmm.... */
1555 }
1556 dprintf(("OSLibForwardMessageToAttachedThread: Forwarding message %#x to %#x\n",
1557 pMsg->message, pTeb->o.odin.tidAttachedInputThread));
1558
1559 /*
1560 * Pack down the message into shared memory.
1561 */
1562 MSG *pMsgCopy = (MSG *)_smalloc(sizeof(MSG));
1563 if (!pMsgCopy)
1564 return FALSE;
1565 *pMsgCopy = *pMsg;
1566
1567 /*
1568 * Figure out how we should send the message.
1569 */
1570 if (WinInSendMsg(pTebTo->o.odin.hab))
1571 {
1572#if 0
1573 /*
1574 * Hmm what do we do here....
1575 */
1576 MRESULT rc = WinSendQueueMsg(pTebTo->o.odin.hmq, /*special! */, pMsgCopy, /*magic*/ );
1577 /* if (hmmSendMsgResult)
1578 *hmmSendMsgResult = (???)rc; */
1579#else
1580 dprintf(("OSLibForwardMessage: ERROR! %x in sendmsg!!!\n", pMsg->message));
1581 DebugInt3();
1582
1583 _sfree(pMsgCopy);
1584 return FALSE;
1585#endif
1586 }
1587 else
1588 {
1589 if (!WinPostQueueMsg(pTebTo->o.odin.hmq, WIN32APP_FORWARDEDPOSTMSG, pMsgCopy, (MPARAM)WIN32APP_FORWARDEDPOSTMSG_MAGIC))
1590 {
1591 dprintf(("OSLibForwardMessage: Failed to post queue message to hmq=%#x\n", pTebTo->o.odin.hmq));
1592 _sfree(pMsgCopy);
1593 }
1594 }
1595
1596 return TRUE;
1597}
Note: See TracBrowser for help on using the repository browser.