source: branches/gcc-kmk/src/user32/oslibmsgtranslate.cpp@ 21885

Last change on this file since 21885 was 21885, checked in by dmik, 14 years ago

Fix crashes in GUI apps when pressing modifier keys.

This was due the fact that BYTE is signed in the toolkit and converting it
to an unsigned int causes the sign bit to be extended in the result while
the code assumes that the extension is made with zeroes (this is how
VAC converts signed integers of smaller precisions to unsigned ones).

File size: 53.4 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 "C" UINT WINAPI GetACP(void); // from winnls.h
56extern "C" UINT WIN32API clipboardPMToOdinFormat(ULONG ulPMFormat);
57
58//For wheel mouse translation
59#define WHEEL_DELTA 120
60#define OS2_WHEEL_CORRECTION 1
61//PF Correction is different for different mouse drivers. For now no correction
62//is ok because lots of Odin controls rely on minimum delta. However in future
63//we will possibly detect mouse driver and use correction if speed will be
64//too high or too low.
65
66//******************************************************************************
67//
68// setThreadQueueExtraCharMessage: queues WM_CHAR message so it is retrieved
69// by GetMessage & PeekMessage
70//
71// NOTE: WM_CHAR message always in ascii format
72//
73//******************************************************************************
74BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
75{
76 if ( teb->o.odin.tidAttachedInputThread
77 && OSLibForwardMessageToAttachedThread(teb, pExtraMsg, NULL))
78 return TRUE;
79
80 // check if the single slot is occupied already
81 if (teb->o.odin.fTranslated == TRUE) {
82 // there's still an already translated message to be processed
83 dprintf(("WARNING: translated message already pending!"));
84 return FALSE;
85 }
86
87 teb->o.odin.fTranslated = TRUE;
88 memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
89 return TRUE;
90}
91
92//******************************************************************************
93//******************************************************************************
94ULONG ConvertNumPadKey(ULONG pmScan)
95{
96 ULONG ret;
97 UCHAR winKey;
98
99 switch (pmScan)
100 {
101 case PMSCAN_PAD7: ret = PMSCAN_HOME; break;
102 case PMSCAN_PAD8: ret = PMSCAN_UP; break;
103 case PMSCAN_PAD9: ret = PMSCAN_PAGEUP; break;
104 case PMSCAN_PAD4: ret = PMSCAN_LEFT; break;
105 case PMSCAN_PAD6: ret = PMSCAN_RIGHT; break;
106 case PMSCAN_PAD1: ret = PMSCAN_END; break;
107 case PMSCAN_PAD2: ret = PMSCAN_DOWN; break;
108 case PMSCAN_PAD3: ret = PMSCAN_PAGEDOWN; break;
109 case PMSCAN_PAD0: ret = PMSCAN_INSERT; break;
110 case PMSCAN_PADPERIOD: ret = PMSCAN_DELETE; break;
111 default:
112 ret = pmScan;
113 }
114
115 KeyTranslatePMScanToWinVKey(ret, FALSE, &winKey, NULL, NULL);
116 return winKey;
117
118}
119//******************************************************************************
120//******************************************************************************
121LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
122{
123 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
124}
125//******************************************************************************
126//******************************************************************************
127void OSLibSetMenuDoubleClick(BOOL fSet)
128{
129 fGenerateDoubleClick = fSet;
130}
131//******************************************************************************
132
133
134/**
135 * Inter process/thread packet cleanup.
136 * See OSLibPackMessage() for details on the packing.
137 *
138 * @param pTeb Pointer to the thread environment block for the current thread.
139 * @param pPacket Pointer to the packet in question.
140 * @param pWinMsg Pointer to the window message corresponding to the packet.
141 */
142inline void OSLibCleanupPacket(TEB *pTeb, POSTMSG_PACKET *pPacket, MSG *pWinMsg)
143{
144 switch (pWinMsg->message)
145 {
146 /*
147 * Place this in the TEB freeing any previous WM_COPYDATA packet.
148 * Note! Nested WM_COPYDATA isn't working.
149 */
150 case WINWM_COPYDATA:
151 {
152 dprintf(("OSLibCleanupPacket: WM_COPYDATA: old %#p new %#p", pTeb->o.odin.pWM_COPYDATA, pPacket));
153 if (pTeb->o.odin.pWM_COPYDATA)
154 _sfree(pTeb->o.odin.pWM_COPYDATA);
155 pTeb->o.odin.pWM_COPYDATA = pPacket;
156 break;
157 }
158
159 /*
160 * Default packing - free the shared memory here.
161 */
162 default:
163 _sfree(pPacket);
164 break;
165 }
166}
167
168//******************************************************************************
169BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
170{
171 Win32BaseWindow *win32wnd = 0;
172 OSLIBPOINT point, ClientPoint;
173 POSTMSG_PACKET *packet;
174 TEB *teb = (TEB *)pTeb;
175 BOOL fWasDisabled = FALSE;
176 BOOL fIsFrame = FALSE;
177 int i;
178
179 /*
180 * Forwarded input (AttachThreadInput()).
181 */
182 if ( os2Msg->hwnd == NULLHANDLE
183 && os2Msg->msg == WIN32APP_FORWARDEDPOSTMSG
184 && os2Msg->mp2 == (MPARAM)WIN32APP_FORWARDEDPOSTMSG_MAGIC
185 && os2Msg->mp1 != NULL)
186 {
187 *winMsg = *(MSG*)os2Msg->mp1;
188 if (fMsgRemoved)
189 _sfree(os2Msg->mp1);
190 dprintf(("OS2ToWinMsgTranslate: Received forwarded messaged %x\n", os2Msg->msg));
191 return TRUE;
192 }
193
194 memset(winMsg, 0, sizeof(MSG));
195 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
196 if(!win32wnd) {
197 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
198 if(win32wnd) {
199 fIsFrame = TRUE;
200 }
201 }
202
203 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
204 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
205 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
206 {
207 goto dummymessage; //not a win32 client window
208 }
209 winMsg->time = os2Msg->time;
210 //CB: PM bug or undocumented feature? ptl.x highword is set!
211 winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
212 winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
213
214 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
215 winMsg->hwnd = win32wnd->getWindowHandle();
216
217 if(os2Msg->msg >= WIN32APP_POSTMSG) {
218 packet = (POSTMSG_PACKET *)os2Msg->mp2;
219 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
220 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
221 winMsg->wParam = packet->wParam;
222 winMsg->lParam = packet->lParam;
223 if (fMsgRemoved == MSG_REMOVE)
224 {
225 /* avoid double free */
226 if (os2Msg->mp2)
227 {
228 OSLibCleanupPacket(teb, packet, winMsg);
229 os2Msg->mp2 = NULL;
230 }
231#ifdef DEBUG
232 else
233 dprintf(("Trying to free NULL in WinMsgTranslate"));
234#endif
235 }
236 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
237 return TRUE;
238 }
239 else {//broadcasted message (no packet present)
240 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
241 winMsg->wParam = (UINT)os2Msg->mp1;
242 winMsg->lParam = (DWORD)os2Msg->mp2;
243 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
244 return TRUE;
245 }
246 goto dummymessage;
247 }
248
249 switch(os2Msg->msg)
250 {
251 //OS/2 msgs
252 case WM_CREATE:
253 {
254 if(teb->o.odin.newWindow == 0) {
255 DebugInt3();
256 goto dummymessage;
257 }
258
259 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
260 win32wnd->addRef();
261
262 winMsg->message = WINWM_CREATE;
263 winMsg->hwnd = win32wnd->getWindowHandle();
264 winMsg->wParam = 0;
265 winMsg->lParam = (LPARAM)win32wnd->tmpcs;
266 break;
267 }
268
269 case WM_QUIT:
270 winMsg->message = WINWM_QUIT;
271 if (fMsgRemoved && win32wnd && (ULONG)os2Msg->mp2 != 0) {
272 // mp2 != 0 -> sent by window list; be nice and close
273 // the window first
274 win32wnd->MsgClose();
275 }
276 break;
277
278 case WM_CLOSE:
279 winMsg->message = WINWM_CLOSE;
280 break;
281
282 case WM_DESTROY:
283 winMsg->message = WINWM_DESTROY;
284 break;
285
286 case WM_ENABLE:
287 winMsg->message = WINWM_ENABLE;
288 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
289 break;
290
291 case WM_SHOW:
292 winMsg->message = WINWM_SHOWWINDOW;
293 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
294 break;
295
296 case WM_REALIZEPALETTE:
297 winMsg->message = WINWM_PALETTECHANGED;
298 break;
299
300 case WM_WINDOWPOSCHANGED:
301 {
302 PSWP pswp = (PSWP)os2Msg->mp1;
303 SWP swpOld = *(pswp + 1);
304 HWND hParent = NULLHANDLE;
305 LONG yDelta = pswp->cy - swpOld.cy;
306 LONG xDelta = pswp->cx - swpOld.cx;
307
308 if(!fIsFrame) goto dummymessage;
309
310 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
311
312 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
313 if (win32wnd->isChild()) {
314 if(win32wnd->getParent()) {
315 hParent = win32wnd->getParent()->getOS2WindowHandle();
316 }
317 else goto dummymessage; //parent has just been destroyed
318 }
319 }
320 if(win32wnd->getParent()) {
321 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
322 win32wnd->getOS2WindowHandle());
323 }
324 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
325
326 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
327
328 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
329 {
330 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
331 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
332 {
333 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
334 if(wndAfter) {
335 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
336 RELEASE_WNDOBJ(wndAfter);
337 }
338 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
339 }
340 }
341 winMsg->message = WINWM_WINDOWPOSCHANGED;
342 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
343 break;
344 }
345
346 case WM_ACTIVATE:
347 {
348 HWND hwndActivate = (HWND)os2Msg->mp2;
349 BOOL fMinimized = FALSE;
350
351 hwndActivate = OS2ToWin32Handle(hwndActivate);
352 if(hwndActivate == 0) {
353 //another (non-win32) application's window
354 //set to desktop window handle
355 hwndActivate = windowDesktop->getWindowHandle();
356 }
357
358 if(win32wnd->getStyle() & WS_MINIMIZE_W)
359 {
360 fMinimized = TRUE;
361 }
362
363 winMsg->message = WINWM_ACTIVATE;
364 winMsg->wParam = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
365 winMsg->lParam = (LPARAM)hwndActivate;
366 break;
367 }
368
369 case WM_SETFOCUS:
370 {
371 HWND hwndFocus = (HWND)os2Msg->mp1;
372
373 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
374 //another (non-win32) application's window
375 //set to NULL (allowed according to win32 SDK) to avoid problems
376 hwndFocus = NULL;
377 }
378 else hwndFocus = OS2ToWin32Handle(hwndFocus);
379
380 if((ULONG)os2Msg->mp2 == TRUE) {
381 winMsg->message = WINWM_SETFOCUS;
382 winMsg->wParam = (WPARAM)hwndFocus;
383 }
384 else {
385 //If SetFocus(0) was called, then the window has already received
386 //a WM_KILLFOCUS; don't send another one
387 if(!fIgnoreKeystrokes) {
388 winMsg->message = WINWM_KILLFOCUS;
389 winMsg->wParam = (WPARAM)hwndFocus;
390 }
391 else {
392 dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
393 goto dummymessage;
394 }
395 }
396 break;
397 }
398
399 //**************************************************************************
400 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
401 //**************************************************************************
402 case WM_BUTTON1DOWN:
403 case WM_BUTTON1UP:
404 case WM_BUTTON1DBLCLK:
405 case WM_BUTTON2DOWN:
406 case WM_BUTTON2UP:
407 case WM_BUTTON2DBLCLK:
408 case WM_BUTTON3DOWN:
409 case WM_BUTTON3UP:
410 case WM_BUTTON3DBLCLK:
411 {
412 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
413
414 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));
415
416 HWND hwnd;
417
418 DisableLogging();
419 if(GetCapture() != winMsg->hwnd)
420 {
421 hwnd = WindowFromPoint(winMsg->pt);
422 if(win32wnd->getWindowHandle() != hwnd) {
423 RELEASE_WNDOBJ(win32wnd);
424 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
425 if(win32wnd == NULL) {
426 DebugInt3();
427 EnableLogging();
428 goto dummymessage;
429 }
430 winMsg->hwnd = hwnd;
431 }
432 }
433
434 //if a window is disabled, its parent receives the mouse messages
435 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
436 if(win32wnd->getParent()) {
437 Win32BaseWindow *parent = win32wnd->getParent();;
438 if(parent) parent->addRef();
439 RELEASE_WNDOBJ(win32wnd);
440 win32wnd = parent;
441 }
442 fWasDisabled = TRUE;
443 }
444
445 if(IsNCMouseMsg(win32wnd)) {
446 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
447 winMsg->wParam = win32wnd->getLastHitTestVal();
448 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
449 }
450 else {
451 ClientPoint.x = winMsg->pt.x;
452 ClientPoint.y = winMsg->pt.y;
453 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
454 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
455 winMsg->wParam = GetMouseKeyState();
456 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
457 }
458 EnableLogging();
459
460 if(fWasDisabled) {
461 if(win32wnd) {
462 winMsg->hwnd = win32wnd->getWindowHandle();
463 }
464 else goto dummymessage; //don't send mouse messages to disabled windows
465 }
466
467 DisableLogging();
468 if ((winMsg->message == WINWM_LBUTTONDOWN) ||
469 (winMsg->message == WINWM_RBUTTONDOWN) ||
470 (winMsg->message == WINWM_MBUTTONDOWN) ||
471 (winMsg->message == WINWM_NCLBUTTONDOWN) ||
472 (winMsg->message == WINWM_NCRBUTTONDOWN) ||
473 (winMsg->message == WINWM_NCMBUTTONDOWN))
474 {
475 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
476 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
477 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
478 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
479 {
480 dprintf(("single -> double click"));
481 if(winMsg->message >= WINWM_LBUTTONDOWN) {
482 winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
483 }
484 else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
485 if(fMsgRemoved) doubleClickMsg.message = 0;
486 }
487 else {
488 dprintf(("save for double click"));
489 if(fMsgRemoved) {
490 doubleClickMsg = *winMsg;
491 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
492 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
493 }
494 }
495 }
496 }
497 EnableLogging();
498
499 if(fMsgRemoved == MSG_REMOVE)
500 {
501 MSLLHOOKSTRUCT hook;
502 ULONG msg;
503
504 if(winMsg->message >= WINWM_NCLBUTTONDOWN && winMsg->message <= WINWM_NCMBUTTONDBLCLK) {
505 msg = winMsg->message - WINWM_NCLBUTTONDOWN + WINWM_LBUTTONDOWN;
506 }
507 else msg = winMsg->message;
508
509 if(msg == WINWM_LBUTTONDBLCLK) {
510 msg = WINWM_LBUTTONDOWN;
511 }
512 else
513 if(msg == WINWM_RBUTTONDBLCLK) {
514 msg = WINWM_RBUTTONDOWN;
515 }
516 else
517 if(msg == WINWM_MBUTTONDBLCLK) {
518 msg = WINWM_MBUTTONDOWN;
519 }
520
521 // First the low-level mouse hook
522 hook.pt = winMsg->pt;
523 hook.mouseData = 0; //todo: XBUTTON1/2 (XP feature) or wheel data
524 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
525 hook.time = winMsg->time;
526 hook.dwExtraInfo = 0;
527
528 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, msg, (LPARAM)&hook)) {
529 goto dummymessage; //hook swallowed message
530 }
531 }
532 MOUSEHOOKSTRUCT mousehk;
533
534 // Now inform the WH_MOUSE hook
535 mousehk.pt = winMsg->pt;
536 mousehk.hwnd = winMsg->hwnd;
537 mousehk.wHitTestCode = win32wnd->getLastHitTestVal();
538 mousehk.dwExtraInfo = 0;
539
540 if(HOOK_CallHooksW( WH_MOUSE_W, (fMsgRemoved == MSG_REMOVE) ? HC_ACTION : HC_NOREMOVE, winMsg->message, (LPARAM)&mousehk)) {
541 //TODO: WH_CBT HCBT_CLICKSKIPPED
542 goto dummymessage; //hook swallowed message
543 }
544 break;
545 }
546
547 case WM_BUTTON2CLICK:
548 case WM_BUTTON1CLICK:
549 case WM_BUTTON3CLICK:
550 goto dummymessage;
551
552 case WM_BUTTON2MOTIONSTART:
553 case WM_BUTTON2MOTIONEND:
554 case WM_BUTTON1MOTIONSTART:
555 case WM_BUTTON1MOTIONEND:
556 case WM_BUTTON3MOTIONSTART:
557 case WM_BUTTON3MOTIONEND:
558 //no break; translate to WM_MOUSEMOVE
559 //Some applications (e.g. Unreal) retrieve all mouse messages
560 //when a mouse button is pressed and don't expect WM_NULL
561
562 case WM_MOUSEMOVE:
563 {
564 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
565
566 HWND hwnd;
567
568 dprintf2(("WM_MOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
569 DisableLogging();
570 if(GetCapture() != winMsg->hwnd)
571 {
572 hwnd = WindowFromPoint(winMsg->pt);
573 if(win32wnd->getWindowHandle() != hwnd) {
574 RELEASE_WNDOBJ(win32wnd);
575 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
576 if(win32wnd == NULL) {
577 DebugInt3();
578 EnableLogging();
579 goto dummymessage;
580 }
581 winMsg->hwnd = hwnd;
582 }
583 }
584
585 //if a window is disabled, its parent receives the mouse messages
586 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
587 if(win32wnd->getParent()) {
588 Win32BaseWindow *parent = win32wnd->getParent();;
589 if(parent) parent->addRef();
590 RELEASE_WNDOBJ(win32wnd);
591 win32wnd = parent;
592 }
593 fWasDisabled = TRUE;
594 }
595 if(IsNCMouseMsg(win32wnd))
596 {
597 winMsg->message = WINWM_NCMOUSEMOVE;
598 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
599 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
600 }
601 else
602 {
603 ClientPoint.x = winMsg->pt.x;
604 ClientPoint.y = winMsg->pt.y;
605 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
606
607 winMsg->message = WINWM_MOUSEMOVE;
608 winMsg->wParam = GetMouseKeyState();
609 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
610 }
611 EnableLogging();
612 if(fWasDisabled) {
613 if(win32wnd) {
614 winMsg->hwnd = win32wnd->getWindowHandle();
615 }
616 else {
617 goto dummymessage; //don't send mouse messages to disabled windows
618 }
619 }
620 MSLLHOOKSTRUCT hook;
621 if(fMsgRemoved == MSG_REMOVE)
622 {
623 hook.pt = winMsg->pt;
624 hook.mouseData = 0;
625 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
626 hook.time = winMsg->time;
627 hook.dwExtraInfo = 0;
628
629 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, winMsg->message, (LPARAM)&hook)) {
630 goto dummymessage; //hook swallowed message
631 }
632 }
633 MOUSEHOOKSTRUCT mousehk;
634
635 // Now inform the WH_MOUSE hook
636 mousehk.pt = winMsg->pt;
637 mousehk.hwnd = winMsg->hwnd;
638 mousehk.wHitTestCode = win32wnd->getLastHitTestVal();
639 mousehk.dwExtraInfo = 0;
640
641 if(HOOK_CallHooksW( WH_MOUSE_W, (fMsgRemoved == MSG_REMOVE) ? HC_ACTION : HC_NOREMOVE, winMsg->message, (LPARAM)&mousehk))
642 {
643 goto dummymessage; //hook swallowed message
644 }
645 break;
646 }
647
648 case WM_CONTROL:
649 goto dummymessage;
650
651 case WM_COMMAND:
652 if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
653 winMsg->message = WINWM_COMMAND;
654 winMsg->wParam = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
655 break;
656 }
657 //todo controls
658 goto dummymessage;
659
660 case WM_SYSCOMMAND:
661 {
662 ULONG x = 0, y = 0;
663 ULONG win32sc;
664
665 if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
666 POINTL pointl;
667 WinQueryPointerPos(HWND_DESKTOP, &pointl);
668 x = pointl.x;
669 y = mapScreenY(y);
670 }
671 switch(SHORT1FROMMP(os2Msg->mp1)) {
672 case SC_MOVE:
673 win32sc = SC_MOVE_W;
674 break;
675 case SC_CLOSE:
676 {
677 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
678 //TRUE -> user clicked on close button -> close window
679 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
680 {
681 HWND hwnd = win32wnd->GetTopParent();
682 if(win32wnd->getWindowHandle() != hwnd) {
683 RELEASE_WNDOBJ(win32wnd);
684 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
685 if(win32wnd == NULL) {
686 DebugInt3();
687 goto dummymessage;
688 }
689 winMsg->hwnd = hwnd;
690 }
691 }
692 win32sc = SC_CLOSE_W;
693 break;
694 }
695 case SC_MAXIMIZE:
696 win32sc = SC_MAXIMIZE_W;
697 break;
698 case SC_MINIMIZE:
699 win32sc = SC_MINIMIZE_W;
700 break;
701 case SC_NEXTFRAME:
702 case SC_NEXTWINDOW:
703 win32sc = SC_NEXTWINDOW_W;
704 break;
705 case SC_RESTORE:
706 win32sc = SC_RESTORE_W;
707 break;
708 case SC_TASKMANAGER:
709 win32sc = SC_TASKLIST_W;
710 break;
711 case SC_SYSMENU:
712 win32sc = SC_KEYMENU_W; //??
713 break;
714 default:
715 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
716 goto dummymessage;
717 }
718 winMsg->message= WINWM_SYSCOMMAND;
719 winMsg->wParam = (WPARAM)win32sc;
720 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
721 break;
722 }
723
724 case WM_CHAR_SPECIAL_ALTGRCONTROL:
725 {
726 // special char message from the keyboard hook
727 dprintf(("PM: WM_CHAR_SPECIAL_ALTGRCONTROL"));
728 // NO BREAK! FALLTHRU CASE!
729 }
730
731 case WM_CHAR_SPECIAL:
732 {
733 // @@@PH
734 // special char message from the keyboard hook
735 if(os2Msg->msg == WM_CHAR_SPECIAL) {
736 dprintf(("PM: WM_CHAR_SPECIAL"));
737 }
738 // NO BREAK! FALLTHRU CASE!
739 }
740
741 case WM_CHAR:
742 {
743 ULONG repeatCount=0;
744 ULONG virtualKey=0;
745 ULONG keyFlags=0;
746 USHORT scanCode=0;
747 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
748 BOOL keyWasPressed;
749 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
750 char c;
751 USHORT usPMScanCode = CHAR4FROMMP(os2Msg->mp1);
752
753 teb->o.odin.fTranslated = FALSE;
754 repeatCount = CHAR3FROMMP(os2Msg->mp1);
755 scanCode = CHAR4FROMMP(os2Msg->mp1);
756 keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
757
758 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x num=%d", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode, numPressed));
759 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
760
761 BOOL fWinExtended;
762 UCHAR uchWinVKey;
763 WORD wWinScan;
764
765 if ( (!IsDBCSEnv() && scanCode == 0) ||
766 (scanCode==0 ) && !( flags & KC_CHAR ) )
767 {
768 goto dummymessage;
769 }
770
771 if( scanCode != 0 )
772 {
773 switch( SHORT2FROMMP( os2Msg->mp2 ))
774 {
775 // for Korean
776 case VK_DBE_HANJA :
777 uchWinVKey = 0x19;
778 break;
779
780 case VK_DBE_HANGEUL :
781 uchWinVKey = 0x15;
782 break;
783
784 case VK_DBE_JAMO :
785 uchWinVKey = 0;
786 break;
787
788 // for Japan
789 case VK_DBE_KATAKANA :
790 uchWinVKey = 0;
791 break;
792
793 case VK_DBE_HIRAGANA :
794 uchWinVKey = 0;
795 break;
796
797 case VK_DBE_SBCSCHAR :
798 uchWinVKey = 0;
799 break;
800
801 case VK_DBE_DBCSCHAR :
802 uchWinVKey = 0;
803 break;
804
805 case VK_DBE_SBCSDBCSCHAR :
806 uchWinVKey = 0;
807 break;
808
809 case VK_DBE_ROMAN :
810 uchWinVKey = 0;
811 break;
812
813 // for PRC-Chinese
814 case VK_DBE_HANZI :
815 uchWinVKey = 0;
816 break;
817
818 // for Taiwan
819 case VK_DBE_TSANGJYE :
820 uchWinVKey = 0;
821 break;
822
823 case VK_DBE_PHONETIC :
824 uchWinVKey = 0;
825 break;
826
827 case VK_DBE_CONV :
828 uchWinVKey = 0;
829 break;
830
831 case VK_DBE_NOCONV :
832 uchWinVKey = 0;
833 break;
834
835 case VK_DBE_ALPHANUMERIC :
836 switch( GetACP())
837 {
838 case 949 : // Korea
839 case 1361 :
840 uchWinVKey = 0x15;
841 break;
842
843 case 932 : // Japan
844 case 942 :
845 case 943 :
846
847 case 936 : // PRC
848 case 1381 :
849
850 case 950 : // Taiwan
851 default :
852 uchWinVKey = 0;
853 }
854 break;
855
856 default :
857 KeyTranslatePMScanToWinVKey(usPMScanCode,
858 FALSE,
859 &uchWinVKey,
860 &wWinScan,
861 &fWinExtended);
862 }
863
864 winMsg->wParam = uchWinVKey;
865 }
866 else
867 {
868 dprintf(("PM: WM_CHAR: DBCS processing "));
869
870 winMsg->wParam = CHAR1FROMMP( os2Msg->mp2 );
871
872 wWinScan = 0;
873 fWinExtended = 0;
874
875 if( CHAR2FROMMP( os2Msg->mp2 )) // DBCS character
876 {
877 CHAR dbcsCh[ 2 ] = { CHAR1FROMMP( os2Msg->mp2 ), CHAR2FROMMP( os2Msg->mp2 )};
878
879 if( isUnicode )
880 {
881 WCHAR uniChar;
882
883 MultiByteToWideChar( CP_ACP, 0, dbcsCh, 2, &uniChar, 1 );
884 winMsg->wParam = ( WPARAM )uniChar;
885 }
886 else
887 winMsg->wParam = ( dbcsCh[ 0 ] << 8 ) | dbcsCh[ 1 ];
888 }
889 }
890 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
891 winMsg->lParam |= (wWinScan & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
892
893 // Set the extended bit when appropriate
894 if (fWinExtended)
895 winMsg->lParam = winMsg->lParam | WIN_KEY_EXTENDED;
896
897 //PF When we press shift we enable non-numeric functions of Numpad
898 if ((!numPressed || (flags & KC_SHIFT)) && (scanCode >= PMSCAN_PAD7) && (scanCode <= PMSCAN_PADPERIOD))
899 winMsg->wParam = ConvertNumPadKey(scanCode);
900
901 //@PF This looks ugly but this is just what we have in win32 both in win98/win2k
902 //what happens is that lParam is tweaked in win32 to contain some illegal codes
903 //I simply reproduce here all situation. Absolute values can be kept because
904 //Break scancode can be acheived only by pressing Ctrl-Break combination
905 if ((usPMScanCode == PMSCAN_BREAK) && !(flags & KC_KEYUP) && (flags & KC_CTRL)
906 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
907 {
908 MSG extramsg;
909 memcpy(&extramsg, winMsg, sizeof(MSG));
910 // adjust our WM_CHAR code
911 extramsg.lParam = 0x01460001;
912
913 //After SetFocus(0), all keystrokes are converted in WM_SYS*
914 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
915
916 setThreadQueueExtraCharMessage(teb, &extramsg);
917 // and finally adjust our WM_KEYDOWN code
918 winMsg->lParam = 0x01460001;
919 }
920
921 if (!(flags & KC_ALT))
922 {
923 //
924 // the Alt key is not pressed
925 // or no more pressed
926 //
927 if (flags & KC_KEYUP)
928 {
929 // check for a lonesome ALT key ...
930 // SvL: Only Left Alt; AltGr generates a WM_KEYUP when released
931 if ( (flags & KC_LONEKEY) &&
932 (winMsg->wParam == VK_LMENU_W) )
933 {
934 winMsg->message = WINWM_SYSKEYUP;
935 // held ALT-key when current key is released
936 // generates additional flag 0x2000000
937 // Note: PM seems to do this differently,
938 // KC_ALT is already reset
939 }
940 else
941 {
942 // send WM_KEYUP message
943 winMsg->message = WINWM_KEYUP;
944 }
945 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, always 1 for a WM_KEYUP message
946 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
947 }
948 else if( scanCode == 0 )
949 {
950 if( CHAR2FROMMP( os2Msg->mp2 ))
951 winMsg->message = WINWM_IME_CHAR;
952 else
953 {
954 //After SetFocus(0), all keystrokes are converted in WM_SYS*
955 winMsg->message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
956 }
957 }
958 else
959 { // send WM_KEYDOWN message
960 winMsg->message = WINWM_KEYDOWN;
961
962 if (keyWasPressed)
963 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
964
965 //Shift-Enter and possibly others need to have special handling
966 if (flags & KC_SHIFT)
967 {
968 if(fMsgRemoved && !(teb->o.odin.fTranslated))
969 {
970 dprintf(("PM: KC_SHIFT: %x",winMsg->wParam));
971 if (winMsg->wParam == VK_RETURN_W)
972 {
973 MSG extramsg;
974 memcpy(&extramsg, winMsg, sizeof(MSG));
975
976 //After SetFocus(0), all keystrokes are converted in WM_SYS*
977 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
978
979 // insert message into the queue
980 setThreadQueueExtraCharMessage(teb, &extramsg);
981 winMsg->lParam &= 0x3FFFFFFF;
982 }
983 } // else ???
984 } // KC_SHIFT
985 else
986 {
987 // in case we handle Enter directly through PMKBDHOOK
988 if ((os2Msg->msg == WM_CHAR_SPECIAL) && (winMsg->wParam == VK_RETURN_W)
989 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
990 {
991 MSG extramsg;
992 memcpy(&extramsg, winMsg, sizeof(MSG));
993
994 //After SetFocus(0), all keystrokes are converted in WM_SYS*
995 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
996
997 // insert message into the queue
998 setThreadQueueExtraCharMessage(teb, &extramsg);
999 }
1000 }
1001 }
1002 // if right alt is down, then we need to set the alt down bit too
1003 // except for the fake Ctrl WM_CHAR sent for AltGr emulation
1004 if (os2Msg->msg != WM_CHAR_SPECIAL_ALTGRCONTROL &&
1005 (WinGetKeyState(HWND_DESKTOP, VK_ALTGRAF) & 0x8000))
1006 {
1007 winMsg->lParam |= WIN_KEY_ALTHELD;
1008 }
1009 }
1010 else
1011 {
1012 //
1013 // the Alt key is pressed
1014 //
1015 if (flags & KC_KEYUP)
1016 {
1017 //@@PF Note that without pmkbdhook there will not be correct message for Alt-Enter
1018 winMsg->message = WINWM_SYSKEYUP;
1019 winMsg->lParam |= WIN_KEY_PREVSTATE;
1020 // No ALTHELD for Alt itself ;)
1021 winMsg->lParam |= WIN_KEY_ALTHELD;
1022 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
1023 }
1024 else
1025 {
1026 // send WM_SYSKEYDOWN message
1027 winMsg->message = WINWM_SYSKEYDOWN;
1028 if (keyWasPressed)
1029 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
1030
1031 // pressed ALT-key generates additional flag 0x2000000
1032 // if the current window has keyboard focus
1033 winMsg->lParam |= WIN_KEY_ALTHELD;
1034 }
1035 }
1036
1037 //After SetFocus(0), all keystrokes are converted in WM_SYS*
1038 if(fIgnoreKeystrokes) {
1039 if(winMsg->message == WINWM_KEYDOWN) {
1040 winMsg->message = WINWM_SYSKEYDOWN;
1041 }
1042 else
1043 if(winMsg->message == WINWM_KEYUP) {
1044 winMsg->message = WINWM_SYSKEYUP;
1045 }
1046 }
1047 break;
1048 }
1049
1050 case WM_TIMER:
1051//Why was this check here????
1052// if (os2Msg->mp2)
1053// {
1054 BOOL sys;
1055 ULONG id, proc;
1056
1057 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id, &proc))
1058 {
1059 winMsg->wParam = (WPARAM)id;
1060 winMsg->lParam = (LPARAM)proc;
1061 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
1062 break;
1063 }
1064// }
1065 goto dummymessage; //for caret blinking
1066
1067 case WM_SETWINDOWPARAMS:
1068 {
1069 WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
1070
1071 if(wndParams->fsStatus & WPM_TEXT) {
1072 winMsg->message = WINWM_SETTEXT;
1073 winMsg->lParam = (LPARAM)wndParams->pszText;
1074 break;
1075 }
1076 goto dummymessage;
1077 }
1078
1079#if 0
1080 case WM_QUERYWINDOWPARAMS:
1081 {
1082 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
1083 ULONG textlen;
1084 PSZ wintext;
1085
1086 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
1087 {
1088 if(wndpars->fsStatus & WPM_CCHTEXT)
1089 wndpars->cchText = win32wnd->MsgGetTextLength();
1090 if(wndpars->fsStatus & WPM_TEXT)
1091 wndpars->pszText = win32wnd->MsgGetText();
1092
1093 wndpars->fsStatus = 0;
1094 wndpars->cbCtlData = 0;
1095 wndpars->cbPresParams = 0;
1096 goto dummymessage;
1097 }
1098 }
1099#endif
1100
1101 case WM_PAINT:
1102 {
1103 if(win32wnd->IsWindowIconic()) {
1104 winMsg->message = WINWM_PAINTICON;
1105 }
1106 else winMsg->message = WINWM_PAINT;
1107 break;
1108 }
1109
1110 case WM_CONTEXTMENU:
1111 winMsg->message = WINWM_CONTEXTMENU;
1112 winMsg->wParam = win32wnd->getWindowHandle();
1113 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
1114 break;
1115
1116 case WM_RENDERFMT:
1117 winMsg->message = WINWM_RENDERFORMAT;
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.