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

Last change on this file since 10607 was 10607, checked in by sandervl, 21 years ago

KOM: Updates

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