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

Last change on this file since 10275 was 10275, checked in by sandervl, 22 years ago

PM windows should have no owner if none is specified. (instead of their parent)

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