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

Last change on this file since 21341 was 21341, checked in by vladest, 16 years ago

Reworked double free check to make sure the patch will not harm other apps

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