source: branches/swt/src/user32/oslibmsgtranslate.cpp@ 22116

Last change on this file since 22116 was 22116, checked in by rousseau, 10 years ago

Fixed missing exit-code in 'msg.wParam' from PostQuitMessage() [odin]

PostQuitMessage() is forwarded to OSLibWinPostQuitMessage(),
which posts a WM_QUIT message (PM-version) on the PM message-queue using
WinPostQueueMsg(). Function OS2ToWinMsgTranslate() translates the
WM_QUIT-pm to a WM_QUIT-win32 message, and this is where the 'wParam'
holding the PostQuitMessage() exit-code got lost.

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